All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] pool metadata spare
@ 2013-07-08 15:15 Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 1/7] thin: add pool metadata spare lv support Zdenek Kabelac
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Updated patch set for spare devices.
Using  _pmspare suffix instead of  lv flag.


Zdenek Kabelac (7):
  thin: add pool metadata spare lv support
  thin: report 'e' volume type pool metadata spare
  thin: removal of spare disables recovery
  thin: add lvchange spare lv manipulation
  thin: add spare lvcreate support
  thin: add lvconvert pool metadata spare
  thin: add vgchange spare support

 lib/config/defaults.h            |   1 +
 lib/format_text/flags.c          |   1 +
 lib/format_text/import_vsn1.c    |  12 +++
 lib/metadata/lv.c                |   1 +
 lib/metadata/lv_manip.c          |  26 ++++++
 lib/metadata/metadata-exported.h |   7 ++
 lib/metadata/metadata.c          |  21 +++++
 lib/metadata/thin_manip.c        | 170 +++++++++++++++++++++++++++++++++++++++
 lib/metadata/vg.h                |   2 +
 lib/misc/lvm-string.c            |   1 +
 man/lvchange.8.in                |   5 ++
 man/lvcreate.8.in                |  11 ++-
 man/lvs.8.in                     |   2 +-
 man/vgchange.8.in                |   5 ++
 tools/args.h                     |   1 +
 tools/commands.h                 |  22 +++--
 tools/lvchange.c                 |  79 +++++++++++++++++-
 tools/lvconvert.c                |  11 +++
 tools/lvcreate.c                 |  18 ++++-
 tools/vgchange.c                 |  25 +++++-
 20 files changed, 407 insertions(+), 14 deletions(-)

-- 
1.8.3.1



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

* [PATCH 1/7] thin: add pool metadata spare lv support
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 2/7] thin: report 'e' volume type pool metadata spare Zdenek Kabelac
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Add support for pool's metadata spare volume.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/format_text/flags.c          |  1 +
 lib/format_text/import_vsn1.c    | 12 +++++++
 lib/metadata/metadata-exported.h |  4 +++
 lib/metadata/metadata.c          | 21 ++++++++++++
 lib/metadata/thin_manip.c        | 71 ++++++++++++++++++++++++++++++++++++++++
 lib/metadata/vg.h                |  2 ++
 lib/misc/lvm-string.c            |  1 +
 7 files changed, 112 insertions(+)

diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index cbccdfd..201ad4a 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -60,6 +60,7 @@ static const struct flag _lv_flags[] = {
 	{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
 	{LV_REBUILD, "REBUILD", STATUS_FLAG},
 	{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
+	{POOL_METADATA_SPARE, NULL, 0},
 	{RAID, NULL, 0},
 	{RAID_META, NULL, 0},
 	{RAID_IMAGE, NULL, 0},
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 54a4a9c..59603bb 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -617,6 +617,18 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
 	if (timestamp && !lv_set_creation(lv, hostname, timestamp))
 		return_0;
 
+	if (!lv_is_visible(lv) && strstr(lv->name, "_pmspare")) {
+		if (vg->pool_metadata_spare_lv) {
+			log_error("Couldn't use another pool metadata spare "
+				  "logical volume %s/%s.", vg->name, lv->name);
+			return 0;
+		}
+		log_debug_metadata("Logical volume %s is pool metadata spare.",
+				   lv->name);
+		lv->status |= POOL_METADATA_SPARE;
+		vg->pool_metadata_spare_lv = lv;
+	}
+
 	return 1;
 }
 
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 412d29c..0250941 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -99,6 +99,7 @@
 #define THIN_POOL_METADATA	UINT64_C(0x0000008000000000)	/* LV */
 
 #define LV_WRITEMOSTLY		UINT64_C(0x0000010000000000)	/* LV (RAID1) */
+#define POOL_METADATA_SPARE	UINT64_C(0x0000020000000000)	/* LV internal */
 
 /* Format features flags */
 #define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
@@ -158,6 +159,7 @@
 #define lv_is_raid_type(lv)	(((lv)->status & (RAID | RAID_IMAGE | RAID_META)) ? 1 : 0)
 
 #define lv_is_virtual(lv)	(((lv)->status & VIRTUAL) ? 1 : 0)
+#define lv_is_pool_metadata_spare(lv)	(((lv)->status & POOL_METADATA_SPARE) ? 1 : 0)
 
 /* Ordered list - see lv_manip.c */
 typedef enum {
@@ -664,6 +666,8 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
 					   uint32_t stripes, uint32_t stripe_size,
 					   uint64_t size, alloc_policy_t alloc,
 					   struct dm_list *pvh);
+int vg_set_pool_metadata_spare(struct logical_volume *lv);
+int vg_remove_pool_metadata_spare(struct volume_group *vg);
 
 /*
  * Activation options
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 96a636c..3796eb6 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2295,6 +2295,7 @@ int vg_validate(struct volume_group *vg)
 	unsigned hidden_lv_count = 0, lv_count = 0, lv_visible_count = 0;
 	unsigned pv_count = 0;
 	unsigned num_snapshots = 0;
+	unsigned spare_count = 0;
 	struct validate_hash vhash = { NULL };
 
 	if (vg->alloc == ALLOC_CLING_BY_TAGS) {
@@ -2474,6 +2475,19 @@ int vg_validate(struct volume_group *vg)
 			r = 0;
 		}
 
+		if (lv_is_pool_metadata_spare(lvl->lv)) {
+			if (++spare_count > 1) {
+				log_error(INTERNAL_ERROR "LV %s is %u. pool metadata spare (>1).",
+					  lvl->lv->name, spare_count);
+				r = 0;
+			}
+			if (vg->pool_metadata_spare_lv != lvl->lv) {
+				log_error(INTERNAL_ERROR "LV %s is not vg pool metadata spare.",
+					  lvl->lv->name);
+				r = 0;
+			}
+		}
+
 		if (!check_lv_segments(lvl->lv, 1)) {
 			log_error(INTERNAL_ERROR "LV segments corrupted in %s.",
 				  lvl->lv->name);
@@ -2526,6 +2540,13 @@ int vg_validate(struct volume_group *vg)
 		r = 0;
 	}
 
+	if (vg->pool_metadata_spare_lv &&
+	    !lv_is_pool_metadata_spare(vg->pool_metadata_spare_lv)) {
+		log_error(INTERNAL_ERROR "VG references non pool metadata spare LV %s.",
+			  vg->pool_metadata_spare_lv->name);
+		r = 0;
+	}
+
 	if (vg_max_lv_reached(vg))
 		stack;
 out:
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index f40fd74..721c1e2 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -721,3 +721,74 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
 
 	return metadata_lv;
 }
+
+int vg_set_pool_metadata_spare(struct logical_volume *lv)
+{
+	char new_name[NAME_LEN];
+	struct volume_group *vg = lv->vg;
+
+	if (vg->pool_metadata_spare_lv) {
+		if (vg->pool_metadata_spare_lv == lv)
+			return 1;
+		if (!vg_remove_pool_metadata_spare(vg))
+			return_0;
+	}
+
+	if (dm_snprintf(new_name, sizeof(new_name), "%s_pmspare", lv->name) < 0) {
+		log_error("Can't create pool metadata spare. Name of pool LV "
+			  "%s is too long.", lv->name);
+		return 0;
+	}
+
+	if (!lv_rename_update(vg->cmd, lv, new_name, 0))
+		return_0;
+
+	lv_set_hidden(lv);
+	lv->status |= POOL_METADATA_SPARE;
+	vg->pool_metadata_spare_lv = lv;
+
+	return 1;
+}
+
+int vg_remove_pool_metadata_spare(struct volume_group *vg)
+{
+	char new_name[NAME_LEN];
+	char *c;
+
+	struct logical_volume *lv = vg->pool_metadata_spare_lv;
+
+	if (!(lv->status & POOL_METADATA_SPARE)) {
+		log_error(INTERNAL_ERROR "LV %s is not pool metadata spare.",
+			  lv->name);
+		return 0;
+	}
+
+	vg->pool_metadata_spare_lv = NULL;
+	lv->status &= ~POOL_METADATA_SPARE;
+	lv_set_visible(lv);
+
+	/* Cut off suffix _pmspare */
+	(void) dm_strncpy(new_name, lv->name, sizeof(new_name));
+	if (!(c = strchr(new_name, '_'))) {
+		log_error(INTERNAL_ERROR "LV %s has no suffix for pool metadata spare.",
+			  new_name);
+		return 0;
+	}
+	*c = 0;
+
+	/* If the name is in use, generate new lvol%d */
+	if (find_lv_in_vg(vg, new_name) &&
+	    !generate_lv_name(vg, "lvol%d", new_name, sizeof(new_name))) {
+		log_error("Failed to generate unique name for "
+			  "pool metadata spare logical volume.");
+		return 0;
+	}
+
+	log_print_unless_silent("Renaming existing pool metadata spare "
+				"logical volume to \"%s\".", new_name);
+
+	if (!lv_rename_update(vg->cmd, lv, new_name, 0))
+		return_0;
+
+	return 1;
+}
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index 8db04d3..bf3a59e 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -20,6 +20,7 @@ struct dm_pool;
 struct format_instance;
 struct dm_list;
 struct id;
+struct logical_volume;
 
 typedef enum {
 	ALLOC_INVALID,
@@ -121,6 +122,7 @@ struct volume_group {
 	uint32_t mda_copies; /* target number of mdas for this VG */
 
 	struct dm_hash_table *hostnames; /* map of creation hostnames */
+	struct logical_volume *pool_metadata_spare_lv; /* one per VG */
 };
 
 struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c
index 9dcdb3d..8aa1f6c 100644
--- a/lib/misc/lvm-string.c
+++ b/lib/misc/lvm-string.c
@@ -105,6 +105,7 @@ int apply_lvname_restrictions(const char *name)
 	static const char * const _reserved_strings[] = {
 		"_mlog",
 		"_mimage",
+		"_pmspare",
 		"_rimage",
 		"_rmeta",
 		"_vorigin",
-- 
1.8.3.1



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

* [PATCH 2/7] thin: report 'e' volume type pool metadata spare
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 1/7] thin: add pool metadata spare lv support Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 3/7] thin: removal of spare disables recovery Zdenek Kabelac
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Reuse m'e'tadata volume type for spar'e' volume as well.
Essentially they are related and there is no big reason
to introduce new flag.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/lv.c | 1 +
 man/lvs.8.in      | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 0742562..31e0c83 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -547,6 +547,7 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
 	else if (lv_is_origin(lv) || lv_is_external_origin(lv))
 		repstr[0] = (lv_is_merging_origin(lv)) ? 'O' : 'o';
 	else if (lv_is_thin_pool_metadata(lv) ||
+		 lv_is_pool_metadata_spare(lv) ||
 		 (lv->status & RAID_META))
 		repstr[0] = 'e';
 	else if (lv->status & RAID)
diff --git a/man/lvs.8.in b/man/lvs.8.in
index 013740f..965d649 100644
--- a/man/lvs.8.in
+++ b/man/lvs.8.in
@@ -135,7 +135,7 @@ Volume type: (m)irrored, (M)irrored without initial sync, (o)rigin,
 (s)napshot, merging (S)napshot, (p)vmove, (v)irtual,
 mirror or raid (i)mage, mirror or raid (I)mage out-of-sync, mirror (l)og device,
 under (c)onversion, thin (V)olume, (t)hin pool, (T)hin pool data, raid or
-thin pool m(e)tadata
+thin pool m(e)tadata or pool metadata spare.
 .IP 2 3
 Permissions: (w)riteable, (r)ead-only, (R)ead-only activation of non-read-only
 volume
-- 
1.8.3.1



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

* [PATCH 3/7] thin: removal of spare disables recovery
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 1/7] thin: add pool metadata spare lv support Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 2/7] thin: report 'e' volume type pool metadata spare Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 4/7] thin: add lvchange spare lv manipulation Zdenek Kabelac
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Warn user when removing spare LV.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/lv_manip.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 9d67e71..d86d070 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4521,7 +4521,9 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
 {
 	percent_t snap_percent;
 	struct dm_list *snh, *snht;
+	struct lv_list *lvl;
 	struct lvinfo info;
+	int found;
 
 	if (lv_is_cow(lv)) {
 		/*
@@ -4579,6 +4581,30 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
 	    !_lv_remove_segs_using_this_lv(cmd, lv, force, level, "pool"))
 		return_0;
 
+	if (lv_is_thin_pool(lv) && lv->vg->pool_metadata_spare_lv) {
+		found = 0;
+		/* When removing last thin pool, remove spare as well */
+		dm_list_iterate_items(lvl, &lv->vg->lvs)
+			if (lv_is_thin_pool(lvl->lv) && lvl->lv != lv) {
+				found = 1;
+				break;
+			}
+
+		if (!found &&
+		    !lv_remove_with_dependencies(cmd, lv->vg->pool_metadata_spare_lv,
+						 force, level + 1))
+			return_0;
+	}
+
+	if (lv_is_pool_metadata_spare(lv) &&
+	    (force == PROMPT) &&
+	    (yes_no_prompt("Removal of pool metadata spare logical volume \"%s\" "
+			   "disables automatic recovery attempts after damage "
+			   "to a thin pool. Proceed? [y/n]: ", lv->name) == 'n')) {
+		log_error("Logical volume \"%s\" not removed.", lv->name);
+		return 0;
+	}
+
 	return lv_remove_single(cmd, lv, force);
 }
 
