spare LV support
cover spare LV support
Initial preparation for handling spare LVs within LV. Spare LV is going to be used for thin pool recovery. There is one spare LV per pool always sized as the largest thin pool metadata LV in the VG.
Zdenek Kabelac (6):
thin: add spare lv support
thin: report spare as 'e' volume type
thin: removal of spare disables recovery
thin: lvchange spare lv manipulation
thin: add spare lvcreate support
thin: unfinished lvconvert
lib/format_text/flags.c | 1 + lib/format_text/import_vsn1.c | 10 +++++ lib/metadata/lv.c | 1 + lib/metadata/lv_manip.c | 19 +++++++++ lib/metadata/metadata-exported.h | 4 ++ lib/metadata/metadata.c | 24 +++++++---- lib/metadata/snapshot_manip.c | 3 +- lib/metadata/vg.h | 2 + tools/args.h | 1 + tools/commands.h | 18 +++++---- tools/lvchange.c | 86 +++++++++++++++++++++++++++++++++++++++- tools/lvconvert.c | 2 + tools/lvcreate.c | 83 +++++++++++++++++++++++++++++++++++++- 13 files changed, 235 insertions(+), 19 deletions(-)
Signature · 1 line
1.8.2.1
PATCH 1/6 thin: add spare lv support
Add support for SPARE volume.
--- lib/format_text/flags.c | 1 + lib/format_text/import_vsn1.c | 10 ++++++++++ lib/metadata/metadata-exported.h | 3 +++ lib/metadata/metadata.c | 24 ++++++++++++++++-------- lib/metadata/snapshot_manip.c | 3 ++- lib/metadata/vg.h | 2 ++ 6 files changed, 34 insertions(+), 9 deletions(-)
lib/format_text/flags.c +1 -0
@@ -59,6 +59,7 @@ static const struct flag _lv_flags[] = { {LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG}, {LV_REBUILD, "REBUILD", STATUS_FLAG}, {LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG}, + {SPARE_LV, "SPARE", STATUS_FLAG}, {RAID, NULL, 0}, {RAID_META, NULL, 0}, {RAID_IMAGE, NULL, 0},
lib/format_text/import_vsn1.c +10 -0
@@ -605,6 +605,16 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),if (timestamp && !lv_set_creation (lv, hostname, timestamp)) return_0; +if (lv_is_spare (lv)) { +if (lv->vg->spare) { +/* CHECKME: maybe just ignore all others ? */ +log_error ("VG with multiple spare LVs is not supported." ); +return 0 ; + } +log_debug_metadata ("Logical volume %s is spare." , lv->name); + lv->vg->spare = lv; + } +return 1 ; }
lib/metadata/metadata-exported.h +3 -0
@@ -92,6 +92,8 @@#define LV_WRITEMOSTLY UINT64_C(0x0000010000000000)/* LV (RAID1) */ +#define SPARE_LV UINT64_C(0x0000020000000000)/* LV internal use */ +#define LVM_READ UINT64_C(0x00000100)/* LV, VG */ #define LVM_WRITE UINT64_C(0x00000200)/* LV, VG */
@@ -153,6 +155,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_spare (lv) (((lv)->status & SPARE_LV) ? 1 : 0)/* Ordered list - see lv_manip.c */ typedef enum {
lib/metadata/metadata.c +16 -8
@@ -2290,9 +2290,10 @@ int vg_validate(struct volume_group *vg)struct str_list *sl; char uuid[64] __attribute__((aligned(8)));int r =1 ; -uint32_t hidden_lv_count =0 , lv_count =0 , lv_visible_count =0 ; -uint32_t pv_count =0 ; -uint32_t num_snapshots =0 ; +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 ) {
@@ -2404,6 +2405,12 @@ int vg_validate(struct volume_group *vg) r =0 ; } +if (lv_is_spare (lvl->lv) && ++spare_count >1 ) { +log_error (INTERNAL_ERROR "LV %s is %d. spare (allowed is one)." , + lvl->lv->name, spare_count); + r =0 ; + } +if (lvl->lv->status &VISIBLE_LV )continue ;
@@ -2429,11 +2436,12 @@ int vg_validate(struct volume_group *vg)/* * all volumes = visible LVs + snapshot_cows + invisible LVs */ -if (lv_count != lv_visible_count + num_snapshots + hidden_lv_count) { -log_error (INTERNAL_ERROR "#internal LVs (%u) != #LVs (%" - PRIu32") + #snapshots (%" PRIu32") + #internal LVs (%u) in VG %s" , - lv_count, lv_visible_count, - num_snapshots, hidden_lv_count, vg->name); +if (lv_count != lv_visible_count + num_snapshots + hidden_lv_count + spare_count) { +log_error (INTERNAL_ERROR "#LVs (%u) != #visible LVs (%u) " +"+ #snapshots (%u) + #internal LVs (%u) " +"+ #spare LV (%u) in VG %s" , + lv_count, lv_visible_count, num_snapshots, + hidden_lv_count, spare_count, vg->name); r =0 ; }
lib/metadata/snapshot_manip.c +2 -1
@@ -75,7 +75,8 @@ int lv_is_cow_covering_origin(const struct logical_volume *lv)int lv_is_visible (const struct logical_volume *lv) { -if (lv->status &SNAPSHOT ) +/* spare LV is implicitely invisible */ +if (lv->status & (SNAPSHOT |SPARE_LV ))return 0 ;if (lv_is_cow (lv)) {
lib/metadata/vg.h +2 -0
@@ -20,6 +20,7 @@ struct dm_pool;struct format_instance ;struct dm_list ;struct id ; +struct logical_volume ; typedef enum { ALLOC_INVALID,
@@ -120,6 +121,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 *spare;/* pointer for spare LV in this VG */ }; struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
Signature · 1 line
1.8.2.1
PATCH 2/6 thin: report spare as 'e' volume type
In reply to Zdenek KabelacReuse m'e'tadata volume type as spar'e'
since essentially they are related and there is no big reason to introduce new flag - but of course we may use some other letters.
--- lib/metadata/lv.c | 1 + 1 file changed, 1 insertion(+)
lib/metadata/lv.c +1 -0
@@ -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_spare (lv) || (lv->status &RAID_META )) repstr[0 ] ='e' ;else if (lv->status &RAID )
Signature · 1 line
1.8.2.1
PATCH 3/6 thin: removal of spare disables recovery
In reply to Zdenek KabelacWarn user when removing spare LV.
--- lib/metadata/lv_manip.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
lib/metadata/lv_manip.c +19 -0
@@ -3623,6 +3623,7 @@ 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;if (lv_is_cow (lv)) {
@@ -3681,6 +3682,24 @@ 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->spare) { + dm_list_iterate_items(lvl, &lv->vg->lvs) +if (lv_is_thin_pool (lvl->lv) && lvl->lv != lv) +break ; + +if ((!lv_is_thin_pool (lvl->lv) || lvl->lv == lv) && + !lv_remove_with_dependencies (cmd, lv->vg->spare, force, level +1 )) + return_0; + } + +if (lv_is_spare (lv) && + (force ==PROMPT ) && + (yes_no_prompt ("Removal of spare logical volume \"%s\" disables thin pool recovery. " +"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.2.1
PATCH 4/6 thin: lvchange spare lv manipulation
In reply to Zdenek KabelacAllow lvchange of spare flag for an LV.
--- tools/args.h | 1 + tools/commands.h | 5 ++-- tools/lvchange.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 3 deletions(-)
tools/args.h +1 -0
@@ -76,6 +76,7 @@ arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0) arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0) arg(discards_ARG, '\0', "discards", discards_arg, 0) arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE) +arg(spare_ARG, '\0', "spare", yes_no_arg, 0) arg(stripes_long_ARG, '\0', "stripes", int_arg, 0) arg(sysinit_ARG, '\0', "sysinit", NULL, 0)arg (thinpool_ARG,'\0' ,"thinpool" , string_arg,0 )
tools/commands.h +3 -2
@@ -92,6 +92,7 @@ xx(lvchange,"\t[-r|--readahead ReadAheadSectors|auto|none]\n" "\t[--refresh]\n" "\t[--resync]\n" +"\t[--spare {y|n}]\n" "\t[--syncaction {check|repair}\n" "\t[--sysinit]\n" "\t[-t|--test]\n"
@@ -106,8 +107,8 @@ xx(lvchange, alloc_ARG, autobackup_ARG, activate_ARG, available_ARG, contiguous_ARG, discards_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, + noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG, + poll_ARG, readahead_ARG, resync_ARG, spare_ARG, refresh_ARG, addtag_ARG, deltag_ARG, syncaction_ARG, sysinit_ARG, test_ARG, writebehind_ARG, writemostly_ARG, zero_ARG)
tools/lvchange.c +85 -1
110 lines not on this page · raw message
Signature · 1 line
1.8.2.1
PATCH 5/6 thin: add spare lvcreate support
In reply to Zdenek KabelacAdd --spare option and create and hanle spare lv
when thin pool is created.
--- lib/metadata/metadata-exported.h | 1 + tools/commands.h | 10 +++-- tools/lvcreate.c | 83 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 6 deletions(-)
lib/metadata/metadata-exported.h +1 -0
@@ -615,6 +615,7 @@ struct lvcreate_params {int minor;/* all */ int log_count;/* mirror */ int nosync;/* mirror */ +int spare;/* thin pool */ activation_change_t activate;/* non-snapshot, non-mirror */ thin_discards_t discards;/* thin */
tools/commands.h +6 -4
@@ -208,6 +208,7 @@ xx(lvcreate,"\t[-T|--thin [-c|--chunksize ChunkSize]\n" "\t [--discards {ignore|nopassdown|passdown}]\n" "\t [--poolmetadatasize MetadataSize[bBsSkKmMgG]]]\n" +"\t [--spare {y|n}]\n" "\t[--thinpool ThinPoolLogicalVolume{Name|Path}]\n" "\t[-t|--test]\n" "\t[--type VolumeType]\n"
@@ -251,10 +252,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, + readahead_ARG, regionsize_ARG, + size_ARG, snapshot_ARG, spare_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 +81 -2
114 lines not on this page · raw message
Signature · 1 line
1.8.2.1
PATCH 6/6 thin: unfinished lvconvert
In reply to Zdenek Kabelacbegining of lvconvert support for spare LV.
will match what can be made in lvcreate.
--- tools/commands.h | 3 ++- tools/lvconvert.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-)
tools/commands.h +2 -1
@@ -166,6 +166,7 @@ xx(lvconvert,"\t[--poolmetadata ThinMetadataLogicalVolume[Path] |\n" "\t [--poolmetadatasize size]\n" "\t [-r|--readahead ReadAheadSectors|auto|none]\n" +"\t [--spare {y|n}]\n" "\t [--stripes Stripes [-I|--stripesize StripeSize]]]\n" "\t[-T|--thin ExternalLogicalVolume[Path]\n" "\t [--originname NewExternalOriginVolumeName]]\n"
@@ -177,7 +178,7 @@ xx(lvconvert, 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, + originname_ARG, spare_ARG, thin_ARG, thinpool_ARG, use_policies_ARG, force_ARG, zero_ARG) xx(lvcreate,
tools/lvconvert.c +2 -0
@@ -22,6 +22,7 @@ struct lvconvert_params {int snapshot;int merge;int merge_mirror; +int spare;int thin;int yes;int zero;
@@ -495,6 +496,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd, return_0; } + lp->spare =arg_uint_value (cmd, spare_ARG,0 ); lp->force =arg_count (cmd, force_ARG); lp->yes =arg_count (cmd, yes_ARG);
Signature · 1 line
1.8.2.1