public inbox for lvm2-cvs@sourceware.org
help / color / mirror / Atom feed
* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2011-12-22 16:37 zkabelac
  0 siblings, 0 replies; 8+ messages in thread
From: zkabelac @ 2011-12-22 16:37 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	zkabelac@sourceware.org	2011-12-22 16:37:03

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 
	daemons/dmeventd/plugins/raid: dmeventd_raid.c 
	daemons/dmeventd/plugins/snapshot: dmeventd_snapshot.c 

Log message:
	Use new dmeventd_lvm2_command function in dmeventd plugins.
	
	For snapshot, prepare whole command in front into private buffer.
	Add also some missing '\n' for syslog messages.
	For raid and mirror only convert creation of command line string.
	This should avoid any unbound growth of mempool for dm_split_names.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2215&r2=1.2216
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.37&r2=1.38
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/raid/dmeventd_raid.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c.diff?cvsroot=lvm2&r1=1.17&r2=1.18

--- LVM2/WHATS_NEW	2011/12/22 15:55:21	1.2215
+++ LVM2/WHATS_NEW	2011/12/22 16:37:01	1.2216
@@ -1,5 +1,6 @@
 Version 2.02.89 - 
 ==================================
+  Use dmeventd_lvm2_command in dmeventd plugins snapshot, raid, mirror.
   Add helper dmeventd_lvm2_command() into libdevmapper-event-lvm2 library.
   Updated documentation for dmeventd.
   Drop extra stat call before opening device.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2010/08/16 18:19:46	1.37
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2011/12/22 16:37:02	1.38
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -133,32 +133,15 @@
 	int r;
 #define CMD_SIZE 256	/* FIXME Use system restriction */
 	char cmd_str[CMD_SIZE];
-	char *vg = NULL, *lv = NULL, *layer = NULL;
 
-	if (strlen(device) > 200)  /* FIXME Use real restriction */
-		return -ENAMETOOLONG;	/* FIXME These return code distinctions are not used so remove them! */
-
-	if (!dm_split_lvm_name(dmeventd_lvm2_pool(), device, &vg, &lv, &layer)) {
-		syslog(LOG_ERR, "Unable to determine VG name from %s.",
-		       device);
-		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */
-	}
-
-	/* strip off the mirror component designations */
-	layer = strstr(lv, "_mlog");
-	if (layer)
-		*layer = '\0';
-
-	/* FIXME Is any sanity-checking required on %s? */
-	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair --use-policies %s/%s", vg, lv)) {
-		/* this error should be caught above, but doesn't hurt to check again */
-		syslog(LOG_ERR, "Unable to form LVM command: Device name too long.");
+	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
+				  "lvconvert --config devices{ignore_suspended_devices=1} "
+				  "--repair --use-policies", device))
 		return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
-	}
 
 	r = dmeventd_lvm2_run(cmd_str);
 
-	syslog(LOG_INFO, "Repair of mirrored LV %s/%s %s.", vg, lv,
+	syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,
 	       (r == ECMD_PROCESSED) ? "finished successfully" : "failed");
 
 	return (r == ECMD_PROCESSED) ? 0 : -1;
@@ -227,9 +210,12 @@
 		    int minor __attribute__((unused)),
 		    void **unused __attribute__((unused)))
 {
-	int r = dmeventd_lvm2_init();
+	if (!dmeventd_lvm2_init())
+		return 0;
+
 	syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
-	return r;
+
+	return 1;
 }
 
 int unregister_device(const char *device,
@@ -241,5 +227,6 @@
 	syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
 	       device);
 	dmeventd_lvm2_exit();
+
 	return 1;
 }
--- LVM2/daemons/dmeventd/plugins/raid/dmeventd_raid.c	2011/12/06 19:30:16	1.2
+++ LVM2/daemons/dmeventd/plugins/raid/dmeventd_raid.c	2011/12/22 16:37:02	1.3
@@ -33,28 +33,16 @@
 	int r;
 #define CMD_SIZE 256	/* FIXME Use system restriction */
 	char cmd_str[CMD_SIZE];
-	char *vg = NULL, *lv = NULL, *layer = NULL;
 
-	if (strlen(device) > 200)  /* FIXME Use real restriction */
+	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
+				  "lvconvert --config devices{ignore_suspended_devices=1} "
+				  "--repair --use-policies", device))
 		return -1;
 
-	if (!dm_split_lvm_name(dmeventd_lvm2_pool(), device, &vg, &lv, &layer)) {
-		syslog(LOG_ERR, "Unable to determine VG name from %s.",
-		       device);
-		return -1;
-	}
-
-	/* FIXME Is any sanity-checking required on %s? */
-	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair --use-policies %s/%s", vg, lv)) {
-		/* this error should be caught above, but doesn't hurt to check again */
-		syslog(LOG_ERR, "Unable to form LVM command: Device name too long.");
-		return -1;
-	}
-
 	r = dmeventd_lvm2_run(cmd_str);
 
 	if (r != ECMD_PROCESSED)
-		syslog(LOG_INFO, "Repair of RAID LV %s/%s failed.", vg, lv);
+		syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
 
 	return (r == ECMD_PROCESSED) ? 0 : -1;
 }
@@ -162,9 +150,12 @@
 		    int minor __attribute__((unused)),
 		    void **unused __attribute__((unused)))
 {
-	int r = dmeventd_lvm2_init();
+	if (!dmeventd_lvm2_init())
+		return 0;
+
 	syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
-	return r;
+
+	return 1;
 }
 
 int unregister_device(const char *device,
@@ -176,5 +167,6 @@
 	syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
 	       device);
 	dmeventd_lvm2_exit();
+
 	return 1;
 }
--- LVM2/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	2011/11/21 12:31:18	1.17
+++ LVM2/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	2011/12/22 16:37:03	1.18
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -43,6 +43,7 @@
 struct dso_state {
 	int percent_check;
 	int known_size;
+	char cmd_str[1024];
 };
 
 /* FIXME possibly reconcile this with target_percent when we gain
@@ -120,22 +121,9 @@
         return 1; /* all good */
 }
 
-static int _extend(const char *device)
+static int _extend(const char *cmd)
 {
-	char *vg = NULL, *lv = NULL, *layer = NULL;
-	char cmd_str[1024];
-
-	if (!dm_split_lvm_name(dmeventd_lvm2_pool(), device, &vg, &lv, &layer)) {
-		syslog(LOG_ERR, "Unable to determine VG name from %s.", device);
-		return 0;
-	}
-	if (dm_snprintf(cmd_str, sizeof(cmd_str),
-			"lvextend --use-policies %s/%s", vg, lv) < 0) {
-		syslog(LOG_ERR, "Unable to form LVM command: Device name too long.");
-		return 0;
-	}
-
-	return dmeventd_lvm2_run(cmd_str) == ECMD_PROCESSED;
+	return dmeventd_lvm2_run(cmd) == ECMD_PROCESSED;
 }
 
 static void _umount(const char *device, int major, int minor)
@@ -165,9 +153,9 @@
 		if (S_ISBLK(st.st_mode) &&
 		    major(st.st_rdev) == major &&
 		    minor(st.st_rdev) == minor) {
-			syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.", device, words[1]);
+			syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]);
                         if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
-                                syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.",
+                                syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n",
                                        device, words[1], strerror(errno));
 		}
 	}
@@ -235,8 +223,8 @@
 		if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
 			syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
 		/* Try to extend the snapshot, in accord with user-set policies */
-		if (!_extend(device))
-			syslog(LOG_ERR, "Failed to extend snapshot %s.", device);
+		if (!_extend(state->cmd_str))
+			syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device);
 	}
 
 out:
@@ -249,17 +237,33 @@
 		    int minor __attribute__((unused)),
 		    void **private)
 {
-	struct dso_state **state = (struct dso_state **) private;
-	int r = dmeventd_lvm2_init();
+	struct dso_state *state;
+
+	if (!dmeventd_lvm2_init())
+		goto out;
 
-	if (!(*state = dm_malloc(sizeof (struct dso_state))))
-		return 0;
+	if (!(state = dm_zalloc(sizeof(*state))))
+		goto bad;
 
-	(*state)->percent_check = CHECK_MINIMUM;
-	(*state)->known_size = 0;
+	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(),
+                                   state->cmd_str, sizeof(state->cmd_str),
+				   "lvextend --use-policies", device))
+		goto bad;
+
+	state->percent_check = CHECK_MINIMUM;
+	state->known_size = 0;
+	*private = state;
 
 	syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
-	return r;
+
+	return 1;
+bad:
+	dm_free(state);
+	dmeventd_lvm2_exit();
+out:
+	syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device);
+
+	return 0;
 }
 
 int unregister_device(const char *device,
@@ -269,10 +273,10 @@
 		      void **private)
 {
 	struct dso_state *state = *private;
-	syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
-	       device);
 
+	syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device);
 	dm_free(state);
 	dmeventd_lvm2_exit();
+
 	return 1;
 }


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2010-03-26 22:15 jbrassow
  0 siblings, 0 replies; 8+ messages in thread
From: jbrassow @ 2010-03-26 22:15 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	jbrassow@sourceware.org	2010-03-26 22:15:44

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 
	lib/activate   : activate.c 
	lib/metadata   : lv_alloc.h lv_manip.c mirror.c 
	man            : lvconvert.8.in lvcreate.8.in 
	test           : t-lvconvert-repair-policy.sh 
	                 t-lvconvert-repair.sh t-lvcreate-operation.sh 
	                 t-mirror-lvconvert.sh t-snapshots-of-mirrors.sh 
	tools          : commands.h lvconvert.c lvcreate.c 

Log message:
	Add ability to create mirrored logs for mirror LVs.
	
	This check-in enables the 'mirrored' log type.  It can be specified
	by using the '--mirrorlog' option as follows:
	#> lvcreate -m1 --mirrorlog mirrored -L 5G -n lv vg
	
	I've also included a couple updates to the testsuite.  These updates
	include tests for the new log type, and some fixes to some of the
	*lvconvert* tests.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1484&r2=1.1485
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.31&r2=1.32
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.c.diff?cvsroot=lvm2&r1=1.167&r2=1.168
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_alloc.h.diff?cvsroot=lvm2&r1=1.26&r2=1.27
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.216&r2=1.217
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/mirror.c.diff?cvsroot=lvm2&r1=1.108&r2=1.109
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvconvert.8.in.diff?cvsroot=lvm2&r1=1.14&r2=1.15
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvcreate.8.in.diff?cvsroot=lvm2&r1=1.16&r2=1.17
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvconvert-repair-policy.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvconvert-repair.sh.diff?cvsroot=lvm2&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvcreate-operation.sh.diff?cvsroot=lvm2&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-mirror-lvconvert.sh.diff?cvsroot=lvm2&r1=1.16&r2=1.17
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-snapshots-of-mirrors.sh.diff?cvsroot=lvm2&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.142&r2=1.143
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.122&r2=1.123
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvcreate.c.diff?cvsroot=lvm2&r1=1.216&r2=1.217

--- LVM2/WHATS_NEW	2010/03/26 15:45:36	1.1484
+++ LVM2/WHATS_NEW	2010/03/26 22:15:43	1.1485
@@ -1,5 +1,6 @@
 Version 2.02.63 -  
 ================================