-- 
1.8.3.1



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

* [PATCH 4/7] thin: add lvchange spare lv manipulation
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
                   ` (2 preceding siblings ...)
  2013-07-08 15:15 ` [PATCH 3/7] thin: removal of spare disables recovery Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 5/7] thin: add spare lvcreate support Zdenek Kabelac
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

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@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@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



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

* [PATCH 5/7] thin: add spare lvcreate support
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
                   ` (3 preceding siblings ...)
  2013-07-08 15:15 ` [PATCH 4/7] thin: add lvchange spare lv manipulation Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 6/7] thin: add lvconvert pool metadata spare Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 7/7] thin: add vgchange spare support Zdenek Kabelac
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Add --poolmetadataspare option and creates and handles
pool metadata spare lv when thin pool is created.
With default setting 'y' it tries to ensure, spare has
at least the size of created LV.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/config/defaults.h            |  1 +
 lib/metadata/metadata-exported.h |  3 ++
 lib/metadata/thin_manip.c        | 99 ++++++++++++++++++++++++++++++++++++++++
 man/lvcreate.8.in                | 11 ++++-
 tools/commands.h                 | 10 ++--
 tools/lvcreate.c                 | 18 +++++++-
 6 files changed, 135 insertions(+), 7 deletions(-)

diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 7ee89ec..3cd92a6 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -73,6 +73,7 @@
 #define DEFAULT_THIN_POOL_CHUNK_SIZE	    64	  /* KB */
 #define DEFAULT_THIN_POOL_DISCARDS "passdown"
 #define DEFAULT_THIN_POOL_ZERO 1
