master - thin: add pool metadata spare lv support
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=460d0254ebc7df...
Commit: 460d0254ebc7df514081997a12238a88e8b203c6
Parent: 08df7ba844f837c4a09540feadaa734d7f3259f8
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Jul 5 17:10:47 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
thin: add pool metadata spare lv support
Add support for pool's metadata spare volume.
---
WHATS_NEW | 1 +
lib/format_text/flags.c | 1 +
lib/format_text/import_vsn1.c | 12 ++++++
lib/metadata/metadata-exported.h | 8 +++-
lib/metadata/metadata.c | 21 +++++++++++
lib/metadata/thin_manip.c | 72 ++++++++++++++++++++++++++++++++++++++
lib/metadata/vg.h | 4 ++-
lib/misc/lvm-string.c | 1 +
tools/args.h | 1 +
9 files changed, 118 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index f9cfa01..e87f781 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Add support for poolmetadataspare LV, that will be used for pool recovery.
Improve activation order when creating thin pools in non-clustered VG.
List thin-pool and thin modules for thin volumes.
Correct thin creation error paths.
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index 66dd86b..5077576 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -61,6 +61,7 @@ static const struct flag _lv_flags[] = {
{LV_REBUILD, "REBUILD", STATUS_FLAG},
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_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 f667139..65999cd 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -97,10 +97,11 @@
#define THIN_POOL UINT64_C(0x0000002000000000) /* LV */
#define THIN_POOL_DATA UINT64_C(0x0000004000000000) /* LV */
#define THIN_POOL_METADATA UINT64_C(0x0000008000000000) /* LV */
+#define POOL_METADATA_SPARE UINT64_C(0x0000010000000000) /* LV internal */
-#define LV_WRITEMOSTLY UINT64_C(0x0000010000000000) /* LV (RAID1) */
+#define LV_WRITEMOSTLY UINT64_C(0x0000020000000000) /* LV (RAID1) */
-#define LV_ACTIVATION_SKIP UINT64_C(0x0000020000000000) /* LV */
+#define LV_ACTIVATION_SKIP UINT64_C(0x0000040000000000) /* LV */
/* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
@@ -160,6 +161,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 {
@@ -665,6 +667,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);
int attach_thin_external_origin(struct lv_segment *seg,
struct logical_volume *external_lv);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index c8d35c9..ddcf0a5 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2293,6 +2293,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) {
@@ -2472,6 +2473,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);
@@ -2524,6 +2538,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 adb0a25..9ee8a55 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -727,3 +727,75 @@ 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 \"%s/%s\" to \"%s/%s\".",
+ vg->name, lv->name, vg->name, 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..5cc5f6d 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -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",
diff --git a/tools/args.h b/tools/args.h
index cde0f91..bac507c 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)
9 years, 10 months
master - thin: improve pool creation activation order
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=08df7ba844f837...
Commit: 08df7ba844f837c4a09540feadaa734d7f3259f8
Parent: 4e724f5f52e3f641d1ccc5a90d0af2ad73a52a8d
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jul 18 16:44:39 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
thin: improve pool creation activation order
Pool creation involves clearing of metadata device
which triggers udev watch rule we cannot udev synchronize with
in current code.
This metadata devices needs to be activated localy,
so in cluster mode deactivation and reactivation
is always needed.
However for non-clustered mode we may reload table
via suspend/resume path which avoids collision with
udev watch rule which was occasionaly triggering
retry deactivation loop.
Code has been also split into 2 separate code paths
for thin pools and thin volumes which improved readability
of the code as well.
Deactivation has been moved out of extend_pool() and
decision is now in _lv_create_an_lv() which knows
the change mode.
---
WHATS_NEW | 1 +
lib/metadata/lv_manip.c | 57 +++++++++++++++++++++++++++++++++++++--------
lib/metadata/thin_manip.c | 8 +-----
3 files changed, 49 insertions(+), 17 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index f49c71c..f9cfa01 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Improve activation order when creating thin pools in non-clustered VG.
List thin-pool and thin modules for thin volumes.
Correct thin creation error paths.
Use local activation for clearing snapshot COW device.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 2bfd65e..42a5f1e 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5701,6 +5701,19 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
lp->activate = CHANGE_AN;
}
+ /*
+ * For thin pools - deactivate when inactive pool is requested or
+ * for cluster give-up local lock and take proper exlusive lock
+ */
+ if (lv_is_thin_pool(lv) &&
+ (!is_change_activating(lp->activate) ||
+ vg_is_clustered(lv->vg)) &&
+ /* Deactivates cleared metadata LV */
+ !deactivate_lv(lv->vg->cmd, lv)) {
+ stack;
+ goto deactivate_failed;
+ }
+
/* store vg on disk(s) */
if (!vg_write(vg) || !vg_commit(vg))
return_NULL;
@@ -5712,7 +5725,32 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
goto out;
}
- if (seg_is_thin(lp)) {
+ if (lv_is_thin_pool(lv)) {
+ if (is_change_activating(lp->activate)) {
+ if (vg_is_clustered(lv->vg)) {
+ if (!activate_lv_excl(cmd, lv)) {
+ log_error("Failed to activate pool %s.", lv->name);
+ goto deactivate_and_revert_new_lv;
+ }
+ } else {
+ /*
+ * Suspend cleared plain metadata LV
+ * but now already commited as pool LV
+ * and resume it as a pool LV.
+ *
+ * This trick avoids collision with udev watch rule.
+ */
+ if (!suspend_lv(cmd, lv)) {
+ log_error("Failed to suspend pool %s.", lv->name);
+ goto deactivate_and_revert_new_lv;
+ }
+ if (!resume_lv(cmd, lv)) {
+ log_error("Failed to resume pool %s.", lv->name);
+ goto deactivate_and_revert_new_lv;
+ }
+ }
+ }
+ } else if (lv_is_thin_volume(lv)) {
/* For snapshot, suspend active thin origin first */
if (org && lv_is_active(org) && lv_is_thin_volume(org)) {
if (!suspend_lv_origin(cmd, org)) {
@@ -5731,16 +5769,14 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
goto revert_new_lv;
}
}
- if ((lp->activate != CHANGE_AN) && (lp->activate != CHANGE_ALN)) {
- /* At this point send message to kernel thin mda */
- pool_lv = lv_is_thin_pool(lv) ? lv : first_seg(lv)->pool_lv;
- if (!update_pool_lv(pool_lv, 1)) {
+ if (is_change_activating(lp->activate)) {
+ /* Send message so that table preload knows new thin */
+ if (!update_pool_lv(first_seg(lv)->pool_lv, 1)) {
stack;
- goto deactivate_and_revert_new_lv;
+ goto revert_new_lv;
}
if (!activate_lv_excl(cmd, lv)) {
- log_error("Aborting. Failed to activate thin %s.",
- lv->name);
+ log_error("Failed to activate thin %s.", lv->name);
goto deactivate_and_revert_new_lv;
}
}
@@ -5838,8 +5874,9 @@ out:
deactivate_and_revert_new_lv:
if (!deactivate_lv(cmd, lv)) {
- log_error("Unable to deactivate failed new LV. "
- "Manual intervention required.");
+deactivate_failed:
+ log_error("Unable to deactivate failed new LV \"%s/%s\". "
+ "Manual intervention required.", lv->vg->name, lv->name);
return NULL;
}
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 8724845..adb0a25 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -473,13 +473,7 @@ int extend_pool(struct logical_volume *pool_lv, const struct segment_type *segty
!set_lv(pool_lv->vg->cmd, pool_lv, UINT64_C(0), 0)) {
log_error("Aborting. Failed to wipe pool metadata %s.",
pool_lv->name);
- return 0;
- }
-
- if (!deactivate_lv_local(pool_lv->vg->cmd, pool_lv)) {
- log_error("Aborting. Could not deactivate pool metadata %s.",
- pool_lv->name);
- return 0;
+ goto bad;
}
} else {
log_warn("WARNING: Pool %s is created without initialization.", pool_lv->name);
9 years, 10 months
master - thin: for thin volumes properly list modules
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=4e724f5f52e3f6...
Commit: 4e724f5f52e3f641d1ccc5a90d0af2ad73a52a8d
Parent: d72f34af418b90c71e8e96f408d4953e679e0895
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jul 18 16:06:26 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
thin: for thin volumes properly list modules
thin volume needs thin-pool and thin kernel modules so print them
both for lvs -o+modules
---
WHATS_NEW | 1 +
lib/thin/thin.c | 38 ++++++++++++++++++++++++++++----------
test/shell/lvcreate-thin.sh | 2 +-
3 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 7b2c2d0..f49c71c 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ List thin-pool and thin modules for thin volumes.
Correct thin creation error paths.
Use local activation for clearing snapshot COW device.
Add lvm2-activation-net systemd unit to activate LVs on net-attached storage.
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index 9bc9e4d..520a3d2 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -27,7 +27,8 @@
#endif
/* Dm kernel module name for thin provisiong */
-#define THIN_MODULE "thin-pool"
+static const char _thin_pool_module[] = "thin-pool";
+static const char _thin_module[] = "thin";
/*
* Macro used as return argument - returns 0.
@@ -376,6 +377,18 @@ static int _thin_pool_target_percent(void **target_state __attribute__((unused))
return 1;
}
+static int _thin_pool_modules_needed(struct dm_pool *mem,
+ const struct lv_segment *seg __attribute__((unused)),
+ struct dm_list *modules)
+{
+ if (!str_list_add(mem, modules, _thin_pool_module)) {
+ log_error("String list allocation failed for thin_pool.");
+ return 0;
+ }
+
+ return 1;
+}
+
# ifdef DMEVENTD
static const char *_get_thin_dso_path(struct cmd_context *cmd)
{
@@ -581,10 +594,10 @@ static int _thin_target_present(struct cmd_context *cmd,
const char *str;
if (!_checked) {
- _present = target_present(cmd, THIN_MODULE, 1);
+ _present = target_present(cmd, _thin_pool_module, 1);
- if (!target_version(THIN_MODULE, &maj, &min, &patchlevel)) {
- log_error("Cannot read " THIN_MODULE " target version.");
+ if (!target_version(_thin_pool_module, &maj, &min, &patchlevel)) {
+ log_error("Cannot read %s target version.", _thin_pool_module);
return 0;
}
@@ -592,7 +605,8 @@ static int _thin_target_present(struct cmd_context *cmd,
if (maj >= _features[i].maj && min >= _features[i].min)
_attrs |= _features[i].thin_feature;
else
- log_very_verbose("Target " THIN_MODULE " does not support %s.",
+ log_very_verbose("Target %s does not support %s.",
+ _thin_pool_module,
_features[i].feature);
_checked = 1;
@@ -623,7 +637,8 @@ static int _thin_target_present(struct cmd_context *cmd,
for (i = 0; i < sizeof(_features)/sizeof(*_features); i++)
if ((_attrs & _features[i].thin_feature) &&
!(_feature_mask & _features[i].thin_feature))
- log_very_verbose("Target "THIN_MODULE " %s support disabled by %s",
+ log_very_verbose("Target %s %s support disabled by %s",
+ _thin_pool_module,
_features[i].feature, _lvmconf);
}
*attributes = _attrs & _feature_mask;
@@ -634,11 +649,14 @@ static int _thin_target_present(struct cmd_context *cmd,
#endif
static int _thin_modules_needed(struct dm_pool *mem,
- const struct lv_segment *seg __attribute__((unused)),
+ const struct lv_segment *seg,
struct dm_list *modules)
{
- if (!str_list_add(mem, modules, THIN_MODULE)) {
- log_error("thin string list allocation failed");
+ if (!_thin_pool_modules_needed(mem, seg, modules))
+ return_0;
+
+ if (!str_list_add(mem, modules, _thin_module)) {
+ log_error("String list allocation failed for thin.");
return 0;
}
@@ -665,7 +683,7 @@ static struct segtype_handler _thin_pool_ops = {
.target_unmonitor_events = _target_unregister_events,
# endif /* DMEVENTD */
#endif
- .modules_needed = _thin_modules_needed,
+ .modules_needed = _thin_pool_modules_needed,
.destroy = _thin_destroy,
};
diff --git a/test/shell/lvcreate-thin.sh b/test/shell/lvcreate-thin.sh
index 275c56f..2ae02ab 100644
--- a/test/shell/lvcreate-thin.sh
+++ b/test/shell/lvcreate-thin.sh
@@ -144,7 +144,7 @@ lvcreate --type snapshot $vg/lv1 --name lv6
lvcreate --type snapshot $vg/lv1 --name lv4
lvcreate --type snapshot $vg/lv1 --name $vg/lv5
-check_lv_field_modules_ thin-pool lv1 snap_lv1 lv2 lv3 lv4 lv5 lv6
+check_lv_field_modules_ thin-pool,thin lv1 snap_lv1 lv2 lv3 lv4 lv5 lv6
check vg_field $vg lv_count 8
lvremove -ff $vg
9 years, 10 months
master - thin: fix error paths for metadata creation
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d72f34af418b90...
Commit: d72f34af418b90c71e8e96f408d4953e679e0895
Parent: 7afa9cebcbce0232c0c889cb3f112f66d10a79b0
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jul 18 16:01:38 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
thin: fix error paths for metadata creation
Since we vg_write&commit metadata LV inside lv_extend() call,
proper restore is needed in case something fails.
So add bad: section which deactivates activated LV
and removes it from VG.
Also check early for metadata LV name lengh fail.
---
lib/metadata/thin_manip.c | 36 +++++++++++++++++++++++++-----------
1 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 4f6e2ec..8724845 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -433,8 +433,7 @@ int extend_pool(struct logical_volume *pool_lv, const struct segment_type *segty
const struct segment_type *striped;
struct logical_volume *meta_lv, *data_lv;
struct lv_segment *seg;
- const size_t len = strlen(pool_lv->name) + 16;
- char name[len];
+ char name[NAME_LEN];
if (pool_lv->le_count) {
/* FIXME move code for manipulation from lv_manip.c */
@@ -486,38 +485,53 @@ int extend_pool(struct logical_volume *pool_lv, const struct segment_type *segty
log_warn("WARNING: Pool %s is created without initialization.", pool_lv->name);
}
- if (dm_snprintf(name, len, "%s_tmeta", pool_lv->name) < 0)
- return_0;
+ if (dm_snprintf(name, sizeof(name), "%s_tmeta", pool_lv->name) < 0) {
+ log_error("Name is too long to be a pool name.");
+ goto bad;
+ }
if (!(meta_lv = lv_create_empty(name, NULL, LVM_READ | LVM_WRITE,
ALLOC_INHERIT, pool_lv->vg)))
- return_0;
+ goto_bad;
if (!move_lv_segments(meta_lv, pool_lv, 0, 0))
- return_0;
+ goto_bad;
/* Pool data segment */
if (!lv_add_segment(ah, 0, stripes, pool_lv, striped, stripe_size, 0, 0))
- return_0;
+ goto_bad;
if (!(data_lv = insert_layer_for_lv(pool_lv->vg->cmd, pool_lv,
pool_lv->status, "_tdata")))
- return_0;
+ goto_bad;
seg = first_seg(pool_lv);
seg->segtype = segtype; /* Set as thin_pool segment */
seg->lv->status |= THIN_POOL;
if (!attach_pool_metadata_lv(seg, meta_lv))
- return_0;
+ goto_bad;
/* Drop reference as attach_pool_data_lv() takes it again */
if (!remove_seg_from_segs_using_this_lv(data_lv, seg))
- return_0;
+ goto_bad;
if (!attach_pool_data_lv(seg, data_lv))
- return_0;
+ goto_bad;
return 1;
+bad:
+ if (activation()) {
+ if (deactivate_lv_local(pool_lv->vg->cmd, pool_lv)) {
+ log_error("Aborting. Could not deactivate pool %s.",
+ pool_lv->name);
+ return 0;
+ }
+ if (!lv_remove(pool_lv) || !vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg))
+ log_error("Manual intervention may be required to remove "
+ "abandoned LV(s) before retrying.");
+ }
+
+ return 0;
}
int update_pool_lv(struct logical_volume *lv, int activate)
9 years, 10 months
master - thin: fix error path in creation path
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7afa9cebcbce02...
Commit: 7afa9cebcbce0232c0c889cb3f112f66d10a79b0
Parent: 1d3f7953bda1826fb5eb957ae6dcefc9285454a1
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Jul 17 15:26:41 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
thin: fix error path in creation path
Remove some calls to revert_new_lv when no LV has been created/commited so far.
When the pool update failed - then only revert is needed.
---
WHATS_NEW | 1 +
lib/metadata/lv_manip.c | 20 +++++++-------------
2 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 641fd53..7b2c2d0 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Correct thin creation error paths.
Use local activation for clearing snapshot COW device.
Add lvm2-activation-net systemd unit to activate LVs on net-attached storage.
Release memory allocated with _cached_info().
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index a5c0d73..2bfd65e 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5646,10 +5646,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
} else if (seg_is_thin_volume(lp)) {
pool_lv = first_seg(lv)->pool_lv;
if (!(first_seg(lv)->device_id =
- get_free_pool_device_id(first_seg(pool_lv)))) {
- stack;
- goto revert_new_lv;
- }
+ get_free_pool_device_id(first_seg(pool_lv))))
+ return_NULL;
/*
* Check if using 'external origin' or the 'normal' snapshot
* within the same thin pool
@@ -5663,17 +5661,13 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
log_error("Cannot use active LV for the external origin.");
return 0; // We can't be sure device is read-only
}
- if (!attach_thin_external_origin(first_seg(lv), org)) {
- stack;
- goto revert_new_lv;
- }
+ if (!attach_thin_external_origin(first_seg(lv), org))
+ return_NULL;
}
if (!attach_pool_message(first_seg(pool_lv),
- DM_THIN_MESSAGE_CREATE_THIN, lv, 0, 0)) {
- stack;
- goto revert_new_lv;
- }
+ DM_THIN_MESSAGE_CREATE_THIN, lv, 0, 0))
+ return_NULL;
} else if (seg_is_raid(lp)) {
first_seg(lv)->min_recovery_rate = lp->min_recovery_rate;
first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
@@ -5734,7 +5728,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
/* At this point remove pool messages, snapshot is active */
if (!update_pool_lv(first_seg(org)->pool_lv, 0)) {
stack;
- goto deactivate_and_revert_new_lv;
+ goto revert_new_lv;
}
}
if ((lp->activate != CHANGE_AN) && (lp->activate != CHANGE_ALN)) {
9 years, 10 months
master - lv_manip: move some validation code before archiving
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1d3f7953bda182...
Commit: 1d3f7953bda1826fb5eb957ae6dcefc9285454a1
Parent: 7b4b97b731053ab2780d5ffdce5fc1c3e0626c2a
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Jul 17 14:52:21 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
lv_manip: move some validation code before archiving
Make as much test we can, before actualy modifying metadata.
Avoids also unnecessary archiving.
---
lib/metadata/lv_manip.c | 65 ++++++++++++++++++++++++-----------------------
1 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 2e34a49..a5c0d73 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5355,6 +5355,21 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
return NULL;
}
+ if (vg_is_clustered(vg) && segtype_is_raid(lp->segtype)) {
+ /*
+ * FIXME:
+ * We could allow a RAID LV to be created as long as it
+ * is activated exclusively. Any subsequent activations
+ * would have to be enforced as exclusive also.
+ *
+ * For now, we disallow the existence of RAID LVs in a
+ * cluster VG
+ */
+ log_error("Unable to create a %s logical volume in a cluster.",
+ lp->segtype->name);
+ return NULL;
+ }
+
if ((segtype_is_mirrored(lp->segtype) ||
segtype_is_raid(lp->segtype) || segtype_is_thin(lp->segtype)) &&
!(vg->fid->fmt->features & FMT_SEGMENTS)) {
@@ -5540,9 +5555,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
!(lp->segtype = get_segtype_from_string(cmd, "striped")))
return_NULL;
- if (!archive(vg))
- return_NULL;
-
if (!dm_list_empty(&lp->tags)) {
if (!(vg->fid->fmt->features & FMT_TAGS)) {
log_error("Volume group %s does not support tags",
@@ -5551,6 +5563,9 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
}
}
+ if (!archive(vg))
+ return_NULL;
+
if (seg_is_thin_volume(lp)) {
/* Ensure all stacked messages are submitted */
if (!(lvl = find_lv_in_vg(vg, lp->pool))) {
@@ -5558,25 +5573,26 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
lp->pool, vg->name);
return NULL;
}
+
+ if (lv_is_active_locally(lvl->lv) &&
+ !pool_below_threshold(first_seg(lvl->lv))) {
+ log_error("Cannot create thin volume. Pool \"%s/%s\" "
+ "is filled over the autoextend threshold.",
+ lvl->lv->vg->name, lvl->lv->name);
+ return NULL;
+ }
+
if (lv_is_active(lvl->lv) ||
((lp->activate != CHANGE_AN) && (lp->activate != CHANGE_ALN)))
if (!update_pool_lv(lvl->lv, 1))
return_NULL;
- }
- if (vg_is_clustered(vg) && segtype_is_raid(lp->segtype)) {
- /*
- * FIXME:
- * We could allow a RAID LV to be created as long as it
- * is activated exclusively. Any subsequent activations
- * would have to be enforced as exclusive also.
- *
- * For now, we disallow the existence of RAID LVs in a
- * cluster VG
- */
- log_error("Unable to create a %s logical volume in a cluster.",
- lp->segtype->name);
- return NULL;
+ /* For thin snapshot we must have matching pool */
+ if (org && lv_is_thin_volume(org) && (!lp->pool ||
+ (strcmp(first_seg(org)->pool_lv->name, lp->pool) == 0)))
+ thin_name = org->name;
+ else
+ thin_name = lp->pool;
}
if (segtype_is_mirrored(lp->segtype) || segtype_is_raid(lp->segtype)) {
@@ -5613,15 +5629,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
dm_list_splice(&lv->tags, &lp->tags);
- if (seg_is_thin_volume(lp)) {
- /* For thin snapshot we must have matching pool */
- if (org && lv_is_thin_volume(org) && (!lp->pool ||
- (strcmp(first_seg(org)->pool_lv->name, lp->pool) == 0)))
- thin_name = org->name;
- else
- thin_name = lp->pool;
- }
-
if (!lv_extend(lv, lp->segtype,
lp->stripes, lp->stripe_size,
lp->mirrors,
@@ -5714,12 +5721,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
if (seg_is_thin(lp)) {
/* For snapshot, suspend active thin origin first */
if (org && lv_is_active(org) && lv_is_thin_volume(org)) {
- if (!pool_below_threshold(first_seg(first_seg(org)->pool_lv))) {
- log_error("Cannot create thin snapshot. Pool %s/%s is filled "
- "over the autoextend threshold.",
- org->vg->name, first_seg(org)->pool_lv->name);
- goto revert_new_lv;
- }
if (!suspend_lv_origin(cmd, org)) {
log_error("Failed to suspend thin snapshot origin %s/%s.",
org->vg->name, org->name);
9 years, 10 months
master - snapshot: local activation for clear COW device
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7b4b97b731053a...
Commit: 7b4b97b731053ab2780d5ffdce5fc1c3e0626c2a
Parent: b5dfe4bec2c5eb24559f650da47678ad1de527b6
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jul 18 16:20:48 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:43 2013 +0200
snapshot: local activation for clear COW device
To clear snapshot cow device in cluster enforce local
activation here.
---
WHATS_NEW | 1 +
lib/metadata/lv_manip.c | 2 +-
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index ae725bb..641fd53 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Use local activation for clearing snapshot COW device.
Add lvm2-activation-net systemd unit to activate LVs on net-attached storage.
Release memory allocated with _cached_info().
Add whole log_lv and metadata_lv sub volumes when creating partial tree.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 7815e53..2e34a49 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5750,7 +5750,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
}
}
} else if (lp->snapshot) {
- if (!activate_lv_excl(cmd, lv)) {
+ if (!activate_lv_local(cmd, lv)) {
log_error("Aborting. Failed to activate snapshot "
"exception store.");
goto revert_new_lv;
9 years, 10 months
master - metadata: add is_change_activating
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b5dfe4bec2c5eb...
Commit: b5dfe4bec2c5eb24559f650da47678ad1de527b6
Parent: e8fc77bd6d8986c5c289d4deaaab0120d646b077
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jul 18 16:17:23 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:42 2013 +0200
metadata: add is_change_activating
Add simple inline function to check, whether the change is activating.
(better then macro since we get type checking).
---
lib/metadata/metadata-exported.h | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b571847..f667139 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -689,6 +689,12 @@ typedef enum activation_change {
CHANGE_AAY = 5 /* automatic activation */
} activation_change_t;
+/* Returns true, when change activates device */
+static inline int is_change_activating(activation_change_t change)
+{
+ return ((change != CHANGE_AN) && (change != CHANGE_ALN));
+}
+
/* FIXME: refactor and reduce the size of this struct! */
struct lvcreate_params {
/* flags */
9 years, 10 months
master - cleanup: move detection of change mode before commit point
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e8fc77bd6d8986...
Commit: e8fc77bd6d8986c5c289d4deaaab0120d646b077
Parent: 20187fc190c248c556fdc44f5651eaa99219d2fb
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jul 18 16:25:16 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:42 2013 +0200
cleanup: move detection of change mode before commit point
Following patch will need to know change state before commit point.
Also the test mode should properly report all ongoing operation.
---
lib/metadata/lv_manip.c | 23 +++++++++++------------
1 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 0999bd0..7815e53 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5685,13 +5685,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
lv_set_activation_skip(lv, lp->activation_skip & ACTIVATION_SKIP_SET,
lp->activation_skip & ACTIVATION_SKIP_SET_ENABLED);
-
- /* store vg on disk(s) */
- if (!vg_write(vg) || !vg_commit(vg))
- return_NULL;
-
- backup(vg);
-
/*
* Check for autoactivation.
* If the LV passes the auto activation filter, activate
@@ -5701,17 +5694,23 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct l
lp->activate = lv_passes_auto_activation_filter(cmd, lv) ?
CHANGE_ALY : CHANGE_ALN;
- if (test_mode()) {
- log_verbose("Test mode: Skipping activation and zeroing.");
- goto out;
- }
-
if (lv_activation_skip(lv, lp->activate, lp->activation_skip & ACTIVATION_SKIP_IGNORE, 0)) {
log_verbose("ACTIVATION_SKIP flag set for LV %s/%s, skipping activation.",
lv->vg->name, lv->name);
lp->activate = CHANGE_AN;
}
+ /* store vg on disk(s) */
+ if (!vg_write(vg) || !vg_commit(vg))
+ return_NULL;
+
+ backup(vg);
+
+ if (test_mode()) {
+ log_verbose("Test mode: Skipping activation and zeroing.");
+ goto out;
+ }
+
if (seg_is_thin(lp)) {
/* For snapshot, suspend active thin origin first */
if (org && lv_is_active(org) && lv_is_thin_volume(org)) {
9 years, 10 months
master - cleanup: use dm_list_empty
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=20187fc190c248...
Commit: 20187fc190c248c556fdc44f5651eaa99219d2fb
Parent: 8bd67f9e5a3d53d78c83d7c554db300d6f82b97c
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Jul 17 14:49:21 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jul 18 18:22:42 2013 +0200
cleanup: use dm_list_empty
Check for empty list directly.
---
lib/format_text/archiver.c | 2 +-
lib/metadata/lv_manip.c | 2 +-
lib/metadata/metadata.c | 6 +++---
lib/metadata/pv_manip.c | 4 ++--
tools/toollib.c | 2 +-
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index 1e6dbac..b6b9fb3 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -430,7 +430,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
return 0;
}
- if (!dm_list_size(&tf->metadata_areas_in_use)) {
+ if (dm_list_empty(&tf->metadata_areas_in_use)) {
log_error(INTERNAL_ERROR "No in use metadata areas to write.");
tf->fmt->ops->destroy_instance(tf);
return 0;
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index e95deca..0999bd0 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -2411,7 +2411,7 @@ int lv_add_segment(struct alloc_handle *ah,
return 0;
}
- if ((status & MIRROR_LOG) && dm_list_size(&lv->segments)) {
+ if ((status & MIRROR_LOG) && !dm_list_empty(&lv->segments)) {
log_error("Log segments can only be added to an empty LV");
return 0;
}
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 96e1355..c8d35c9 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1339,7 +1339,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
* this means checking every VG by scanning every PV on the
* system.
*/
- if (pv && is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use)) {
+ if (pv && is_orphan(pv) && dm_list_empty(&pv->fid->metadata_areas_in_use)) {
free_pv_fid(pv);
if (!scan_vgs_for_pvs(cmd, 0))
return_0;
@@ -1831,7 +1831,7 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
goto bad;
}
- if (is_orphan_vg(pv->vg_name) && !dm_list_size(&pv->fid->metadata_areas_in_use)) {
+ if (is_orphan_vg(pv->vg_name) && dm_list_empty(&pv->fid->metadata_areas_in_use)) {
/* If a PV has no MDAs - need to search all VGs for it */
if (!scan_vgs_for_pvs(cmd, 1))
goto_bad;
@@ -4527,7 +4527,7 @@ int mdas_empty_or_ignored(struct dm_list *mdas)
{
struct metadata_area *mda;
- if (!dm_list_size(mdas))
+ if (dm_list_empty(mdas))
return 1;
dm_list_iterate_items(mda, mdas) {
if (mda_is_ignored(mda))
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index 2b16206..fb29ef4 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -687,8 +687,8 @@ static int pvremove_check(struct cmd_context *cmd, const char *name,
* means checking every VG by scanning every
* PV on the system.
*/
- if (is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use) &&
- !dm_list_size(&pv->fid->metadata_areas_ignored)) {
+ if (is_orphan(pv) && dm_list_empty(&pv->fid->metadata_areas_in_use) &&
+ dm_list_empty(&pv->fid->metadata_areas_ignored)) {
if (!scan_vgs_for_pvs(cmd, 0)) {
log_error("Rescan for PVs without metadata areas "
"failed.");
diff --git a/tools/toollib.c b/tools/toollib.c
index 5db537f..ce449e7 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -770,7 +770,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
* PV on the system.
*/
if (!scanned && is_orphan(pv) &&
- !dm_list_size(&pv->fid->metadata_areas_in_use)) {
+ dm_list_empty(&pv->fid->metadata_areas_in_use)) {
if (!scan_label_only &&
!scan_vgs_for_pvs(cmd, 1)) {
stack;
9 years, 10 months