+  Add ability to create mirrored logs for mirror LVs.
   Use a real socket for singlenode clvmd to fix clvmd's high cpu load.
   Fix clvmd cluster propagation of dmeventd monitoring mode.
   Allow ALLOC_ANYWHERE to split contiguous areas.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2010/01/22 12:48:58	1.31
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2010/03/26 22:15:43	1.32
@@ -148,6 +148,11 @@
 		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */
 	}
 
+	/* strip off the mirror component designations */
+	layer = strstr(lv, "_mlog");
+	if (layer)
+		*layer = '\0';
+
 	/* FIXME Is any sanity-checking required on %s? */
 	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair --use-policies %s/%s", vg, lv)) {
 		/* this error should be caught above, but doesn't hurt to check again */
--- LVM2/lib/activate/activate.c	2010/03/05 14:48:34	1.167
+++ LVM2/lib/activate/activate.c	2010/03/26 22:15:43	1.168
@@ -703,6 +703,7 @@
 	int r = 1;
 	struct dm_list *tmp, *snh, *snht;
 	struct lv_segment *seg;
+	struct lv_segment *log_seg;
 	int (*monitor_fn) (struct lv_segment *s, int e);
 	uint32_t s;
 
@@ -738,6 +739,16 @@
 		return r;
 	}
 
+	/*
+	 * If the volume is mirrored and its log is also mirrored, monitor
+	 * the log volume as well.
+	 */
+	if ((seg = first_seg(lv)) != NULL && seg->log_lv != NULL &&
+	    (log_seg = first_seg(seg->log_lv)) != NULL &&
+	    seg_is_mirrored(log_seg))
+		if (!monitor_dev_for_events(cmd, seg->log_lv, monitor))
+			r = 0;
+
 	dm_list_iterate(tmp, &lv->segments) {
 		seg = dm_list_item(tmp, struct lv_segment);
 
--- LVM2/lib/metadata/lv_alloc.h	2010/03/01 20:00:21	1.26
+++ LVM2/lib/metadata/lv_alloc.h	2010/03/26 22:15:43	1.27
@@ -68,7 +68,8 @@
 		      uint32_t num_extra_areas,
 		      uint64_t status, uint32_t region_size);
 
-int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv);
+int lv_add_log_segment(struct alloc_handle *ah, uint32_t first_area,
+		       struct logical_volume *log_lv, uint64_t status);
 int lv_add_virtual_segment(struct logical_volume *lv, uint64_t status,
                            uint32_t extents, const struct segment_type *segtype);
 
--- LVM2/lib/metadata/lv_manip.c	2010/03/25 21:19:27	1.216
+++ LVM2/lib/metadata/lv_manip.c	2010/03/26 22:15:43	1.217
@@ -1635,14 +1635,32 @@
 
 /*
  * Turn an empty LV into a mirror log.
+ *
+ * FIXME: Mirrored logs are built inefficiently.
+ * A mirrored log currently uses the same layout that a mirror
+ * LV uses.  The mirror layer sits on top of AREA_LVs which form the
+ * legs, rather on AREA_PVs.  This is done to allow re-use of the
+ * various mirror functions to also handle the mirrored LV that makes
+ * up the log.
+ *
+ * If we used AREA_PVs under the mirror layer of a log, we could
+ * assemble it all at once by calling 'lv_add_segment' with the
+ * appropriate segtype (mirror/stripe), like this:
+ * 	lv_add_segment(ah, ah->area_count, ah->log_area_count,
+ *		       log_lv, segtype, 0, MIRROR_LOG, 0);
+ *
+ * For now, we use the same mechanism to build a mirrored log as we
+ * do for building a mirrored LV: 1) create initial LV, 2) add a
+ * mirror layer, and 3) add the remaining copy LVs
  */
-int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
+int lv_add_log_segment(struct alloc_handle *ah, uint32_t first_area,
+		       struct logical_volume *log_lv, uint64_t status)
 {
-	const char *segtype_name = ah->log_area_count > 1 ? "mirror" : "striped";
 
-	return lv_add_segment(ah, ah->area_count, ah->log_area_count, log_lv,
-			      get_segtype_from_string(log_lv->vg->cmd, segtype_name),
-			      0, MIRROR_LOG, 0);
+	return lv_add_segment(ah, ah->area_count + first_area, 1, log_lv,
+			      get_segtype_from_string(log_lv->vg->cmd,
+						      "striped"),
+			      0, status, 0);
 }
 
 static int _lv_extend_mirror(struct alloc_handle *ah,
--- LVM2/lib/metadata/mirror.c	2010/03/01 20:00:21	1.108
+++ LVM2/lib/metadata/mirror.c	2010/03/26 22:15:43	1.109
@@ -709,8 +709,8 @@
  *
  * Arguments:
  *   num_removed:   the requested (maximum) number of mirrors to be removed
- *   removable_pvs: if not NULL, only mirrors using PVs in this list
- *                  will be removed
+ *   removable_pvs: if not NULL and list not empty, only mirrors using PVs
+ *                  in this list will be removed
  *   remove_log:    if non-zero, log_lv will be removed
  *                  (even if it's 0, log_lv will be removed if there is no
  *                   mirror remaining after the removal)
@@ -737,6 +737,7 @@
 {
 	uint32_t m;
 	uint32_t s;
+	int removable_pvs_specified;
 	struct logical_volume *sub_lv;
 	struct logical_volume *detached_log_lv = NULL;
 	struct logical_volume *temp_layer_lv = NULL;
@@ -746,6 +747,9 @@
 	struct lv_list *lvl;
 	struct dm_list tmp_orphan_lvs;
 
+	removable_pvs_specified = (removable_pvs &&
+				   !dm_list_empty(removable_pvs)) ? 1 : 0;
+
 	if (removed)
 		*removed = 0;
 
@@ -755,13 +759,13 @@
 			 remove_log ? " and no log volume" : "");
 
 	if (collapse &&
-	    (removable_pvs || (old_area_count - num_removed != 1))) {
+	    (removable_pvs_specified || (old_area_count - num_removed != 1))) {
 		log_error("Incompatible parameters to _remove_mirror_images");
 		return 0;
 	}
 
 	/* Move removable_pvs to end of array */
-	if (removable_pvs) {
+	if (removable_pvs_specified) {
 		for (s = 0; s < mirrored_seg->area_count &&
 			    old_area_count - new_area_count < num_removed; s++) {
 			sub_lv = seg_lv(mirrored_seg, s);
@@ -1171,7 +1175,8 @@
 static int _create_mimage_lvs(struct alloc_handle *ah,
 			      uint32_t num_mirrors,
 			      struct logical_volume *lv,
-			      struct logical_volume **img_lvs)
+			      struct logical_volume **img_lvs,
+			      int log)
 {
 	uint32_t m;
 	char *img_name;
@@ -1199,14 +1204,23 @@
 			return 0;
 		}
 
-		if (!lv_add_segment(ah, m, 1, img_lvs[m],
-				    get_segtype_from_string(lv->vg->cmd,
-							    "striped"),
-				    0, 0, 0)) {
-			log_error("Aborting. Failed to add mirror image segment "
-				  "to %s. Remove new LV and retry.",
-				  img_lvs[m]->name);
-			return 0;
+		if (log) {
+			if (!lv_add_log_segment(ah, m + 1, img_lvs[m], 0)) {
+				log_error("Aborting. Failed to add mirror image segment "
+					  "to %s. Remove new LV and retry.",
+					  img_lvs[m]->name);
+				return 0;
+			}
+		} else {
+			if (!lv_add_segment(ah, m, 1, img_lvs[m],
+					    get_segtype_from_string(lv->vg->cmd,
+								    "striped"),
+					    0, 0, 0)) {
+				log_error("Aborting. Failed to add mirror image segment "
+					  "to %s. Remove new LV and retry.",
+					  img_lvs[m]->name);
+				return 0;
+			}
 		}
 	}
 
@@ -1541,17 +1555,57 @@
 				       alloc, lv->vg)))
 		return_NULL;
 
-	if (!lv_add_log_segment(ah, log_lv))
+	if (!lv_add_log_segment(ah, 0, log_lv, MIRROR_LOG))
 		return_NULL;
 
 	return log_lv;
 }
 
+/*
+ * Returns: 1 on success, 0 on error
+ */
+static int _form_mirror(struct cmd_context *cmd, struct alloc_handle *ah,
+			struct logical_volume *lv,
+			uint32_t mirrors, uint32_t region_size, int log)
+{
+	struct logical_volume **img_lvs;
+
+	/*
+	 * insert a mirror layer
+	 */
+	if (dm_list_size(&lv->segments) != 1 ||
+	    seg_type(first_seg(lv), 0) != AREA_LV)
+		if (!insert_layer_for_lv(cmd, lv, 0, "_mimage_%d"))
+			return 0;
+
+	/*
+	 * create mirror image LVs
+	 */
+	if (!(img_lvs = alloca(sizeof(*img_lvs) * mirrors))) {
+		log_error("img_lvs allocation failed. "
+			  "Remove new LV and retry.");
+		return 0;
+	}
+
+	if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs, log))
+		return 0;
+
+	if (!lv_add_mirror_lvs(lv, img_lvs, mirrors,
+			       MIRROR_IMAGE | (lv->status & LOCKED),
+			       region_size)) {
+		log_error("Aborting. Failed to add mirror segment. "
+			  "Remove new LV and retry.");
+		return 0;
+	}
+
+	return 1;
+}
+
 static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd,
 						 struct alloc_handle *ah,
 						 struct logical_volume *lv,
 						 uint32_t log_count,