+#define DEFAULT_POOL_METADATA_SPARE 1
 
 #define DEFAULT_UMASK 0077
 
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0250941..de69fd7 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -668,6 +668,8 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
 					   struct dm_list *pvh);
 int vg_set_pool_metadata_spare(struct logical_volume *lv);
 int vg_remove_pool_metadata_spare(struct volume_group *vg);
+int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
+			       struct dm_list *pvh, int poolmetadataspare);
 
 /*
  * Activation options
@@ -692,6 +694,7 @@ struct lvcreate_params {
 	int minor; /* all */
 	int log_count; /* mirror */
 	int nosync; /* mirror */
+	int poolmetadataspare; /* thin pool */
 	activation_change_t activate; /* non-snapshot, non-mirror */
 	thin_discards_t discards;     /* thin */
 
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 721c1e2..72496d9 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -790,5 +790,104 @@ int vg_remove_pool_metadata_spare(struct volume_group *vg)
 	if (!lv_rename_update(vg->cmd, lv, new_name, 0))
 		return_0;
 
+	/* To display default warning */
+	(void) handle_pool_metadata_spare(vg, 0, 0, 0);
+
+	return 1;
+}
+
+static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg,
+							 uint32_t extents,
+							 struct dm_list *pvh)
+{
+	struct logical_volume *lv;
+
+	/* FIXME: Make lvm2api usable */
+	struct lvcreate_params lp = {
+		.activate = CHANGE_ALY,
+		.alloc = ALLOC_INHERIT,
+		.extents = extents,
+		.major = -1,
+		.minor = -1,
+		.permission = LVM_READ | LVM_WRITE,
+		.pvh = pvh ? : &vg->pvs,
+		.read_ahead = DM_READ_AHEAD_AUTO,
+		.stripes = 1,
+		.vg_name = vg->name,
+		.zero = 1,
+	};
+
+	dm_list_init(&lp.tags);
+
+	if (!(lp.segtype = get_segtype_from_string(vg->cmd, "striped")))
+		return_0;
+
+	/* FIXME: Maybe using silent mode ? */
+	if (!(lv = lv_create_single(vg, &lp)))
+		return_0;
+
+	/* Spare LV should not be active */
+	if (!deactivate_lv_local(vg->cmd, lv)) {
+		log_error("Unable to deactivate pool metadata spare LV. "
+			  "Manual intervention required.");
+		return 0;
+	}
+
+	if (!vg_set_pool_metadata_spare(lv))
+		return_0;
+
+	return lv;
+}
+
+/*
+ * Create/resize pool metadata spare LV
+ * Caller does vg_write(), vg_commit() with pool creation
+ * extents is 0, max size is determined
+ */
+int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
+			       struct dm_list *pvh, int poolmetadataspare)
+{
+	struct logical_volume *lv = vg->pool_metadata_spare_lv;
+	uint32_t seg_mirrors;
+	struct lv_segment *seg;
+	const struct lv_list *lvl;
+
+	if (!extents)
+		/* Find maximal size of metadata LV */
+		dm_list_iterate_items(lvl, &vg->lvs)
+			if (lv_is_thin_pool_metadata(lvl->lv) &&
+			    (lvl->lv->le_count > extents))
+				extents = lvl->lv->le_count;
+
+	if (!poolmetadataspare) {
+		/* TODO: Not showing when lvm.conf would define 'n' ? */
+		if (DEFAULT_POOL_METADATA_SPARE && extents)
+			/* Warn if there would be any user */
+			log_warn("WARNING: recovery of pools without pool "
+				 "metadata spare LV is not automated.");
+		return 1;
+	}
+
+	if (!lv) {
+		if (!_alloc_pool_metadata_spare(vg, extents, pvh))
+			return_0;
+
+		return 1;
+	}
+
+	seg = last_seg(lv);
+	seg_mirrors = lv_mirror_count(lv);
+
+	/* Check spare LV is big enough and preserve segtype */
+	if ((lv->le_count < extents) && seg &&
+	    !lv_extend(lv, seg->segtype,
+		       seg->area_count / seg_mirrors,
+		       seg->stripe_size,
+		       seg_mirrors,
+		       seg->region_size,
+		       extents - lv->le_count, NULL,
+		       pvh, lv->alloc))
+		return_0;
+
 	return 1;
 }
diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
index ac5cf65..163b2f4 100644
--- a/man/lvcreate.8.in
+++ b/man/lvcreate.8.in
@@ -61,7 +61,9 @@ lvcreate \- create a logical volume in an existing volume group
 .RB [ \-\-discards
 .RI { ignore | nopassdown | passdown }]
 .RB [ \-\-poolmetadatasize
-.IR MetadataVolumeSize [ bBsSkKmMgG ]]]
+.IR MetadataVolumeSize [ bBsSkKmMgG ]]
+.RB [ \-\-poolmetadataspare
+.RI { y | n }]]
 .RB [ \-\-thinpool
 .IR ThinPoolLogicalVolume { Name | Path }
 .RB [ \-s | \-\-snapshot
@@ -277,6 +279,13 @@ Supported values are in range between 2MiB and 16GiB.
 Default value is  (Pool_LV_size / Pool_LV_chunk_size * 64b).
 Default unit is megabytes.
 .TP
+.IR \fB\-\-poolmetadataspare " {"  y | n }
+Controls creation and maintanence of pool metadata spare logical volume
+that will be used for automated thin pool recovery.
+Only one such volume is maintained within a volume group
+with the size of the biggest thin metadata volume.
+Default is \fIy\fPes.
+.TP
 .IR \fB\-r ", " \fB\-\-readahead " {" ReadAheadSectors | auto | none }
 Sets read ahead sector count of this logical volume.
 For volume groups with metadata in lvm1 format, this must
