[lvm-devel] [PATCH 4/4] lvm2app: Implement lv resize

Tony Asleson tasleson at redhat.com
Wed Jan 9 05:53:17 UTC 2013


When re-sizing a LV with the command line, after the re-size
occurs the code used to do a vg_write and then a number of
operations before and after the commit.  As the API requires
the ability to have the re-size done independantly of the
write and commit a flag was added so that when we go through
vg_commit we will do the same required steps to commit the
lv size change regardless if it was done through the command
line or the API.

Signed-off-by: Tony Asleson <tasleson at redhat.com>
---
 lib/format_text/flags.c          |  1 +
 lib/metadata/lv_manip.c          | 68 ++----------------------------
 lib/metadata/metadata-exported.h |  8 ++++
 lib/metadata/metadata.c          | 90 +++++++++++++++++++++++++++++++++++++++-
 liblvm/lvm2app.h                 |  2 -
 liblvm/lvm_lv.c                  | 19 +++++++--
 tools/lvresize.c                 | 32 ++++++++++----
 7 files changed, 142 insertions(+), 78 deletions(-)

diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index a3a3d0e..4edf7e1 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -77,6 +77,7 @@ static const struct flag _lv_flags[] = {
 	{THIN_POOL, NULL, 0},
 	{THIN_POOL_DATA, NULL, 0},
 	{THIN_POOL_METADATA, NULL, 0},
+	{LV_RESIZE, NULL, 0},
 	{0, NULL, 0}
 };
 
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 26a137d..dd5f0ce 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3047,10 +3047,6 @@ int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
  * Core lv resize code
  */
 
-#define SIZE_BUF 128
-
-
-
 static int _validate_stripesize(struct cmd_context *cmd,
 				const struct volume_group *vg,
 				struct lvresize_params *lp)
@@ -3123,8 +3119,7 @@ static int _request_confirmation(struct cmd_context *cmd,
 
 	return 1;
 }
-
-enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
+#define SIZE_BUF 128
 #define FSADM_CMD "fsadm"
 #define FSADM_CMD_MAX_ARGS 6
 #define FSADM_CHECK_FAILS_FOR_MOUNTED 3 /* shell exist status code */
@@ -3133,7 +3128,7 @@ enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
  * FSADM_CMD --dry-run --verbose --force check lv_path
  * FSADM_CMD --dry-run --verbose --force resize lv_path size
  */
-static int _fsadm_cmd(struct cmd_context *cmd,
+int _fsadm_cmd(struct cmd_context *cmd,
 		      const struct volume_group *vg,
 		      const struct lvresize_params *lp,
 		      enum fsadm_cmd_e fcmd,
@@ -3277,7 +3272,6 @@ int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 	uint32_t size_rest;
 	uint32_t pv_extent_count;
 	alloc_policy_t alloc;
-	struct logical_volume *lock_lv;
 	struct lv_list *lvl;
 	struct lv_segment *seg, *uninitialized_var(mirr_seg);
 	uint32_t seg_extents;
@@ -3714,62 +3708,8 @@ int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		return ECMD_FAILED;
 	}
 
-	/* store vg on disk(s) */
-	if (!vg_write(vg)) {
-		stack;
-		return ECMD_FAILED;
-	}
-
-	/* If snapshot, must suspend all associated devices */
-	if (lv_is_cow(lv))
-		lock_lv = origin_from_cow(lv);
-	else
-		lock_lv = lv;
-
-	if (!suspend_lv(cmd, lock_lv)) {
-		log_error("Failed to suspend %s", lp->lv_name);
-		vg_revert(vg);
-		backup(vg);
-		return ECMD_FAILED;
-	}
-
-	if (!vg_commit(vg)) {
-		stack;
-		if (!resume_lv(cmd, lock_lv))
-			stack;
-		backup(vg);
-		return ECMD_FAILED;
-	}
-
-	if (!resume_lv(cmd, lock_lv)) {
-		log_error("Problem reactivating %s", lp->lv_name);
-		backup(vg);
-		return ECMD_FAILED;
-	}
-
-	backup(vg);
-
-	/*
-	 * Update lvm pool metadata (drop messages) if the pool has been
-	 * resumed and do a pool active/deactivate in other case.
-	 *
-	 * Note: Active thin pool can be waiting for resize.
-	 *
-	 * FIXME: Activate only when thin volume is active
-	 */
-	if (lv_is_thin_pool(lv) &&
-	    !update_pool_lv(lv, !lv_is_active(lv))) {
-		stack;
-		return ECMD_FAILED;
-	}
-
-	log_print_unless_silent("Logical volume %s successfully resized", lp->lv_name);
-
-	if (lp->resizefs && (lp->resize == LV_EXTEND) &&
-	    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL)) {
-		stack;
-		return ECMD_FAILED;
-	}
+	/* Set the flag to tell commit that we have addl. work todo*/
+	lv->status |= LV_RESIZE;
 
 	return ECMD_PROCESSED;
 }
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 040b2e5..a04addd 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -26,6 +26,7 @@
 #include "vg.h"
 #include "lv.h"
 #include "lvm-percent.h"
