Propagate --monitor around cluster.
Filter LCK_NONBLOCK in clvmd lock_vg.
Version 2.02.06 -
=================================
+ Propagate --monitor around cluster.
+ Add --monitor to vgcreate and lvcreate to control dmeventd registration.
+ Filter LCK_NONBLOCK in clvmd lock_vg.
Add --nosync to lvcreate with LV flag NOTSYNCED.
Use mirror's uuid for a core log.
Add mirror log fault-handling policy.
}
else {
- status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
+ status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
if (status)
status = errno;
else
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(1);
+ if (!(lock_flags & LCK_DMEVENTD_MONITOR))
+ init_dmeventd_register(0);
+
switch (command) {
case LCK_LV_EXCLUSIVE:
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
if (lock_flags & LCK_PARTIAL_MODE)
init_partial(0);
+ if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
+ init_mirror_in_sync(0);
+
+ if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
+ init_dmeventd_register(DEFAULT_DMEVENTD_MONITOR);
+
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
}
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
- struct volume_group *vg)
+ struct volume_group *vg)
{
return 0;
}
return count;
}
-static int _register_dev_for_events(struct cmd_context *cmd,
- struct logical_volume *lv, int do_reg)
+/*
+ * register_dev_for_events
+ *
+ * This function uses proper error codes (but breaks convention)
+ * to return:
+ * -1 on error
+ * 0 if the lv's targets don't do event [un]registration
+ * 0 if the lv is already [un]registered -- FIXME: not implemented
+ * 1 if the lv had a segment which was [un]registered
+ *
+ * Returns: -1 on error
+ */
+int register_dev_for_events(struct cmd_context *cmd,
+ struct logical_volume *lv, int do_reg)
{
#ifdef DMEVENTD
+ int r = 0;
struct list *tmp;
struct lv_segment *seg;
int (*reg) (struct dm_pool *mem, struct lv_segment *,
struct config_tree *cft, int events);
+ if (do_reg && !dmeventd_register_mode())
+ return 1;
+
list_iterate(tmp, &lv->segments) {
seg = list_item(tmp, struct lv_segment);
reg = seg->segtype->ops->target_unregister_events;
if (!reg)
- return_0;
+ continue;
- /* FIXME specify events */
+ /* FIXME specify events */
if (!reg(cmd->mem, seg, cmd->cft, 0)) {
stack;
- return 0;
+ return -1;
}
+
+ r = 1;
}
-#endif
+ return r;
+#else
return 1;
+#endif
}
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
}
- if (!_register_dev_for_events(cmd, lv, 0))
+ if (register_dev_for_events(cmd, lv, 0) != 1)
/* FIXME Consider aborting here */
stack;
memlock_dec();
fs_unlock();
- if (!_register_dev_for_events(cmd, lv, 1))
+ if (register_dev_for_events(cmd, lv, 1) != 1)
stack;
return 1;
return 0;
}
- if (!_register_dev_for_events(cmd, lv, 0))
+ if (register_dev_for_events(cmd, lv, 0) != 1)
stack;
memlock_inc();
memlock_dec();
fs_unlock();
- if (!_register_dev_for_events(cmd, lv, 1))
+ if (!register_dev_for_events(cmd, lv, 1) != 1)
stack;
return r;
* Returns 1 on failure.
*/
int pv_uses_vg(struct physical_volume *pv,
- struct volume_group *vg)
+ struct volume_group *vg)
{
if (!activation())
return 0;
int lvs_in_vg_activated(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);
+
+int register_dev_for_events(struct cmd_context *cmd,
+ struct logical_volume *lv, int do_reg);
+
/*
* Returns 1 if PV has a dependency tree that uses anything in VG.
*/
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
+#define DEFAULT_DMEVENTD_MONITOR 1
#define DEFAULT_UMASK 0077
if (mirror_in_sync())
args[1] |= LCK_MIRROR_NOSYNC_MODE;
+ if (dmeventd_register_mode())
+ args[1] |= LCK_DMEVENTD_REGISTER_MODE;
+
/*
* VG locks are just that: locks, and have no side effects
* so we only need to do them on the local node because all
*/
#define LCK_PARTIAL_MODE 0x00000001 /* Running in partial mode */
#define LCK_MIRROR_NOSYNC_MODE 0x00000002 /* Mirrors don't require sync */
+#define LCK_DMEVENTD_REGISTER_MODE 0x00000004 /* Register with dmeventd */
+
/*
* Common combinations
#include "device.h"
#include "memlock.h"
#include "lvm-string.h"
+#include "defaults.h"
#include <stdarg.h>
#include <syslog.h>
static char _msg_prefix[30] = " ";
static int _already_logging = 0;
static int _mirror_in_sync = 0;
+static int _dmeventd_register = DEFAULT_DMEVENTD_MONITOR;
static lvm2_log_fn_t _lvm2_log_fn = NULL;
_mirror_in_sync = in_sync;
}
+void init_dmeventd_register(int reg)
+{
+ _dmeventd_register = reg;
+}
+
void init_cmd_name(int status)
{
_log_cmd_name = status;
return _mirror_in_sync;
}
+int dmeventd_register_mode(void)
+{
+ return _dmeventd_register;
+}
+
void init_debug(int level)
{
_debug_level = level;
void init_lockingfailed(int level);
void init_security_level(int level);
void init_mirror_in_sync(int in_sync);
+void init_dmeventd_register(int reg);
void set_cmd_name(const char *cmd_name);
int lockingfailed(void);
int security_level(void);
int mirror_in_sync(void);
+int dmeventd_register_mode(void);
/* Suppress messages to stdout/stderr (1) or everywhere (2) */
/* Returns previous setting */
arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL)
arg(nosync_ARG, '\0', "nosync", NULL)
arg(corelog_ARG, '\0', "corelog", NULL)
+arg(monitor_ARG, '\0', "monitor", yes_no_arg)
/* Allow some variations */
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
"\t[-f|--force]\n"
"\t[-h|--help]\n"
"\t[--ignorelockingfailure]\n"
+ "\t[--monitor {y|n}]\n"
"\t[-M|--persistent y|n] [--major major] [--minor minor]\n"
"\t[-P|--partial] " "\n"
"\t[-p|--permission r|rw]\n"
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
alloc_ARG, autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
- ignorelockingfailure_ARG, major_ARG, minor_ARG, partial_ARG, permission_ARG,
- persistent_ARG, readahead_ARG, refresh_ARG, addtag_ARG, deltag_ARG,
- test_ARG)
+ ignorelockingfailure_ARG, major_ARG, minor_ARG, monitor_ARG,
+ partial_ARG, permission_ARG, persistent_ARG, readahead_ARG,
+ refresh_ARG, addtag_ARG, deltag_ARG, test_ARG)
xx(lvconvert,
"Change logical volume layout",
"\t[-v|--verbose]\n"
"\t[--version]" "\n"
"\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n",
-
+
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG,
separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
"\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n"
"\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
- abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
+ abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
interval_ARG, name_ARG, test_ARG)
xx(pvremove,
"\t[-v|--verbose]\n"
"\t[--version]\n"
"\t[PhysicalVolume [PhysicalVolume...]]\n",
-
+
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG,
separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
"\t[-d|--debug] " "\n"
"\t[-h|--help] " "\n"
"\t[--ignorelockingfailure]\n"
+ "\t[--monitor {y|n}]\n"
"\t[-t|--test]" "\n"
"\t[-u|--uuid] " "\n"
"\t[-v|--verbose] " "\n"
addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, logicalvolume_ARG,
- partial_ARG, physicalextentsize_ARG, resizeable_ARG, resizable_ARG,
- test_ARG, uuid_ARG)
+ monitor_ARG, partial_ARG, physicalextentsize_ARG, resizeable_ARG,
+ resizable_ARG, test_ARG, uuid_ARG)
xx(vgck,
"Check the consistency of volume group(s)",
"\t[-v|--verbose]\n"
"\t[--version]\n"
"\t[VolumeGroupName [VolumeGroupName...]]\n",
-
+
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, separator_ARG,
sort_ARG, unbuffered_ARG, units_ARG)
"\t[--ignorelockingfailure]\n"
"\t[--mknodes]\n"
"\t[-P|--partial] " "\n"
- "\t[-v|--verbose]\n"
+ "\t[-v|--verbose]\n"
"\t[--version]" "\n",
ignorelockingfailure_ARG, mknodes_ARG, partial_ARG)
return 1;
}
+static int lvchange_registration(struct cmd_context *cmd,
+ struct logical_volume *lv)
+{
+ int r;
+ struct lvinfo info;
+
+ if (!lv_info(cmd, lv, &info, 0) || !info.exists) {
+ log_error("Logical volume, %s, is not active", lv->name);
+ return 0;
+ }
+
+ /* do not register pvmove lv's */
+ if (lv->status & PVMOVE)
+ return 1;
+
+ log_verbose("%smonitoring logical volume \"%s\"",
+ (dmeventd_register_mode()) ? "" : "Not ", lv->name);
+ r = register_dev_for_events(cmd, lv, dmeventd_register_mode());
+
+ if (r < 0) {
+ log_error("Unable to %smonitor logical volume, %s",
+ (dmeventd_register_mode()) ? "" : "un", lv->name);
+ r = 0;
+ } else if (!r) {
+ log_verbose("Logical volume %s needs no monitoring.",
+ lv->name);
+ r = 1;
+ }
+
+ return r;
+}
+
static int lvchange_availability(struct cmd_context *cmd,
struct logical_volume *lv)
{
return ECMD_FAILED;
}
+ init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
+
/* access permission change */
if (arg_count(cmd, permission_ARG)) {
if (!archive(lv->vg))
log_print("Logical volume \"%s\" changed", lv->name);
/* availability change */
- if (arg_count(cmd, available_ARG))
+ if (arg_count(cmd, available_ARG)) {
if (!lvchange_availability(cmd, lv))
return ECMD_FAILED;
+ }
if (arg_count(cmd, refresh_ARG))
if (!lvchange_refresh(cmd, lv))
return ECMD_FAILED;
+ if (!arg_count(cmd, available_ARG) &&
+ !arg_count(cmd, refresh_ARG) &&
+ arg_count(cmd, monitor_ARG)) {
+ if (!lvchange_registration(cmd, lv))
+ return ECMD_FAILED;
+ }
+
return ECMD_PROCESSED;
}
&& !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
&& !arg_count(cmd, persistent_ARG) && !arg_count(cmd, addtag_ARG)
&& !arg_count(cmd, deltag_ARG) && !arg_count(cmd, refresh_ARG)
- && !arg_count(cmd, alloc_ARG)) {
- log_error("One or more of -a, -C, -j, -m, -M, -p, -r, "
- "--refresh, --alloc, --addtag or --deltag required");
+ && !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)) {
+ log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
+ "--refresh, --alloc, --addtag, --deltag "
+ "or --monitor");
return EINVALID_CMD_LINE;
}
#include "tools.h"
+static int _register_lvs_in_vg(struct cmd_context *cmd,
+ struct volume_group *vg, int reg)
+{
+ struct lv_list *lvl;
+ struct logical_volume *lv;
+ struct lvinfo info;
+ int lv_active;
+ int count = 0;
+ int r;
+
+ list_iterate_items(lvl, &vg->lvs) {
+ lv = lvl->lv;
+
+ if (!lv_info(cmd, lv, &info, 0))
+ lv_active = 0;
+ else
+ lv_active = info.exists;
+
+ /*
+ * FIXME: Need to consider all cases... PVMOVE, etc
+ */
+ if ((lv->status & PVMOVE) || !lv_active)
+ continue;
+
+ r = register_dev_for_events(cmd, lv, reg);
+
+ if (r < 0) {
+ log_error("Failed to %s logical volume, %s",
+ (reg) ? "register" : "unregister",
+ lv->name);
+ continue;
+ }
+
+ if (r)
+ count++;
+ }
+
+ /*
+ * returns the number of monitored devices, not the number
+ * of _new_ monitored devices
+ */
+
+ return count;
+}
+
static int _activate_lvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg, int activate)
{
return count;
}
+static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg)
+{
+ int active, monitored;
+
+ if ((active = lvs_in_vg_activated(vg))) {
+ monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
+ log_print("%d logical volume(s) in volume group "
+ "\"%s\" now %smonitored",
+ monitored, vg->name, (dmeventd_register_mode()) ? "" : "un");
+ }
+
+ return ECMD_PROCESSED;
+}
+
static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
{
- int lv_open, active;
+ int lv_open, active, monitored;
int available;
int activate = 1;
if (activate && !lockingfailed())
check_current_backup(vg);
- if (activate && (active = lvs_in_vg_activated(vg)))
+ if (activate && (active = lvs_in_vg_activated(vg))) {
log_verbose("%d logical volume(s) in volume group \"%s\" "
"already active", active, vg->name);
+ monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
+ log_verbose("%d existing logical volume(s) in volume "
+ "group \"%s\" now %smonitored",
+ monitored, vg->name,
+ dmeventd_register_mode() ? "" : "un");
+ }
if (activate && _activate_lvs_in_vg(cmd, vg, available))
log_verbose("Activated logical volumes in "
return ECMD_FAILED;
}
+ init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
+
if (arg_count(cmd, available_ARG))
r = _vgchange_available(cmd, vg);
+ else if (arg_count(cmd, monitor_ARG))
+ r = _vgchange_monitoring(cmd, vg);
+
else if (arg_count(cmd, resizeable_ARG))
r = _vgchange_resizeable(cmd, vg);
arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
arg_count(cmd, physicalextentsize_ARG) +
- arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG))) {
+ arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG) +
+ arg_count(cmd, monitor_ARG))) {
log_error("One of -a, -c, -l, -s, -x, --uuid, --alloc, --addtag or "
"--deltag required");
return EINVALID_CMD_LINE;
* and add to list of LVs to be removed later.
* Doesn't apply to snapshots/origins yet - they're already deactivated.
*/
- if (lv_info(cmd, lv, &info, 0) && info.exists) {
+ /*
+ * If the LV is a part of mirror segment,
+ * the mirrored LV also should be cleaned up.
+ * Clean-up is currently done by caller (_make_vg_consistent()).
+ */
+ if ((lv_info(cmd, lv, &info, 0) && info.exists)
+ || first_seg(lv)->mirror_seg) {
extents = lv->le_count;
mirror_seg = first_seg(lv)->mirror_seg;
if (!lv_empty(lv)) {