diff --git a/tools/commands.h b/tools/commands.h
index 89d8764..3aec4bc 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -210,6 +210,7 @@ xx(lvcreate,
    "\t[-T|--thin  [-c|--chunksize  ChunkSize]\n"
    "\t  [--discards {ignore|nopassdown|passdown}]\n"
    "\t  [--poolmetadatasize MetadataSize[bBsSkKmMgG]]]\n"
+   "\t  [--poolmetadataspare {y|n}]\n"
    "\t[--thinpool ThinPoolLogicalVolume{Name|Path}]\n"
    "\t[-t|--test]\n"
    "\t[--type VolumeType]\n"
@@ -253,10 +254,11 @@ xx(lvcreate,
    chunksize_ARG, contiguous_ARG, corelog_ARG, discards_ARG, extents_ARG,
    ignoremonitoring_ARG, major_ARG, minor_ARG, mirrorlog_ARG, mirrors_ARG,
    monitor_ARG, minrecoveryrate_ARG, maxrecoveryrate_ARG, name_ARG, nosync_ARG,
-   noudevsync_ARG, permission_ARG,
-   persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG,
-   stripes_ARG, stripesize_ARG, test_ARG, thin_ARG, thinpool_ARG, type_ARG,
-   virtualoriginsize_ARG, poolmetadatasize_ARG, virtualsize_ARG, zero_ARG)
+   noudevsync_ARG, permission_ARG, persistent_ARG, poolmetadatasize_ARG,
+   poolmetadataspare_ARG, readahead_ARG, regionsize_ARG,
+   size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG,
+   test_ARG, thin_ARG, thinpool_ARG, type_ARG,
+   virtualoriginsize_ARG, virtualsize_ARG, zero_ARG)
 
 xx(lvdisplay,
    "Display information about a logical volume",
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 698d72f..caecc46 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -887,6 +887,14 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 		return 0;
 	}
 
+	if (lp->create_thin_pool) {
+		/* TODO: add lvm.conf default y|n */
+		lp->poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG,
+						      DEFAULT_POOL_METADATA_SPARE);
+	} else if (arg_count(cmd, poolmetadataspare_ARG)) {
+		log_error("--poolmetadataspare is only available with thin pool creation.");
+		return 0;
+	}
 	/*
 	 * Allocation parameters
 	 */