+#include "errors.h"
 
 #define MAX_STRIPES 128U
 #define SECTOR_SHIFT 9L
@@ -64,6 +65,7 @@
 
 #define LV_NOTSYNCED		UINT64_C(0x00080000)	/* LV */
 #define LV_REBUILD		UINT64_C(0x00100000)	/* LV */
+#define LV_RESIZE		UINT64_C(0x00200000)	/* LV - internal use only */
 //#define PRECOMMITTED		UINT64_C(0x00200000)	/* VG - internal use only */
 #define CONVERTING		UINT64_C(0x00400000)	/* LV */
 
@@ -500,6 +502,12 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname);
 int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		     struct lvresize_params *lp, struct dm_list *pvh);
 
+enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
+int _fsadm_cmd(struct cmd_context *cmd,
+		      const struct volume_group *vg,
+		      const struct lvresize_params *lp,
+		      enum fsadm_cmd_e fcmd,
+		      int *status);
 /*
  * Return a handle to VG metadata.
  */
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index a472b18..30f1f0b 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2703,6 +2703,79 @@ static int _vg_commit_mdas(struct volume_group *vg)
 	return cache_updated;
 }
 
+/* Check to see if we have a lv that was re-sized, if yes then suspend the lv */
+static int _pre_lv_resize(struct volume_group *vg)
+{
+	struct lv_list *lvl = NULL;
+	struct logical_volume *lock_lv = NULL;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (lvl->lv->status & LV_RESIZE) {
+			if (lv_is_cow(lvl->lv))
+				lock_lv = origin_from_cow(lvl->lv);
+			else
+				lock_lv = lvl->lv;
+
+			if (!suspend_lv(vg->cmd, lock_lv)) {
+				log_error("Failed to suspend %s", lvl->lv->name);
+				vg_revert(vg);
+				backup(vg);
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+/* If we have lv resize then resume the suspended lv */
+static int _post_lv_resize(struct volume_group *vg, int ok)
+{
+	struct lv_list *lvl = NULL;
+	struct logical_volume *lock_lv = NULL;
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (lvl->lv->status & LV_RESIZE) {
+
+			/* Clear the flag */
+			lvl->lv->status &= ~LV_RESIZE;
+
+			if (lv_is_cow(lvl->lv))
+				lock_lv = origin_from_cow(lvl->lv);
+			else
+				lock_lv = lvl->lv;
+
+			if (!resume_lv(vg->cmd, lock_lv)) {
+				log_error("Problem reactivating %s", lvl->lv->name);
+				backup(vg);
+				return_0;
+			}
+
+			backup(vg);
+
+			/* We could have been called after an error has occurred, in that
+			   case we will not do the next step */
+			if (ok) {
+
+				/*
+				* Update lvm pool metadata (drop messages) if the pool has been
+				* resumed and do a pool active/deactivate in other case.
+				*
+				* Note: Active thin pool can be waiting for resize.
+				*
+				* FIXME: Activate only when thin volume is active
+				*/
+				if (lv_is_thin_pool(lvl->lv) &&
+					!update_pool_lv(lvl->lv, !lv_is_active(lvl->lv))) {
+					return_0;
+				}
+			}
+		}
+	}
+
+	return 1;
+}
+
+
 /* Commit pending changes */
 int vg_commit(struct volume_group *vg)
 {
@@ -2714,9 +2787,15 @@ int vg_commit(struct volume_group *vg)
 		return cache_updated;
 	}
 
+	if (!_pre_lv_resize(vg))
+		return_0;
+
 	/* Skip if we already did this in vg_write */
 	if ((vg->fid->fmt->features & FMT_PRECOMMIT) && !lvmetad_vg_update(vg))
-		return_0;
+	{
+		cache_updated = 0;
+		goto_out;
+	}
 
 	cache_updated = _vg_commit_mdas(vg);
 
@@ -2736,6 +2815,15 @@ int vg_commit(struct volume_group *vg)
 		log_error("Attempt to drop cached metadata failed "
 			  "after commit for VG %s.", vg->name);
 
+out:
+	if (!_post_lv_resize(vg, cache_updated)) {
+		cache_updated = 0;
+	}
+
+	if (!cache_updated) {
+		stack;
+	}
+
 	/* If at least one mda commit succeeded, it was committed */
 	return cache_updated;
 }
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 00f92ab..7515973 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1365,8 +1365,6 @@ int lvm_lv_rename(lv_t lv, const char *new_name);
  *
  * \memberof lv_t
  *
- * NOTE: This function is currently not implemented.
- *
  * \param   lv
  * Logical volume handle.
  *
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 91948a6..7e8b469 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -309,9 +309,22 @@ int lvm_lv_rename(lv_t lv, const char *new_name)
 
 int lvm_lv_resize(const lv_t lv, uint64_t new_size)
 {
-	/* FIXME: add lv resize code here */
-	log_error("NOT IMPLEMENTED YET");
-	return -1;
+	struct lvresize_params lp = { 0 };
+
+	lp.vg_name = lv->vg->name;
+	lp.lv_name = lv->name;
+	lp.sign = SIGN_NONE;
+	lp.percent = PERCENT_NONE;
+	lp.resize = LV_ANY;
+	lp.size = new_size >> SECTOR_SHIFT;
+	lp.ac_force = 1;	/* Assume the user has a good backup? */
+
+	if (ECMD_PROCESSED != _lvresize(lv->vg->cmd, lv->vg, &lp, &lv->vg->pvs)) {
+		log_verbose("LV Re-size failed.");
+		return -1;
+	}
+
+	return 0;
 }
 
 lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name, uint64_t max_snap_size)
