* [PATCH 0/6] spare LV support
@ 2013-06-25 11:56 Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 1/6] thin: add spare lv support Zdenek Kabelac
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 UTC (permalink / raw)
To: lvm-devel
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(-)
--
1.8.2.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/6] thin: add spare lv support
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
@ 2013-06-25 11:56 ` Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 2/6] thin: report spare as 'e' volume type Zdenek Kabelac
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 UTC (permalink / raw)
To: lvm-devel
Add support for SPARE volume.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
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(-)
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index 28a7dc4..6d15d20 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -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},
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 852f2c5..d9f05c9 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -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;
}
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 10aea9e..453b98b 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -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 {
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 8a98aa6..ecedbdc 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -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;
}
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
index e0d2f5b..6da592e 100644
--- a/lib/metadata/snapshot_manip.c
+++ b/lib/metadata/snapshot_manip.c
@@ -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)) {
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index 0dc3ba7..dc5bb12 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,
@@ -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,
--
1.8.2.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] thin: report spare as 'e' volume type
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 1/6] thin: add spare lv support Zdenek Kabelac
@ 2013-06-25 11:56 ` Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 3/6] thin: removal of spare disables recovery Zdenek Kabelac
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 UTC (permalink / raw)
To: lvm-devel
Reuse 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.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/metadata/lv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 6215e1a..b95d0a3 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_spare(lv) ||
(lv->status & RAID_META))
repstr[0] = 'e';
else if (lv->status & RAID)
--
1.8.2.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] thin: removal of spare disables recovery
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 1/6] thin: add spare lv support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 2/6] thin: report spare as 'e' volume type Zdenek Kabelac
@ 2013-06-25 11:56 ` Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 4/6] thin: lvchange spare lv manipulation Zdenek Kabelac
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 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 | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 8acca49..f0fad05 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -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);
}
--
1.8.2.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] thin: lvchange spare lv manipulation
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
` (2 preceding siblings ...)
2013-06-25 11:56 ` [PATCH 3/6] thin: removal of spare disables recovery Zdenek Kabelac
@ 2013-06-25 11:56 ` Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 5/6] thin: add spare lvcreate support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 6/6] thin: unfinished lvconvert Zdenek Kabelac
5 siblings, 0 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 UTC (permalink / raw)
To: lvm-devel
Allow lvchange of spare flag for an LV.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
tools/args.h | 1 +
tools/commands.h | 5 ++--
tools/lvchange.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/tools/args.h b/tools/args.h
index 2fed97e..b8d0ad6 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -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)
diff --git a/tools/commands.h b/tools/commands.h
index 2d99d5a..ca29b81 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -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)
diff --git a/tools/lvchange.c b/tools/lvchange.c
index c88d8ef..f7fcf44 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -101,6 +101,77 @@ 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, spare_ARG, 0);
+
+ if (lv_is_active(lv)) {
+ log_error("Cannot change spare for active logical volume \"%s\".",
+ lv->name);
+ return 0;
+ }
+
+ if (spare) {
+ if (lv_is_spare(lv)) {
+ log_error("Logical volume \"%s\" is already spare volume.",
+ lv->name);
+ return 0;
+ }
+
+ if (!(lv->status & LVM_WRITE)) {
+ log_error("Cannot use read-only logical volume \"%s\" for spare.",
+ lv->name);
+ return 0;
+ }
+
+ if (!lv_is_visible(lv)) {
+ log_error("Cannot use invisible logical volume \"%s\" for 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 spare.",
+ lv->name, display_size(lv->vg->cmd, max_size));
+ return 0;
+ }
+
+ if (lv->vg->spare) {
+ log_print_unless_silent("Replacing spare logical volume \"%s\".",
+ lv->vg->spare->name);
+ lv->vg->spare->status &= ~SPARE_LV;
+ }
+
+ lv->vg->spare = lv;
+ lv->status |= SPARE_LV;
+ } else {
+ if (!lv_is_spare(lv)) {
+ log_error("Logical volume \"%s\" is not a spare volume.",
+ lv->name);
+ return 0;
+ }
+
+ lv->vg->spare = NULL;
+ lv->status &= ~SPARE_LV;
+ }
+
+ 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)
{
@@ -930,7 +1001,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_spare(lv) &&
+ !lv_is_virtual_origin(lv)) {
log_error("Unable to change internal LV %s directly",
lv->name);
return ECMD_FAILED;
@@ -997,6 +1070,16 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
}
}
+ if (arg_count(cmd, spare_ARG)) {
+ if (!archived && !archive(lv->vg)) {
+ stack;
+ return ECMD_FAILED;
+ }
+ archived = 1;
+ doit += lvchange_spare(cmd, lv);
+ docmds++;
+ }
+
if (arg_count(cmd, discards_ARG) ||
arg_count(cmd, zero_ARG)) {
if (!archived && !archive(lv->vg)) {
@@ -1120,6 +1203,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, spare_ARG) ||
arg_count(cmd, persistent_ARG) ||
arg_count(cmd, addtag_ARG) ||
arg_count(cmd, deltag_ARG);
--
1.8.2.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] thin: add spare lvcreate support
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
` (3 preceding siblings ...)
2013-06-25 11:56 ` [PATCH 4/6] thin: lvchange spare lv manipulation Zdenek Kabelac
@ 2013-06-25 11:56 ` Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 6/6] thin: unfinished lvconvert Zdenek Kabelac
5 siblings, 0 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 UTC (permalink / raw)
To: lvm-devel
Add --spare option and create and hanle spare lv
when thin pool is created.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/metadata/metadata-exported.h | 1 +
tools/commands.h | 10 +++--
tools/lvcreate.c | 83 +++++++++++++++++++++++++++++++++++++++-
3 files changed, 88 insertions(+), 6 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 453b98b..a368dca 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -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 */
diff --git a/tools/commands.h b/tools/commands.h
index ca29b81..d1cef36 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -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",
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 80ca1bc..a149c64 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,12 @@ static int _lvcreate_params(struct lvcreate_params *lp,
return 0;
}
+ if (lp->create_thin_pool) {
+ lp->spare = arg_uint_value(cmd, spare_ARG, 1); /* TODO: lvm.conf default */
+ } else if (arg_count(cmd, spare_ARG)) {
+ log_error("--spare is only available with thin pool creation.");
+ return 0;
+ }
/*
* Allocation parameters
*/
@@ -945,6 +951,7 @@ static int _check_thin_parameters(struct volume_group *vg, struct lvcreate_param
contiguous_ARG,
discards_ARG,
poolmetadatasize_ARG,
+ spare_ARG,
stripes_ARG,
stripesize_ARG,
zero_ARG
@@ -1043,6 +1050,71 @@ static int _validate_internal_thin_processing(const struct lvcreate_params *lp)
return r;
}
+/* Create spare LV */
+static int _handle_spare(struct volume_group *vg, uint32_t extents,
+ struct dm_list *pvh)
+{
+ struct logical_volume *lv = vg->spare;
+ uint32_t seg_mirrors;
+ struct lv_segment *seg;
+ struct lvcreate_params lp = {
+ .activate = CHANGE_ALY,
+ .alloc = ALLOC_INHERIT,
+ .extents = extents,
+ .lv_name = "spare_%d",
+ .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;
+
+ /* vg_write & vg_commit with pool creation */
+ /* FIXME: resolve archive */
+ if (lv) {
+ seg = last_seg(lv);
+ seg_mirrors = lv_mirror_count(lv);
+
+ /* Check spare 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;
+ }
+
+ /* FIXME: Maybe using silent mode ? */
+ if (!(lv = lv_create_single(vg, &lp)))
+ return_0;
+
+ /* no need to keep active */
+ if (!deactivate_lv(vg->cmd, lv)) {
+ log_error("Unable to deactivate spare LV. "
+ "Manual intervention required.");
+ return 0;
+ }
+
+ lv->status |= SPARE_LV;
+ vg->spare = lv;
+
+ return 1;
+}
+
int lvcreate(struct cmd_context *cmd, int argc, char **argv)
{
int r = ECMD_PROCESSED;
@@ -1090,9 +1162,16 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
goto_out;
}
- if (lp.create_thin_pool)
+ if (lp.create_thin_pool) {
+ if (!lp.spare)
+ log_warn("WARNING: recovery without spare LV for "
+ "pool %s is not automated.", lp.pool);
+ else if (!_handle_spare(vg, lp.poolmetadataextents, lp.pvh))
+ return_0;
+
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.2.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] thin: unfinished lvconvert
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
` (4 preceding siblings ...)
2013-06-25 11:56 ` [PATCH 5/6] thin: add spare lvcreate support Zdenek Kabelac
@ 2013-06-25 11:56 ` Zdenek Kabelac
5 siblings, 0 replies; 7+ messages in thread
From: Zdenek Kabelac @ 2013-06-25 11:56 UTC (permalink / raw)
To: lvm-devel
begining of lvconvert support for spare LV.
will match what can be made in lvcreate.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
tools/commands.h | 3 ++-
tools/lvconvert.c | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/commands.h b/tools/commands.h
index d1cef36..b1e5544 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -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,
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index be6b55f..7ee3d4b 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -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);
--
1.8.2.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-06-25 11:56 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-25 11:56 [PATCH 0/6] spare LV support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 1/6] thin: add spare lv support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 2/6] thin: report spare as 'e' volume type Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 3/6] thin: removal of spare disables recovery Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 4/6] thin: lvchange spare lv manipulation Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 5/6] thin: add spare lvcreate support Zdenek Kabelac
2013-06-25 11:56 ` [PATCH 6/6] thin: unfinished lvconvert 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.