@@ -945,6 +953,7 @@ static int _check_thin_parameters(struct volume_group *vg, struct lvcreate_param
 			contiguous_ARG,
 			discards_ARG,
 			poolmetadatasize_ARG,
+			poolmetadataspare_ARG,
 			stripes_ARG,
 			stripesize_ARG,
 			zero_ARG
@@ -1079,9 +1088,14 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
 	if (seg_is_thin(&lp) && !_validate_internal_thin_processing(&lp))
 		goto_out;
 
-	if (lp.create_thin_pool)
+	if (lp.create_thin_pool) {
+		if (!handle_pool_metadata_spare(vg, lp.poolmetadataextents,
+						lp.pvh, lp.poolmetadataspare))
+			goto_out;
+
 		log_verbose("Making thin pool %s in VG %s using segtype %s",
 			    lp.pool ? : "with generated name", lp.vg_name, lp.segtype->name);
+	}
 
 	if (lp.thin)
 		log_verbose("Making thin LV %s in pool %s in VG %s%s%s using segtype %s",
-- 
1.8.3.1



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

* [PATCH 6/7] thin: add lvconvert pool metadata spare
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
                   ` (4 preceding siblings ...)
  2013-07-08 15:15 ` [PATCH 5/7] thin: add spare lvcreate support Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  2013-07-08 15:15 ` [PATCH 7/7] thin: add vgchange spare support Zdenek Kabelac
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Support poolmetadataspare when convering volumes into thin pool.
Same rules applied as with lvcreate.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/commands.h  |  6 ++++--
 tools/lvconvert.c | 11 +++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/tools/commands.h b/tools/commands.h
index 3aec4bc..cb4ef44 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -168,6 +168,7 @@ xx(lvconvert,
    "\t[--poolmetadata ThinMetadataLogicalVolume[Path] |\n"
    "\t [--poolmetadatasize size]\n"
    "\t [-r|--readahead ReadAheadSectors|auto|none]\n"
+   "\t [--poolmetadataspare {y|n}]\n"
    "\t [--stripes Stripes [-I|--stripesize StripeSize]]]\n"
    "\t[-T|--thin ExternalLogicalVolume[Path]\n"
    "\t [--originname NewExternalOriginVolumeName]]\n"
@@ -178,8 +179,9 @@ xx(lvconvert,
    merge_ARG, mirrorlog_ARG, mirrors_ARG, name_ARG, noudevsync_ARG,
    readahead_ARG, regionsize_ARG, repair_ARG, replace_ARG, snapshot_ARG, splitmirrors_ARG,
    trackchanges_ARG, type_ARG, stripes_long_ARG, stripesize_ARG, test_ARG,
-   chunksize_ARG, discards_ARG, poolmetadata_ARG, poolmetadatasize_ARG,
-   originname_ARG, thin_ARG, thinpool_ARG,
+   chunksize_ARG, discards_ARG, originname_ARG,
+   poolmetadata_ARG, poolmetadatasize_ARG, poolmetadataspare_ARG,
+   thin_ARG, thinpool_ARG,
    use_policies_ARG, force_ARG, zero_ARG)
 
 xx(lvcreate,
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 3ea1987..7cbf3d4 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -22,6 +22,7 @@ struct lvconvert_params {
 	int snapshot;
 	int merge;
 	int merge_mirror;
+	int poolmetadataspare;
 	int thin;
 	int yes;
 	int zero;
@@ -254,6 +255,9 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
 	} else if (arg_count(cmd, discards_ARG)) {
 		log_error("--discards is only valid with --thinpool.");
 		return 0;
+	} else if (arg_count(cmd, poolmetadataspare_ARG)) {
+		log_error("--poolmetadataspare is only valid with --thinpool.");
+		return 0;
 	}
 
 	/*
@@ -487,6 +491,9 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
 			return_0;
 	}
 
+	/* TODO: default in lvm.conf ? */
+	lp->poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG,
+					      DEFAULT_POOL_METADATA_SPARE);
 	lp->force = arg_count(cmd, force_ARG);
 	lp->yes = arg_count(cmd, yes_ARG);
 
@@ -2159,6 +2166,10 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
 		return 0;
 	}
 
+	if (!handle_pool_metadata_spare(pool_lv->vg, metadata_lv->le_count,
+					lp->pvh, lp->poolmetadataspare))
+		return_0;
+
 	old_name = data_lv->name; /* Use for pool name */
 	/*
 	 * Since we wish to have underlaying devs to match _tdata
-- 
1.8.3.1



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

* [PATCH 7/7] thin: add vgchange spare support
  2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
                   ` (5 preceding siblings ...)
  2013-07-08 15:15 ` [PATCH 6/7] thin: add lvconvert pool metadata spare Zdenek Kabelac
@ 2013-07-08 15:15 ` Zdenek Kabelac
  6 siblings, 0 replies; 8+ messages in thread
From: Zdenek Kabelac @ 2013-07-08 15:15 UTC (permalink / raw)
  To: lvm-devel

Since the pool metadata spare could be seen as VG property
(only one such spare is supported per VG) - allow the manipulation
on vg level.

Support operation are:
removal --poolmetadata n   - removes spare LV if exists.
creation --poolmetadata y  - creates LV with maxsize of metadata

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 man/vgchange.8.in |  5 +++++
 tools/commands.h  |  2 ++
 tools/vgchange.c  | 25 +++++++++++++++++++++++--
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/man/vgchange.8.in b/man/vgchange.8.in
index ab76ed0..c1872ea 100644
--- a/man/vgchange.8.in
+++ b/man/vgchange.8.in
@@ -39,6 +39,8 @@ vgchange \- change attributes of a volume group
 .RB [ \-P | \-\-partial ]
 .RB [ \-s | \-\-physicalextentsize
 .IR PhysicalExtentSize [ bBsSkKmMgGtTpPeE ]]
+.RB [ \-\-poolmetadataspare
+.RI { y | n }]
 .RB [ \-\-refresh ]
 .RB [ -t | \-\-test ]
 .RB [ \-v | \-\-verbose ]
@@ -196,6 +198,9 @@ impact on I/O performance to the logical volume.  The smallest PE is 1KiB.
 
 The 2.4 kernel has a limitation of 2TiB per block device.
 .TP
+.IR \fB\-\-poolmetadataspare " {" y | n }
+Change presence of pool metadata spare volume in this volume group.
+.TP
 .BR \-\-refresh
 If any logical volume in the volume group is active, reload its metadata.
 This is not necessary in normal operation, but may be useful
diff --git a/tools/commands.h b/tools/commands.h
index cb4ef44..1ce32eb 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -784,6 +784,7 @@ xx(vgchange,
    "\t[--monitor {y|n}]\n"
    "\t[--[vg]metadatacopies #copies] " "\n"
    "\t[--poll {y|n}]\n"
+   "\t[--poolmetadataspare {y|n}]\n"
    "\t[--noudevsync]\n"
    "\t[--refresh]\n"
    "\t[--sysinit]\n"
@@ -806,6 +807,7 @@ xx(vgchange,
    ignorelockingfailure_ARG, ignoremonitoring_ARG, logicalvolume_ARG,
    maxphysicalvolumes_ARG, monitor_ARG, noudevsync_ARG, metadatacopies_ARG,
    vgmetadatacopies_ARG, partial_ARG, physicalextentsize_ARG, poll_ARG,
+   poolmetadataspare_ARG,
    refresh_ARG, resizeable_ARG, resizable_ARG, sysinit_ARG, test_ARG, uuid_ARG)
 
 xx(vgck,
diff --git a/tools/vgchange.c b/tools/vgchange.c
index d3e93f2..af75857 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -443,6 +443,25 @@ static int _vgchange_profile(struct cmd_context *cmd,
 	return 1;
 }
 
+static int _vgchange_pool_metadata_spare(struct cmd_context *cmd,
+					 struct volume_group *vg)
+{
+	int pms = arg_int_value(cmd, poolmetadataspare_ARG, 0);
+	/* Defaults not used here, value is given on cmdline */
+
+	if (pms) {
+		if (!handle_pool_metadata_spare(vg, 0, NULL, 1))
+			return_0;
+	} else if (vg->pool_metadata_spare_lv) {
+		if (!vg_remove_pool_metadata_spare(vg))
+			return_0;
+	} else
+		log_warn("Volume group \"%s\" is already without "
+			 "pool metadata spare volume.", vg->name);
+
+	return 1;
+}
+
 static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
 			   struct volume_group *vg,
 			   void *handle __attribute__((unused)))
@@ -464,6 +483,7 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
 		{ clustered_ARG, &_vgchange_clustered },
 		{ vgmetadatacopies_ARG, &_vgchange_metadata_copies },
 		{ profile_ARG, &_vgchange_profile},
+		{ poolmetadataspare_ARG, &_vgchange_pool_metadata_spare},
 		{ detachprofile_ARG, &_vgchange_profile},
 	};
 
@@ -545,6 +565,7 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
 		arg_count(cmd, resizeable_ARG) ||
 		arg_count(cmd, uuid_ARG) ||
 		arg_count(cmd, physicalextentsize_ARG) ||
+		arg_count(cmd, poolmetadataspare_ARG) ||
 		arg_count(cmd, clustered_ARG) ||
 		arg_count(cmd, alloc_ARG) ||
 		arg_count(cmd, vgmetadatacopies_ARG);
@@ -557,8 +578,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
 	    !arg_count(cmd, refresh_ARG)) {
 		log_error("Need 1 or more of -a, -c, -l, -p, -s, -x, "
 			  "--refresh, --uuid, --alloc, --addtag, --deltag, "
-			  "--monitor, --poll, --vgmetadatacopies or "
-			  "--metadatacopies");
+			  "--monitor, --poll, --poolmetadataspare "
+			  "--vgmetadatacopies or --metadatacopies");
 		return EINVALID_CMD_LINE;
 	}
 
-- 
1.8.3.1



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

end of thread, other threads:[~2013-07-08 15:15 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-08 15:15 [PATCH 0/7] pool metadata spare Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 1/7] thin: add pool metadata spare lv support Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 2/7] thin: report 'e' volume type pool metadata spare Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 3/7] thin: removal of spare disables recovery Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 4/7] thin: add lvchange spare lv manipulation Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 5/7] thin: add spare lvcreate support Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 6/7] thin: add lvconvert pool metadata spare Zdenek Kabelac
2013-07-08 15:15 ` [PATCH 7/7] thin: add vgchange spare support Zdenek Kabelac

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.