master - lvconvert: remove unused code
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=802ed9d4597443...
Commit: 802ed9d4597443e21086b392d9ee160f6d99dde9
Parent: 2282f53ac73d33311661226894ee90e72772f0db
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Jun 29 16:59:32 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Jun 29 16:59:32 2016 -0500
lvconvert: remove unused code
This code became unused with the previous commit 2282f5.
---
tools/lvconvert.c | 221 -----------------------------------------------------
1 files changed, 0 insertions(+), 221 deletions(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 1a863a4..4808090 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2023,68 +2023,6 @@ static int _lvconvert_split_cached(struct cmd_context *cmd,
return 1;
}
-#if 0
-static int _lvconvert_splitcache(struct cmd_context *cmd,
- struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- struct lv_segment *seg;
-
- if (lv_is_thin_pool(lv))
- lv = seg_lv(first_seg(lv), 0); /* cached _tdata ? */
-
- /* When passed used cache-pool of used cached LV -> split cached LV */
- if (lv_is_cache_pool(lv) &&
- (dm_list_size(&lv->segs_using_this_lv) == 1) &&
- (seg = get_only_segment_using_this_lv(lv)) &&
- seg_is_cache(seg))
- lv = seg->lv;
-
- /* Supported LV types for split */
- if (!lv_is_cache(lv)) {
- log_error("Split of %s is not cache.", display_lvname(lv));
- return 0;
- }
-
- if (!_lvconvert_split_cached(cmd, lv))
- return_0;
-
- return 1;
-}
-#endif
-
-#if 0
-static int _lvconvert_split(struct cmd_context *cmd,
- struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- struct lv_segment *seg;
-
- if (lv_is_thin_pool(lv) &&
- lv_is_cache(seg_lv(first_seg(lv), 0)))
- lv = seg_lv(first_seg(lv), 0); /* cached _tdata ? */
-
- /* When passed used cache-pool of used cached LV -> split cached LV */
- if (lv_is_cache_pool(lv) &&
- (dm_list_size(&lv->segs_using_this_lv) == 1) &&
- (seg = get_only_segment_using_this_lv(lv)) &&
- seg_is_cache(seg))
- lv = seg->lv;
-
- /* Supported LV types for split */
- if (lv_is_cache(lv)) {
- if (!_lvconvert_split_cached(cmd, lv))
- return_0;
- /* Add more types here */
- } else {
- log_error("Split of %s is unsupported.", display_lvname(lv));
- return 0;
- }
-
- return 1;
-}
-#endif
-
static int _lvconvert_uncache(struct cmd_context *cmd,
struct logical_volume *lv,
struct lvconvert_params *lp)
@@ -3341,165 +3279,6 @@ static int _lvconvert_cache(struct cmd_context *cmd,
return 1;
}
-#if 0
-static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- struct logical_volume *origin = NULL;
- struct dm_list *failed_pvs;
-
- if (lv_is_locked(lv)) {
- log_error("Cannot convert locked LV %s.", display_lvname(lv));
- return ECMD_FAILED;
- }
-
- if (lv_is_cow(lv) && !lp->merge_snapshot && !lp->splitsnapshot) {
- log_error("Cannot convert snapshot logical volume %s.",
- display_lvname(lv));
- return ECMD_FAILED;
- }
-
- if (lv_is_pvmove(lv)) {
- log_error("Unable to convert pvmove LV %s.",
- display_lvname(lv));
- return ECMD_FAILED;
- }
-
- if (lp->splitsnapshot) {
- if (!_lvconvert_splitsnapshot(cmd, lv, lp))
- return_ECMD_FAILED;
- return ECMD_PROCESSED;
- }
-
- if (lp->splitcache) {
- if (!_lvconvert_splitcache(cmd, lv, lp))
- return_ECMD_FAILED;
- return ECMD_PROCESSED;
- }
-
- if (lp->split) {
- if (!_lvconvert_split(cmd, lv, lp))
- return_ECMD_FAILED;
- return ECMD_PROCESSED;
- }
-
- if (lp->uncache) {
- if (!_lvconvert_uncache(cmd, lv, lp))
- return_ECMD_FAILED;
- return ECMD_PROCESSED;
- }
-
- /* Validate origin prior we start conversion of pool */
- if (lp->cache &&
- !validate_lv_cache_create_origin(lv))
- return_ECMD_FAILED;
-
- if (lp->thin) {
- if (lv_is_cache_type(lv) ||
- lv_is_pool(lv) ||
- lv_is_thin_pool_data(lv) ||
- lv_is_thin_pool_metadata(lv)) {
- log_error("Can't convert %s %s to external origin.",
- first_seg(lv)->segtype->name,
- display_lvname(lv));
- return ECMD_FAILED;
- }
- }
-
- if (lp->repair) {
- if (lv_is_pool(lv)) {
- if (lv_is_cache_pool(lv)) {
- log_error("Repair for cache pool %s not yet implemented.",
- display_lvname(lv));
- return ECMD_FAILED;
- }
- if (!_lvconvert_thin_pool_repair(cmd, lv, lp))
- return_ECMD_FAILED;
- return ECMD_PROCESSED;
- }
- if (!lv_is_mirrored(lv) && !lv_is_raid(lv)) {
- if (arg_is_set(cmd, usepolicies_ARG))
- return ECMD_PROCESSED; /* nothing to be done here */
- log_error("Cannot repair logical volume %s of segtype %s.",
- display_lvname(lv), lvseg_name(first_seg(lv)));
- return ECMD_FAILED;
- }
- }
-
- /* forward splitmirror operations to the cache origin, which may be raid
- * or old-style mirror */
- if (lp->keep_mimages && lv_is_cache_type(lv) &&
- (origin = seg_lv(first_seg(lv), 0)) && lv_is_cache_origin(origin)) {
- log_warn("WARNING: Selected operation does not work with cache-type LVs.");
- log_warn("WARNING: Proceeding using the cache origin volume %s instead.",
- display_lvname(origin));
- lv = origin;
- }
-
- if (!lp->segtype) {
- /* segtype not explicitly set in _read_params */
- lp->segtype = first_seg(lv)->segtype;
-
- /*
- * If we are converting to mirror/raid1 and
- * the segtype was not specified, then we need
- * to consult the default.
- */
- if (lp->mirrors_supplied && !lv_is_mirrored(lv)) {
- if (!(lp->segtype = get_segtype_from_string(cmd, find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL))))
- return_ECMD_FAILED;
- }
- }
- if (lp->merge_snapshot) {
- if ((lv_is_thin_volume(lv) && !_lvconvert_merge_thin_snapshot(cmd, lv, lp)) ||
- (!lv_is_thin_volume(lv) && !_lvconvert_merge_old_snapshot(cmd, lv, lp))) {
- log_print_unless_silent("Unable to merge volume %s into its origin.",
- display_lvname(lv));
- return ECMD_FAILED;
- }
- } else if (lp->snapshot) {
- if (!_lvconvert_snapshot(cmd, lv, lp))
- return_ECMD_FAILED;
- } else if (segtype_is_pool(lp->segtype) || lp->thin || lp->cache) {
- if (!_lvconvert_pool(cmd, lv, lp))
- return_ECMD_FAILED;
-
- if ((lp->thin && !_lvconvert_thin(cmd, lv, lp)) ||
- (lp->cache && !_lvconvert_cache(cmd, lv, lp)))
- return_ECMD_FAILED;
- } else if (segtype_is_raid(lp->segtype) ||
- (lv->status & RAID) || lp->merge_mirror) {
- if (!archive(lv->vg))
- return_ECMD_FAILED;
-
- if (!_lvconvert_raid(lv, lp))
- return_ECMD_FAILED;
-
- if (!(failed_pvs = _failed_pv_list(lv->vg)))
- return_ECMD_FAILED;
-
- /* If repairing and using policies, remove missing PVs from VG */
- if (lp->repair && arg_is_set(cmd, usepolicies_ARG))
- _remove_missing_empty_pv(lv->vg, failed_pvs);
- } else if (lp->mirrors_supplied || lp->keep_mimages || lv_is_mirrored(lv)) {
- if (!archive(lv->vg))
- return_ECMD_FAILED;
-
- if (!_lvconvert_mirrors(cmd, lv, lp))
- return_ECMD_FAILED;
-
- if (!(failed_pvs = _failed_pv_list(lv->vg)))
- return_ECMD_FAILED;
-
- /* If repairing and using policies, remove missing PVs from VG */
- if (lp->repair && arg_is_set(cmd, usepolicies_ARG))
- _remove_missing_empty_pv(lv->vg, failed_pvs);
- }
-
- return ECMD_PROCESSED;
-}
-#endif
-
/*
* Functions called to perform a specific operation on a specific LV type.
*
7 years, 5 months
master - lvconvert: rework routing of operations
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2282f53ac73d33...
Commit: 2282f53ac73d33311661226894ee90e72772f0db
Parent: eac0706761e628532ffcd27f3e4d7fa559a5f818
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jun 28 12:24:41 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Jun 29 16:55:27 2016 -0500
lvconvert: rework routing of operations
Add new logic to identify each unique operation and route
it to the correct function to perform it. The functions
that perform the conversions remain unchanged.
This new code checks every allowed combination of LV type
and requested operation, and for each valid combination
calls the function that performs that conversion.
The first stage of option validation which checks for
incompatible combinations of command line options, is done
done before process_each is called. This is unchanged.
(This new code will allow that first stage validation to
be simplified in a future commit.)
The second stage of checking options against the specific
LV type is done by this new code. For each valid combination
of operation + LV type, the new code calls an existing
function that implements it.
With this in place, the ad hoc checks for valid combinations
of LV types and operations can be removed from the existing
code in a future commit.
(The #if 0 is used to keep the patch clean, and the
disabled code will be removed by a following patch.)
---
test/shell/lvconvert-cache.sh | 2 +-
test/shell/lvconvert-mirror.sh | 21 +-
tools/lvconvert.c | 786 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 799 insertions(+), 10 deletions(-)
diff --git a/test/shell/lvconvert-cache.sh b/test/shell/lvconvert-cache.sh
index cab5964..58274de 100644
--- a/test/shell/lvconvert-cache.sh
+++ b/test/shell/lvconvert-cache.sh
@@ -144,7 +144,7 @@ lvcreate -H -L 4 -n corigin --cachepool $vg/cpool
# unsupported yet
fail lvconvert --repair $vg/cpool 2>&1 | tee out
-grep "not yet implemented" out
+grep "Cannot convert internal LV" out
lvremove -f $vg
diff --git a/test/shell/lvconvert-mirror.sh b/test/shell/lvconvert-mirror.sh
index 078ebad..1d4fb08 100644
--- a/test/shell/lvconvert-mirror.sh
+++ b/test/shell/lvconvert-mirror.sh
@@ -85,9 +85,12 @@ offset=$(( offset + 2 ))
# update in case mirror ever gets faster and allows parallel read
aux delay_dev "$dev2" 0 2000 ${offset}:1
lvcreate -aey -l5 -Zn -Wn --type mirror --regionsize 16K -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev4" "$dev3:$DEVRANGE"
+# FIXME: add a new explicit option to define the polling behavior
+# done here with 'lvconvert vg/lv'. That option can specify
+# that the command succeeds even if the LV doesn't need polling.
should not lvconvert -m-1 $vg/$lv1 "$dev1"
aux enable_dev "$dev2"
-lvconvert $vg/$lv1 # wait
+should lvconvert $vg/$lv1 # wait
lvconvert -m2 $vg/$lv1 "$dev1" "$dev2" "$dev4" "$dev3:0" # If the above "should" failed...
aux wait_for_sync $vg $lv1
@@ -113,7 +116,7 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# Next convert should fail b/c we can't have 2 at once
should not lvconvert -m+1 $vg/$lv1 "$dev5"
aux enable_dev "$dev4"
-lvconvert $vg/$lv1 # wait
+should lvconvert $vg/$lv1 # wait
lvconvert -m2 $vg/$lv1 # In case the above "should" actually failed
check mirror $vg $lv1 "$dev3"
@@ -156,7 +159,7 @@ lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE
lvchange -an $vg/$lv1
lvconvert -m+1 $vg/$lv1 "$dev4"
lvchange -aey $vg/$lv1
-lvconvert $vg/$lv1 # wait
+should lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
lvremove -ff $vg
@@ -168,7 +171,7 @@ lvremove -ff $vg
lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE"
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
lvconvert -m-1 $vg/$lv1 "$dev4"
-lvconvert $vg/$lv1 # wait
+should lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -179,7 +182,7 @@ lvremove -ff $vg
lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE"
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+2 -b $vg/$lv1 "$dev4" "$dev5"
lvconvert -m-1 $vg/$lv1 "$dev4"
-lvconvert $vg/$lv1 # wait
+should lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -192,9 +195,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
-lvconvert $vg/$lv1
+should lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
-lvconvert $vg/$lv1
+should lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -207,9 +210,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
-lvconvert $vg/$lv1
+should lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
-lvconvert $vg/$lv1
+should lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 65143a1..1a863a4 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2023,6 +2023,7 @@ static int _lvconvert_split_cached(struct cmd_context *cmd,
return 1;
}
+#if 0
static int _lvconvert_splitcache(struct cmd_context *cmd,
struct logical_volume *lv,
struct lvconvert_params *lp)
@@ -2050,7 +2051,9 @@ static int _lvconvert_splitcache(struct cmd_context *cmd,
return 1;
}
+#endif
+#if 0
static int _lvconvert_split(struct cmd_context *cmd,
struct logical_volume *lv,
struct lvconvert_params *lp)
@@ -2080,6 +2083,7 @@ static int _lvconvert_split(struct cmd_context *cmd,
return 1;
}
+#endif
static int _lvconvert_uncache(struct cmd_context *cmd,
struct logical_volume *lv,
@@ -3337,6 +3341,7 @@ static int _lvconvert_cache(struct cmd_context *cmd,
return 1;
}
+#if 0
static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3493,6 +3498,787 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_PROCESSED;
}
+#endif
+
+/*
+ * Functions called to perform a specific operation on a specific LV type.
+ *
+ * _convert_<lvtype>_<operation>
+ *
+ * For cases where an operation does not apply to the LV itself, but
+ * is implicitly redirected to a sub-LV, these functions locate the
+ * correct sub-LV and call the operation on that sub-LV. If a sub-LV
+ * of the proper type is not found, these functions report the error.
+ *
+ * FIXME: the _lvconvert_foo() functions can be cleaned up since they
+ * are now only called for valid combinations of LV type and operation.
+ * After that happens, the code remaining in those functions can be
+ * moved into the _convert_lvtype_operation() functions below.
+ */
+
+static int _convert_cow_snapshot_splitsnapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_splitsnapshot(cmd, lv, lp);
+}
+
+static int _convert_cow_snapshot_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_merge_old_snapshot(cmd, lv, lp);
+}
+
+static int _convert_thin_volume_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_merge_thin_snapshot(cmd, lv, lp);
+}
+
+static int _convert_thin_pool_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1;
+
+ sublv1 = seg_lv(first_seg(lv), 0); /* cached _tdata ? */
+
+ if (!lv_is_cache(sublv1)) {
+ log_error("Sub LV %s must be cache.", display_lvname(sublv1));
+ return 0;
+ }
+
+ return _lvconvert_split_cached(cmd, sublv1);
+}
+
+static int _convert_thin_pool_uncache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1 = NULL;
+
+ sublv1 = seg_lv(first_seg(lv), 0); /* cached _tdata ? */
+
+ if (!lv_is_cache(sublv1)) {
+ log_error("Sub LV %s must be cache.", display_lvname(sublv1));
+ return 0;
+ }
+
+ return _lvconvert_uncache(cmd, sublv1, lp);
+}
+
+static int _convert_thin_pool_repair(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_thin_pool_repair(cmd, lv, lp);
+}
+
+static int _convert_thin_pool_cache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
+ return 0;
+ }
+
+ /* Do we need to grab the tdata sub LV to pass on? */
+
+ return _lvconvert_cache(cmd, lv, lp);
+}
+
+static int _convert_thin_pool_swapmetadata(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_cache_volume_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_split_cached(cmd, lv);
+}
+
+static int _convert_cache_volume_uncache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_uncache(cmd, lv, lp);
+}
+
+static int _convert_cache_volume_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1;
+
+ sublv1 = seg_lv(first_seg(lv), 0);
+
+ if (lv_is_raid(sublv1))
+ return _lvconvert_raid(sublv1, lp);
+
+ if (lv_is_mirror(sublv1))
+ return _lvconvert_mirrors(cmd, lv, lp);
+
+ log_error("Sub LV %s must be raid or mirror.", display_lvname(sublv1));
+ return 0;
+}
+
+static int _convert_cache_volume_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_cache_pool_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *sublv1;
+ struct lv_segment *seg;
+
+ /* When passed used cache-pool of used cached LV -> split cached LV */
+
+ if ((dm_list_size(&lv->segs_using_this_lv) == 1) &&
+ (seg = get_only_segment_using_this_lv(lv)) &&
+ seg_is_cache(seg))
+ sublv1 = seg->lv;
+ else {
+ log_error("Sub LV of cache type not found.");
+ return 0;
+ }
+
+ if (!lv_is_cache(sublv1)) {
+ log_error("Sub LV %s must be cache.", display_lvname(sublv1));
+ return 0;
+ }
+
+ return _lvconvert_split_cached(cmd, sublv1);
+}
+
+static int _convert_cache_pool_swapmetadata(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_mirror_number(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_mirror_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_mirror_repair(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct dm_list *failed_pvs;
+ int ret;
+
+ ret = _lvconvert_mirrors_repair(cmd, lv, lp);
+
+ if (ret && arg_is_set(cmd, usepolicies_ARG)) {
+ if ((failed_pvs = _failed_pv_list(lv->vg)))
+ _remove_missing_empty_pv(lv->vg, failed_pvs);
+ }
+
+ return ret;
+}
+
+static int _convert_mirror_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_number(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: split the splitmirrors section out of _lvconvert_raid and call it here. */
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: split the merge section out of _lvconvert_raid and call it here. */
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_repair(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct dm_list *failed_pvs;
+ int ret;
+
+ /* FIXME: split the repair section out of _lvconvert_raid and call it here. */
+ ret = _lvconvert_raid(lv, lp);
+
+ if (ret && arg_is_set(cmd, usepolicies_ARG)) {
+ if ((failed_pvs = _failed_pv_list(lv->vg)))
+ _remove_missing_empty_pv(lv->vg, failed_pvs);
+ }
+
+ return ret;
+}
+
+static int _convert_raid_replace(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* FIXME: remove the replace section from _lvconvert_raid */
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_snapshot(cmd, lv, lp);
+}
+
+static int _convert_raid_thin(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --thin includes an implicit conversion of the thinpool arg to type thin-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --thinpool arg to type thin-pool failed.");
+ return 0;
+ }
+
+ return _lvconvert_thin(cmd, lv, lp);
+}
+
+static int _convert_raid_cache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
+ return 0;
+ }
+
+ return _lvconvert_cache(cmd, lv, lp);
+}
+
+static int _convert_raid_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_raid_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_raid_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_striped(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_raid_linear(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_striped_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_snapshot(cmd, lv, lp);
+}
+
+static int _convert_striped_merge(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+static int _convert_striped_thin(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --thin includes an implicit conversion of the thinpool arg to type thin-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --thinpool arg to type thin-pool failed.");
+ return 0;
+ }
+
+ return _lvconvert_thin(cmd, lv, lp);
+}
+
+static int _convert_striped_cache(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ if (!_lvconvert_pool(cmd, lv, lp)) {
+ log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
+ return 0;
+ }
+
+ return _lvconvert_cache(cmd, lv, lp);
+}
+
+static int _convert_striped_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_striped_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_pool(cmd, lv, lp);
+}
+
+static int _convert_striped_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_mirrors(cmd, lv, lp);
+}
+
+static int _convert_striped_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_raid(lv, lp);
+}
+
+/*
+ * Functions called to perform all valid operations on a given LV type.
+ *
+ * _convert_<lvtype>
+ */
+
+static int _convert_cow_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->splitsnapshot)
+ return _convert_cow_snapshot_splitsnapshot(cmd, lv, lp);
+
+ if (lp->merge)
+ return _convert_cow_snapshot_merge(cmd, lv, lp);
+
+ log_error("Operation not permitted on COW snapshot LV %s", display_lvname(lv));
+ log_error("Operations permitted on a COW snapshot LV are:\n"
+ " --splitsnapshot\n"
+ " --merge\n");
+ return 0;
+}
+
+static int _convert_thin_volume(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->merge)
+ return _convert_thin_volume_merge(cmd, lv, lp);
+
+ log_error("Operation not permitted on thin LV %s", display_lvname(lv));
+ log_error("Operations permitted on a thin LV are:\n"
+ " --merge\n");
+ return 0;
+}
+
+static int _convert_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->splitcache || lp->split)
+ return _convert_thin_pool_splitcache(cmd, lv, lp);
+
+ if (lp->uncache)
+ return _convert_thin_pool_uncache(cmd, lv, lp);
+
+ if (lp->cache)
+ return _convert_thin_pool_cache(cmd, lv, lp);
+
+ if (lp->repair)
+ return _convert_thin_pool_repair(cmd, lv, lp);
+
+ /* FIXME: swapping the thin pool metadata LV needs a specific option like --swapmetadata */
+ if (arg_is_set(cmd, poolmetadata_ARG))
+ return _convert_thin_pool_swapmetadata(cmd, lv, lp);
+
+ /* FIXME: add --swapmetadata to list of permitted operations. */
+
+ log_error("Operation not permitted on thin pool LV %s", display_lvname(lv));
+ log_error("Operations permitted on a thin pool LV are:\n"
+ " --splitcache (operates on cache sub LV)\n"
+ " --uncache (operates on cache sub LV)\n"
+ " --cache (operates on data sub LV)\n"
+ " --repair\n");
+ return 0;
+}
+
+static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+
+ if (lp->splitcache || lp->split)
+ return _convert_cache_volume_splitcache(cmd, lv, lp);
+
+ if (lp->uncache)
+ return _convert_cache_volume_uncache(cmd, lv, lp);
+
+ /* FIXME: add lp->splitmirrors to reflect the arg. */
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_cache_volume_splitmirrors(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "thin-pool"))
+ return _convert_cache_volume_thin_pool(cmd, lv, lp);
+
+ log_error("Operation not permitted on cache LV %s", display_lvname(lv));
+ log_error("Operations permitted on a cache LV are:\n"
+ " --splitcache\n"
+ " --uncache\n"
+ " --splitmirrors (operates on mirror or raid sub LV)\n"
+ " --type thin-pool\n");
+ return 0;
+}
+
+static int _convert_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ if (lp->splitcache || lp->split)
+ return _convert_cache_pool_splitcache(cmd, lv, lp);
+
+ /* FIXME: swapping the cache pool metadata LV needs a specific option like --swapmetadata */
+ if (arg_is_set(cmd, poolmetadata_ARG))
+ return _convert_cache_pool_swapmetadata(cmd, lv, lp);
+
+ /* FIXME: add --swapmetadata to list of permitted operations. */
+
+ log_error("Operation not permitted on cache pool LV %s", display_lvname(lv));
+ log_error("Operations permitted on a cache pool LV are:\n"
+ " --splitcache (operates on cache LV)\n");
+ return 0;
+}
+
+static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+ const struct segment_type *new_segtype = NULL;
+
+ if (new_type)
+ new_segtype = get_segtype_from_string(cmd, new_type);
+
+ if (lp->mirrors_supplied)
+ return _convert_mirror_number(cmd, lv, lp);
+
+ /* FIXME: add lp->splitmirrors to reflect the arg. */
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_mirror_splitmirrors(cmd, lv, lp);
+
+ if (lp->mirrorlog || lp->corelog)
+ return _convert_mirror_log(cmd, lv, lp);
+
+ if (lp->repair)
+ return _convert_mirror_repair(cmd, lv, lp);
+
+ if (new_type && new_segtype && segtype_is_raid(new_segtype))
+ return _convert_mirror_raid(cmd, lv, lp);
+
+ /*
+ * FIXME: this is here to preserve old behavior, but an
+ * explicit option should be added to enable this case,
+ * rather than making it the result of an ambiguous
+ * "lvconvert vg/lv" command.
+ *
+ * Old behavior was described as:
+ * "Collapsing a stack of mirrors.
+ * If called with no argument, try collapsing the resync layers"
+ */
+ log_debug("Checking if LV %s is converting.", display_lvname(lv));
+ if (lv_is_converting(lv)) {
+ lp->need_polling = 1;
+ return 1;
+ }
+
+ log_error("Operation not permitted on mirror LV %s", display_lvname(lv));
+ log_error("Operations permitted on a mirror LV are:\n"
+ " --mirrors\n"
+ " --splitmirrors\n"
+ " --mirrorlog\n"
+ " --repair\n"
+ " --type raid*\n");
+ return 0;
+}
+
+static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+ const struct segment_type *new_segtype = NULL;
+
+ if (new_type)
+ new_segtype = get_segtype_from_string(cmd, new_type);
+
+ if (lp->mirrors_supplied)
+ return _convert_raid_number(cmd, lv, lp);
+
+ /* FIXME: add lp->splitmirrors to reflect the arg. */
+ if (arg_is_set(cmd, splitmirrors_ARG))
+ return _convert_raid_splitmirrors(cmd, lv, lp);
+
+ if (lp->merge_mirror)
+ return _convert_raid_merge(cmd, lv, lp);
+
+ if (lp->repair)
+ return _convert_raid_repair(cmd, lv, lp);
+
+ if (lp->replace)
+ return _convert_raid_replace(cmd, lv, lp);
+
+ if (lp->snapshot)
+ return _convert_raid_snapshot(cmd, lv, lp);
+
+ if (lp->thin)
+ return _convert_raid_thin(cmd, lv, lp);
+
+ if (lp->cache)
+ return _convert_raid_cache(cmd, lv, lp);
+
+ /* The --thinpool alias is ambiguous and not preferred. */
+
+ if ((new_type && !strcmp(new_type, "thin-pool")) || arg_is_set(cmd, thinpool_ARG))
+ return _convert_raid_thin_pool(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "cache-pool"))
+ return _convert_raid_cache_pool(cmd, lv, lp);
+
+ if (new_type && new_segtype && segtype_is_raid(new_segtype))
+ return _convert_raid_raid(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "striped"))
+ return _convert_raid_striped(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "linear"))
+ return _convert_raid_linear(cmd, lv, lp);
+
+ /* The --thinpool alias for --type thin-pool is not preferred, so not shown. */
+
+ log_error("Operation not permitted on raid LV %s", display_lvname(lv));
+ log_error("Operations permitted on a raid LV are:\n"
+ " --mirrors\n"
+ " --splitmirrors\n"
+ " --merge\n"
+ " --repair\n"
+ " --replace\n"
+ " --snapshot\n"
+ " --thin\n"
+ " --cache\n"
+ " --type thin-pool\n"
+ " --type cache-pool\n"
+ " --type raid*\n"
+ " --type striped\n"
+ " --type linear\n");
+ return 0;
+}
+
+static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ const char *new_type = arg_str_value(cmd, type_ARG, NULL);
+ const struct segment_type *new_segtype = NULL;
+ const char *mirrors_type = find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL);
+
+ if (new_type)
+ new_segtype = get_segtype_from_string(cmd, new_type);
+
+ if (lp->snapshot)
+ return _convert_striped_snapshot(cmd, lv, lp);
+
+ /* FIXME: add a new option to make this case more clear, e.g. --merge-splitmirror */
+ if (lp->merge)
+ return _convert_striped_merge(cmd, lv, lp);
+
+ if (lp->thin)
+ return _convert_striped_thin(cmd, lv, lp);
+
+ if (lp->cache)
+ return _convert_striped_cache(cmd, lv, lp);
+
+ /* The --thinpool alias is ambiguous and not preferred. */
+
+ if ((new_type && !strcmp(new_type, "thin-pool")) || arg_is_set(cmd, thinpool_ARG))
+ return _convert_striped_thin_pool(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "cache-pool"))
+ return _convert_striped_cache_pool(cmd, lv, lp);
+
+ if (new_type && !strcmp(new_type, "mirror"))
+ return _convert_striped_mirror(cmd, lv, lp);
+
+ if (new_type && new_segtype && segtype_is_raid(new_segtype))
+ return _convert_striped_raid(cmd, lv, lp);
+
+ /* --mirrors can mean --type mirror or --type raid1 depending on config setting. */
+
+ if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, "mirror"))
+ return _convert_striped_mirror(cmd, lv, lp);
+
+ if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, "raid1"))
+ return _convert_striped_raid(cmd, lv, lp);
+
+ /* The --thinpool alias for --type thin-pool is not preferred, so not shown. */
+
+ log_error("Operation not permitted on striped or linear LV %s", display_lvname(lv));
+ log_error("Operations permitted on a striped or linear LV are:\n"
+ " --snapshot\n"
+ " --merge\n"
+ " --thin\n"
+ " --cache\n"
+ " --type thin-pool\n"
+ " --type cache-pool\n"
+ " --type mirror | --mirrors\n"
+ " --type raid* | --mirrors\n");
+ return 0;
+}
+
+/*
+ * lvconvert performs a specific <operation> on a specific <lv_type>.
+ *
+ * The <operation> is specified by command args found in lp fields.
+ * The <lv_type> is found using lv_is_foo(lv) functions.
+ *
+ * lvconvert --operation LV
+ *
+ * lp->operation = arg_value(operation);
+ * lv_type = lv_is_foo(LV);
+ *
+ * for each lvtype,
+ * _convert_lvtype();
+ * for each lp->operation
+ * _convert_lvtype_operation();
+ */
+
+static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ struct lv_segment *lv_seg = first_seg(lv);
+ int ret = 0;
+
+ log_debug("lvconvert lv %s is type %s status %llx to type %s",
+ display_lvname(lv),
+ lv_seg->segtype->name,
+ (unsigned long long)lv->status,
+ arg_str_value(cmd, type_ARG, ""));
+
+ /*
+ * Check some conditions that can never be processed.
+ */
+
+ if (lv_is_locked(lv)) {
+ log_error("Cannot convert locked LV %s.", display_lvname(lv));
+ ret = 0;
+ goto out;
+ }
+
+ if (lv_is_pvmove(lv)) {
+ log_error("Cannot convert pvmove LV %s.", display_lvname(lv));
+ ret = 0;
+ goto out;
+ }
+
+ if (!lv_is_visible(lv)) {
+ /*
+ * FIXME: there are some exceptions to the rule of only
+ * operating on visible LVs. These should be fixed by running
+ * the command on the visible LV with an option indicating
+ * which sub LV is intended rather than naming the !visible LV.
+ */
+ if (!lv_is_cache_pool_metadata(lv) &&
+ !lv_is_cache_pool_data(lv) &&
+ !lv_is_thin_pool_metadata(lv) &&
+ !lv_is_thin_pool_data(lv) &&
+ !lv_is_raid_image(lv)) {
+ log_error("Cannot convert internal LV %s.", display_lvname(lv));
+ ret = 0;
+ goto out;
+ }
+ }
+
+ /*
+ * Each LV type that can be converted.
+ * (The existing type of the LV, not a requested type.)
+ */
+
+ if (lv_is_cow(lv)) {
+ ret = _convert_cow_snapshot(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_thin_volume(lv)) {
+ ret = _convert_thin_volume(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_thin_pool(lv)) {
+ ret = _convert_thin_pool(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_cache(lv)) {
+ ret = _convert_cache_volume(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_cache_pool(lv)) {
+ ret = _convert_cache_pool(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_mirror(lv)) {
+ ret = _convert_mirror(cmd, lv, lp);
+ goto out;
+ }
+
+ if (lv_is_raid(lv)) {
+ ret = _convert_raid(cmd, lv, lp);
+ goto out;
+ }
+
+ /*
+ * FIXME: add lv_is_striped() and lv_is_linear()?
+ * This does not include raid0.
+ * If operations differ between striped and linear, split this case.
+ */
+ if (segtype_is_striped(lv_seg->segtype) || segtype_is_linear(lv_seg->segtype)) {
+ ret = _convert_striped(cmd, lv, lp);
+ goto out;
+ }
+
+ /*
+ * Check for LV types that cannot be converted and print an error.
+ */
+
+ /*
+ * The intention is to explicitly check all cases above and never
+ * reach here, but this covers anything that was missed.
+ */
+ log_error("Cannot convert LV %s.", display_lvname(lv));
+ ret = 0;
+
+out:
+ return ret ? ECMD_PROCESSED : ECMD_FAILED;
+
+}
static struct convert_poll_id_list* _convert_poll_id_list_create(struct cmd_context *cmd,
const struct logical_volume *lv)
7 years, 5 months
master - libdm: do not issue 'Failed to create directory' message for failure in dm_create_dir
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=eac0706761e628...
Commit: eac0706761e628532ffcd27f3e4d7fa559a5f818
Parent: 686acce23fed6bd72af63201e4cc56bc5958379e
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 29 15:58:14 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 29 15:58:18 2016 +0200
libdm: do not issue 'Failed to create directory' message for failure in dm_create_dir
There are detailed messages inside _create_dir_recursive that
dm_create_dir calls (except EROFS which where the message is not
generated, like anywhere else in the code).
---
libdm/libdm-file.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/libdm/libdm-file.c b/libdm/libdm-file.c
index 9867824..2c313b3 100644
--- a/libdm/libdm-file.c
+++ b/libdm/libdm-file.c
@@ -97,10 +97,8 @@ int dm_create_dir(const char *dir)
if (stat(dir, &info) == 0 && S_ISDIR(info.st_mode))
return 1;
- if (!_create_dir_recursive(dir)) {
- log_error("Failed to create directory %s.", dir);
- return 0;
- }
+ if (!_create_dir_recursive(dir))
+ return_0;
return 1;
}
7 years, 5 months
master - lvconvert: Conversions between striped and raid0.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=686acce23fed6b...
Commit: 686acce23fed6bd72af63201e4cc56bc5958379e
Parent: 6f216692b47b38f480e50d213de5c513a309d9e0
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue Jun 28 23:44:15 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue Jun 28 23:44:15 2016 +0100
lvconvert: Conversions between striped and raid0.
---
WHATS_NEW | 1 +
lib/metadata/lv.c | 30 ++-
lib/metadata/lv_manip.c | 3 +-
lib/metadata/metadata.h | 4 +
lib/metadata/raid_manip.c | 595 +++++++++++++++++++++++++++++++++++++++++----
lib/metadata/segtype.c | 13 +
lib/metadata/segtype.h | 2 +
lib/misc/util.h | 2 +
8 files changed, 593 insertions(+), 57 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 3184412..619c64d 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.159 -
=================================
+ Support conversions between striped and raid0 segment types.
Add infrastructure for raid takeover lvconvert options.
Version 2.02.158 - 25th June 2016
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index cdf658e..e7a56cf 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -577,14 +577,14 @@ char *lv_name_dup(struct dm_pool *mem, const struct logical_volume *lv)
char *lv_fullname_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
- char lvfullname[NAME_LEN * 2 + 2];
+ char lvfullname[NAME_LEN * 2 + 2];
- if (dm_snprintf(lvfullname, sizeof(lvfullname), "%s/%s", lv->vg->name, lv->name) < 0) {
- log_error("lvfullname snprintf failed");
- return NULL;
- }
+ if (dm_snprintf(lvfullname, sizeof(lvfullname), "%s/%s", lv->vg->name, lv->name) < 0) {
+ log_error("lvfullname snprintf failed");
+ return NULL;
+ }
- return dm_pool_strdup(mem, lvfullname);
+ return dm_pool_strdup(mem, lvfullname);
}
struct logical_volume *lv_parent(const struct logical_volume *lv)
@@ -930,7 +930,7 @@ char *lv_dmpath_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (!*lv->vg->name)
return dm_pool_strdup(mem, "");
- if (!(name = dm_build_dm_name(mem, lv->vg->name, lv->name, NULL))) {
+ if (!(name = dm_build_dm_name(mem, lv->vg->name, lv->name, NULL))) {
log_error("dm_build_dm_name failed");
return NULL;
}
@@ -1581,3 +1581,19 @@ struct profile *lv_config_profile(const struct logical_volume *lv)
{
return lv->profile ? : lv->vg->profile;
}
+
+int lv_has_constant_stripes(struct logical_volume *lv)
+{
+ uint32_t previous_area_count = 0;
+ struct lv_segment *seg;
+
+ dm_list_iterate_items(seg, &lv->segments) {
+ if (!seg_is_striped(seg))
+ return 0;
+ if (previous_area_count && previous_area_count != seg->area_count)
+ return 0;
+ previous_area_count = seg->area_count;
+ }
+
+ return 1;
+}
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 40c1c1a..db71939 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3301,7 +3301,8 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
void alloc_destroy(struct alloc_handle *ah)
{
- dm_pool_destroy(ah->mem);
+ if (ah)
+ dm_pool_destroy(ah->mem);
}
/*
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 31c9346..e6dc14a 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -415,6 +415,10 @@ struct logical_volume *alloc_lv(struct dm_pool *mem);
*/
int check_lv_segments(struct logical_volume *lv, int complete_vg);
+/*
+ * Does every LV segment have the same number of stripes?
+ */
+int lv_has_constant_stripes(struct logical_volume *lv);
/*
* Checks that a replicator segment is correct.
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 2cef777..71334b5 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -116,16 +116,16 @@ static int _raid_in_sync(struct logical_volume *lv)
/*
* _raid_remove_top_layer
* @lv
- * @removal_list
+ * @removal_lvs
*
* Remove top layer of RAID LV in order to convert to linear.
* This function makes no on-disk changes. The residual LVs
- * returned in 'removal_list' must be freed by the caller.
+ * returned in 'removal_lvs' must be freed by the caller.
*
* Returns: 1 on succes, 0 on failure
*/
static int _raid_remove_top_layer(struct logical_volume *lv,
- struct dm_list *removal_list)
+ struct dm_list *removal_lvs)
{
struct lv_list *lvl_array, *lvl;
struct lv_segment *seg = first_seg(lv);
@@ -147,19 +147,19 @@ static int _raid_remove_top_layer(struct logical_volume *lv,
if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, 2 * sizeof(*lvl))))
return_0;
- /* Add last metadata area to removal_list */
+ /* Add last metadata area to removal_lvs */
lvl_array[0].lv = seg_metalv(seg, 0);
lv_set_visible(seg_metalv(seg, 0));
if (!remove_seg_from_segs_using_this_lv(seg_metalv(seg, 0), seg))
return_0;
seg_metatype(seg, 0) = AREA_UNASSIGNED;
- dm_list_add(removal_list, &(lvl_array[0].list));
+ dm_list_add(removal_lvs, &(lvl_array[0].list));
- /* Remove RAID layer and add residual LV to removal_list*/
+ /* Remove RAID layer and add residual LV to removal_lvs*/
seg_lv(seg, 0)->status &= ~RAID_IMAGE;
lv_set_visible(seg_lv(seg, 0));
lvl_array[1].lv = seg_lv(seg, 0);
- dm_list_add(removal_list, &(lvl_array[1].list));
+ dm_list_add(removal_lvs, &(lvl_array[1].list));
if (!remove_layer_from_lv(lv, seg_lv(seg, 0)))
return_0;
@@ -377,13 +377,6 @@ static struct logical_volume *_alloc_image_component(struct logical_volume *lv,
struct logical_volume *tmp_lv;
const struct segment_type *segtype;
- if (!ah) {
- log_error(INTERNAL_ERROR
- "Stand-alone %s area allocation not implemented",
- (type == RAID_META) ? "metadata" : "data");
- return 0;
- }
-
switch (type) {
case RAID_META:
type_suffix = "rmeta";
@@ -409,12 +402,14 @@ static struct logical_volume *_alloc_image_component(struct logical_volume *lv,
return 0;
}
- if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
- return_0;
+ if (ah) {
+ if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
+ return_0;
- if (!lv_add_segment(ah, first_area, 1, tmp_lv, segtype, 0, status, 0)) {
- log_error("Failed to add segment to LV, %s", img_name);
- return 0;
+ if (!lv_add_segment(ah, first_area, 1, tmp_lv, segtype, 0, status, 0)) {
+ log_error("Failed to add segment to LV, %s", img_name);
+ return 0;
+ }
}
lv_set_visible(tmp_lv);
@@ -432,7 +427,7 @@ static int _alloc_image_components(struct logical_volume *lv,
uint32_t extents;
struct lv_segment *seg = first_seg(lv);
const struct segment_type *segtype;
- struct alloc_handle *ah;
+ struct alloc_handle *ah = NULL;
struct dm_list *parallel_areas;
struct lv_list *lvl_array;
@@ -473,7 +468,9 @@ static int _alloc_image_components(struct logical_volume *lv,
(lv->le_count / (seg->area_count - segtype->parity_devs)) :
lv->le_count;
- if (!(ah = allocate_extents(lv->vg, NULL, segtype, 0, count, count,
+ /* Do we need to allocate any extents? */
+ if (pvs && !dm_list_empty(pvs) &&
+ !(ah = allocate_extents(lv->vg, NULL, segtype, 0, count, count,
region_size, extents, pvs,
lv->alloc, 0, parallel_areas)))
return_0;
@@ -485,19 +482,25 @@ static int _alloc_image_components(struct logical_volume *lv,
* allocated areas. Thus, the metadata areas are pulled
* from 's + count'.
*/
- if (!(lvl_array[s + count].lv =
- _alloc_image_component(lv, NULL, ah, s + count, RAID_META))) {
- alloc_destroy(ah);
- return_0;
+
+ /* new_meta_lvs are optional for raid0 */
+ if (new_meta_lvs) {
+ if (!(lvl_array[s + count].lv =
+ _alloc_image_component(lv, NULL, ah, s + count, RAID_META))) {
+ alloc_destroy(ah);
+ return_0;
+ }
+ dm_list_add(new_meta_lvs, &(lvl_array[s + count].list));
}
- dm_list_add(new_meta_lvs, &(lvl_array[s + count].list));
- if (!(lvl_array[s].lv =
- _alloc_image_component(lv, NULL, ah, s, RAID_IMAGE))) {
- alloc_destroy(ah);
- return_0;
+ if (new_data_lvs) {
+ if (!(lvl_array[s].lv =
+ _alloc_image_component(lv, NULL, ah, s, RAID_IMAGE))) {
+ alloc_destroy(ah);
+ return_0;
+ }
+ dm_list_add(new_data_lvs, &(lvl_array[s].list));
}
- dm_list_add(new_data_lvs, &(lvl_array[s].list));
}
alloc_destroy(ah);
@@ -955,16 +958,16 @@ static int _raid_extract_images(struct logical_volume *lv, uint32_t new_count,
static int _raid_remove_images(struct logical_volume *lv,
uint32_t new_count, struct dm_list *pvs)
{
- struct dm_list removal_list;
+ struct dm_list removal_lvs;
struct lv_list *lvl;
if (!archive(lv->vg))
return_0;
- dm_list_init(&removal_list);
+ dm_list_init(&removal_lvs);
if (!_raid_extract_images(lv, new_count, pvs, 1,
- &removal_list, &removal_list)) {
+ &removal_lvs, &removal_lvs)) {
log_error("Failed to extract images from %s/%s",
lv->vg->name, lv->name);
return 0;
@@ -972,7 +975,7 @@ static int _raid_remove_images(struct logical_volume *lv,
/* Convert to linear? */
if (new_count == 1) {
- if (!_raid_remove_top_layer(lv, &removal_list)) {
+ if (!_raid_remove_top_layer(lv, &removal_lvs)) {
log_error("Failed to remove RAID layer"
" after linear conversion");
return 0;
@@ -1005,7 +1008,7 @@ static int _raid_remove_images(struct logical_volume *lv,
* and won't conflict with the remaining (possibly shifted)
* sub-LVs.
*/
- dm_list_iterate_items(lvl, &removal_list) {
+ dm_list_iterate_items(lvl, &removal_lvs) {
if (!activate_lv_excl_local(lv->vg->cmd, lvl->lv)) {
log_error("Failed to resume extracted LVs");
return 0;
@@ -1027,8 +1030,8 @@ static int _raid_remove_images(struct logical_volume *lv,
/*
* Eliminate the extracted LVs
*/
- if (!dm_list_empty(&removal_list)) {
- dm_list_iterate_items(lvl, &removal_list) {
+ if (!dm_list_empty(&removal_lvs)) {
+ dm_list_iterate_items(lvl, &removal_lvs) {
if (!deactivate_lv(lv->vg->cmd, lvl->lv))
return_0;
if (!lv_remove(lvl->lv))
@@ -1089,14 +1092,14 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
uint32_t new_count, struct dm_list *splittable_pvs)
{
struct lv_list *lvl;
- struct dm_list removal_list, data_list;
+ struct dm_list removal_lvs, data_list;
struct cmd_context *cmd = lv->vg->cmd;
uint32_t old_count = lv_raid_image_count(lv);
struct logical_volume *tracking;
struct dm_list tracking_pvs;
int historical;
- dm_list_init(&removal_list);
+ dm_list_init(&removal_lvs);
dm_list_init(&data_list);
if (is_lockd_type(lv->vg->lock_type)) {
@@ -1151,14 +1154,14 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
}
if (!_raid_extract_images(lv, new_count, splittable_pvs, 1,
- &removal_list, &data_list)) {
+ &removal_lvs, &data_list)) {
log_error("Failed to extract images from %s/%s",
lv->vg->name, lv->name);
return 0;
}
/* Convert to linear? */
- if ((new_count == 1) && !_raid_remove_top_layer(lv, &removal_list)) {
+ if ((new_count == 1) && !_raid_remove_top_layer(lv, &removal_lvs)) {
log_error("Failed to remove RAID layer after linear conversion");
return 0;
}
@@ -1197,7 +1200,7 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
if (!activate_lv_excl_local(cmd, lvl->lv))
return_0;
- dm_list_iterate_items(lvl, &removal_list)
+ dm_list_iterate_items(lvl, &removal_lvs)
if (!activate_lv_excl_local(cmd, lvl->lv))
return_0;
@@ -1217,7 +1220,7 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
/*
* Eliminate the residual LVs
*/
- dm_list_iterate_items(lvl, &removal_list) {
+ dm_list_iterate_items(lvl, &removal_lvs) {
if (!deactivate_lv(cmd, lvl->lv))
return_0;
@@ -1365,6 +1368,9 @@ int lv_raid_merge(struct logical_volume *image_lv)
return 1;
}
+/*
+ * General conversion functions
+ */
static int _convert_mirror_to_raid1(struct logical_volume *lv,
const struct segment_type *new_segtype)
{
@@ -1460,6 +1466,470 @@ static int _convert_mirror_to_raid1(struct logical_volume *lv,
return 1;
}
+/* Add new @lvs to @lv at @area_offset */
+static int _add_image_component_list(struct lv_segment *seg, int delete_from_list,
+ uint64_t lv_flags, struct dm_list *lvs, uint32_t area_offset)
+{
+ uint32_t s = area_offset;
+ struct lv_list *lvl, *tmp;
+
+ dm_list_iterate_items_safe(lvl, tmp, lvs) {
+ if (delete_from_list)
+ dm_list_del(&lvl->list);
+
+ if (lv_flags & VISIBLE_LV)
+ lv_set_visible(lvl->lv);
+ else
+ lv_set_hidden(lvl->lv);
+
+ if (lv_flags & LV_REBUILD)
+ lvl->lv->status |= LV_REBUILD;
+ else
+ lvl->lv->status &= ~LV_REBUILD;
+
+ if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0 /* le */, lvl->lv->status)) {
+ log_error("Failed to add sublv %s", lvl->lv->name);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * All areas from LV segments are moved to new
+ * segments allocated with area_count=1 for data_lvs.
+ */
+static int _striped_to_raid0_move_segs_to_raid0_lvs(struct logical_volume *lv,
+ struct dm_list *data_lvs)
+{
+ uint32_t s = 0, le;
+ struct logical_volume *dlv;
+ struct lv_segment *seg_from, *seg_new;
+ struct lv_list *lvl;
+ struct segment_type *segtype;
+ uint64_t status;
+
+ if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
+ return_0;
+
+ /* Move segment areas across to the N data LVs of the new raid0 LV */
+ dm_list_iterate_items(lvl, data_lvs) {
+ dlv = lvl->lv;
+ le = 0;
+ dm_list_iterate_items(seg_from, &lv->segments) {
+ status = RAID | SEG_RAID | (seg_from->status & (LVM_READ | LVM_WRITE));
+
+ /* Allocate a data LV segment with one area for each segment in the striped LV */
+ if (!(seg_new = alloc_lv_segment(segtype, dlv,
+ le, seg_from->area_len,
+ status,
+ 0 /* stripe_size */, NULL, 1 /* area_count */,
+ seg_from->area_len,
+ 0 /* chunk_size */, 0 /* region_size */, 0, NULL)))
+ return_0;
+
+ seg_type(seg_new, 0) = AREA_UNASSIGNED;
+ dm_list_add(&dlv->segments, &seg_new->list);
+ le += seg_from->area_len;
+
+ /* Move the respective area across to our new segment */
+ if (!move_lv_segment_area(seg_new, 0, seg_from, s))
+ return_0;
+ }
+
+ /* Adjust le count and LV size */
+ dlv->le_count = le;
+ dlv->size = (uint64_t) le * lv->vg->extent_size;
+ s++;
+ }
+
+ /* Remove the empty segments from the striped LV */
+ dm_list_init(&lv->segments);
+
+ return 1;
+}
+
+/*
+ * Find the smallest area across all the subLV segments at area_le.
+ */
+static uint32_t _min_sublv_area_at_le(struct lv_segment *seg, uint32_t area_le)
+{
+ uint32_t s, area_len = ~0U;
+ struct lv_segment *seg1;
+
+ /* Find smallest segment of each of the data image LVs at offset area_le */
+ for (s = 0; s < seg->area_count; s++) {
+ seg1 = find_seg_by_le(seg_lv(seg, s), area_le);
+ area_len = min(area_len, seg1->len);
+ }
+
+ return area_len;
+}
+
+/*
+ * Split segments in segment LVs in all areas of seg at offset area_le
+ */
+static int _split_area_lvs_segments(struct lv_segment *seg, uint32_t area_le)
+{
+ uint32_t s;
+
+ /* Make sure that there's a segment starting at area_le in all data LVs */
+ for (s = 0; s < seg->area_count; s++)
+ if (area_le < seg_lv(seg, s)->le_count &&
+ !lv_split_segment(seg_lv(seg, s), area_le))
+ return_0;
+
+ return 1;
+}
+
+static int _alloc_and_add_new_striped_segment(struct logical_volume *lv,
+ uint32_t le, uint32_t area_len,
+ struct dm_list *new_segments)
+{
+ struct lv_segment *seg, *new_seg;
+ struct segment_type *striped_segtype;
+
+ seg = first_seg(lv);
+
+ if (!(striped_segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
+ return_0;
+
+ /* Allocate a segment with seg->area_count areas */
+ if (!(new_seg = alloc_lv_segment(striped_segtype, lv, le, area_len * seg->area_count,
+ seg->status & ~RAID,
+ seg->stripe_size, NULL, seg->area_count,
+ area_len, seg->chunk_size, 0, 0, NULL)))
+ return_0;
+
+ dm_list_add(new_segments, &new_seg->list);
+
+ return 1;
+}
+
+static int _extract_image_component_error_seg(struct lv_segment *seg,
+ uint64_t type, uint32_t idx,
+ struct logical_volume **extracted_lv,
+ int set_error_seg)
+{
+ struct logical_volume *lv;
+
+ switch (type) {
+ case RAID_META:
+ lv = seg_metalv(seg, idx);
+ seg_metalv(seg, idx) = NULL;
+ seg_metatype(seg, idx) = AREA_UNASSIGNED;
+ break;
+ case RAID_IMAGE:
+ lv = seg_lv(seg, idx);
+ seg_lv(seg, idx) = NULL;
+ seg_type(seg, idx) = AREA_UNASSIGNED;
+ break;
+ default:
+ log_error(INTERNAL_ERROR "Bad type provided to %s.", __func__);
+ return 0;
+ }
+
+ log_very_verbose("Extracting image component %s from %s", lv->name, lvseg_name(seg));
+ lv->status &= ~(type | RAID);
+ lv_set_visible(lv);
+
+ /* remove reference from seg to lv */
+ if (!remove_seg_from_segs_using_this_lv(lv, seg))
+ return_0;
+
+ if (!(lv->name = _generate_raid_name(lv, "extracted_", -1)))
+ return_0;
+
+ if (set_error_seg && !replace_lv_with_error_segment(lv))
+ return_0;
+
+ *extracted_lv = lv;
+
+ return 1;
+}
+
+/*
+ * Extract all sub LVs of type from seg starting at idx excluding end and
+ * put them on removal_lvs setting mappings to "error" if error_seg.
+ */
+static int _extract_image_component_sublist(struct lv_segment *seg,
+ uint64_t type, uint32_t idx, uint32_t end,
+ struct dm_list *removal_lvs,
+ int error_seg)
+{
+ uint32_t s;
+ struct lv_list *lvl;
+
+ if (!(lvl = dm_pool_alloc(seg_lv(seg, idx)->vg->vgmem, sizeof(*lvl) * (end - idx))))
+ return_0;
+
+ for (s = idx; s < end; s++) {
+ if (!_extract_image_component_error_seg(seg, type, s, &lvl->lv, error_seg))
+ return 0;
+
+ dm_list_add(removal_lvs, &lvl->list);
+ lvl++;
+ }
+
+ if (!idx && end == seg->area_count) {
+ if (type == RAID_IMAGE)
+ seg->areas = NULL;
+ else
+ seg->meta_areas = NULL;
+ }
+
+ return 1;
+}
+
+/* Extract all sub LVs of type from seg starting with idx and put them on removal_Lvs */
+static int _extract_image_component_list(struct lv_segment *seg,
+ uint64_t type, uint32_t idx,
+ struct dm_list *removal_lvs)
+{
+ return _extract_image_component_sublist(seg, type, idx, seg->area_count, removal_lvs, 1);
+}
+
+/*
+ * All areas from lv image component LV's segments are
+ * being split at "striped" compatible boundaries and
+ * moved to allocated new_segments.
+ *
+ * The data component LVs are mapped to an
+ * error target and linked to removal_lvs for disposal
+ * by the caller.
+ */
+static int _raid0_to_striped_retrieve_segments_and_lvs(struct logical_volume *lv,
+ struct dm_list *removal_lvs)
+{
+ uint32_t s, area_le, area_len, le;
+ struct lv_segment *data_seg, *seg, *seg_to;
+ struct dm_list new_segments;
+
+ seg = first_seg(lv);
+
+ dm_list_init(&new_segments);
+
+ /*
+ * Walk all segments of all data LVs splitting them up at proper boundaries
+ * and create the number of new striped segments we need to move them across
+ */
+ area_le = le = 0;
+ while (le < lv->le_count) {
+ area_len = _min_sublv_area_at_le(seg, area_le);
+ area_le += area_len;
+
+ if (!_split_area_lvs_segments(seg, area_le) ||
+ !_alloc_and_add_new_striped_segment(lv, le, area_len, &new_segments))
+ return_0;
+
+ le = area_le * seg->area_count;
+ }
+
+ /* Now move the prepared split areas across to the new segments */
+ area_le = 0;
+ dm_list_iterate_items(seg_to, &new_segments) {
+ for (s = 0; s < seg->area_count; s++) {
+ data_seg = find_seg_by_le(seg_lv(seg, s), area_le);
+
+ /* Move the respective area across to our new segments area */
+ if (!move_lv_segment_area(seg_to, s, data_seg, 0))
+ return_0;
+ }
+
+ /* Presumes all data LVs have equal size */
+ area_le += data_seg->len;
+ }
+
+ /* Extract any metadata LVs and the empty data LVs for disposal by the caller */
+ if (!_extract_image_component_list(seg, RAID_IMAGE, 0, removal_lvs))
+ return_0;
+
+ /*
+ * Remove the one segment holding the image component areas
+ * from the top-level LV, then add the new segments to it
+ */
+ dm_list_del(&seg->list);
+ dm_list_splice(&lv->segments, &new_segments);
+
+ return 1;
+}
+
+/*
+ * Deactivate and remove the LVs on removal_lvs list from vg.
+ */
+static int _deactivate_and_remove_lvs(struct volume_group *vg, struct dm_list *removal_lvs)
+{
+ struct lv_list *lvl;
+
+ dm_list_iterate_items(lvl, removal_lvs)
+ if (!deactivate_lv(vg->cmd, lvl->lv) ||
+ !lv_remove(lvl->lv))
+ return_0;
+
+ return 1;
+}
+
+/* FIXME Move this out */
+/* Write, commit and optionally backup metadata of vg */
+static int _vg_write_commit_backup(struct volume_group *vg)
+{
+ if (!vg_write(vg) || !vg_commit(vg)) {
+ log_error("Failed to commit VG %s metadata.", vg->name);
+ return 0;
+ }
+
+ if (!backup(vg))
+ log_warn("WARNING: Backup of VG %s metadata failed. Continuing.", vg->name);
+
+ return 1;
+}
+
+/*
+ * Eliminate the extracted LVs on @removal_lvs from @vg incl. vg write, commit and backup
+ */
+static int _eliminate_extracted_lvs_optional_write_vg(struct volume_group *vg,
+ struct dm_list *removal_lvs,
+ int vg_write_requested)
+{
+ if (!removal_lvs || dm_list_empty(removal_lvs))
+ return 1;
+
+ if (!_deactivate_and_remove_lvs(vg, removal_lvs))
+ return_0;
+
+ dm_list_init(removal_lvs);
+
+ /* Wait for events following any deactivation. */
+ sync_local_dev_names(vg->cmd);
+
+ if (vg_write_requested && !_vg_write_commit_backup(vg))
+ return_0;
+
+ return 1;
+}
+
+static int _eliminate_extracted_lvs(struct volume_group *vg, struct dm_list *removal_lvs)
+{
+ return _eliminate_extracted_lvs_optional_write_vg(vg, removal_lvs, 1);
+}
+/*
+ * Convert a RAID0 set to striped
+ */
+static int _convert_raid0_to_striped(struct logical_volume *lv,
+ int update_and_reload,
+ struct dm_list *removal_lvs)
+{
+ struct lv_segment *seg = first_seg(lv);
+
+ /* Move the AREA_PV areas across to new top-level segments of type "striped" */
+ if (!_raid0_to_striped_retrieve_segments_and_lvs(lv, removal_lvs)) {
+ log_error("Failed to retrieve raid0 segments from %s.", lv->name);
+ return 0;
+ }
+
+ lv->status &= ~RAID;
+
+ if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
+ return_0;
+
+ if (update_and_reload) {
+ if (!lv_update_and_reload(lv))
+ return_0;
+
+ /* Eliminate the residual LVs, write VG, commit it and take a backup */
+ return _eliminate_extracted_lvs(lv->vg, removal_lvs);
+ }
+
+ return 1;
+}
+
+/*
+ * Inserts hidden LVs for all segments and the parallel areas in lv and moves
+ * given segments and areas across.
+ *
+ * Optionally updates metadata and reloads mappings.
+ */
+static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
+ int update_and_reload,
+ struct dm_list *allocate_pvs)
+{
+ uint32_t area_count, area_len = 0, stripe_size;
+ struct lv_segment *seg, *raid0_seg;
+ struct segment_type *segtype;
+ struct dm_list data_lvs;
+
+ dm_list_iterate_items(seg, &lv->segments)
+ area_len += seg->area_len;
+
+ seg = first_seg(lv);
+ stripe_size = seg->stripe_size;
+ area_count = seg->area_count;
+
+ /* Check for not (yet) supported varying area_count on multi-segment striped LVs */
+ if (!lv_has_constant_stripes(lv)) {
+ log_error("Cannot convert striped LV %s with varying stripe count to raid0",
+ display_lvname(lv));
+ return NULL;
+ }
+
+ if (!is_power_of_2(seg->stripe_size)) {
+ log_error("Cannot convert striped LV %s with non-power of 2 stripe size %u",
+ display_lvname(lv), seg->stripe_size);
+ // log_error("Please use \"lvconvert --duplicate ...\"");
+ return NULL;
+ }
+
+ if (!(segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0)))
+ return_NULL;
+
+ /* Allocate empty rimage components */
+ dm_list_init(&data_lvs);
+ if (!_alloc_image_components(lv, NULL, area_count, NULL, &data_lvs)) {
+ log_error("Failed to allocate empty image components for raid0 LV %s.",
+ display_lvname(lv));
+ return NULL;
+ }
+
+ /* Move the AREA_PV areas across to the new rimage components; empties lv->segments */
+ if (!_striped_to_raid0_move_segs_to_raid0_lvs(lv, &data_lvs)) {
+ log_error("Failed to insert linear LVs underneath %s.", display_lvname(lv));
+ return NULL;
+ }
+
+ /*
+ * Allocate single segment to hold the image component
+ * areas based on the first data LVs properties derived
+ * from the first new raid0 LVs first segment
+ */
+ seg = first_seg(dm_list_item(dm_list_first(&data_lvs), struct lv_list)->lv);
+ if (!(raid0_seg = alloc_lv_segment(segtype, lv,
+ 0 /* le */, lv->le_count /* len */,
+ seg->status | SEG_RAID,
+ stripe_size, NULL /* log_lv */,
+ area_count, area_len,
+ 0 /* chunk_size */,
+ 0 /* seg->region_size */, 0u /* extents_copied */ ,
+ NULL /* pvmove_source_seg */))) {
+ log_error("Failed to allocate new raid0 segement for LV %s.", display_lvname(lv));
+ return NULL;
+ }
+
+ /* Add new single raid0 segment to emptied LV segments list */
+ dm_list_add(&lv->segments, &raid0_seg->list);
+
+ /* Add data LVs to the top-level LVs segment; resets LV_REBUILD flag on them */
+ if (!_add_image_component_list(raid0_seg, 1, 0, &data_lvs, 0))
+ return NULL;
+
+ lv->status |= RAID;
+
+ if (update_and_reload && !lv_update_and_reload(lv))
+ return NULL;
+
+ return raid0_seg;
+}
+
/*
* Individual takeover functions.
*/
@@ -1480,7 +1950,7 @@ typedef int (*takeover_fn_t)(TAKEOVER_FN_ARGS);
*/
static int _takeover_noop(TAKEOVER_FN_ARGS)
{
- log_error("Logical volume %s is already of requested type %s",
+ log_error("Logical volume %s is already of requested type %s.",
display_lvname(lv), lvseg_name(first_seg(lv)));
return 0;
@@ -1500,9 +1970,9 @@ static int _takeover_unsupported(TAKEOVER_FN_ARGS)
static int _takeover_not_possible(takeover_fn_t takeover_fn)
{
if (takeover_fn == _takeover_noop || takeover_fn == _takeover_unsupported)
- return 0;
+ return 1;
- return 1;
+ return 0;
}
static int _takeover_unsupported_yet(const struct logical_volume *lv, const struct segment_type *new_segtype)
@@ -1598,7 +2068,16 @@ static int _takeover_from_raid0_to_raid6(TAKEOVER_FN_ARGS)
static int _takeover_from_raid0_to_striped(TAKEOVER_FN_ARGS)
{
- return _takeover_unsupported_yet(lv, new_segtype);
+ struct dm_list removal_lvs;
+
+ dm_list_init(&removal_lvs);
+
+ /* Archive metadata */
+ if (!archive(lv->vg))
+ return_0;
+
+ /* FIXME update_and_reload is only needed if the LV is already active */
+ return _convert_raid0_to_striped(lv, 1, &removal_lvs);
}
/*
@@ -1743,9 +2222,26 @@ static int _takeover_from_raid6_to_striped(TAKEOVER_FN_ARGS)
return _takeover_unsupported_yet(lv, new_segtype);
}
+static int _striped_to_raid0_wrapper(struct logical_volume *lv,
+ const struct segment_type *new_segtype,
+ int yes, int force, int alloc_metadata_devs,
+ struct dm_list *allocate_pvs)
+{
+ /* Archive metadata */
+ if (!archive(lv->vg))
+ return_0;
+
+ /* FIXME update_and_reload is only needed if the LV is already active */
+ /* FIXME Some of the validation in here needs moving before the archiving */
+ if (!_convert_striped_to_raid0(lv, 1 /* update_and_reload */, allocate_pvs))
+ return_0;
+
+ return 1;
+}
+
static int _takeover_from_striped_to_raid0(TAKEOVER_FN_ARGS)
{
- return _takeover_unsupported_yet(lv, new_segtype);
+ return _striped_to_raid0_wrapper(lv, new_segtype, yes, force, 0, allocate_pvs);
}
static int _takeover_from_striped_to_raid01(TAKEOVER_FN_ARGS)
@@ -1921,6 +2417,7 @@ int lv_raid_convert(struct logical_volume *lv,
return takeover_fn(lv, new_segtype, yes, force, new_image_count, new_stripes, new_stripe_size, allocate_pvs);
/* FIXME If not active, prompt and activate */
+ /* FIXME Some operations do not require the LV to be active */
/* LV must be active to perform raid conversion operations */
if (!lv_is_active(lv)) {
log_error("%s must be active to perform this operation.",
diff --git a/lib/metadata/segtype.c b/lib/metadata/segtype.c
index 0e17111..8d8b28c 100644
--- a/lib/metadata/segtype.c
+++ b/lib/metadata/segtype.c
@@ -34,3 +34,16 @@ struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
return segtype;
}
+
+struct segment_type *get_segtype_from_flag(struct cmd_context *cmd, uint64_t flag)
+{
+ struct segment_type *segtype;
+
+ dm_list_iterate_items(segtype, &cmd->segtypes)
+ if (flag & segtype->flags)
+ return segtype;
+
+ log_error(INTERNAL_ERROR "Unrecognised segment type flag 0x%" PRIu64, flag);
+
+ return NULL;
+}
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index f3b1510..b43f228 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -222,6 +222,8 @@ struct segtype_handler {
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
const char *str);
+struct segment_type *get_segtype_from_flag(struct cmd_context *cmd,
+ uint64_t flag);
struct segtype_library;
int lvm_register_segtype(struct segtype_library *seglib,
diff --git a/lib/misc/util.h b/lib/misc/util.h
index 1011fdd..730b903 100644
--- a/lib/misc/util.h
+++ b/lib/misc/util.h
@@ -27,6 +27,8 @@
(void) (&_a == &_b); \
_a > _b ? _a : _b; })
+#define is_power_of_2(n) ((n) && !((n) & ((n) - 1)))
+
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
#define uninitialized_var(x) x
#else
7 years, 5 months
master - lvmdbustest: Comment out refresh check for LV create
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6f216692b47b38...
Commit: 6f216692b47b38f480e50d213de5c513a309d9e0
Parent: 1d3532d0a7d458550b53218a6b21798eab30b68e
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 13:36:32 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 13:36:32 2016 -0500
lvmdbustest: Comment out refresh check for LV create
When we test Vg.LvCreateRaid some of the hidden LVs volume type go from
'I' to 'i' between the time it takes us to create the LV and
the time it takes to call into refresh to verify the service is up to date.
This is a fairly rare occurance.
---
test/dbus/lvmdbustest.py | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
index 4443b0c..457db96 100755
--- a/test/dbus/lvmdbustest.py
+++ b/test/dbus/lvmdbustest.py
@@ -373,7 +373,11 @@ class TestDbusService(unittest.TestCase):
lv = ClientProxy(self.bus, path)
# TODO verify object properties
- self.assertEqual(self._refresh(), 0)
+ # We are quick enough now that we can get VolumeType changes from
+ # 'I' to 'i' between the time it takes to create a RAID and it returns
+ # and when we refresh state here. Not sure how we can handle this as
+ # we cannot just sit and poll all the time for changes...
+ # self.assertEqual(self._refresh(), 0)
return lv
def test_lv_create(self):
7 years, 5 months
master - lvmdbusd: Add --nojson command line option
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1d3532d0a7d458...
Commit: 1d3532d0a7d458550b53218a6b21798eab30b68e
Parent: e6e5c3d3ecb7de18ec2d103df8e5b0229df9ce1c
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 13:32:39 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 13:32:39 2016 -0500
lvmdbusd: Add --nojson command line option
Add ability to not use the JSON output even if available.
---
daemons/lvmdbusd/main.py | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/daemons/lvmdbusd/main.py b/daemons/lvmdbusd/main.py
index aa16a2e..f28b402 100644
--- a/daemons/lvmdbusd/main.py
+++ b/daemons/lvmdbusd/main.py
@@ -101,6 +101,10 @@ def main():
help="Dump debug messages", default=False,
dest='debug')
+ parser.add_argument("--nojson", action='store_false',
+ help="Do not use LVM JSON output", default=None,
+ dest='use_json')
+
use_session = os.getenv('LVMDBUSD_USE_SESSION', False)
# Ensure that we get consistent output for parsing stdout/stderr
@@ -137,7 +141,7 @@ def main():
cfg.load = load
- cfg.db = lvmdb.DataStore()
+ cfg.db = lvmdb.DataStore(args.use_json)
# Start up thread to monitor pv moves
thread_list.append(
7 years, 5 months
master - lvmdbusd: Remove WARNING for 'lvm help'
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e6e5c3d3ecb7de...
Commit: e6e5c3d3ecb7de18ec2d103df8e5b0229df9ce1c
Parent: 7c5a08521b687c7c7074b41d880e1e559d4ea6b8
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:52:31 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:54:48 2016 -0500
lvmdbusd: Remove WARNING for 'lvm help'
We call 'lvm help' to find out if fullreport is supported. Lvm
dumps help to stderr. Common code prints a warning if we exit
with 0, but have something in stderr so we are skipping the warning
message.
---
daemons/lvmdbusd/cmdhandler.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/daemons/lvmdbusd/cmdhandler.py b/daemons/lvmdbusd/cmdhandler.py
index 560b389..391757d 100644
--- a/daemons/lvmdbusd/cmdhandler.py
+++ b/daemons/lvmdbusd/cmdhandler.py
@@ -110,7 +110,7 @@ def call_lvm(command, debug=False):
_debug_c(command, process.returncode, (stdout_text, stderr_text))
if process.returncode == 0:
- if cfg.DEBUG and out[1] and len(out[1]):
+ if cfg.DEBUG and out[1] and len(out[1]) and 'help' not in command:
log_error('WARNING: lvm is out-putting text to STDERR on success!')
_debug_c(command, process.returncode, (stdout_text, stderr_text))
7 years, 5 months
master - lvmdbusd: Remove unneeded comment
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7c5a08521b687c...
Commit: 7c5a08521b687c7c7074b41d880e1e559d4ea6b8
Parent: 9e3ad37828a14924dd12f65e62194bef286a16f0
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:45:55 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:45:55 2016 -0500
lvmdbusd: Remove unneeded comment
---
daemons/lvmdbusd/lv.py | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/daemons/lvmdbusd/lv.py b/daemons/lvmdbusd/lv.py
index 8f063dc..5658d29 100644
--- a/daemons/lvmdbusd/lv.py
+++ b/daemons/lvmdbusd/lv.py
@@ -472,8 +472,6 @@ class Lv(LvCommon):
# it is a thin lv
if not dbo.IsThinVolume:
if optional_size == 0:
- # TODO: Should we pick a sane default or force user to
- # make a decision?
space = dbo.SizeBytes / 80
remainder = space % 512
optional_size = space + 512 - remainder
7 years, 5 months
master - lvmdbusd: Clean up ws
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9e3ad37828a149...
Commit: 9e3ad37828a14924dd12f65e62194bef286a16f0
Parent: c11003c860fe9242f49ba6ccffadd964501f1d1f
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:45:28 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:45:28 2016 -0500
lvmdbusd: Clean up ws
---
daemons/lvmdbusd/cmdhandler.py | 2 +-
daemons/lvmdbusd/lvmdb.py | 1 -
daemons/lvmdbusd/objectmanager.py | 2 +-
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/daemons/lvmdbusd/cmdhandler.py b/daemons/lvmdbusd/cmdhandler.py
index 138142f..560b389 100644
--- a/daemons/lvmdbusd/cmdhandler.py
+++ b/daemons/lvmdbusd/cmdhandler.py
@@ -448,7 +448,7 @@ def lvm_full_report_json():
'vg_uuid']
pv_seg_columns = ['pvseg_start', 'pvseg_size', 'segtype',
- 'pv_uuid', 'lv_uuid', 'pv_name']
+ 'pv_uuid', 'lv_uuid', 'pv_name']
vg_columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
'vg_sysid', 'vg_extent_size', 'vg_extent_count',
diff --git a/daemons/lvmdbusd/lvmdb.py b/daemons/lvmdbusd/lvmdb.py
index 51794d5..2dc593b 100755
--- a/daemons/lvmdbusd/lvmdb.py
+++ b/daemons/lvmdbusd/lvmdb.py
@@ -234,7 +234,6 @@ class DataStore(object):
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
-
@staticmethod
def _parse_lvs_json(_all):
diff --git a/daemons/lvmdbusd/objectmanager.py b/daemons/lvmdbusd/objectmanager.py
index c93f207..178003e 100644
--- a/daemons/lvmdbusd/objectmanager.py
+++ b/daemons/lvmdbusd/objectmanager.py
@@ -224,7 +224,7 @@ class ObjectManager(AutomatedProperties):
return path
def get_object_path_by_uuid_lvm_id(self, uuid, lvm_id, path_create=None,
- gen_new=True):
+ gen_new=True):
"""
For a given lvm asset return the dbus object registered to it. If the
object is not found and gen_new == True and path_create is a valid
7 years, 5 months
master - lvmdbusd: Remove unused imports and function parameter
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c11003c860fe92...
Commit: c11003c860fe9242f49ba6ccffadd964501f1d1f
Parent: dd5d865020acd545712d4bcc0f3236143de4d76d
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:44:45 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:44:45 2016 -0500
lvmdbusd: Remove unused imports and function parameter
---
daemons/lvmdbusd/background.py | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/daemons/lvmdbusd/background.py b/daemons/lvmdbusd/background.py
index ca3d60e..2c719fc 100644
--- a/daemons/lvmdbusd/background.py
+++ b/daemons/lvmdbusd/background.py
@@ -13,9 +13,7 @@ from . import cfg
import time
from .cmdhandler import options_to_cli_args
import dbus
-from .job import Job, JobState
-from .utils import pv_range_append, pv_dest_ranges, log_debug, log_error
-from .request import RequestEntry
+from .utils import pv_range_append, pv_dest_ranges, log_error
import traceback
_rlock = threading.RLock()
@@ -125,7 +123,7 @@ def background_reaper():
time.sleep(3)
-def background_execute(command, background_job, skip_first_line=False):
+def background_execute(command, background_job):
# Wrap this whole operation in an exception handler, otherwise if we
# hit a code bug we will silently exit this thread without anyone being
7 years, 5 months