[lvm-devel] [RFC][PATCH] add --poll flag to vgchange and lvchange

Mike Snitzer snitzer at redhat.com
Tue Dec 1 22:46:34 UTC 2009


Add a [--poll {y|n}] flag to vgchange and lvchange to control whether
the background polldaemon is allowed to start.  It can be used
standalone or in conjunction with --refresh or --available y.

Control over when the background polldaemon starts will be particularly
important for snapshot-merge of a root filesystem.

Dracut will be updated to activate all LVs with: --poll n

The lvm2-monitor initscript will start polling with: --poll y

Because we currently have no way of knowing if a background polldaemon
is active for a given LV the following limitations exist:
1) it is not possible to stop an active polldaemon; so the lvm2-monitor
   initscript doesn't stop running polldaemon(s)
2) redundant polldaemon instances will be started for all specified LVs
   if vgchange or lvchange are repeatedly used with '--poll y'

TODO:
At a minimum I believe we need to add an LV flag that tells us the
background polldaemon is already active for a given LV.

I'll also update the vgchange and lvchange man pages once I get feedback
on this RFC patch.

---
 lib/config/defaults.h                   |    1 
 lib/misc/lvm-globals.c                  |   11 +++++
 lib/misc/lvm-globals.h                  |    2 +
 scripts/lvm2_monitoring_init_red_hat.in |    4 +-
 tools/args.h                            |    1 
 tools/commands.h                        |    8 ++--
 tools/lvchange.c                        |   37 ++++++++++++++++--
 tools/vgchange.c                        |   64 ++++++++++++++++++++++++++++++--
 8 files changed, 115 insertions(+), 13 deletions(-)

Index: lvm2/lib/config/defaults.h
===================================================================
--- lvm2.orig/lib/config/defaults.h
+++ lvm2/lib/config/defaults.h
@@ -50,6 +50,7 @@
 #define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
 #define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
 #define DEFAULT_DMEVENTD_MONITOR 1
+#define DEFAULT_BACKGROUND_POLLING 1
 
 #define DEFAULT_UMASK 0077
 
Index: lvm2/lib/misc/lvm-globals.c
===================================================================
--- lvm2.orig/lib/misc/lvm-globals.c
+++ lvm2/lib/misc/lvm-globals.c
@@ -35,6 +35,7 @@ static int _security_level = SECURITY_LE
 static char _cmd_name[30] = "";
 static int _mirror_in_sync = 0;
 static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
+static int _background_polling = DEFAULT_BACKGROUND_POLLING;
 static int _ignore_suspended_devices = 0;
 static int _error_message_produced = 0;
 static unsigned _is_static = 0;
@@ -91,6 +92,11 @@ void init_dmeventd_monitor(int reg)
 	_dmeventd_monitor = reg;
 }
 
+void init_background_polling(int polling)
+{
+	_background_polling = polling;
+}
+
 void init_ignore_suspended_devices(int ignore)
 {
 	_ignore_suspended_devices = ignore;
@@ -155,6 +161,11 @@ int trust_cache()
 	return _trust_cache;
 }
 
+int background_polling()
+{
+	return _background_polling;
+}
+
 int ignorelockingfailure()
 {
 	return _ignorelockingfailure;
Index: lvm2/lib/misc/lvm-globals.h
===================================================================
--- lvm2.orig/lib/misc/lvm-globals.h
+++ lvm2/lib/misc/lvm-globals.h
@@ -32,6 +32,7 @@ void init_lockingfailed(int level);
 void init_security_level(int level);
 void init_mirror_in_sync(int in_sync);
 void init_dmeventd_monitor(int reg);
+void init_background_polling(int polling);
 void init_ignore_suspended_devices(int ignore);
 void init_error_message_produced(int produced);
 void init_is_static(unsigned value);
@@ -49,6 +50,7 @@ int ignorelockingfailure(void);
 int lockingfailed(void);
 int security_level(void);
 int mirror_in_sync(void);
+int background_polling(void);
 int ignore_suspended_devices(void);
 const char *log_command_name(void);
 unsigned is_static(void);
Index: lvm2/tools/args.h
===================================================================
--- lvm2.orig/tools/args.h
+++ lvm2/tools/args.h
@@ -64,6 +64,7 @@ arg(dataalignmentoffset_ARG, '\0', "data
 arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0)
 arg(virtualsize_ARG, '\0', "virtualsize", size_mb_arg, 0)
 arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0)
