[lvm-devel] [PATCH 4/7] thin: add lvchange spare lv manipulation

Zdenek Kabelac zkabelac at redhat.com
Mon Jul 8 15:15:56 UTC 2013


Allow lvchange of pool metadata spare flag for the LV.

User could remove flag from already existing spare LV
(--poolmetadata n) - needs to specify name of invisible LV.

Also it's possible to select any other LV name and replace
the existing spare LV with a new LV.

Signed-off-by: Zdenek Kabelac <zkabelac at redhat.com>
---
 man/lvchange.8.in |  5 ++++
 tools/args.h      |  1 +
 tools/commands.h  |  4 ++-
 tools/lvchange.c  | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/man/lvchange.8.in b/man/lvchange.8.in
index 44426ef..5e23b7c 100644
--- a/man/lvchange.8.in
+++ b/man/lvchange.8.in
@@ -44,6 +44,8 @@ lvchange \- change attributes of a logical volume
 .RB [ \-P | \-\-partial ]
 .RB [ \-p | \-\-permission
 .RI { r | rw }]
+.RB [ \-\-poolmetadataspare
+.RI { y | n }]
 .RB [ \-r | \-\-readahead
 .RI { ReadAheadSectors | auto | none }]
 .RB [ \-\-refresh ]
@@ -182,6 +184,9 @@ Set to y to make the minor number specified persistent.
 .BR \-p ", " \-\-permission " {" \fIr | \fIrw }
 Change access permission to read-only or read/write.
 .TP
+.IR \fB\-\-poolmetadataspare " {" y | n }
+Change status of pool metadata spare volume.
+.TP
 .BR \-r ", " \-\-readahead " {" \fIReadAheadSectors | \fIauto | \fInone }
 Set read ahead sector count of this logical volume.
 For volume groups with metadata in lvm1 format, this must
diff --git a/tools/args.h b/tools/args.h
index 73312ca..2768640 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -74,6 +74,7 @@ arg(originname_ARG, '\0', "originname", string_arg, 0)
 arg(poll_ARG, '\0', "poll", yes_no_arg, 0)
 arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0)
 arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0)
+arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", yes_no_arg, 0)
 arg(discards_ARG, '\0', "discards", discards_arg, 0)
 arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE)
 arg(stripes_long_ARG, '\0', "stripes", int_arg, 0)
diff --git a/tools/commands.h b/tools/commands.h
index f84aa35..89d8764 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -93,6 +93,7 @@ xx(lvchange,
    "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
    "\t[--refresh]\n"
    "\t[--resync]\n"
+   "\t[--poolmetadataspare {y|n}]\n"
    "\t[--syncaction {check|repair}\n"
    "\t[--sysinit]\n"
    "\t[-t|--test]\n"
@@ -108,7 +109,8 @@ xx(lvchange,
    discards_ARG, detachprofile_ARG, force_ARG, ignorelockingfailure_ARG,
    ignoremonitoring_ARG, major_ARG, minor_ARG, monitor_ARG, minrecoveryrate_ARG,
    maxrecoveryrate_ARG, noudevsync_ARG, partial_ARG, permission_ARG,
-   persistent_ARG, poll_ARG, readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG,
+   persistent_ARG, poll_ARG, poolmetadataspare_ARG,
+   readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG,
    deltag_ARG, syncaction_ARG, sysinit_ARG, test_ARG, writebehind_ARG,
    writemostly_ARG, zero_ARG)
 
diff --git a/tools/lvchange.c b/tools/lvchange.c
index f7ce7fd..13b2e22 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -101,6 +101,73 @@ out:
 	return r;
 }
 
+static int _lvchange_spare(struct cmd_context *cmd,
+			   struct logical_volume *lv)
+{
+	struct lv_list *lvl;
+	uint64_t max_size = 0;
+	unsigned spare = arg_uint_value(cmd, poolmetadataspare_ARG, 0);
+
+	if (lv_is_active(lv)) {
+		log_error("Cannot change pool metadata spare status for active logical volume \"%s\".",
+			  lv->name);
+		return 0;
+	}
+
+	if (!spare) {
+		if (!lv_is_pool_metadata_spare(lv)) {
+			log_error("Logical volume \"%s\" is not a pool metadata spare volume.",
+				  lv->name);
+			return 0;
+		}
+
+		if (!vg_remove_pool_metadata_spare(lv->vg))
+			return_0;
+	} else {
+		if (lv_is_pool_metadata_spare(lv)) {
+			log_error("Logical volume \"%s\" is already pool metadata spare volume.",
+				  lv->name);
+			return 0;
+		}
+
+		if (!(lv->status & LVM_WRITE)) {
+			log_error("Cannot use read-only logical volume \"%s\" for pool metadata spare.",
+				  lv->name);
+			return 0;
+		}
+
+		if (!lv_is_visible(lv)) {
+			log_error("Cannot use invisible logical volume \"%s\" for pool metadata spare.",
+				  lv->name);
+			return 0;
+		}
+
+		/* FIXME: validate size */
+		dm_list_iterate_items(lvl, &lv->vg->lvs)
+			if (lv_is_thin_pool_metadata(lvl->lv) &&
+			    (max_size < lvl->lv->size))
+				max_size = lvl->lv->size;
+
+		if (lv->size < max_size) {
+			log_error("Logical volume \"%s\" must have at least %s for pool metadata spare.",
+				  lv->name, display_size(lv->vg->cmd, max_size));
+			return 0;
+		}
+
+		if (!vg_set_pool_metadata_spare(lv))
+			return_0;
+	}
+
+	log_very_verbose("Updating spare logical volume \"%s\" on disk(s).", lv->name);
+
+	if (!vg_write(lv->vg) || !vg_commit(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	return 1;
+}
+
 static int lvchange_pool_update(struct cmd_context *cmd,
 				struct logical_volume *lv)
 {
@@ -955,7 +1022,9 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 	    lv_is_virtual_origin(origin = origin_from_cow(lv)))
 		lv = origin;
 
-	if (!(lv_is_visible(lv)) && !lv_is_virtual_origin(lv)) {
+	if (!lv_is_visible(lv) &&
+	    !lv_is_pool_metadata_spare(lv) &&
+	    !lv_is_virtual_origin(lv)) {
 		log_error("Unable to change internal LV %s directly",
 			  lv->name);
 		return ECMD_FAILED;
@@ -1008,6 +1077,13 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 			return_ECMD_FAILED;
 	}
 
+	if (arg_count(cmd, poolmetadataspare_ARG)) {
+		if (!archive(lv->vg))
+			return_ECMD_FAILED;
+		doit += _lvchange_spare(cmd, lv);
+		docmds++;
+	}
+
 	if (arg_count(cmd, discards_ARG) ||
 	    arg_count(cmd, zero_ARG)) {
 		if (!archive(lv->vg))
@@ -1102,6 +1178,7 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
 		arg_count(cmd, contiguous_ARG) ||
 		arg_count(cmd, permission_ARG) ||
 		arg_count(cmd, readahead_ARG) ||
+		arg_count(cmd, poolmetadataspare_ARG) ||
 		arg_count(cmd, persistent_ARG) ||
 		arg_count(cmd, addtag_ARG) ||
 		arg_count(cmd, deltag_ARG) ||
-- 
1.8.3.1




More information about the lvm-devel mailing list