diff --git a/tools/lvresize.c b/tools/lvresize.c
index bb576e0..3a8c464 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -14,8 +14,7 @@
  */
 
 #include "tools.h"
-
-
+#include "metadata.h"
 
 static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
 			    struct lvresize_params *lp)
@@ -161,7 +160,6 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
 	if (!_lvresize_params(cmd, argc, argv, &lp))
 		return EINVALID_CMD_LINE;
 
-
 	log_verbose("Finding volume group %s", lp.vg_name);
 	vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
 	if (vg_read_error(vg)) {
@@ -173,14 +171,32 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
 	/* How does this list get cleaned up? */
 	if (!(pvh = lp.argc ? create_pv_list(cmd->mem, vg, lp.argc,
 						     lp.argv, 1) : &vg->pvs)) {
-		stack;
-		return ECMD_FAILED;
+		r = ECMD_FAILED;
+		goto_out;
 	}
 
-	if (!(r = _lvresize(cmd, vg, &lp, pvh)))
-		stack;
+	r = _lvresize(cmd, vg, &lp, pvh);
 
-	unlock_and_release_vg(cmd, vg, lp.vg_name);
+	if (ECMD_PROCESSED == r) {
+		if (!vg_write(vg)) {
+			r = ECMD_FAILED;
+			goto_out;
+		}
 
+		if (!vg_commit(vg)) {
+			r = ECMD_FAILED;
+			goto_out;
+		}
+
+		log_print_unless_silent("Logical volume %s successfully resized", lp.lv_name);
+
+		if (lp.resizefs && (lp.resize == LV_EXTEND) &&
+			!_fsadm_cmd(cmd, vg, &lp, FSADM_CMD_RESIZE, NULL)) {
+			r = ECMD_FAILED;
+		}
+	}
+
+out:
+	unlock_and_release_vg(cmd, vg, lp.vg_name);
 	return r;
 }
-- 
1.7.11.7




More information about the lvm-devel mailing list