+arg(poll_ARG, '\0', "poll", yes_no_arg, 0)
 
 /* Allow some variations */
 arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0)
Index: lvm2/tools/commands.h
===================================================================
--- lvm2.orig/tools/commands.h
+++ lvm2/tools/commands.h
@@ -72,6 +72,7 @@ xx(lvchange,
    "\t[--ignorelockingfailure]\n"
    "\t[--ignoremonitoring]\n"
    "\t[--monitor {y|n}]\n"
+   "\t[--poll {y|n}]\n"
    "\t[--noudevsync]\n"
    "\t[-M|--persistent y|n] [--major major] [--minor minor]\n"
    "\t[-P|--partial] " "\n"
@@ -88,8 +89,8 @@ xx(lvchange,
    alloc_ARG, autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
    ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
    monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG,
-   readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG, test_ARG,
-   yes_ARG)
+   poll_ARG, readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG,
+   test_ARG, yes_ARG)
 
 xx(lvconvert,
    "Change logical volume layout",
@@ -688,6 +689,7 @@ xx(vgchange,
    "\t[--ignorelockingfailure]\n"
    "\t[--ignoremonitoring]\n"
    "\t[--monitor {y|n}]\n"
+   "\t[--poll {y|n}]\n"
    "\t[--noudevsync]\n"
    "\t[--refresh]\n"
    "\t[-t|--test]" "\n"
@@ -707,7 +709,7 @@ xx(vgchange,
    addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
    clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, ignoremonitoring_ARG,
    logicalvolume_ARG, maxphysicalvolumes_ARG, monitor_ARG, noudevsync_ARG,
-   partial_ARG, physicalextentsize_ARG, refresh_ARG, resizeable_ARG,
+   partial_ARG, physicalextentsize_ARG, poll_ARG, refresh_ARG, resizeable_ARG,
    resizable_ARG, test_ARG, uuid_ARG)
 
 xx(vgck,
Index: lvm2/tools/lvchange.c
===================================================================
--- lvm2.orig/tools/lvchange.c
+++ lvm2/tools/lvchange.c
@@ -101,6 +101,22 @@ static int lvchange_monitoring(struct cm
 	return 1;
 }
 
+static int lvchange_background_polling(struct cmd_context *cmd,
+				       struct logical_volume *lv)
+{
+	struct lvinfo info;
+
+	if (!lv_info(cmd, lv, &info, 0, 0) || !info.exists) {
+		log_error("Logical volume, %s, is not active", lv->name);
+		return 0;
+	}
+
+	if (background_polling())
+		lv_spawn_background_polling(cmd, lv);
+
+	return 1;
+}
+
 static int lvchange_availability(struct cmd_context *cmd,
 				 struct logical_volume *lv)
 {
@@ -135,7 +151,8 @@ static int lvchange_availability(struct 
 				return_0;
 		}
 
-		lv_spawn_background_polling(cmd, lv);
+		if (background_polling())
+			lv_spawn_background_polling(cmd, lv);
 	}
 
 	return 1;
@@ -577,6 +594,9 @@ static int lvchange_single(struct cmd_co
 					    (is_static() || arg_count(cmd, ignoremonitoring_ARG)) ?
 					    DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
 
+	init_background_polling(arg_int_value(cmd, poll_ARG,
+					      DEFAULT_BACKGROUND_POLLING));
+
 	/* access permission change */
 	if (arg_count(cmd, permission_ARG)) {
 		if (!archive(lv->vg)) {
@@ -679,6 +699,15 @@ static int lvchange_single(struct cmd_co
 		}
 	}
 
+	if (!arg_count(cmd, available_ARG) &&
+	    !arg_count(cmd, refresh_ARG) &&
+	    arg_count(cmd, poll_ARG)) {
+		if (!lvchange_background_polling(cmd, lv)) {
+			stack;
+			return ECMD_FAILED;
+		}
+	}
+
 	if (doit != docmds) {
 		stack;
 		return ECMD_FAILED;
@@ -695,10 +724,10 @@ int lvchange(struct cmd_context *cmd, in
 	    && !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) && !arg_count(cmd, monitor_ARG)
-	    && !arg_count(cmd, resync_ARG)) {
+	    && !arg_count(cmd, poll_ARG) && !arg_count(cmd, resync_ARG)) {
 		log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
-			  "--resync, --refresh, --alloc, --addtag, --deltag "
-			  "or --monitor");
+			  "--resync, --refresh, --alloc, --addtag, --deltag, "
+			  "--monitor or --poll");
 		return EINVALID_CMD_LINE;
 	}
 
Index: lvm2/tools/vgchange.c
===================================================================
--- lvm2.orig/tools/vgchange.c
+++ lvm2/tools/vgchange.c
@@ -51,6 +51,39 @@ static int _monitor_lvs_in_vg(struct cmd
 	return count;
 }
 
+static int _poll_lvs_in_vg(struct cmd_context *cmd,
+			   struct volume_group *vg)
+{
+	struct lv_list *lvl;
+	struct logical_volume *lv;
+	struct lvinfo info;
+	int lv_active;
+	int count = 0;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
+
+		if (!lv_info(cmd, lv, &info, 0, 0))
+			lv_active = 0;
+		else
+			lv_active = info.exists;
+
+		if (!lv_active ||
+		    !(lv->status & (PVMOVE|CONVERTING)))
+			continue;
+
+		lv_spawn_background_polling(cmd, lv);
+		count++;
+	}
+
+	/*
+	 * returns the number of polled devices
+	 * - FIXME: no way to know if lv is already being polled
+	 */
+
+	return count;
+}
+
 static int _activate_lvs_in_vg(struct cmd_context *cmd,
 			       struct volume_group *vg, int activate)
 {
@@ -95,7 +128,8 @@ static int _activate_lvs_in_vg(struct cm
 		} else if (!activate_lv(cmd, lv))
 			continue;
 
-		if (activate != CHANGE_AN && activate != CHANGE_ALN &&
+		if (background_polling() &&
+		    activate != CHANGE_AN && activate != CHANGE_ALN &&
 		    (lv->status & (PVMOVE|CONVERTING)))
 			lv_spawn_background_polling(cmd, lv);
 
@@ -125,6 +159,20 @@ static int _vgchange_monitoring(struct c
 	return ECMD_PROCESSED;
 }
 
+static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg)
+{
+	int polled;
+
+	if (lvs_in_vg_activated(vg) && background_polling()) {
+	        polled = _poll_lvs_in_vg(cmd, vg);
+		log_print("Background polling started for %d logical volume(s) "
+			  "in volume group \"%s\"",
+			  polled, vg->name);
+	}
+
+	return ECMD_PROCESSED;
+}
+
 static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
 {
 	int lv_open, active, monitored;
@@ -490,12 +538,18 @@ static int vgchange_single(struct cmd_co
 					    (is_static() || arg_count(cmd, ignoremonitoring_ARG)) ?
 					    DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
 
+	init_background_polling(arg_int_value(cmd, poll_ARG,
+					      DEFAULT_BACKGROUND_POLLING));
+
 	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, poll_ARG))
+		r = _vgchange_background_polling(cmd, vg);
+
 	else if (arg_count(cmd, resizeable_ARG))
 		r = _vgchange_resizeable(cmd, vg);
 
@@ -538,9 +592,11 @@ int vgchange(struct cmd_context *cmd, in
 	     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, monitor_ARG) + arg_count(cmd, refresh_ARG))) {
-		log_error("One of -a, -c, -l, -p, -s, -x, --refresh, "
-				"--uuid, --alloc, --addtag or --deltag required");
+	     arg_count(cmd, monitor_ARG) + arg_count(cmd, poll_ARG) +
+	     arg_count(cmd, refresh_ARG))) {
+		log_error("Need 1 or more of -a, -c, -l, -p, -s, -x, "
+			  "--refresh, --uuid, --alloc, --addtag, --deltag, "
+			  "--monitor or --poll");
 		return EINVALID_CMD_LINE;
 	}
 
Index: lvm2/scripts/lvm2_monitoring_init_red_hat.in
===================================================================
--- lvm2.orig/scripts/lvm2_monitoring_init_red_hat.in
+++ lvm2/scripts/lvm2_monitoring_init_red_hat.in
@@ -26,7 +26,7 @@
 # Required-Stop: $local_fs
 # Default-Start: 1 2 3 4 5
 # Default-Stop: 0 6
-# Short-Description: Monitoring of LVM2 mirrors, snapshots etc. using dmeventd
+# Short-Description: Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or polldaemon
 ### END INIT INFO
 
 . /etc/init.d/functions
@@ -50,7 +50,7 @@ start()
 	VGSLIST=`$VGS --noheadings -o name 2> /dev/null`
 	for vg in $VGSLIST
 	do
-	    action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y $vg || ret=$?
+	    action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y --poll y $vg || ret=$?
 	done
 
 	return $ret




More information about the lvm-devel mailing list