Skip to contentSkip to conversation

pool metadata spare

PATCH New Zdenek Kabelac 1 participant 8 messages Jul 8, 2013

lore
Share & tools
lore
#0 lore raw

cover pool metadata spare

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(-)
Signature · 1 line
1.8.3.1
#1 lore raw

PATCH 1/7 thin: add pool metadata spare lv support

Add support for pool's metadata spare volume.

---
 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(+)
lib/format_text/flags.c +1 -0
index cbccdfd..201ad4a 100644
@@ -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},
lib/format_text/import_vsn1.c +12 -0
index 54a4a9c..59603bb 100644
@@ -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;
 }
 
lib/metadata/metadata-exported.h +4 -0
index 412d29c..0250941 100644
@@ -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
lib/metadata/metadata.c +21 -0
index 96a636c..3796eb6 100644
@@ -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:
lib/metadata/thin_manip.c +71 -0

74 lines not on this page · raw message

lib/metadata/vg.h +2 -0
index 8db04d3..bf3a59e 100644
@@ -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,
lib/misc/lvm-string.c +1 -0
index 9dcdb3d..8aa1f6c 100644
@@ -105,6 +105,7 @@ int apply_lvname_restrictions(const char *name)
 	static const char * const _reserved_strings[] = {
 		"_mlog",
 		"_mimage",
+		"_pmspare",
 		"_rimage",
 		"_rmeta",
 		"_vorigin",
Signature · 1 line
1.8.3.1
#2 lore raw

PATCH 2/7 thin: report 'e' volume type pool metadata spare

In reply to Zdenek Kabelac

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.

---
 lib/metadata/lv.c | 1 +
 man/lvs.8.in      | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
lib/metadata/lv.c +1 -0
index 0742562..31e0c83 100644
@@ -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)
man/lvs.8.in +1 -1
index 013740f..965d649 100644
@@ -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
Signature · 1 line
1.8.3.1
#3 lore raw

PATCH 3/7 thin: removal of spare disables recovery

In reply to Zdenek Kabelac

Warn user when removing spare LV.

---
 lib/metadata/lv_manip.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
lib/metadata/lv_manip.c +26 -0
index 9d67e71..d86d070 100644
@@ -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);
 }
 
Signature · 1 line
1.8.3.1
#4 lore raw

PATCH 4/7 thin: add lvchange spare lv manipulation

In reply to Zdenek Kabelac

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.

---
 man/lvchange.8.in |  5 ++++
 tools/args.h      |  1 +
 tools/commands.h  |  4 ++-
 tools/lvchange.c  | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 87 insertions(+), 2 deletions(-)
man/lvchange.8.in +5 -0
index 44426ef..5e23b7c 100644
@@ -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
tools/args.h +1 -0
index 73312ca..2768640 100644
@@ -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)
tools/commands.h +3 -1
index f84aa35..89d8764 100644
@@ -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)
 
tools/lvchange.c +78 -1

103 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#5 lore raw

PATCH 5/7 thin: add spare lvcreate support

In reply to Zdenek Kabelac

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.

---
 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(-)
lib/config/defaults.h +1 -0
index 7ee89ec..3cd92a6 100644
@@ -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
 
lib/metadata/metadata-exported.h +3 -0
index 0250941..de69fd7 100644
@@ -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 */
 
lib/metadata/thin_manip.c +99 -0

104 lines not on this page · raw message

man/lvcreate.8.in +10 -1
index ac5cf65..163b2f4 100644
@@ -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
tools/commands.h +6 -4
index 89d8764..3aec4bc 100644
@@ -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",
tools/lvcreate.c +16 -2
index 698d72f..caecc46 100644
@@ -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",
Signature · 1 line
1.8.3.1
#6 lore raw

PATCH 6/7 thin: add lvconvert pool metadata spare

In reply to Zdenek Kabelac

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

---
 tools/commands.h  |  6 ++++--
 tools/lvconvert.c | 11 +++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
tools/commands.h +4 -2
index 3aec4bc..cb4ef44 100644
@@ -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,
tools/lvconvert.c +11 -0
index 3ea1987..7cbf3d4 100644
@@ -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
Signature · 1 line
1.8.3.1
#7 lore raw

PATCH 7/7 thin: add vgchange spare support

In reply to Zdenek Kabelac

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

---
 man/vgchange.8.in |  5 +++++
 tools/commands.h  |  2 ++
 tools/vgchange.c  | 25 +++++++++++++++++++++++--
 3 files changed, 30 insertions(+), 2 deletions(-)
man/vgchange.8.in +5 -0
index ab76ed0..c1872ea 100644
@@ -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
tools/commands.h +2 -0
index cb4ef44..1ce32eb 100644
@@ -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,
tools/vgchange.c +23 -2
index d3e93f2..af75857 100644
@@ -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;
 	}
 
Signature · 1 line
1.8.3.1