-						 uint32_t region_size __attribute((unused)),
+						 uint32_t region_size,
 						 alloc_policy_t alloc,
 						 int in_sync)
 {
@@ -1563,11 +1617,6 @@
 
 	init_mirror_in_sync(in_sync);
 
-	if (log_count != 1) {
-		log_error("log_count != 1 is not supported.");
-		return NULL;
-	}
-
 	/* Mirror log name is lv_name + suffix, determined as the following:
 	 *   1. suffix is:
 	 *        o "_mlog" for the original mirror LV.
@@ -1600,6 +1649,12 @@
 		return NULL;
 	}
 
+	if ((log_count > 1) &&
+	    !_form_mirror(cmd, ah, log_lv, log_count-1, region_size, 1)) {
+		log_error("Failed to form mirrored log.");
+		return NULL;
+	}
+
 	if (!_init_mirror_log(cmd, log_lv, in_sync, &lv->tags, 1)) {
 		log_error("Failed to initialise mirror log.");
 		return NULL;
@@ -1630,12 +1685,6 @@
 	struct lvinfo info;
 	int r = 0;
 
-	/* Unimplemented features */
-	if (log_count > 1) {
-		log_error("log_count > 1 is not supported");
-		return 0;
-	}
-
 	if (dm_list_size(&lv->segments) != 1) {
 		log_error("Multiple-segment mirror is not supported");
 		return 0;
@@ -1707,7 +1756,6 @@
 	struct alloc_handle *ah;
 	const struct segment_type *segtype;
 	struct dm_list *parallel_areas;
-	struct logical_volume **img_lvs;
 	struct logical_volume *log_lv = NULL;
 
 	if (stripes > 1) {
@@ -1747,34 +1795,9 @@
 	   So from here on, if failure occurs, the log must be explicitly
 	   removed and the updated vg metadata should be committed. */
 
-	/*
-	 * insert a mirror layer
-	 */
-	if (dm_list_size(&lv->segments) != 1 ||
-	    seg_type(first_seg(lv), 0) != AREA_LV)
-		if (!insert_layer_for_lv(cmd, lv, 0, "_mimage_%d"))
-			goto out_remove_log;
-
-	/*
-	 * create mirror image LVs
-	 */
-	if (!(img_lvs = alloca(sizeof(*img_lvs) * mirrors))) {
-		log_error("img_lvs allocation failed. "
-			  "Remove new LV and retry.");
-		goto out_remove_log;
-	}
-
-	if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs))
+	if (!_form_mirror(cmd, ah, lv, mirrors, region_size, 0))
 		goto out_remove_log;
 
-	if (!lv_add_mirror_lvs(lv, img_lvs, mirrors,
-			       MIRROR_IMAGE | (lv->status & LOCKED),
-			       region_size)) {
-		log_error("Aborting. Failed to add mirror segment. "
-			  "Remove new LV and retry.");
-		goto out_remove_images;
-	}
-
 	if (log_count && !attach_mirror_log(first_seg(lv), log_lv))
 		stack;
 
--- LVM2/man/lvconvert.8.in	2010/02/05 22:44:37	1.14
+++ LVM2/man/lvconvert.8.in	2010/03/26 22:15:43	1.15
@@ -3,7 +3,7 @@
 lvconvert \- convert a logical volume from linear to mirror or snapshot
 .SH SYNOPSIS
 .B lvconvert
-\-m|\-\-mirrors Mirrors [\-\-mirrorlog {disk|core}] [\-\-corelog] [\-R|\-\-regionsize MirrorLogRegionSize]
+\-m|\-\-mirrors Mirrors [\-\-mirrorlog {disk|core|mirrored}] [\-\-corelog] [\-R|\-\-regionsize MirrorLogRegionSize]
 [\-A|\-\-alloc AllocationPolicy]
 [\-b|\-\-background] [\-f|\-\-force] [\-i|\-\-interval Seconds]
 [\-h|\-?|\-\-help]
@@ -83,6 +83,7 @@
 Core may be useful for short-lived mirrors: It means the mirror is
 regenerated by copying the data from the first device again every
 time the device is activated - perhaps, for example, after every reboot.
+Using "mirrored" will create a persistent log that is itself mirrored.
 .TP
 .I \-\-corelog
 The optional argument "--corelog" is the same as specifying "--mirrorlog core".
--- LVM2/man/lvcreate.8.in	2010/03/23 22:30:20	1.16
+++ LVM2/man/lvcreate.8.in	2010/03/26 22:15:43	1.17
@@ -13,7 +13,7 @@
 {\-l|\-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}] |
  \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
 [\-M|\-\-persistent y|n] [\-\-minor minor]
-[\-m|\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core}] [\-\-corelog]
+[\-m|\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core|mirrored}] [\-\-corelog]
 [\-R|\-\-regionsize MirrorLogRegionSize]]
 [\-n|\-\-name LogicalVolumeName]
 [\-p|\-\-permission r|rw] [\-r|\-\-readahead ReadAheadSectors|auto|none]
@@ -113,9 +113,10 @@
 The optional argument --mirrorlog specifies the type of log to be used.
 The default is disk, which is persistent and requires
 a small amount of storage space, usually on a separate device from the
-data being mirrored. Using core means the mirror is regenerated
+data being mirrored.  Using core means the mirror is regenerated
 by copying the data from the first device again each time the
-device is activated, for example, after every reboot.
+device is activated, for example, after every reboot.  Using "mirrored"
+will create a persistent log that is itself mirrored.
 
 The optional argument --corelog is equivalent to --mirrorlog core.
 
--- LVM2/test/t-lvconvert-repair-policy.sh	2010/01/08 13:04:10	1.1
+++ LVM2/test/t-lvconvert-repair-policy.sh	2010/03/26 22:15:44	1.2
@@ -13,12 +13,15 @@
 
 prepare_vg 4
 
+# Clean-up and create a 2-way mirror, where the the
+# leg devices are always on $dev[12] and the log
+# is always on $dev3.  ($dev4 behaves as a spare)
 cleanup() {
 	vgreduce --removemissing $vg
 	for d in "$@"; do enable_dev $d; done
 	for d in "$@"; do vgextend $vg $d; done
 	lvremove -ff $vg/mirror
-	lvcreate -m 1 -L 1 -n mirror $vg
+	lvcreate -m 1 -l 2 -n mirror $vg $dev1 $dev2 $dev3:0
 }
 
 repair() {
@@ -28,34 +31,42 @@
 lvcreate -m 1 -L 1 -n mirror $vg
 lvchange -a n $vg/mirror
 
+# Fail a leg of a mirror.
+# Expected result: linear
 disable_dev $dev1
 lvchange --partial -a y $vg/mirror
 repair 'activation { mirror_image_fault_policy = "remove" }'
 lvs | grep -- -wi-a- # non-mirror
 cleanup $dev1
 
+# Fail a leg of a mirror.
+# Expected result: Mirror (leg replaced)
 disable_dev $dev1
 repair 'activation { mirror_image_fault_policy = "replace" }'
 lvs | grep -- mwi-a- # mirror
 lvs | grep mirror_mlog
 cleanup $dev1
 
+# Fail a leg of a mirror (use old name for policy specification)
+# Expected result: Mirror (leg replaced)
 disable_dev $dev1
 repair 'activation { mirror_device_fault_policy = "replace" }'
 lvs | grep -- mwi-a- # mirror
 lvs | grep mirror_mlog
 cleanup $dev1
 
+# Fail a leg of a mirror w/ no available spare
+# Expected result: linear
 disable_dev $dev2 $dev4
-# no room for repair, downconversion should happen
 repair 'activation { mirror_image_fault_policy = "replace" }'
 lvs | grep -- -wi-a-
 cleanup $dev2 $dev4
 
-disable_dev $dev2 $dev4
-# no room for new log, corelog conversion should happen
+# Fail the log device of a mirror w/ no available spare
+# Expected result: mirror w/ corelog
+disable_dev $dev3 $dev4
 repair 'activation { mirror_image_fault_policy = "replace" }'
 lvs
 lvs | grep -- mwi-a-
 lvs | not grep mirror_mlog
-cleanup $dev2 $dev4
+cleanup $dev3 $dev4
--- LVM2/test/t-lvconvert-repair.sh	2009/12/28 18:33:04	1.4
+++ LVM2/test/t-lvconvert-repair.sh	2010/03/26 22:15:44	1.5
@@ -69,5 +69,5 @@
 lvcreate -m 2 -l 1 -n mirror2 $vg $dev1 $dev2 $dev3 $dev4
 vgchange -a n $vg
 pvremove -ff -y $dev4
-echo 'y' | not lvconvert -y -i 1 --repair $vg/mirror2
+echo 'y' | lvconvert -y -i 1 --repair $vg/mirror2
 vgs
--- LVM2/test/t-lvcreate-operation.sh	2009/12/28 18:33:04	1.2
+++ LVM2/test/t-lvcreate-operation.sh	2010/03/26 22:15:44	1.3
@@ -25,9 +25,18 @@
 aux pvcreate --metadatacopies 0 $dev1
 aux vgcreate -c n $vg $devs
 
-#COMM create snapshots of LVs on --metadatacopies 0 PV (bz450651)
+# ---
+# Create snapshots of LVs on --metadatacopies 0 PV (bz450651)
 lvcreate -n$lv1 -l4 $vg $dev1
 lvcreate -n$lv2 -l4 -s $vg/$lv1
-#lvremove -f $vg/$lv2
 cleanup_lvs
 
+# ---
+# Create mirror on two devices with mirrored log using --alloc anywhere
+lvcreate -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere $dev1 $dev2
+cleanup_lvs
+
+# --
+# Create mirror on one dev with mirrored log using --alloc anywhere, should fail
+lvcreate -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere $dev1
+cleanup_lvs
--- LVM2/test/t-mirror-lvconvert.sh	2010/03/25 12:14:14	1.16
+++ LVM2/test/t-mirror-lvconvert.sh	2010/03/26 22:15:44	1.17
@@ -281,6 +281,38 @@
 check_and_cleanup_lvs_
 
 # ---
+# core log to mirrored log
+
+# change the log type from 'core' to 'mirrored'
+prepare_lvs_
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+check_mirror_count_ $vg/$lv1 2
+not_sh check_mirror_log_ $vg/$lv1
+lvconvert --mirrorlog mirrored -i1 $vg/$lv1 $dev3 $dev4
+check_no_tmplvs_ $vg/$lv1
+check_mirror_log_ $vg/$lv1
+mimages_are_redundant_ $vg $lv1
+
+# ---
+# mirrored log to core log
+
+# change the log type from 'mirrored' to 'core'
+lvconvert --mirrorlog core -i1 $vg/$lv1 $dev3 $dev4
+check_no_tmplvs_ $vg/$lv1
+not_sh check_mirror_log_ $vg/$lv1
+mimages_are_redundant_ $vg $lv1
+check_and_cleanup_lvs_
+
+# ---
+# Linear to mirror with mirrored log using --alloc anywhere
+prepare_lvs_
+lvcreate -l2 -n $lv1 $vg $dev1
+lvconvert -m +1 --mirrorlog mirrored $vg/$lv1 $dev1 $dev2 --alloc anywhere
+mimages_are_redundant_ $vg $lv1
+check_and_cleanup_lvs_
+
+
+# ---
 # check polldaemon restarts
 
 # convert inactive mirror and start polling
--- LVM2/test/t-snapshots-of-mirrors.sh	2010/01/12 14:19:46	1.3
+++ LVM2/test/t-snapshots-of-mirrors.sh	2010/03/26 22:15:44	1.4
@@ -21,11 +21,11 @@
 # Log conversion (disk -> core)
 lvconvert --mirrorlog core $vg/lv
 
-# Log conversion (core -> redundant)
-not lvconvert --mirrorlog redundant $vg/lv
+# Log conversion (core -> mirrored)
+lvconvert --mirrorlog mirrored $vg/lv
 
-# Log conversion (redundant -> core)
-# lvconvert --mirrorlog core $vg/lv
+# Log conversion (mirrored -> core)
+lvconvert --mirrorlog core $vg/lv
 
 # Log conversion (core -> disk)
 lvconvert --mirrorlog disk $vg/lv
--- LVM2/tools/commands.h	2010/03/23 22:30:20	1.142
+++ LVM2/tools/commands.h	2010/03/26 22:15:44	1.143
@@ -96,7 +96,7 @@
    "Change logical volume layout",
    0,
    "lvconvert "
-   "[-m|--mirrors Mirrors [{--mirrorlog {disk|core}|--corelog}]]\n"
+   "[-m|--mirrors Mirrors [{--mirrorlog {disk|core|mirrored}|--corelog}]]\n"
    "\t[--repair [--use-policies]]\n"
    "\t[-R|--regionsize MirrorLogRegionSize]\n"
    "\t[--alloc AllocationPolicy]\n"
@@ -156,7 +156,7 @@
    "\t{-l|--extents LogicalExtentsNumber[%{VG|PVS|FREE}] |\n"
    "\t -L|--size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
    "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
-   "\t[-m|--mirrors Mirrors [--nosync] [{--mirrorlog {disk|core}|--corelog}]]\n"
+   "\t[-m|--mirrors Mirrors [--nosync] [{--mirrorlog {disk|core|mirrored}|--corelog}]]\n"
    "\t[-n|--name LogicalVolumeName]\n"
    "\t[--noudevsync]\n"
    "\t[-p|--permission {r|rw}]\n"
--- LVM2/tools/lvconvert.c	2010/03/16 14:37:39	1.122
+++ LVM2/tools/lvconvert.c	2010/03/26 22:15:44	1.123
@@ -647,31 +647,72 @@
 	}
 }
 
