From 445dd17db3cf70559c67fe416a8dd1b571ec1653 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 12 May 2006 19:16:48 +0000 Subject: [PATCH] Add --monitor to vgcreate and lvcreate to control dmeventd registration. Propagate --monitor around cluster. Filter LCK_NONBLOCK in clvmd lock_vg. --- WHATS_NEW | 3 ++ daemons/clvmd/clvmd-command.c | 2 +- daemons/clvmd/lvm-functions.c | 9 ++++ lib/activate/activate.c | 44 ++++++++++++++------ lib/activate/activate.h | 4 ++ lib/config/defaults.h | 1 + lib/locking/cluster_locking.c | 3 ++ lib/locking/locking.h | 2 + lib/log/log.c | 12 ++++++ lib/log/log.h | 2 + tools/args.h | 1 + tools/commands.h | 22 +++++----- tools/lvchange.c | 51 +++++++++++++++++++++-- tools/vgchange.c | 77 +++++++++++++++++++++++++++++++++-- tools/vgreduce.c | 8 +++- 15 files changed, 210 insertions(+), 31 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 4913b9a87..01b2a8f24 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,8 @@ 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. diff --git a/daemons/clvmd/clvmd-command.c b/daemons/clvmd/clvmd-command.c index f5a4d7615..ee623baa8 100644 --- a/daemons/clvmd/clvmd-command.c +++ b/daemons/clvmd/clvmd-command.c @@ -180,7 +180,7 @@ static int lock_vg(struct local_client *client) } 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 diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c index 4d387f929..5f3093bf0 100644 --- a/daemons/clvmd/lvm-functions.c +++ b/daemons/clvmd/lvm-functions.c @@ -309,6 +309,9 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource) 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); @@ -340,6 +343,12 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource) 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); diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 0eb554621..d27c31bc4 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -152,7 +152,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv) } int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv, - struct volume_group *vg) + struct volume_group *vg) { return 0; } @@ -574,15 +574,31 @@ int lvs_in_vg_opened(struct volume_group *vg) 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); @@ -595,17 +611,21 @@ static int _register_dev_for_events(struct cmd_context *cmd, 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, @@ -643,7 +663,7 @@ 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; @@ -697,7 +717,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s, memlock_dec(); fs_unlock(); - if (!_register_dev_for_events(cmd, lv, 1)) + if (register_dev_for_events(cmd, lv, 1) != 1) stack; return 1; @@ -743,7 +763,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) return 0; } - if (!_register_dev_for_events(cmd, lv, 0)) + if (register_dev_for_events(cmd, lv, 0) != 1) stack; memlock_inc(); @@ -816,7 +836,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, memlock_dec(); fs_unlock(); - if (!_register_dev_for_events(cmd, lv, 1)) + if (!register_dev_for_events(cmd, lv, 1) != 1) stack; return r; @@ -863,7 +883,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv) * Returns 1 on failure. */ int pv_uses_vg(struct physical_volume *pv, - struct volume_group *vg) + struct volume_group *vg) { if (!activation()) return 0; diff --git a/lib/activate/activate.h b/lib/activate/activate.h index cbcdd5491..f8a602269 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -80,6 +80,10 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, 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. */ diff --git a/lib/config/defaults.h b/lib/config/defaults.h index b1b27b83c..ebeaf582f 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -37,6 +37,7 @@ #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 diff --git a/lib/locking/cluster_locking.c b/lib/locking/cluster_locking.c index 6e7f60679..ce16e660b 100644 --- a/lib/locking/cluster_locking.c +++ b/lib/locking/cluster_locking.c @@ -336,6 +336,9 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name) 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 diff --git a/lib/locking/locking.h b/lib/locking/locking.h index 9153595f3..245de5f54 100644 --- a/lib/locking/locking.h +++ b/lib/locking/locking.h @@ -75,6 +75,8 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname); */ #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 diff --git a/lib/log/log.c b/lib/log/log.c index 08673daf4..db1796152 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -17,6 +17,7 @@ #include "device.h" #include "memlock.h" #include "lvm-string.h" +#include "defaults.h" #include #include @@ -46,6 +47,7 @@ static char _cmd_name[30] = ""; 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; @@ -181,6 +183,11 @@ void init_mirror_in_sync(int in_sync) _mirror_in_sync = in_sync; } +void init_dmeventd_register(int reg) +{ + _dmeventd_register = reg; +} + void init_cmd_name(int status) { _log_cmd_name = status; @@ -250,6 +257,11 @@ int mirror_in_sync(void) return _mirror_in_sync; } +int dmeventd_register_mode(void) +{ + return _dmeventd_register; +} + void init_debug(int level) { _debug_level = level; diff --git a/lib/log/log.h b/lib/log/log.h index e8afd4d71..8d983d08c 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -74,6 +74,7 @@ void init_ignorelockingfailure(int 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); @@ -87,6 +88,7 @@ int ignorelockingfailure(void); 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 */ diff --git a/tools/args.h b/tools/args.h index 0254ed27b..a0f32446d 100644 --- a/tools/args.h +++ b/tools/args.h @@ -47,6 +47,7 @@ arg(separator_ARG, '\0', "separator", string_arg) 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) diff --git a/tools/commands.h b/tools/commands.h index ac079ef9f..f81b49f8b 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -63,6 +63,7 @@ xx(lvchange, "\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" @@ -74,9 +75,9 @@ xx(lvchange, "\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", @@ -347,7 +348,7 @@ xx(lvs, "\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) @@ -494,7 +495,7 @@ xx(pvmove, "\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, @@ -531,7 +532,7 @@ xx(pvs, "\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) @@ -595,6 +596,7 @@ xx(vgchange, "\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" @@ -610,8 +612,8 @@ xx(vgchange, 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)", @@ -822,7 +824,7 @@ xx(vgs, "\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) @@ -835,7 +837,7 @@ xx(vgscan, "\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) diff --git a/tools/lvchange.c b/tools/lvchange.c index 147519d01..cb69a41dc 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -72,6 +72,38 @@ static int lvchange_permission(struct cmd_context *cmd, 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) { @@ -422,6 +454,8 @@ static int lvchange_single(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)) @@ -474,14 +508,22 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv, 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; } @@ -492,9 +534,10 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv) && !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; } diff --git a/tools/vgchange.c b/tools/vgchange.c index dd7c6181b..89c152783 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -15,6 +15,51 @@ #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) { @@ -65,9 +110,23 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd, 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; @@ -93,9 +152,15 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg) 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 " @@ -429,9 +494,14 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name, 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); @@ -466,7 +536,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv) 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; diff --git a/tools/vgreduce.c b/tools/vgreduce.c index c637aaccd..49bb656c2 100644 --- a/tools/vgreduce.c +++ b/tools/vgreduce.c @@ -111,7 +111,13 @@ static int _remove_lv(struct cmd_context *cmd, struct logical_volume *lv, * 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)) {