[lvm-devel] master - thin: fix error paths for metadata creation

Zdenek Kabelac zkabelac at fedoraproject.org
Thu Jul 18 16:26:41 UTC 2013


Gitweb:        http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d72f34af418b90c71e8e96f408d4953e679e0895
Commit:        d72f34af418b90c71e8e96f408d4953e679e0895
Parent:        7afa9cebcbce0232c0c889cb3f112f66d10a79b0
Author:        Zdenek Kabelac <zkabelac at redhat.com>
AuthorDate:    Thu Jul 18 16:01:38 2013 +0200
Committer:     Zdenek Kabelac <zkabelac at 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)




More information about the lvm-devel mailing list