-static int _using_corelog(struct logical_volume *lv)
+/*
+ * _get_log_count
+ * @lv: the mirror LV
+ *
+ * Get the number of on-disk copies of the log.
+ *  0  = 'core'
+ *  1  = 'disk'
+ *  2+ = 'mirrored'
+ */
+static int _get_log_count(struct logical_volume *lv)
 {
-	return !first_seg(_original_lv(lv))->log_lv;
+	struct logical_volume *log_lv;
+
+	log_lv = first_seg(_original_lv(lv))->log_lv;
+	if (!log_lv)
+		return 0;
+
+	return lv_mirror_count(log_lv);
 }
 
 static int _lv_update_log_type(struct cmd_context *cmd,
 			       struct lvconvert_params *lp,
 			       struct logical_volume *lv,
+			       struct dm_list *operable_pvs,
 			       int log_count)
 {
-	struct logical_volume *original_lv = _original_lv(lv);
-	if (_using_corelog(lv) && log_count) {
+	uint32_t region_size;
+	int old_log_count;
+	struct logical_volume *original_lv;
+	struct logical_volume *log_lv;
+
+	old_log_count = _get_log_count(lv);
+	if (old_log_count == log_count)
+		return 1;
+
+	original_lv = _original_lv(lv);
+	region_size = adjusted_mirror_region_size(lv->vg->extent_size,
+						  lv->le_count,
+						  lp->region_size);
+
+	/* Add a log where there is none */
+	if (!old_log_count) {
 		if (!add_mirror_log(cmd, original_lv, log_count,
-				    adjusted_mirror_region_size(
-					lv->vg->extent_size,
-					lv->le_count,
-					lp->region_size),
-				    lp->pvh, lp->alloc))
+				    region_size, operable_pvs, lp->alloc))
 			return_0;
-	} else if (!_using_corelog(lv) && !log_count) {
-		if (!remove_mirror_log(cmd, original_lv,
-				       lp->pv_count ? lp->pvh : NULL))
+		return 1;
+	}
+
+	/* Remove an existing log completely */
+	if (!log_count) {
+		if (!remove_mirror_log(cmd, original_lv, operable_pvs))
 			return_0;
+		return 1;
 	}
-	return 1;
+
+	log_lv = first_seg(original_lv)->log_lv;
+
+	/* Adding redundancy to the log */
+	if (old_log_count < log_count) {
+		log_error("Adding log redundancy not supported yet.");
+		log_error("Try converting the log to 'core' first.");
+		return_0;
+	}
+
+	/* Reducing redundancy of the log */
+	return remove_mirror_images(log_lv, log_count, operable_pvs, 1U);
 }
 
 /*
@@ -712,138 +753,134 @@
 	}
 }
 
-static int _lvconvert_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
-			      struct lvconvert_params *lp)
+/*
+ * _lvconvert_mirrors_parse_params
+ *
+ * This function performs the following:
+ *  1) Gets the old values of mimage and log counts
+ *  2) Parses the CLI args to find the new desired values
+ *  3) Adjusts 'lp->mirrors' to the appropriate absolute value.
+ *     (Remember, 'lp->mirrors' is specified in terms of the number of "copies"
+ *      vs. the number of mimages.  It can also be a relative value.)
+ *  4) Sets 'lp->need_polling' if collapsing
+ *  5) Validates other mirror params
+ *
+ * Returns: 1 on success, 0 on error
+ */
+static int _lvconvert_mirrors_parse_params(struct cmd_context *cmd,
+					   struct logical_volume *lv,
+					   struct lvconvert_params *lp,
+					   uint32_t *old_mimage_count,
+					   uint32_t *old_log_count,
+					   uint32_t *new_mimage_count,
+					   uint32_t *new_log_count)
 {
-	struct lv_segment *seg;
-	uint32_t existing_mirrors;
-	const char *mirrorlog;
-	unsigned log_count = 1;
-	int r = 0;
-	struct logical_volume *log_lv, *layer_lv;
-	int failed_mirrors = 0, failed_log = 0;
-	struct dm_list *old_pvh = NULL, *remove_pvs = NULL, *failed_pvs = NULL;
-
 	int repair = arg_count(cmd, repair_ARG);
-	int replace_log = 1, replace_mirrors = 1;
-	int failure_code = 0;
-
-	seg = first_seg(lv);
-	existing_mirrors = lv_mirror_count(lv);
+	const char *mirrorlog;
+	*old_mimage_count = lv_mirror_count(lv);
+	*old_log_count = _get_log_count(lv);
 
-	/* If called with no argument, try collapsing the resync layers */
+	/*
+	 * Collapsing a stack of mirrors:
+	 *
+	 * If called with no argument, try collapsing the resync layers
+	 */
 	if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG) &&
 	    !arg_count(cmd, corelog_ARG) && !arg_count(cmd, regionsize_ARG) &&
 	    !arg_count(cmd, splitmirrors_ARG) && !repair) {
+		*new_mimage_count = *old_mimage_count;
+		*new_log_count = *old_log_count;
+
 		if (find_temporary_mirror(lv) || (lv->status & CONVERTING))
 			lp->need_polling = 1;
 		return 1;
 	}
 
-	if (arg_count(cmd, mirrors_ARG) && repair) {
-		log_error("You may only use one of --mirrors and --repair.");
+	if ((arg_count(cmd, mirrors_ARG) && repair) ||
+	    (arg_count(cmd, mirrorlog_ARG) && repair) ||
+	    (arg_count(cmd, corelog_ARG) && repair)) {
+		log_error("--repair cannot be used with --mirrors, --mirrorlog,"
+			  " or --corelog");
+		return 0;
+	}
+
+	if (arg_count(cmd, mirrorlog_ARG) && arg_count(cmd, corelog_ARG)) {
+		log_error("--mirrorlog and --corelog are incompatible");
 		return 0;
 	}
 
 	/*
-	 * Adjust required number of mirrors
-	 *
-	 * We check mirrors_ARG again to see if it
-	 * was supplied.  If not, they want the mirror
-	 * count to remain the same.  They may be changing
-	 * the logging type.
+	 * Adjusting mimage count?
 	 */
 	if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, splitmirrors_ARG))
-		lp->mirrors = existing_mirrors;
+		lp->mirrors = *old_mimage_count;
 	else if (lp->mirrors_sign == SIGN_PLUS)
-		lp->mirrors = existing_mirrors + lp->mirrors;
+		lp->mirrors = *old_mimage_count + lp->mirrors;
 	else if (lp->mirrors_sign == SIGN_MINUS)
-		lp->mirrors = existing_mirrors - lp->mirrors;
+		lp->mirrors = *old_mimage_count - lp->mirrors;
 	else
 		lp->mirrors += 1;
 
+	*new_mimage_count = lp->mirrors;
+
+	/* Too many mimages? */
 	if (lp->mirrors > DEFAULT_MIRROR_MAX_IMAGES) {
 		log_error("Only up to %d images in mirror supported currently.",
 			  DEFAULT_MIRROR_MAX_IMAGES);
 		return 0;
 	}
 
-	/*
-	 * If we are converting from one type of mirror to another, and
-	 * the type of log wasn't specified, then let's keep the log type
-	 * the same.
-	 */
-	if ((existing_mirrors > 1) && (lp->mirrors > 1) &&
-	    (lp->mirrors != existing_mirrors) && !(lv->status & CONVERTING) &&
-	    !arg_count(cmd, mirrorlog_ARG) && !arg_count(cmd, corelog_ARG)) {
-		log_count = (first_seg(lv)->log_lv) ?
-			lv_mirror_count(first_seg(lv)->log_lv) : 0;
+	/* Did the user try to subtract more legs than available? */
+	if (lp->mirrors < 1) {
+		log_error("Logical volume %s only has %" PRIu32 " mirrors.",
+			  lv->name, *old_mimage_count);
+		return 0;
 	}
 
-	if (repair) {
-		cmd->handles_missing_pvs = 1;
-		cmd->partial_activation = 1;
-		lp->need_polling = 0;
-		if (!(lv->status & PARTIAL_LV)) {
-			log_error("The mirror is consistent. Nothing to repair.");
-			return 1;
-		}
-		if ((failed_mirrors = _failed_mirrors_count(lv)) < 0)
-			return_0;
-		lp->mirrors -= failed_mirrors;
-		log_error("Mirror status: %d of %d images failed.",
-			  failed_mirrors, existing_mirrors);
-		old_pvh = lp->pvh;
-		if (!(failed_pvs = _failed_pv_list(lv->vg)))
-			return_0;
-		lp->pvh = lp->failed_pvs = failed_pvs;
-		log_lv = first_seg(lv)->log_lv;
-		if (!log_lv || log_lv->status & PARTIAL_LV) {
-			failed_log = 1;
-			log_count = 0;
-		}
-	} else {
-		/*
-		 * Did the user try to subtract more legs than available?
-		 */
-		if (lp->mirrors < 1) {
-			log_error("Logical volume %s only has %" PRIu32 " mirrors.",
-				  lv->name, existing_mirrors);
-			return 0;
-		}
-
-		/*
-		 * Adjust log type
-		 */
-		if (arg_count(cmd, corelog_ARG))
-			log_count = 0;
+	/*
+	 * FIXME: It would be nice to say what we are adjusting to, but
+	 * I really don't know whether to specify the # of copies or mimages.
+	 */
+	if (*old_mimage_count != *new_mimage_count)
+		log_verbose("Adjusting mirror image count of %s", lv->name);
 
-		mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
-					  !log_count ? "core" : DEFAULT_MIRRORLOG);
+	/*
+	 * Adjust log type
+	 *
+	 * If we are converting from a mirror to another mirror or simply
+	 * changing the log type, we start by assuming they want the log
+	 * type the same and then parse the given args.  OTOH, If we are
+	 * converting from linear to mirror, then we start from the default
+	 * position that the user would like a 'disk' log.
+	 */
+	*new_log_count = (*old_mimage_count > 1) ? *old_log_count : 1;
+	if (!arg_count(cmd, corelog_ARG) && !arg_count(cmd, mirrorlog_ARG))
+		return 1;
 
-		if (strcmp("core", mirrorlog) && !log_count) {
-			log_error("--mirrorlog disk and --corelog "
-				  "are incompatible");
-			return 0;
-		}
+	if (arg_count(cmd, corelog_ARG))
+		*new_log_count = 0;
 
-		if (!strcmp("disk", mirrorlog))
-			log_count = 1;
-		else if (!strcmp("core", mirrorlog))
-			log_count = 0;
-		else {
-			log_error("Unknown mirrorlog type: %s", mirrorlog);
-			return 0;
-		}
+	mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
+				  !*new_log_count ? "core" : DEFAULT_MIRRORLOG);
 
-		log_verbose("Setting logging type to %s", mirrorlog);
+	if (!strcmp("mirrored", mirrorlog))
+		*new_log_count = 2;
+	else if (!strcmp("disk", mirrorlog))
+		*new_log_count = 1;
+	else if (!strcmp("core", mirrorlog))
+		*new_log_count = 0;
+	else {
+		log_error("Unknown mirrorlog type: %s", mirrorlog);
+		return 0;
 	}
 
+	log_verbose("Setting logging type to %s", mirrorlog);
+
 	/*
 	 * Region size must not change on existing mirrors
 	 */
 	if (arg_count(cmd, regionsize_ARG) && (lv->status & MIRRORED) &&
-	    (lp->region_size != seg->region_size)) {
+	    (lp->region_size != first_seg(lv)->region_size)) {
 		log_error("Mirror log region size cannot be changed on "
 			  "an existing mirror.");
 		return 0;
@@ -859,48 +896,54 @@
 		return 0;
 	}
 
-	if (repair)
-		_lvconvert_mirrors_repair_ask(cmd, failed_log, failed_mirrors,
-					      &replace_log, &replace_mirrors);
+	return 1;
+}
 
- restart:
-	/*
-	 * Converting from mirror to linear
-	 */
-	if ((lp->mirrors == 1)) {
-		if (!(lv->status & MIRRORED)) {
-			log_error("Logical volume %s is already not mirrored.",
-				  lv->name);
-			return 1;
-		}
+/*
+ * _lvconvert_mirrors_aux
+ *
+ * Add/remove mirror images and adjust log type.  'operable_pvs'
+ * are the set of PVs open to removal or allocation - depending
+ * on the operation being performed.
+ *
+ * If 'allocation_failures_ok' is set, and there is a failure to
+ * convert due to space, success will be returned.
+ */
+static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
+				  struct logical_volume *lv,
+				  struct lvconvert_params *lp,
+				  struct dm_list *operable_pvs,
+				  uint32_t new_mimage_count,
+				  uint32_t new_log_count,
+				  int allocation_failures_ok)
+{
+	uint32_t region_size;
+	struct dm_list *tmp;
+	struct lv_segment *seg;
+	struct logical_volume *layer_lv;
+	uint32_t old_mimage_count = lv_mirror_count(lv);
+	uint32_t old_log_count = _get_log_count(lv);
+	int failure_code = (allocation_failures_ok) ? 1 : 0;
+
+	if ((lp->mirrors == 1) && !(lv->status & MIRRORED)) {
+		log_error("Logical volume %s is already not mirrored.",
+			  lv->name);
+		return 1;
 	}
 
-	/*
-	 * Downconversion.
-	 */
-	if (lp->mirrors < existing_mirrors) {
-		/* Reduce number of mirrors */
-		if (repair || lp->pv_count)
-			remove_pvs = lp->pvh;
+	region_size = adjusted_mirror_region_size(lv->vg->extent_size,
+						  lv->le_count,
+						  lp->region_size);
 
-		if (lp->keep_mimages) {
-			if (!lv_split_mirror_images(lv, lp->lv_split_name,
-						    existing_mirrors - lp->mirrors,
-						    remove_pvs))
-				return 0;
-		} else if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
-					      (!log_count || lp->mirrors == 1) ? 1U : 0U,
-					      remove_pvs, 0))
-			return_0;
+	if (!operable_pvs)
+		operable_pvs = lp->pvh;
 
-		if (lp->mirrors > 1 &&
-		    !_lv_update_log_type(cmd, lp, lv, log_count))
-			return_0;
-	} else if (!(lv->status & MIRRORED)) {
-		/*
-		 * Converting from linear to mirror
-		 */
+	seg = first_seg(lv);
 
+	/*
+	 * Up-convert from linear to mirror
+	 */
+	if (!(lv->status & MIRRORED)) {
 		/* FIXME Share code with lvcreate */
 
 		/* FIXME Why is this restriction here?  Fix it! */
@@ -916,19 +959,22 @@
 		 * currently taken by the mirror? Would make more sense from
 		 * user perspective.
 		 */
-		if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, 1,
-				    adjusted_mirror_region_size(
-						lv->vg->extent_size,
-						lv->le_count,
-						lp->region_size),
-				    log_count, lp->pvh, lp->alloc,
-				    MIRROR_BY_LV)) {
+		if (!lv_add_mirrors(cmd, lv, new_mimage_count - 1, 1,
+				    region_size, new_log_count, operable_pvs,
+				    lp->alloc, MIRROR_BY_LV)) {
 			stack;
 			return failure_code;
 		}
 		if (lp->wait_completion)
 			lp->need_polling = 1;
-	} else if (lp->mirrors > existing_mirrors || failed_mirrors) {
+
+		goto out;
+	}
+
+	/*
+	 * Up-convert m-way mirror to n-way mirror
+	 */
+	if (new_mimage_count > old_mimage_count) {
 		if (lv->status & MIRROR_NOTSYNCED) {
 			log_error("Can't add mirror to out-of-sync mirrored "
 				  "LV: use lvchange --resync first.");
@@ -953,23 +999,23 @@
 		 * insertion to make the end result consistent with
 		 * linear-to-mirror conversion.
 		 */
-		if (!_lv_update_log_type(cmd, lp, lv, log_count)) {
+		if (!_lv_update_log_type(cmd, lp, lv,
+					 operable_pvs, new_log_count)) {
 			stack;
 			return failure_code;
 		}
+
 		/* Insert a temporary layer for syncing,
 		 * only if the original lv is using disk log. */
 		if (seg->log_lv && !_insert_lvconvert_layer(cmd, lv)) {
 			log_error("Failed to insert resync layer");
 			return 0;
 		}
+
 		/* FIXME: can't have multiple mlogs. force corelog. */
-		if (!lv_add_mirrors(cmd, lv, lp->mirrors - existing_mirrors, 1,
-				    adjusted_mirror_region_size(
-						lv->vg->extent_size,
-						lv->le_count,
-						lp->region_size),
-				    0U, lp->pvh, lp->alloc,
+		if (!lv_add_mirrors(cmd, lv,
+				    new_mimage_count - old_mimage_count, 1,
+				    region_size, 0U, operable_pvs, lp->alloc,
 				    MIRROR_BY_LV)) {
 			layer_lv = seg_lv(first_seg(lv), 0);
 			if (!remove_layer_from_lv(lv, layer_lv) ||
@@ -989,24 +1035,45 @@
 		if (seg->log_lv)
 			lv->status |= CONVERTING;
 		lp->need_polling = 1;
+
+		goto out_skip_log_convert;
 	}
 
-	if (lp->mirrors == existing_mirrors) {
-		if (_using_corelog(lv) != !log_count) {
-			if (!_lv_update_log_type(cmd, lp, lv, log_count)) {
-				stack;
-				return failure_code;
-			}
-		} else {
-			log_error("Logical volume %s already has %"
-				  PRIu32 " mirror(s).", lv->name,
-				  lp->mirrors - 1);
-			if (lv->status & CONVERTING)
-				lp->need_polling = 1;
-			return 1;
+	/*
+	 * Down-convert (reduce # of mimages).
+	 */
+	if (new_mimage_count < old_mimage_count) {
+		uint32_t nmc = old_mimage_count - new_mimage_count;
+		uint32_t nlc = (!new_log_count || lp->mirrors == 1) ? 1U : 0U;
+
+		/* FIXME: We did nlc used to be calculated that way? */
+
+		/* Reduce number of mirrors */
+		if (lp->keep_mimages) {
+			if (!lv_split_mirror_images(lv, lp->lv_split_name,
+						    nmc, operable_pvs))
+				return 0;
+		} else if (!lv_remove_mirrors(cmd, lv, nmc, nlc,
+					      operable_pvs, 0))
+			return_0;
+
+		goto out; /* Just in case someone puts code between */
+	}
+
+out:
+	/*
+	 * Converting the log type
+	 */
+	if (old_log_count != new_log_count) {
+		if (!_lv_update_log_type(cmd, lp, lv,
+					 operable_pvs, new_log_count)) {
+			stack;
+			return failure_code;
 		}
 	}
 
+out_skip_log_convert:
+
 	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
 
 	if (!vg_write(lv->vg))
@@ -1031,35 +1098,170 @@
 		goto out;
 	}
 
-	if (failed_log || failed_mirrors) {
-		lp->pvh = old_pvh;
-		if (failed_log && replace_log) {
-			failed_log = 0;
-			log_count = 1;
-		}
-		if (replace_mirrors)
-			lp->mirrors += failed_mirrors;
-		failed_mirrors = 0;
-		existing_mirrors = lv_mirror_count(lv);
+	return 1;
+}
+
+/*
+ * _lvconvert_mirrors_repair
+ *
+ * This function operates in two phases.  First, all of the bad
+ * devices are removed from the mirror.  Then, if desired by the
+ * user, the devices are replaced.
+ *
+ * 'old_mimage_count' and 'old_log_count' are there so we know
+ * what to convert to after the removal of devices.
+ */
+static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
+				     struct logical_volume *lv,
+				     struct lvconvert_params *lp,
+				     uint32_t old_mimage_count,
+				     uint32_t old_log_count)
+{
+	int failed_log = 0;
+	int failed_mirrors = 0;
+	int replace_log = 0;
+	int replace_mirrors = 0;
+	uint32_t new_log_count;
+	struct dm_list *failed_pvs = NULL;
+	struct logical_volume *log_lv;
+
+	cmd->handles_missing_pvs = 1;
+	cmd->partial_activation = 1;
+	lp->need_polling = 0;
+
+	if (!(lv->status & PARTIAL_LV)) {
+		log_error("%s is consistent. Nothing to repair.", lv->name);
+		return 1;
+	}
+
+	/*
+	 * Count the failed mimages - negative if 'lv' is not a mirror
+	 */
+	if ((failed_mirrors = _failed_mirrors_count(lv)) < 0)
+		return_0;
+
+	lp->mirrors = old_mimage_count - failed_mirrors;
+
+	if (lp->mirrors != old_mimage_count)
+		log_error("Mirror status: %d of %d images failed.",
+			  failed_mirrors, old_mimage_count);
+
+	/*
+	 * Count the failed log devices
+	 */
+	new_log_count = old_log_count;
+	log_lv = first_seg(lv)->log_lv;
+	if (log_lv) {
+		new_log_count = lv_mirror_count(log_lv);
+		if (log_lv->status & PARTIAL_LV) {
+			failed_log = 1;
+			if (log_lv->status & MIRRORED)
+				new_log_count -= _failed_mirrors_count(log_lv);
+			else
+				new_log_count = 0;
+		}
+	}
+	if (old_log_count != new_log_count)
+		log_error("Mirror log status: %d of %d images failed%s",
+			  old_log_count - new_log_count, old_log_count,
+			  (!new_log_count) ? " - switching to core" : "");
+
+	/*
+	 * Find out our policies
+	 */
+	_lvconvert_mirrors_repair_ask(cmd, failed_log, failed_mirrors,
+				      &replace_log, &replace_mirrors);
+
+	/*
+	 * First phase - remove faulty devices
+	 */
+	if (!(failed_pvs = _failed_pv_list(lv->vg)))
+		return_0;
+
+	/*
+	 * We must adjust the log first, or the entire mirror
+	 * will get stuck during a suspend.
+	 */
+	if (!_lv_update_log_type(cmd, lp, lv, failed_pvs, new_log_count))
+		return 0;
+
+	if (!_lvconvert_mirrors_aux(cmd, lv, lp, failed_pvs,
+				    lp->mirrors, new_log_count, 0))
+		return 0;
+
+	/*
+	 * Second phase - replace faulty devices
+	 *
+	 * FIXME: It would be nice to do this all in one step, but
+	 *        for simplicity, we replace mimages first and then
+	 *        work on the log.
+	 */
+	if (replace_mirrors && (old_mimage_count != lp->mirrors)) {
+		lp->mirrors = old_mimage_count;
+		if (!_lvconvert_mirrors_aux(cmd, lv, lp, NULL,
+					    old_mimage_count, new_log_count, 1))
+			return 0;
+	}
+
+	log_lv = first_seg(lv)->log_lv;
+	if (replace_log && (old_log_count != new_log_count)) {
 		/*
-		 * Ignore failure in upconversion if this is a policy-driven
-		 * action. If we got this far, only unexpected failures are
-		 * reported.
+		 * If we are up-converting the log from linear to
+		 * mirrored, then we must use '_lvconvert_mirrors_aux'
 		 */
-		if (arg_count(cmd, use_policies_ARG))
-			failure_code = 1;
-		/* Now replace missing devices. */
-		if (replace_log || replace_mirrors)
-			goto restart;
+		if ((new_log_count == 1) && (old_log_count > 1)) {
+			if (!_lvconvert_mirrors_aux(cmd, log_lv, lp, NULL,
+						    old_log_count, 0, 1))
+				return 0;
+		} else if (!_lv_update_log_type(cmd, lp, lv,
+						lp->pvh, new_log_count))
+			return 0;
 	}
 
+	return 1;
+}
+
+/*
+ * _lvconvert_mirrors
+ *
+ * Determine what is being done.  Are we doing a conversion, repair, or
+ * collapsing a stack?  Once determined, call helper functions.
+ */
+static int _lvconvert_mirrors(struct cmd_context *cmd,
+			      struct logical_volume *lv,
+			      struct lvconvert_params *lp)
+{
+	int repair = arg_count(cmd, repair_ARG);
+	uint32_t old_mimage_count;
+	uint32_t old_log_count;
+	uint32_t new_mimage_count;
+	uint32_t new_log_count;
+
+	/* Adjust mimage and/or log count */
+	if (!_lvconvert_mirrors_parse_params(cmd, lv, lp,
+					     &old_mimage_count, &old_log_count,
+					     &new_mimage_count, &new_log_count))
+		return 0;
+
+	/* Nothing to do?  (Probably finishing collapse.) */
+	if ((old_mimage_count == new_mimage_count) &&
+	    (old_log_count == new_log_count) && !repair)
+		return 1;
+
+	if (repair)
+		return _lvconvert_mirrors_repair(cmd, lv, lp,
+						 old_mimage_count,
+						 old_log_count);
+
+	if (!_lvconvert_mirrors_aux(cmd, lv, lp, NULL,
+				    new_mimage_count, new_log_count, 0))
+		return 0;
+
 	if (!lp->need_polling)
 		log_print("Logical volume %s converted.", lv->name);
 
-	r = 1;
-out:
 	backup(lv->vg);
-	return r;
+	return 1;
 }
 
 static int lvconvert_snapshot(struct cmd_context *cmd,
--- LVM2/tools/lvcreate.c	2010/03/23 22:30:20	1.216
+++ LVM2/tools/lvcreate.c	2010/03/26 22:15:44	1.217
@@ -337,12 +337,14 @@
 	mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
 				  corelog ? "core" : DEFAULT_MIRRORLOG);
 
-	if (!strcmp("disk", mirrorlog)) {
-		if (corelog) {
-			log_error("--mirrorlog disk and --corelog "
-				  "are incompatible");
-			return 0;
-		}
+	if (strcmp("core", mirrorlog) && corelog) {
+		log_error("Please use only one of --mirrorlog or --corelog");
+		return 0;
+	}
+
+	if (!strcmp("mirrored", mirrorlog)) {
+		lp->log_count = 2;
+	} else if (!strcmp("disk", mirrorlog)) {
 		lp->log_count = 1;
 	} else if (!strcmp("core", mirrorlog))
 		lp->log_count = 0;


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2010-01-06 13:26 mbroz
  0 siblings, 0 replies; 8+ messages in thread
From: mbroz @ 2010-01-06 13:26 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mbroz@sourceware.org	2010-01-06 13:26:22

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 
	tools          : lvconvert.c 

Log message:
	Remove empty "repaired" devices if empty in lvconvert.
	
	The logic was that lvconvert repair volumes, marking
	PV as MISSING and following vgreduce --removemissing
	removes these missing devices.
	
	Previously dmeventd mirror DSO removed all LV and PV
	from VG by simply relying on
	vgreduce --removemissing --force.
	
	Now, there are two subsequent calls:
	lvconvert --repair --use-policies
	vgreduce --removemissing
	
	So the VG is locked twice, opening space for all races
	between other running lvm processes. If the PV reappears
	with old metadata on it (so the winner performs autorepair,
	if locking VG for update) the situation is even worse.
	
	Patch simply adds removemissing PV functionality into
	lvconcert BUT ONLY if running with --repair and --use-policies
	and removing only these empty missing PVs which are
	involved in repair.
	(This combination is expected to run only from dmeventd.)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1365&r2=1.1366
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.28&r2=1.29
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.99&r2=1.100

--- LVM2/WHATS_NEW	2010/01/06 13:25:36	1.1365
+++ LVM2/WHATS_NEW	2010/01/06 13:26:21	1.1366
@@ -1,5 +1,6 @@
 Version 2.02.57 -
 ====================================
+  Remove empty PV devices if lvconvert --repair is using defined policies.
   Use fixed buffer to prevent stack overflow in persistent filter dump.
   Use snapshot metadata usage to determine if a snapshot is empty.
   Insert missing stack macros to all activate_lv and deactivate_lv callers.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/11/25 15:59:08	1.28
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2010/01/06 13:26:21	1.29
@@ -193,11 +193,7 @@
 
 	r = lvm2_run(_lvm_handle, cmd_str);
 
-	if (r == ECMD_PROCESSED) {
-		snprintf(cmd_str, CMD_SIZE, "vgreduce --removemissing %s", vg);
-		if (lvm2_run(_lvm_handle, cmd_str) != 1)
-			syslog(LOG_ERR, "Unable to remove failed PVs from VG %s", vg);
-	}
+	syslog(LOG_INFO, "Repair of mirrored LV %s/%s %s.", vg, lv, (r == ECMD_PROCESSED) ? "finished successfully" : "failed");
 
 	dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */
 	return (r == ECMD_PROCESSED) ? 0 : -1;
--- LVM2/tools/lvconvert.c	2010/01/05 21:07:31	1.99
+++ LVM2/tools/lvconvert.c	2010/01/06 13:26:21	1.100
@@ -428,6 +428,16 @@
 		if (!(pvl->pv->status & MISSING_PV))
 			continue;
 
+		/* 
+		 * Finally, --repair will remove empty PVs.
+		 * But we only want remove these which are output of repair,
+		 * Do not count these which are already empty here.
+		 * FIXME: code should traverse PV in LV not in whole VG.
+		 * FIXME: layer violation? should it depend on vgreduce --removemising?
+		 */
+		if (pvl->pv->pe_alloc_count == 0)
+			continue;
+
 		if (!(new_pvl = dm_pool_alloc(vg->vgmem, sizeof(*new_pvl)))) {
 			log_error("Allocation of failed_pvs list entry failed.");
 			return_NULL;
@@ -522,6 +532,44 @@
 	return 1;
 }
 
+/*
+ * Reomove missing and empty PVs from VG, if are also in provided list
+ */
+static void _remove_missing_empty_pv(struct volume_group *vg, struct dm_list *remove_pvs)
+{
+	struct pv_list *pvl, *pvl_vg, *pvlt;
+	int removed = 0;
+
+	if (!remove_pvs)
+		return;
+
+	dm_list_iterate_items(pvl, remove_pvs) {
+		dm_list_iterate_items_safe(pvl_vg, pvlt, &vg->pvs) {
+			if (!id_equal(&pvl->pv->id, &pvl_vg->pv->id) ||
+			    !(pvl_vg->pv->status & MISSING_PV) ||
+			    pvl_vg->pv->pe_alloc_count != 0)
+				continue;
+
+			/* FIXME: duplication of vgreduce code, move this to library */
+			vg->free_count -= pvl_vg->pv->pe_count;
+			vg->extent_count -= pvl_vg->pv->pe_count;
+			vg->pv_count--;
+			dm_list_del(&pvl_vg->list);
+
+			removed++;
+		}
+	}
+
+	if (removed) {
+		if (!vg_write(vg) || !vg_commit(vg)) {
+			stack;
+			return;
+		}
+
+		log_warn("%d missing and now unallocated Physical Volumes removed from VG.", removed);
+	}
+}
+
 static int _lvconvert_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
 			      struct lvconvert_params *lp)
 {
@@ -532,7 +580,7 @@
 	int r = 0;
 	struct logical_volume *log_lv, *layer_lv;
 	int failed_mirrors = 0, failed_log = 0;
-	struct dm_list *old_pvh = NULL, *remove_pvs = NULL;
+	struct dm_list *old_pvh = NULL, *remove_pvs = NULL, *failed_pvs = NULL;
 
 	int repair = arg_count(cmd, repair_ARG);
 	int replace_log = 1, replace_mirrors = 1;
@@ -593,6 +641,7 @@
 		old_pvh = lp->pvh;
 		if (!(lp->pvh = _failed_pv_list(lv->vg)))
 			return_0;
+		failed_pvs = lp->pvh;
 		log_lv=first_seg(lv)->log_lv;
 		if (!log_lv || log_lv->status & PARTIAL_LV)
 			failed_log = corelog = 1;
@@ -821,6 +870,10 @@
 			goto restart;
 	}
 
+	/* If repairing and using policies, remove missing PVs from VG */
+	if (repair && arg_count(cmd, use_policies_ARG))
+		_remove_missing_empty_pv(lv->vg, failed_pvs);
+
 	if (!lp->need_polling)
 		log_print("Logical volume %s converted.", lv->name);
 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2009-11-25 15:59 agk
  0 siblings, 0 replies; 8+ messages in thread
From: agk @ 2009-11-25 15:59 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	agk@sourceware.org	2009-11-25 15:59:08

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 

Log message:
	Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1331&r2=1.1332
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.27&r2=1.28

--- LVM2/WHATS_NEW	2009/11/24 22:55:55	1.1331
+++ LVM2/WHATS_NEW	2009/11/25 15:59:07	1.1332
@@ -1,6 +1,7 @@
 Version 2.02.57 -
 ====================================
- Switch status from 32-bit to 64-bit.
+  Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
+  Extend internal PV/VG/LV/segment status variables from 32-bit to 64-bit.
 
 Version 2.02.56 - 24th November 2009
 ====================================
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/10/22 10:40:41	1.27
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/11/25 15:59:08	1.28
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -27,6 +27,8 @@
 
 #include <syslog.h> /* FIXME Replace syslog with multilog */
 /* FIXME Missing openlog? */
+/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
+/* FIXME Reformat to 80 char lines. */
 
 #define ME_IGNORE    0
 #define ME_INSYNC    1
@@ -51,6 +53,36 @@
  */
 static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+static int _process_status_code(const char status_code, const char *dev_name,
+				const char *dev_type, int r)
+{
+	/*
+	 *    A => Alive - No failures
+	 *    D => Dead - A write failure occurred leaving mirror out-of-sync
+	 *    F => Flush failed.
+	 *    S => Sync - A sychronization failure occurred, mirror out-of-sync
+	 *    R => Read - A read failure occurred, mirror data unaffected
+	 *    U => Unclassified failure (bug)
+	 */ 
+	if (status_code == 'F') {
+		syslog(LOG_ERR, "%s device %s flush failed.\n",
+		       dev_type, dev_name);
+		r = ME_FAILURE;
+	} else if (status_code == 'S')
+		syslog(LOG_ERR, "%s device %s sync failed.\n",
+		       dev_type, dev_name);
+	else if (status_code == 'R')
+		syslog(LOG_ERR, "%s device %s read failed.\n",
+		       dev_type, dev_name);
+	else if (status_code != 'A') {
+		syslog(LOG_ERR, "%s device %s has failed (%c).\n",
+		       dev_type, dev_name, status_code);
+		r = ME_FAILURE;
+	}
+
+	return r;
+}
+
 static int _get_mirror_event(char *params)
 {
 	int i, r = ME_INSYNC;
@@ -90,17 +122,14 @@
 
 	/* Check for bad mirror devices */
 	for (i = 0; i < num_devs; i++)
-		if (dev_status_str[i] == 'D') {
-			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
-			r = ME_FAILURE;
-		}
+		r = _process_status_code(dev_status_str[i], args[i],
+			i ? "Secondary mirror" : "Primary mirror", r);
 
 	/* Check for bad disk log device */
-	if (log_argc > 1 && log_status_str[0] == 'D') {
-		syslog(LOG_ERR, "Log device, %s, has failed.\n",
-		       args[2 + num_devs + log_argc]);
-		r = ME_FAILURE;
-	}
+	if (log_argc > 1)
+		r = _process_status_code(log_status_str[0],
+					 args[2 + num_devs + log_argc],
+					 "Log", r);
 
 	if (r == ME_FAILURE)
 		goto out;


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2009-09-17 10:37 agk
  0 siblings, 0 replies; 8+ messages in thread
From: agk @ 2009-09-17 10:37 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	agk@sourceware.org	2009-09-17 10:37:24

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 
	daemons/dmeventd/plugins/snapshot: dmeventd_snapshot.c 

Log message:
	Fix dmeventd _temporary_log_fn parameters. (2.02.50)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1269&r2=1.1270
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.25&r2=1.26
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c.diff?cvsroot=lvm2&r1=1.3&r2=1.4

--- LVM2/WHATS_NEW	2009/09/16 23:48:41	1.1269
+++ LVM2/WHATS_NEW	2009/09/17 10:37:23	1.1270
@@ -1,5 +1,6 @@
 Version 2.02.53 - 
 =====================================
+  Fix dmeventd _temporary_log_fn parameters. (2.02.50)
   Enable dmeventd monitoring section of config file by default.
   Update lvm2 monitoring script to lvm2_monitoring_init_red_hat.in.
   Fix lvm2app test to run under test/api subdirectory only when configured.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/06/30 18:39:31	1.25
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/09/17 10:37:24	1.26
@@ -126,8 +126,10 @@
 	return ME_IGNORE;
 }
 
-static void _temporary_log_fn(int level, const char *file __attribute((unused)),
+static void _temporary_log_fn(int level,
+			      const char *file __attribute((unused)),
 			      int line __attribute((unused)),
+			      int dm_errno __attribute((unused)),
 			      const char *format)
 {
 	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
--- LVM2/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	2008/10/13 12:06:30	1.3
+++ LVM2/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	2009/09/17 10:37:24	1.4
@@ -57,6 +57,7 @@
 static void _temporary_log_fn(int level,
 			      const char *file __attribute((unused)),
 			      int line __attribute((unused)),
+			      int dm_errno __attribute((unused)),
 			      const char *format)
 {
 	if (!strncmp(format, "WARNING: ", 9) && (level < 5))


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2009-06-04 12:01 mbroz
  0 siblings, 0 replies; 8+ messages in thread
From: mbroz @ 2009-06-04 12:01 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mbroz@sourceware.org	2009-06-04 12:01:16

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 
	doc            : example.conf 
	lib/config     : defaults.h 
	man            : lvconvert.8.in 
	test           : t-lvconvert-repair.sh 
	tools          : args.h commands.h lvconvert.c 

Log message:
	Use lvconvert --repair instead of vgreduce in mirror dmeventd DSO (mornfall)
	Introduce lvconvert --use_policies (mornfall)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1140&r2=1.1141
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.22&r2=1.23
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/doc/example.conf.diff?cvsroot=lvm2&r1=1.39&r2=1.40
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/defaults.h.diff?cvsroot=lvm2&r1=1.44&r2=1.45
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvconvert.8.in.diff?cvsroot=lvm2&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvconvert-repair.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/args.h.diff?cvsroot=lvm2&r1=1.64&r2=1.65
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.126&r2=1.127
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.77&r2=1.78

--- LVM2/WHATS_NEW	2009/06/03 13:42:02	1.1140
+++ LVM2/WHATS_NEW	2009/06/04 12:01:15	1.1141
@@ -1,5 +1,7 @@
 Version 2.02.48 - 
 ===============================
+  Use lvconvert --repair instead of vgreduce in mirror dmeventd DSO.
+  Introduce lvconvert --use_policies (repair policy according to lvm.conf).
   Fix clvmd-corosync to match new corosync API.
   Fix makefile to build also shared libraries when running plain make.
   Fix rename of active snapshot with virtual origin.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/05/20 22:24:49	1.22
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/06/04 12:01:15	1.23
@@ -152,7 +152,7 @@
 	}
 
 	/* FIXME Is any sanity-checking required on %s? */
-	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing --force %s", vg)) {
+	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair --use-policies %s/%s", vg, lv)) {
 		/* this error should be caught above, but doesn't hurt to check again */
 		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 		dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */
--- LVM2/doc/example.conf	2009/02/22 19:00:26	1.39
+++ LVM2/doc/example.conf	2009/06/04 12:01:15	1.40
@@ -317,8 +317,10 @@
     # A disk log ensures that a mirror does not need to be re-synced
     # (all copies made the same) every time a machine reboots or crashes.
     #
-    # In the event of a failure, the specified policy will be used to
-    # determine what happens:
+    # In the event of a failure, the specified policy will be used to determine
+    # what happens. This applies to automatic repairs (when the mirror is being
+    # monitored by dmeventd) and to manual lvconvert --repair when
+    # --use-policies is given.
     #
     # "remove" - Simply remove the faulty device and run without it.  If
     #            the log device fails, the mirror would convert to using
@@ -338,20 +340,13 @@
     #            will preserve the mirror characteristic of the device.
     #            This policy acts like "remove" if no suitable device and
     #            space can be allocated for the replacement.
-    #            Currently this is not implemented properly and behaves
-    #            similarly to:
     #
-    # "allocate_anywhere" - Operates like "allocate", but it does not
-    #            require that the new space being allocated be on a
-    #            device is not part of the mirror.  For a log device
-    #            failure, this could mean that the log is allocated on
-    #            the same device as a mirror device.  For a mirror
-    #            device, this could mean that the mirror device is
-    #            allocated on the same device as another mirror device.
-    #            This policy would not be wise for mirror devices
-    #            because it would break the redundant nature of the
-    #            mirror.  This policy acts like "remove" if no suitable
-    #            device and space can be allocated for the replacement.
+    # "allocate_anywhere" - Not yet implemented. Useful to place the log device
+    #            temporarily on same physical volume as one of the mirror
+    #            images. This policy is not recommended for mirror devices
+    #            since it would break the redundant nature of the mirror. This
+    #            policy acts like "remove" if no suitable device and space can
+    #            be allocated for the replacement.
 
     mirror_log_fault_policy = "allocate"
     mirror_device_fault_policy = "remove"
--- LVM2/lib/config/defaults.h	2008/09/19 06:41:58	1.44
+++ LVM2/lib/config/defaults.h	2009/06/04 12:01:15	1.45
@@ -126,4 +126,7 @@
 #define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
 #define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
 
+#define DEFAULT_MIRROR_DEVICE_FAULT_POLICY "remove"
+#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
+
 #endif				/* _LVM_DEFAULTS_H */
--- LVM2/man/lvconvert.8.in	2009/04/23 16:56:22	1.3
+++ LVM2/man/lvconvert.8.in	2009/06/04 12:01:15	1.4
@@ -63,8 +63,14 @@
 .TP
 .I \-\-repair
 Repair a mirror that has suffered a disk failure. The mirror will be brought
-back into a consistent state, and if possible, the original number of
-mirrors will be restored.
+back into a consistent state, and if possible, the original number of mirrors
+will be restored, if so desired. By default, lvconvert will prompt you whether
+to perform the replacement. If you instead wish to unconditionally replace
+missing devices, you may specify \-y on the commandline and if you instead want
+no replacement to happen at all, you may provide \-f. Additionally, you may use
+"--use-policies" - this option will use the device replacement policy specified
+in lvm.conf, specifically "activation/mirror_log_fault_policy" and
+"activation/mirror_device_fault_policy".
 .br
 .TP
 .I \-s, \-\-snapshot
--- LVM2/test/t-lvconvert-repair.sh	2009/04/23 16:56:21	1.1
+++ LVM2/test/t-lvconvert-repair.sh	2009/06/04 12:01:16	1.2
@@ -22,19 +22,19 @@
 lvchange --partial -a y $vg/mirror
 
 not vgreduce -v --removemissing $vg
-lvconvert -i 1 --repair $vg/mirror
+lvconvert -y -i 1 --repair $vg/mirror
 vgreduce --removemissing $vg
 
 enable_dev $dev1
 vgextend $vg $dev1
 disable_dev $dev2
-lvconvert -i 1 --repair $vg/mirror
+lvconvert -y -i 1 --repair $vg/mirror
 vgreduce --removemissing $vg
 
 enable_dev $dev2
 vgextend $vg $dev2
 disable_dev $dev3
-lvconvert -i 1 --repair $vg/mirror
+lvconvert -y -i 1 --repair $vg/mirror
 vgreduce --removemissing $vg
 
 enable_dev $dev3
@@ -42,5 +42,5 @@
 lvcreate -m 2 -l 1 -n mirror2 $vg $dev1 $dev2 $dev3 $dev4
 vgchange -a n $vg
 pvremove -ff -y $dev4
-echo 'y' | not lvconvert -i 1 --repair $vg/mirror2
+echo 'y' | not lvconvert -y -i 1 --repair $vg/mirror2
 vgs
--- LVM2/tools/args.h	2009/05/27 16:30:30	1.64
+++ LVM2/tools/args.h	2009/06/04 12:01:16	1.65
@@ -50,6 +50,7 @@
 arg(corelog_ARG, '\0', "corelog", NULL, 0)
 arg(mirrorlog_ARG, '\0', "mirrorlog", string_arg, 0)
 arg(repair_ARG, '\0', "repair", NULL, 0)
+arg(use_policies_ARG, '\0', "use-policies", NULL, 0)
 arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0)
 arg(config_ARG, '\0', "config", string_arg, 0)
 arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
--- LVM2/tools/commands.h	2009/05/27 16:30:30	1.126
+++ LVM2/tools/commands.h	2009/06/04 12:01:16	1.127
@@ -94,7 +94,7 @@
    0,
    "lvconvert "
    "[-m|--mirrors Mirrors [{--mirrorlog {disk|core}|--corelog}]]\n"
-   "\t[--repair]\n"
+   "\t[--repair [--use-policies]]\n"
    "\t[-R|--regionsize MirrorLogRegionSize]\n"
    "\t[--alloc AllocationPolicy]\n"
    "\t[-b|--background]\n"
@@ -117,7 +117,7 @@
 
    alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, interval_ARG,
    mirrorlog_ARG, mirrors_ARG, regionsize_ARG, repair_ARG, snapshot_ARG,
-   test_ARG, zero_ARG)
+   test_ARG, use_policies_ARG, yes_ARG, force_ARG, zero_ARG)
 
 xx(lvcreate,
    "Create a logical volume",
--- LVM2/tools/lvconvert.c	2009/06/01 14:43:28	1.77
+++ LVM2/tools/lvconvert.c	2009/06/04 12:01:16	1.78
@@ -457,6 +457,49 @@
 	return next_lv;
 }
 
+static void _lvconvert_mirrors_repair_ask(struct cmd_context *cmd,
+					  int failed_log, int failed_mirrors,
+					  int *replace_log, int *replace_mirrors)
+{
+	const char *leg_policy = NULL, *log_policy = NULL;
+
+	int force = arg_count(cmd, force_ARG);
+	int yes = arg_count(cmd, yes_ARG);
+
+	*replace_log = *replace_mirrors = 1;
+
+	if (arg_count(cmd, use_policies_ARG)) {
+		leg_policy = find_config_tree_str(cmd,
+					"activation/mirror_device_fault_policy",
+					DEFAULT_MIRROR_DEVICE_FAULT_POLICY);
+		log_policy = find_config_tree_str(cmd,
+					"activation/mirror_log_fault_policy",
+					DEFAULT_MIRROR_LOG_FAULT_POLICY);
+		*replace_mirrors = strcmp(leg_policy, "remove");
+		*replace_log = strcmp(log_policy, "remove");
+		return;
+	}
+
+	if (yes)
+		return;
+
+	if (force != PROMPT) {
+		*replace_log = *replace_mirrors = 0;
+		return;
+	}
+
+	if (failed_log &&
+	    yes_no_prompt("Attempt to replace failed mirror log? [y/n]: ") == 'n') {
+		*replace_log = 0;
+	}
+
+	if (failed_mirrors &&
+	    yes_no_prompt("Attempt to replace failed mirror images "
+			  "(requires full device resync)? [y/n]: ") == 'n') {
+		*replace_mirrors = 0;
+	}
+}
+
 static int _lvconvert_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
 			      struct lvconvert_params *lp)
 {
@@ -470,18 +513,21 @@
 	int failed_mirrors = 0, failed_log = 0;
 	struct dm_list *old_pvh = NULL, *remove_pvs = NULL;
 
+	int repair = arg_count(cmd, repair_ARG);
+	int replace_log = 1, replace_mirrors = 1;
+
 	seg = first_seg(lv);
 	existing_mirrors = lv_mirror_count(lv);
 
 	/* If called with no argument, try collapsing the resync layers */
 	if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG) &&
 	    !arg_count(cmd, corelog_ARG) && !arg_count(cmd, regionsize_ARG) &&
-	    !arg_count(cmd, repair_ARG)) {
+	    !repair) {
 		lp->need_polling = 1;
 		return 1;
 	}
 
-	if (arg_count(cmd, mirrors_ARG) && arg_count(cmd, repair_ARG)) {
+	if (arg_count(cmd, mirrors_ARG) && repair) {
 		log_error("You can only use one of -m, --repair.");
 		return 0;
 	}
@@ -503,7 +549,7 @@
 	else
 		lp->mirrors += 1;
 
-	if (arg_count(cmd,repair_ARG)) {
+	if (repair) {
 		cmd->handles_missing_pvs = 1;
 		cmd->partial_activation = 1;
 		lp->need_polling = 0;
@@ -514,7 +560,7 @@
 		if ((failed_mirrors = _failed_mirrors_count(lv)) < 0)
 			return_0;
 		lp->mirrors -= failed_mirrors;
-		log_error("Mirror status: %d/%d legs failed.",
+		log_error("Mirror status: %d/%d images failed.",
 			  failed_mirrors, existing_mirrors);
 		old_pvh = lp->pvh;
 		if (!(lp->pvh = _failed_pv_list(lv->vg)))
@@ -577,6 +623,10 @@
 		return 0;
 	}
 
+	if (repair)
+		_lvconvert_mirrors_repair_ask(cmd, failed_log, failed_mirrors,
+					      &replace_log, &replace_mirrors);
+
  restart:
 	/*
 	 * Converting from mirror to linear
@@ -594,7 +644,7 @@
 	 */
 	if (lp->mirrors < existing_mirrors) {
 		/* Reduce number of mirrors */
-		if (arg_count(cmd, repair_ARG) || lp->pv_count)
+		if (repair || lp->pv_count)
 			remove_pvs = lp->pvh;
 		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
 				       (corelog || lp->mirrors == 1) ? 1U : 0U,
@@ -727,13 +777,15 @@
 
 	if (failed_log || failed_mirrors) {
 		lp->pvh = old_pvh;
-		if (failed_log)
+		if (failed_log && replace_log)
 			failed_log = corelog = 0;
-		lp->mirrors += failed_mirrors;
+		if (replace_mirrors)
+			lp->mirrors += failed_mirrors;
 		failed_mirrors = 0;
 		existing_mirrors = lv_mirror_count(lv);
 		/* Now replace missing devices. */
-		goto restart;
+		if (replace_log || replace_mirrors)
+			goto restart;
 	}
 
 	if (!lp->need_polling)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2009-05-20 22:24 agk
  0 siblings, 0 replies; 8+ messages in thread
From: agk @ 2009-05-20 22:24 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	agk@sourceware.org	2009-05-20 22:24:49

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 

Log message:
	Revert:
	Use lvconvert --repair in dmeventd mirror DSO.
	for now.
	
	It replaces bad behaviour in one set of circumstances with bad behaviour
	in a different set.  We think the behaviour needs to be more configurable.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1119&r2=1.1120
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.21&r2=1.22

--- LVM2/WHATS_NEW	2009/05/20 11:09:49	1.1119
+++ LVM2/WHATS_NEW	2009/05/20 22:24:48	1.1120
@@ -5,7 +5,6 @@
   Enable online resizing of mirrors.
   Use suspend with flush when device size was changed during table preload.
   Introduce CLVMD_CMD_LOCK_QUERY command for clvmd.
-  Use lvconvert --repair in dmeventd mirror DSO.
   Fix pvmove to revert operation if temporary mirror creation fails.
   Fix metadata export for VG with missing PVs.
   Add vgimportclone and install it and the man page by default.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/05/19 10:25:16	1.21
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/05/20 22:24:49	1.22
@@ -152,7 +152,7 @@
 	}
 
 	/* FIXME Is any sanity-checking required on %s? */
-	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair %s/%s", vg, lv)) {
+	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing --force %s", vg)) {
 		/* this error should be caught above, but doesn't hurt to check again */
 		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 		dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */


^ permalink raw reply	[flat|nested] 8+ messages in thread

* LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr ...
@ 2009-05-19 10:25 mbroz
  0 siblings, 0 replies; 8+ messages in thread
From: mbroz @ 2009-05-19 10:25 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mbroz@sourceware.org	2009-05-19 10:25:17

Modified files:
	.              : WHATS_NEW 
	daemons/dmeventd/plugins/mirror: dmeventd_mirror.c 

Log message:
	Use lvconvert --repair in dmeventd DSO (mornfall)
	
	This means two things:
	
	1) Non-mirrored LVs will be no longer affected by mirror monitoring. (Before,
	if you had a LV that went partially missing on a VG where a mirror leg failed,
	this LV would be removed automatically by dmeventd... Probably not an
	unrecoverable dataloss bug, but still quite unpleasant.)
	
	2) If enough parallel PV space is available at the time of the mirror failure,
	the failed devices will be automatically replaced using this spare space. Which
	(and whether) free space may be used is still not configurable, but is a
	planned feature. Since it is relatively easy to undo the action by converting
	the mirror manually, I don't consider this to be a showstopper. In fact, I
	think the compromise is much better than what we have now.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1114&r2=1.1115
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c.diff?cvsroot=lvm2&r1=1.20&r2=1.21

--- LVM2/WHATS_NEW	2009/05/19 09:51:02	1.1114
+++ LVM2/WHATS_NEW	2009/05/19 10:25:16	1.1115
@@ -1,5 +1,6 @@
 Version 2.02.46 - 
 ================================
+  Use lvconvert --repair in dmeventd mirror DSO.
   Fix pvmove to revert operation if temporary mirror creation fails.
   Fix metadata export for VG with missing PVs.
   Add vgimportclone and install it and the man page by default.
--- LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2008/09/25 15:52:29	1.20
+++ LVM2/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c	2009/05/19 10:25:16	1.21
@@ -152,7 +152,7 @@
 	}
 
 	/* FIXME Is any sanity-checking required on %s? */
-	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing --force %s", vg)) {
+	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair %s/%s", vg, lv)) {
 		/* this error should be caught above, but doesn't hurt to check again */
 		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 		dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-12-22 16:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-22 16:37 LVM2 ./WHATS_NEW daemons/dmeventd/plugins/mirr zkabelac
  -- strict thread matches above, loose matches on Subject: below --
2010-03-26 22:15 jbrassow
2010-01-06 13:26 mbroz
2009-11-25 15:59 agk
2009-09-17 10:37 agk
2009-06-04 12:01 mbroz
2009-05-20 22:24 agk
2009-05-19 10:25 mbroz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).