All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] Looking for reviews
@ 2013-05-08 22:45 Tony Asleson
  2013-05-08 22:45 ` [PATCH 01/19] lvm2app: Add thin and thin pool lv creation V4 Tony Asleson
                   ` (18 more replies)
  0 siblings, 19 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Many of these patches have been around for a while.
Looking for comments.  If I don't hear anything I
will assume everything is good and push them in the
next few days.

Thanks,
Tony

Tony Asleson (19):
  lvm2app: Add thin and thin pool lv creation V4
  lvm2app: Implementation of pv resize (v6)
  lvm2app: Move percent_of_extents to lvm-percent.[h|c]
  lvm2app: Rework argument handling for lv resize
  lvm2app: Move core lv re-size code (v2)
  lvm2app: Implement lv resize (v2)
  lvm2app: Add function to retrieve list of PVs
  lvm2app: Implement lvm_pv_remove
  python-lvm: Add bindings for lvm_pv_remove
  lvm2app: Set suppress to 1
  _get_pvs: Remove unused variable
  lib2app: Fix warnings in lvm_list_pvs_free
  lib2app: Added PV create.
  python-lvm: Add pvCreate python method
  lvm2app: Add method to retrieve attr from lv.
  python-lvm: Add method to retrieve lv attr.
  lvm2app: Add function to retrieve the origin.
  python-lvm: Added lv method getOrigin
  python-lvm: Bindings for thin pool, thin lv creation V3

 lib/metadata/lv_manip.c          | 734 ++++++++++++++++++++++++++++++++++++
 lib/metadata/metadata-exported.h |  59 ++-
 lib/metadata/metadata.c          |  82 ++--
 lib/metadata/metadata.h          |   7 +
 lib/metadata/pv_manip.c          | 152 ++++++++
 lib/misc/lvm-percent.c           |   5 +
 lib/misc/lvm-percent.h           |  17 +
 lib/report/columns.h             |   2 +
 lib/report/properties.c          |  30 ++
 lib/report/properties.h          |   6 +
 lib/report/report.c              |   1 +
 lib/report/report.h              |   3 +-
 liblvm/lvm2app.h                 | 219 ++++++++++-
 liblvm/lvm_base.c                |   6 +
 liblvm/lvm_lv.c                  | 241 +++++++++++-
 liblvm/lvm_misc.c                |  16 +-
 liblvm/lvm_misc.h                |   6 +-
 liblvm/lvm_pv.c                  | 135 ++++++-
 liblvm/lvm_vg.c                  |   4 +-
 python/liblvm.c                  | 331 +++++++++++++++-
 tools/lvresize.c                 | 793 ++-------------------------------------
 tools/pvcreate.c                 |  11 +-
 tools/pvremove.c                 | 135 +------
 tools/reporter.c                 |   4 +
 tools/toollib.c                  |   6 -
 tools/tools.h                    |  16 -
 26 files changed, 2049 insertions(+), 972 deletions(-)

-- 
1.8.1.4



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/19] lvm2app: Add thin and thin pool lv creation V4
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 02/19] lvm2app: Implementation of pv resize (v6) Tony Asleson
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Add thin and thin pool lv creation support to lvm library

This is Mohan's thinp patch, re-worked to include suggestions
from Zdenek and Mohan.

V2: Remove const lvm_lv_params_create_thin
    Add const lvm_lv_params_skip_zero_get

V3: Changed get/set to use generic functions like current
    property

V4: Corrected macro in properties.c

Based on work done by M. Mohan Kumar <mohan@in.ibm.com>

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/report/columns.h    |   2 +
 lib/report/properties.c |  30 +++++++
 lib/report/properties.h |   6 ++
 lib/report/report.c     |   1 +
 lib/report/report.h     |   3 +-
 liblvm/lvm2app.h        | 133 ++++++++++++++++++++++++++++++
 liblvm/lvm_lv.c         | 212 +++++++++++++++++++++++++++++++++++++++++++++++-
 liblvm/lvm_misc.c       |  16 +++-
 liblvm/lvm_misc.h       |   6 +-
 liblvm/lvm_pv.c         |   4 +-
 liblvm/lvm_vg.c         |   4 +-
 tools/reporter.c        |   4 +
 12 files changed, 410 insertions(+), 11 deletions(-)

diff --git a/lib/report/columns.h b/lib/report/columns.h
index 201b3c4..5364f20 100644
--- a/lib/report/columns.h
+++ b/lib/report/columns.h
@@ -160,4 +160,6 @@ FIELD(SEGS, seg, STR, "Monitor", list, 7, segmonitor, monitor, "Dmeventd monitor
 
 FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, pvseg_start, "Physical Extent number of start of segment.", 0)
 FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, pvseg_size, "Number of extents in segment.", 0)
+
+FIELD(LV_CREATE_PARAMS, lvcreate_params, NUM, "skip_zero", zero, 2, uint32, skip_zero, "Skip zeroing on lv creation", 1)
 /* *INDENT-ON* */
diff --git a/lib/report/properties.c b/lib/report/properties.c
index 03ebc6f..2e60c67 100644
--- a/lib/report/properties.c
+++ b/lib/report/properties.c
@@ -39,6 +39,9 @@ static int _ ## NAME ## _get (const void *obj, struct lvm_property_type *prop) \
 	GET_NUM_PROPERTY_FN(NAME, VALUE, lv_segment, lvseg)
 #define GET_PVSEG_NUM_PROPERTY_FN(NAME, VALUE) \
 	GET_NUM_PROPERTY_FN(NAME, VALUE, pv_segment, pvseg)
+#define GET_LVCREATEPARAMS_NUM_PROPERTY_FN(NAME, VALUE)\
+	GET_NUM_PROPERTY_FN(NAME, VALUE, lvcreate_params, lvcp)
+
 
 #define SET_NUM_PROPERTY_FN(NAME, SETFN, TYPE, VAR)			\
 static int _ ## NAME ## _set (void *obj, struct lvm_property_type *prop) \
@@ -48,6 +51,15 @@ static int _ ## NAME ## _set (void *obj, struct lvm_property_type *prop) \
 	SETFN(VAR, prop->value.integer);		\
 	return 1; \
 }
+
+#define SET_NUM_PROPERTY(NAME, VALUE, TYPE, VAR)			\
+static int _ ## NAME ## _set (void *obj, struct lvm_property_type *prop) \
+{ \
+	struct TYPE *VAR = (struct TYPE *)obj; \
+\
+	VALUE = prop->value.integer;		\
+	return 1; \
+}
 #define SET_VG_NUM_PROPERTY_FN(NAME, SETFN) \
 	SET_NUM_PROPERTY_FN(NAME, SETFN, volume_group, vg)
 #define SET_PV_NUM_PROPERTY_FN(NAME, SETFN) \
@@ -55,6 +67,9 @@ static int _ ## NAME ## _set (void *obj, struct lvm_property_type *prop) \
 #define SET_LV_NUM_PROPERTY_FN(NAME, SETFN) \
 	SET_NUM_PROPERTY_FN(NAME, SETFN, logical_volume, lv)
 
+#define SET_LVCREATEPARAMS_NUM_PROPERTY_FN(NAME, VALUE) \
+	SET_NUM_PROPERTY(NAME, VALUE, lvcreate_params, lvcp)
+
 #define GET_STR_PROPERTY_FN(NAME, VALUE, TYPE, VAR)			\
 static int _ ## NAME ## _get (const void *obj, struct lvm_property_type *prop) \
 { \
@@ -344,6 +359,9 @@ GET_PVSEG_NUM_PROPERTY_FN(pvseg_start, pvseg->pe)
 GET_PVSEG_NUM_PROPERTY_FN(pvseg_size, (SECTOR_SIZE * pvseg->len))
 #define _pvseg_size_set _not_implemented_set
 
+/* lv create parameters */
+GET_LVCREATEPARAMS_NUM_PROPERTY_FN(skip_zero, lvcp->zero)
+SET_LVCREATEPARAMS_NUM_PROPERTY_FN(skip_zero, lvcp->zero)
 
 #define STR DM_REPORT_FIELD_TYPE_STRING
 #define NUM DM_REPORT_FIELD_TYPE_NUMBER
@@ -448,6 +466,18 @@ int pvseg_get_property(const struct pv_segment *pvseg,
 	return _get_property(pvseg, prop, PVSEGS);
 }
 
+int lv_create_param_get_property(const struct lvcreate_params *lvcp,
+		struct lvm_property_type *prop)
+{
+	return _get_property(lvcp, prop, LV_CREATE_PARAMS);
+}
+
+int lv_create_param_set_property(struct lvcreate_params *lvcp,
+		    struct lvm_property_type *prop)
+{
+	return _set_property(lvcp, prop, LV_CREATE_PARAMS);
+}
+
 int pv_get_property(const struct physical_volume *pv,
 		    struct lvm_property_type *prop)
 {
diff --git a/lib/report/properties.h b/lib/report/properties.h
index aefd3f5..1a08589 100644
--- a/lib/report/properties.h
+++ b/lib/report/properties.h
@@ -50,4 +50,10 @@ int vg_set_property(struct volume_group *vg,
 int pv_set_property(struct physical_volume *pv,
 		    struct lvm_property_type *prop);
 
+int lv_create_param_get_property(const struct lvcreate_params *lvcp,
+		struct lvm_property_type *prop);
+
+int lv_create_param_set_property(struct lvcreate_params *lvcp,
+		    struct lvm_property_type *prop);
+
 #endif
diff --git a/lib/report/report.c b/lib/report/report.c
index 27c9708..bf241ea 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -1234,6 +1234,7 @@ typedef struct logical_volume type_lv;
 typedef struct volume_group type_vg;
 typedef struct lv_segment type_seg;
 typedef struct pv_segment type_pvseg;
+typedef struct lvcreate_params type_lvcreate_params;
 
 static const struct dm_report_field_type _fields[] = {
 #include "columns.h"
diff --git a/lib/report/report.h b/lib/report/report.h
index 26cc2f7..d5bfb6a 100644
--- a/lib/report/report.h
+++ b/lib/report/report.h
@@ -24,7 +24,8 @@ typedef enum {
 	VGS	= 4,
 	SEGS	= 8,
 	PVSEGS	= 16,
-	LABEL	= 32
+	LABEL	= 32,
+	LV_CREATE_PARAMS = 64
 } report_type_t;
 
 struct field;
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 93a78c3..b1d6abd 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -97,6 +97,7 @@ struct volume_group;
 struct logical_volume;
 struct lv_segment;
 struct pv_segment;
+struct lvm_lv_create_params;
 
 /**
  * \class lvm_t
@@ -153,6 +154,14 @@ typedef struct lv_segment *lvseg_t;
 typedef struct pv_segment *pvseg_t;
 
 /**
+ * \class lv_create_params
+ *
+ * This lv_create_params represents the plethora of available options when
+ * creating a logical volume
+ */
+typedef struct lvm_lv_create_params *lv_create_params_t;
+
+/**
  * Logical Volume object list.
  *
  * Lists of these structures are returned by lvm_vg_list_lvs().
@@ -1400,6 +1409,130 @@ int lvm_lv_resize(const lv_t lv, uint64_t new_size);
  */
 lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name, uint64_t max_snap_size);
 
+/**
+ * Thin provisioning discard policies
+ */
+typedef enum {
+	LVM_THIN_DISCARDS_IGNORE,
+	LVM_THIN_DISCARDS_NO_PASSDOWN,
+	LVM_THIN_DISCARDS_PASSDOWN,
+} lvm_thin_discards_t;
+
+/**
+ * Create a thinpool parameter passing object for the specified VG
+ *
+ * \param   vg
+ * Volume Group handle.
+ *
+ * \param   pool_name
+ * Name of the pool.
+ *
+ * \param   size
+ * size of the pool
+ *
+ * \param   chunk_size
+ * data block size of the pool
+ * Default value is DEFAULT_THIN_POOL_CHUNK_SIZE * 2 when 0 passed as chunk_size
+ * DM_THIN_MIN_DATA_BLOCK_SIZE < chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE
+ *
+ * \param meta_size
+ * Size of thin pool's metadata logical volume. Allowed range is 2MB-16GB.
+ * Default value (ie if 0) pool size / pool chunk size * 64
+ *
+ * \param discard
+ * Thin discard policy
+ * Note: THIN_DISCARDS_PASSDOWN is the default.
+ *
+ * \return
+ * Valid lv_create_params pointer on success, else NULL on error.
+ * Note: Memory is associated with the vg, it will get reclaimed when vg is
+ * closed.
+ *
+ */
+lv_create_params_t lvm_lv_params_create_thin_pool(vg_t vg,
+		const char *pool_name, uint64_t size, uint32_t chunk_size,
+		uint64_t meta_size, lvm_thin_discards_t discard);
+
+#define lvm_lv_params_create_thin_pool_default(vg, pool_name, size) \
+			lvm_lv_params_create_thin_pool((vg), (pool_name), (size), 0, 0, \
+			LVM_THIN_DISCARDS_PASSDOWN)
+
+
+
+/**
+ * Get the specific value of a lv create parameter by name
+ *
+ * \param	params		lv create parameters
+ *
+ * \param	name		name of parameter
+ *
+ * \return
+ * lvm_property_value structure that will contain the current
+ * value of the property.  Caller should check 'is_valid' flag before using
+ * the value.  If 'is_valid' is not set, caller should check lvm_errno()
+ * for specific error.
+ */
+struct lvm_property_value lvm_lv_params_get_property(
+											const lv_create_params_t params,
+											const char *name);
+
+
+/**
+ * Set the specific value of a lv create parameter by name
+ *
+ * Note that the property must be a 'settable' property, as evidenced '
+ * by the 'is_settable' flag when querying the property.
+ *
+ * The memory allocated for a string property value is tied to the vg_t
+ * handle associated with the lv_create_params_t and will be released when
+ * lvm_vg_close() is called.
+ *
+ * \param	params		lv create parameters
+ *
+ * \param	name		name of parameter
+ *
+ * \param	prop		Property value to use for setting
+ *
+ * \return
+ * 0 on success, -1 on error.
+ */
+int lvm_lv_params_set_property(lv_create_params_t params,
+								const char *name,
+								struct lvm_property_value *prop);
+
+/**
+ * Create a thin LV creation parameters in a given VG & thin pool
+ *
+ * \param   vg
+ * Volume Group handle.
+ *
+ * \param   pool_name
+ * Name of the pool.
+ *
+ * \param lvname
+ * Name of the LV to create
+ *
+ * \param   size
+ * Size of logical volume
+ *
+ * \return
+ * Valid lv_create_params pointer on success, else NULL on error.
+ * Note: Memory is associated with the vg, it will get reclaimed when vg is
+ * closed.
+ *
+ */
+lv_create_params_t lvm_lv_params_create_thin(const vg_t vg, const char *pool_name,
+									const char *lvname, uint64_t size);
+/**
+ * Create the actual logical volume.
+ *
+ * \param	params		The parameters object for lv creation
+ *
+ * \return
+ * Valid lv pointer on success, else NULL on error.
+ */
+lv_t lvm_lv_create(lv_create_params_t params);
+
 /************************** physical volume handling ************************/
 
 /**
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 91948a6..4fbd06b 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -22,6 +22,15 @@
 #include "lvm_misc.h"
 #include "lvm2app.h"
 
+struct lvm_lv_create_params
+{
+	uint32_t magic;
+	vg_t vg;
+	struct lvcreate_params lvp;
+};
+
+#define LV_CREATE_PARAMS_MAGIC 0xFEED0001
+
 static int _lv_check_handle(const lv_t lv, const int vg_writeable)
 {
 	if (!lv || !lv->vg || vg_read_error(lv->vg))
@@ -50,13 +59,13 @@ const char *lvm_lv_get_name(const lv_t lv)
 
 struct lvm_property_value lvm_lv_get_property(const lv_t lv, const char *name)
 {
-	return get_property(NULL, NULL, lv, NULL, NULL, name);
+	return get_property(NULL, NULL, lv, NULL, NULL, NULL, name);
 }
 
 struct lvm_property_value lvm_lvseg_get_property(const lvseg_t lvseg,
 						 const char *name)
 {
-	return get_property(NULL, NULL, NULL, lvseg, NULL, name);
+	return get_property(NULL, NULL, NULL, lvseg, NULL, NULL, name);
 }
 
 uint64_t lvm_lv_is_active(const lv_t lv)
@@ -350,3 +359,202 @@ lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name, uint64_t max_snap_siz
 		return NULL;
 	return (lv_t) lvl->lv;
 }
+
+/* Set defaults for thin pool specific LV parameters */
+static void _lv_set_pool_params(struct lvcreate_params *lp,
+				vg_t vg, const char *pool,
+				uint64_t extents, uint64_t meta_size)
+{
+	_lv_set_default_params(lp, vg, NULL, extents);
+
+	lp->pool = pool;
+
+	lp->create_thin_pool = 1;
+	lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool");
+	lp->stripes = 1;
+
+	if (!meta_size) {
+		lp->poolmetadatasize = extents * vg->extent_size /
+			(lp->chunk_size * (SECTOR_SIZE / 64));
+		while ((lp->poolmetadatasize >
+			(2 * DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) &&
+		       lp->chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE) {
+			lp->chunk_size <<= 1;
+			lp->poolmetadatasize >>= 1;
+	         }
+	} else
+		lp->poolmetadatasize = meta_size;
+
+	if (lp->poolmetadatasize % vg->extent_size)
+		lp->poolmetadatasize +=
+			vg->extent_size - lp->poolmetadatasize % vg->extent_size;
+
+	lp->poolmetadataextents =
+		extents_from_size(vg->cmd, lp->poolmetadatasize / SECTOR_SIZE,
+						   vg->extent_size);
+}
+
+lv_create_params_t lvm_lv_params_create_thin_pool(vg_t vg,
+		const char *pool_name, uint64_t size, uint32_t chunk_size,
+		uint64_t meta_size, lvm_thin_discards_t discard)
+{
+	uint64_t extents = 0;
+	struct lvm_lv_create_params *lvcp = NULL;
+
+	if (meta_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
+		log_error("Invalid metadata size");
+		return NULL;
+	}
+
+	if (meta_size &&
+		meta_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
+		log_error("Invalid metadata size");
+		return NULL;
+	}
+
+	if (vg_read_error(vg))
+		return NULL;
+
+	if (!vg_check_write_mode(vg))
+		return NULL;
+
+	if (pool_name == NULL || !strlen(pool_name)) {
+		log_error("pool_name invalid");
+		return NULL;
+	}
+
+	if (!(extents = extents_from_size(vg->cmd, size / SECTOR_SIZE,
+					  vg->extent_size))) {
+		log_error("Unable to create LV thin pool without size.");
+		return NULL;
+	}
+
+	lvcp = dm_pool_zalloc(vg->vgmem, sizeof (struct lvm_lv_create_params));
+
+	if (lvcp) {
+		lvcp->vg = vg;
+		lvcp->lvp.discards = discard;
+
+		if (chunk_size)
+			lvcp->lvp.chunk_size = chunk_size;
+		else
+			lvcp->lvp.chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
+
+		if (lvcp->lvp.chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE ||
+				lvcp->lvp.chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE) {
+			log_error("Invalid chunk_size");
+			return NULL;
+		}
+
+		_lv_set_pool_params(&lvcp->lvp, vg, pool_name, extents, meta_size);
+
+		lvcp->magic = LV_CREATE_PARAMS_MAGIC;
+	}
+	return lvcp;
+}
+
+/* Set defaults for thin LV specific parameters */
+static void _lv_set_thin_params(struct lvcreate_params *lp,
+				vg_t vg, const char *pool,
+				const char *lvname,
+				uint64_t extents)
+{
+	_lv_set_default_params(lp, vg, lvname, extents);
+
+	lp->thin = 1;
+	lp->pool = pool;
+	lp->segtype = get_segtype_from_string(vg->cmd, "thin");
+
+	lp->voriginsize = extents * vg->extent_size;
+	lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize,
+						   vg->extent_size);
+
+	lp->stripes = 1;
+}
+
+lv_create_params_t lvm_lv_params_create_thin(const vg_t vg, const char *pool_name,
+									const char *lvname, uint64_t size)
+{
+	struct lvm_lv_create_params *lvcp = NULL;
+	uint64_t extents = 0;
+
+	/* precondition checks */
+	if (vg_read_error(vg))
+		return NULL;
+
+	if (!vg_check_write_mode(vg))
+		return NULL;
+
+	if (pool_name == NULL || !strlen(pool_name)) {
+		log_error("pool_name invalid");
+		return NULL;
+	}
+
+	if (lvname == NULL || !strlen(lvname)) {
+		log_error("lvname invalid");
+		return NULL;
+	}
+
+	if (!(extents = extents_from_size(vg->cmd, size / SECTOR_SIZE,
+			vg->extent_size))) {
+		log_error("Unable to create thin LV without size.");
+		return NULL;
+	}
+
+	lvcp = dm_pool_zalloc(vg->vgmem, sizeof (struct lvm_lv_create_params));
+	if (lvcp) {
+		lvcp->vg = vg;
+		_lv_set_thin_params(&lvcp->lvp, vg, pool_name, lvname, extents);
+		lvcp->magic = LV_CREATE_PARAMS_MAGIC;
+	}
+
+	return lvcp;
+}
+
+struct lvm_property_value lvm_lv_params_get_property(
+						const lv_create_params_t params,
+						const char *name)
+{
+	struct lvm_property_value rc;
+
+	rc.is_valid = 0;
+
+	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
+		rc = get_property(NULL, NULL, NULL, NULL, NULL, &params->lvp, name);
+	} else {
+		log_error("Invalid lv_create_params parameter");
+	}
+	return rc;
+}
+
+int lvm_lv_params_set_property(lv_create_params_t params, const char *name,
+								struct lvm_property_value *prop)
+{
+	int rc = -1;
+
+	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
+		rc = set_property(NULL, NULL, NULL, &params->lvp, name, prop);
+	} else {
+		log_error("Invalid lv_create_params parameter");
+	}
+	return rc;
+}
+
+lv_t lvm_lv_create(lv_create_params_t params)
+{
+	struct lv_list *lvl = NULL;
+
+	if (params && params->magic == LV_CREATE_PARAMS_MAGIC) {
+		if (!params->lvp.segtype) {
+			log_error("segtype parameter is NULL");
+			return_NULL;
+		}
+		if (!lv_create_single(params->vg, &params->lvp))
+				return_NULL;
+		if (!(lvl = find_lv_in_vg(params->vg, params->lvp.pool)))
+			return_NULL;
+		return (lv_t) lvl->lv;
+	}
+	log_error("Invalid lv_create_params parameter");
+	return NULL;
+}
diff --git a/liblvm/lvm_misc.c b/liblvm/lvm_misc.c
index 0a0ea12..de66417 100644
--- a/liblvm/lvm_misc.c
+++ b/liblvm/lvm_misc.c
@@ -47,7 +47,8 @@ struct dm_list *tag_list_copy(struct dm_pool *p, struct dm_list *tag_list)
 
 struct lvm_property_value get_property(const pv_t pv, const vg_t vg,
 				       const lv_t lv, const lvseg_t lvseg,
-				       const pvseg_t pvseg, const char *name)
+				       const pvseg_t pvseg, const struct lvcreate_params *lvcp,
+				       const char *name)
 {
 	struct lvm_property_type prop;
 	struct lvm_property_value v = { 0 };
@@ -69,6 +70,9 @@ struct lvm_property_value get_property(const pv_t pv, const vg_t vg,
 	} else if (pvseg) {
 		if (!pvseg_get_property(pvseg, &prop))
 			return v;
+	} else if (lvcp) {
+		if (!lv_create_param_get_property(lvcp, &prop))
+					return v;
 	} else {
 		log_errno(EINVAL, "Invalid NULL handle passed to library function.");
 		return v;
@@ -87,7 +91,8 @@ struct lvm_property_value get_property(const pv_t pv, const vg_t vg,
 
 
 int set_property(const pv_t pv, const vg_t vg, const lv_t lv,
-		 const char *name, struct lvm_property_value *v)
+			struct lvcreate_params *lvcp, const char *name,
+			struct lvm_property_value *v)
 {
 	struct lvm_property_type prop;
 
@@ -111,6 +116,13 @@ int set_property(const pv_t pv, const vg_t vg, const lv_t lv,
 			v->is_valid = 0;
 			return -1;
 		}
+	} else if (lvcp) {
+		if (!lv_create_param_set_property(lvcp, &prop)) {
+			v->is_valid = 0;
+			return -1;
+		}
+	} else {
+		return -1;
 	}
 	return 0;
 }
diff --git a/liblvm/lvm_misc.h b/liblvm/lvm_misc.h
index a0324b8..76f4e0a 100644
--- a/liblvm/lvm_misc.h
+++ b/liblvm/lvm_misc.h
@@ -20,8 +20,10 @@
 struct dm_list *tag_list_copy(struct dm_pool *p, struct dm_list *tag_list);
 struct lvm_property_value get_property(const pv_t pv, const vg_t vg,
 				       const lv_t lv, const lvseg_t lvseg,
-				       const pvseg_t pvseg, const char *name);
+				       const pvseg_t pvseg, const struct lvcreate_params *lvcp,
+				       const char *name);
 int set_property(const pv_t pv, const vg_t vg, const lv_t lv,
-		 const char *name, struct lvm_property_value *value);
+			struct lvcreate_params *lvcp, const char *name,
+			struct lvm_property_value *value);
 
 #endif
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 90edaed..3924af4 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -51,13 +51,13 @@ uint64_t lvm_pv_get_free(const pv_t pv)
 
 struct lvm_property_value lvm_pv_get_property(const pv_t pv, const char *name)
 {
-	return get_property(pv, NULL, NULL, NULL, NULL, name);
+	return get_property(pv, NULL, NULL, NULL, NULL, NULL, name);
 }
 
 struct lvm_property_value lvm_pvseg_get_property(const pvseg_t pvseg,
 						 const char *name)
 {
-	return get_property(NULL, NULL, NULL, NULL, pvseg, name);
+	return get_property(NULL, NULL, NULL, NULL, pvseg, NULL, name);
 }
 
 struct dm_list *lvm_pv_list_pvsegs(pv_t pv)
diff --git a/liblvm/lvm_vg.c b/liblvm/lvm_vg.c
index 405a91a..f257438 100644
--- a/liblvm/lvm_vg.c
+++ b/liblvm/lvm_vg.c
@@ -339,13 +339,13 @@ const char *lvm_vg_get_name(const vg_t vg)
 
 struct lvm_property_value lvm_vg_get_property(const vg_t vg, const char *name)
 {
-	return get_property(NULL, vg, NULL, NULL, NULL, name);
+	return get_property(NULL, vg, NULL, NULL, NULL, NULL, name);
 }
 
 int lvm_vg_set_property(const vg_t vg, const char *name,
 			struct lvm_property_value *value)
 {
-	return set_property(NULL, vg, NULL, name, value);
+	return set_property(NULL, vg, NULL, NULL, name, value);
 }
 
 struct dm_list *lvm_list_vg_names(lvm_t libh)
diff --git a/tools/reporter.c b/tools/reporter.c
index 2744fcd..1bcded3 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -283,6 +283,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
 		else
 			options = find_config_tree_str(cmd, report_pvsegs_cols_verbose_CFG);
 		break;
+	case LV_CREATE_PARAMS:
 	default:
 		log_error(INTERNAL_ERROR "Unknown report type.");
 		return ECMD_FAILED;
@@ -395,6 +396,9 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
 			r = process_each_vg(cmd, argc, argv, 0,
 					    report_handle, &_pvsegs_in_vg);
 		break;
+
+	case LV_CREATE_PARAMS:
+			break;
 	}
 
 	dm_report_output(report_handle);
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/19] lvm2app: Implementation of pv resize (v6)
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
  2013-05-08 22:45 ` [PATCH 01/19] lvm2app: Add thin and thin pool lv creation V4 Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 03/19] lvm2app: Move percent_of_extents to lvm-percent.[h|c] Tony Asleson
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 liblvm/lvm2app.h |  2 --
 liblvm/lvm_pv.c  | 20 +++++++++++++++++---
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index b1d6abd..633b026 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1759,8 +1759,6 @@ pv_t lvm_pv_from_uuid(vg_t vg, const char *uuid);
  *
  * \memberof pv_t
  *
- * NOTE: This function is currently not implemented.
- *
  * \param   pv
  * Physical volume handle.
  *
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 3924af4..18b1069 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -123,7 +123,21 @@ pv_t lvm_pv_from_uuid(vg_t vg, const char *uuid)
 
 int lvm_pv_resize(const pv_t pv, uint64_t new_size)
 {
-	/* FIXME: add pv resize code here */
-	log_error("NOT IMPLEMENTED YET");
-	return -1;
+	uint64_t size = new_size >> SECTOR_SHIFT;
+
+	if (new_size % SECTOR_SIZE) {
+		log_errno(EINVAL, "Size not a multiple of 512");
+		return -1;
+	}
+
+	if (!vg_check_write_mode(pv->vg)) {
+		return -1;
+	}
+
+	if (!pv_resize(pv, pv->vg, size)) {
+		log_error("PV re-size failed!");
+		return -1;
+	} else {
+		return 0;
+	}
 }
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/19] lvm2app: Move percent_of_extents to lvm-percent.[h|c]
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
  2013-05-08 22:45 ` [PATCH 01/19] lvm2app: Add thin and thin pool lv creation V4 Tony Asleson
  2013-05-08 22:45 ` [PATCH 02/19] lvm2app: Implementation of pv resize (v6) Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 04/19] lvm2app: Rework argument handling for lv resize Tony Asleson
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/misc/lvm-percent.c |  5 +++++
 lib/misc/lvm-percent.h | 17 +++++++++++++++++
 tools/toollib.c        |  6 ------
 tools/tools.h          | 16 ----------------
 4 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/lib/misc/lvm-percent.c b/lib/misc/lvm-percent.c
index 4b73db4..1dafa57 100644
--- a/lib/misc/lvm-percent.c
+++ b/lib/misc/lvm-percent.c
@@ -38,3 +38,8 @@ percent_t make_percent(uint64_t numerator, uint64_t denominator)
     }
 }
 
+uint32_t percent_of_extents(uint32_t percents, uint32_t count, int roundup)
+{
+	return (uint32_t)(((uint64_t)percents * (uint64_t)count +
+			   ((roundup) ? 99 : 0)) / 100);
+}
diff --git a/lib/misc/lvm-percent.h b/lib/misc/lvm-percent.h
index bf30a7e..ff3de42 100644
--- a/lib/misc/lvm-percent.h
+++ b/lib/misc/lvm-percent.h
@@ -31,6 +31,21 @@
 typedef int32_t percent_t;
 
 typedef enum {
+	SIGN_NONE = 0,
+	SIGN_PLUS = 1,
+	SIGN_MINUS = 2
+} sign_t;
+
+typedef enum {
+	PERCENT_NONE = 0,
+	PERCENT_VG,
+	PERCENT_FREE,
+	PERCENT_LV,
+	PERCENT_PVS,
+	PERCENT_ORIGIN
+} percent_type_t;
+
+typedef enum {
 	PERCENT_0 = 0,
 	PERCENT_1 = 1000000,
 	PERCENT_100 = 100 * PERCENT_1,
@@ -41,4 +56,6 @@ typedef enum {
 float percent_to_float(percent_t v);
 percent_t make_percent(uint64_t numerator, uint64_t denominator);
 
+uint32_t percent_of_extents(uint32_t percents, uint32_t count, int roundup);
+
 #endif
diff --git a/tools/toollib.c b/tools/toollib.c
index e9be968..6b2df0d 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1746,9 +1746,3 @@ int change_tag(struct cmd_context *cmd, struct volume_group *vg,
 	return 1;
 }
 
-/* Return percents of extents and avoid overflow, with optional roundup */
-uint32_t percent_of_extents(uint32_t percents, uint32_t count, int roundup)
-{
-	return (uint32_t)(((uint64_t)percents * (uint64_t)count +
-			   ((roundup) ? 99 : 0)) / 100);
-}
diff --git a/tools/tools.h b/tools/tools.h
index 15d1f84..6e820bf 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -74,21 +74,6 @@ enum {
 #undef arg
 };
 
-typedef enum {
-	SIGN_NONE = 0,
-	SIGN_PLUS = 1,
-	SIGN_MINUS = 2
-} sign_t;
-
-typedef enum {
-	PERCENT_NONE = 0,
-	PERCENT_VG,
-	PERCENT_FREE,
-	PERCENT_LV,
-	PERCENT_PVS,
-	PERCENT_ORIGIN
-} percent_type_t;
-
 #define ARG_COUNTABLE 0x00000001	/* E.g. -vvvv */
 #define ARG_GROUPABLE 0x00000002	/* E.g. --addtag */
 
@@ -189,7 +174,6 @@ int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv, unsigned
 int mirror_remove_missing(struct cmd_context *cmd,
 			  struct logical_volume *lv, int force);
 
-uint32_t percent_of_extents(uint32_t percents, uint32_t count, int roundup);
 
 int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
 		       activation_change_t activate);
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/19] lvm2app: Rework argument handling for lv resize
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (2 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 03/19] lvm2app: Move percent_of_extents to lvm-percent.[h|c] Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 05/19] lvm2app: Move core lv re-size code (v2) Tony Asleson
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Extend the lv resize parameter structure to contain everything
the re-size functions need so that the command line does not
need to be present for lower level calls when we call from
library functions.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 tools/lvresize.c | 120 +++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 81 insertions(+), 39 deletions(-)

diff --git a/tools/lvresize.c b/tools/lvresize.c
index e44fd82..4d11c16 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -44,18 +44,28 @@ struct lvresize_params {
 
 	int argc;
 	char **argv;
+
+	/* Arg counts & values */
+	unsigned ac_policy;
+	unsigned ac_stripes;
+	uint32_t ac_stripes_value;
+	unsigned ac_mirrors;
+	uint32_t ac_mirrors_value;
+	unsigned ac_stripesize;
+	uint64_t ac_stripesize_value;
+	unsigned ac_alloc;
+	unsigned ac_no_sync;
+	unsigned ac_force;
+
+	const char *ac_type;
 };
 
 static int _validate_stripesize(struct cmd_context *cmd,
 				const struct volume_group *vg,
 				struct lvresize_params *lp)
 {
-	if (arg_sign_value(cmd, stripesize_ARG, SIGN_NONE) == SIGN_MINUS) {
-		log_error("Stripesize may not be negative.");
-		return 0;
-	}
 
-	if (arg_uint64_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) {
+	if ( lp->ac_stripesize_value > STRIPE_SIZE_LIMIT * 2) {
 		log_error("Stripe size cannot be larger than %s",
 			  display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
 		return 0;
@@ -63,15 +73,14 @@ static int _validate_stripesize(struct cmd_context *cmd,
 
 	if (!(vg->fid->fmt->features & FMT_SEGMENTS))
 		log_warn("Varied stripesize not supported. Ignoring.");
-	else if (arg_uint_value(cmd, stripesize_ARG, 0) > (uint64_t) vg->extent_size * 2) {
+	else if (lp->ac_stripesize_value > (uint64_t) vg->extent_size * 2) {
 		log_error("Reducing stripe size %s to maximum, "
 			  "physical extent size %s",
-			  display_size(cmd,
-				       (uint64_t) arg_uint_value(cmd, stripesize_ARG, 0)),
+			  display_size(cmd,lp->ac_stripesize_value),
 			  display_size(cmd, (uint64_t) vg->extent_size));
 		lp->stripe_size = vg->extent_size;
 	} else
-		lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
+		lp->stripe_size = lp->ac_stripesize_value;
 
 	if (lp->stripe_size & (lp->stripe_size - 1)) {
 		log_error("Stripe size must be power of 2");
@@ -111,7 +120,7 @@ static int _request_confirmation(struct cmd_context *cmd,
 
 	log_warn("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
 
-	if (!arg_count(cmd, force_ARG)) {
+	if (!lp->ac_force) {
 		if (yes_no_prompt("Do you really want to reduce %s? [y/n]: ",
 				  lp->lv_name) == 'n') {
 			log_error("Logical volume %s NOT reduced", lp->lv_name);
@@ -152,7 +161,7 @@ static int _fsadm_cmd(struct cmd_context *cmd,
 	if (verbose_level() >= _LOG_NOTICE)
 		argv[i++] = "--verbose";
 
-	if (arg_count(cmd, force_ARG))
+	if (lp->ac_force)
 		argv[i++] = "--force";
 
 	argv[i++] = (fcmd == FSADM_CMD_RESIZE) ? "resize" : "check";
@@ -277,6 +286,43 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
 	lp->argc = argc;
 	lp->argv = argv;
 
+	lp->ac_policy = arg_count(cmd, use_policies_ARG);
+	lp->ac_stripes = arg_count(cmd, stripes_ARG);
+	if (lp->ac_stripes) {
+		lp->ac_stripes_value = arg_uint_value(cmd, stripes_ARG, 1);
+	} else {
+		lp->ac_stripes_value = 0;
+	}
+
+	lp->ac_mirrors = arg_count(cmd, mirrors_ARG);
+
+	if (lp->ac_mirrors) {
+		if (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) == SIGN_MINUS) {
+			log_error("Mirrors argument may not be negative");
+			return 0;
+		}
+
+		lp->ac_mirrors_value = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
+	} else {
+		lp->ac_mirrors_value = 0;
+	}
+
+	lp->ac_stripesize = arg_count(cmd, stripesize_ARG);
+	if (lp->ac_stripesize) {
+		if (arg_sign_value(cmd, stripesize_ARG, SIGN_NONE) == SIGN_MINUS) {
+			log_error("Stripesize may not be negative.");
+			return 0;
+		}
+
+		lp->ac_stripesize_value = arg_uint64_value(cmd, stripesize_ARG, 0);
+	}
+
+	lp->ac_no_sync = arg_count(cmd, nosync_ARG);
+	lp->ac_alloc = arg_uint_value(cmd, alloc_ARG, 0);
+
+	lp->ac_type = arg_str_value(cmd, type_ARG, NULL);
+	lp->ac_force = arg_count(cmd, force_ARG);
+
 	return 1;
 }
 
@@ -359,7 +405,7 @@ static uint32_t lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize)
 }
 
 static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
-		     struct lvresize_params *lp)
+		     struct lvresize_params *lp, struct dm_list *pvh)
 {
 	struct logical_volume *lv;
 	struct lvinfo info;
@@ -376,8 +422,6 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 	uint32_t seg_extents;
 	uint32_t sz, str;
 	int status;
-	struct dm_list *pvh = NULL;
-	int use_policy = arg_count(cmd, use_policies_ARG);
 
 	/* does LV exist? */
 	if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
@@ -408,31 +452,27 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		return ECMD_FAILED;
 	}
 
-	if (arg_count(cmd, stripes_ARG)) {
+	if (lp->ac_stripes) {
 		if (vg->fid->fmt->features & FMT_SEGMENTS)
-			lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
+			lp->stripes = lp->ac_stripes_value;
 		else
 			log_warn("Varied striping not supported. Ignoring.");
 	}
 
-	if (arg_count(cmd, mirrors_ARG)) {
+	if (lp->ac_mirrors) {
 		if (vg->fid->fmt->features & FMT_SEGMENTS)
-			lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
+			lp->mirrors = lp->ac_mirrors_value;
 		else
 			log_warn("Mirrors not supported. Ignoring.");
-		if (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) == SIGN_MINUS) {
-			log_error("Mirrors argument may not be negative");
-			return EINVALID_CMD_LINE;
-		}
 	}
 
-	if (arg_count(cmd, stripesize_ARG) &&
+	if (lp->ac_stripesize &&
 	    !_validate_stripesize(cmd, vg, lp))
 		return EINVALID_CMD_LINE;
 
 	lv = lvl->lv;
 
-	if (use_policy) {
+	if (lp->ac_policy) {
 		if (!lv_is_cow(lv) &&
 		    !lv_is_thin_pool(lv)) {
 			log_error("Policy-based resize is supported only for snapshot and thin pool volumes.");
@@ -457,7 +497,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		return ECMD_FAILED;
 	}
 
-	alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, lv->alloc);
+	alloc = (alloc_policy_t)(lp->ac_alloc)?lp->ac_alloc: lv->alloc;
 
 	/*
 	 * First adjust to an exact multiple of extent size.
@@ -480,12 +520,6 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		lp->extents = lp->size / vg->extent_size;
 	}
 
-	if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
-						     lp->argv, 1) : &vg->pvs)) {
-		stack;
-		return ECMD_FAILED;
-	}
-
 	switch(lp->percent) {
 		case PERCENT_VG:
 			lp->extents = percent_of_extents(lp->extents, vg->extent_count,
@@ -545,7 +579,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 	}
 
 	if (lp->extents == lv->le_count) {
-		if (use_policy)
+		if (lp->ac_policy)
 			return ECMD_PROCESSED; /* Nothing to do. */
 		if (!lp->resizefs) {
 			log_error("New size (%d extents) matches existing size "
@@ -563,8 +597,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 	}
 
 	/* FIXME Support LVs with mixed segment types */
-	if (lp->segtype != get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG,
-								      lp->segtype->name))) {
+	if (lp->segtype != get_segtype_from_string(cmd, (lp->ac_type)?lp->ac_type:lp->segtype->name)) {
 		log_error("VolumeType does not match (%s)", lp->segtype->name);
 		return EINVALID_CMD_LINE;
 	}
@@ -575,7 +608,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		 * Has the user specified that they would like the additional
 		 * extents of a mirror not to have an initial sync?
 		 */
-		if (seg_is_mirrored(first_seg(lv)) && arg_count(cmd, nosync_ARG))
+		if (seg_is_mirrored(first_seg(lv)) && lp->ac_no_sync)
 			lv->status |= LV_NOTSYNCED;
 
 		dm_list_iterate_back_items(mirr_seg, &lv->segments) {
@@ -586,12 +619,12 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 			break;
 		}
 
-		if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
+		if (!lp->ac_mirrors && seg_mirrors) {
 			log_print_unless_silent("Extending %" PRIu32 " mirror images.",
 						seg_mirrors);
 			lp->mirrors = seg_mirrors;
 		}
-		if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
+		if ((lp->ac_mirrors || seg_mirrors) &&
 		    (lp->mirrors != seg_mirrors)) {
 			log_error("Cannot vary number of mirrors in LV yet.");
 			return EINVALID_CMD_LINE;
@@ -739,7 +772,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
 		}
 		lp->resize = LV_EXTEND;
 	} else if (lp->extents == lv->le_count) {
-		if (use_policy)
+		if (lp->ac_policy)
 			return ECMD_PROCESSED; /* Nothing to do. */
 		if (!lp->resizefs) {
 			log_error("New size (%d extents) matches existing size "
@@ -892,10 +925,12 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
 	struct lvresize_params lp = { 0 };
 	struct volume_group *vg;
 	int r;
+	struct dm_list *pvh = NULL;
 
 	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)) {
@@ -904,7 +939,14 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
 		return ECMD_FAILED;
 	}
 
-	if (!(r = _lvresize(cmd, vg, &lp)))
+	/* 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;
+	}
+
+	if (!(r = _lvresize(cmd, vg, &lp, pvh)))
 		stack;
 
 	unlock_and_release_vg(cmd, vg, lp.vg_name);
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/19] lvm2app: Move core lv re-size code (v2)
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (3 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 04/19] lvm2app: Rework argument handling for lv resize Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-09  7:13   ` Zdenek Kabelac
  2013-05-08 22:45 ` [PATCH 06/19] lvm2app: Implement lv resize (v2) Tony Asleson
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Moved to allow use from command line and for library use.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/metadata/lv_manip.c          | 734 +++++++++++++++++++++++++++++++++++++
 lib/metadata/metadata-exported.h |  46 +++
 tools/lvresize.c                 | 773 +--------------------------------------
 3 files changed, 781 insertions(+), 772 deletions(-)

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 42e0fab..587cbd2 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -27,6 +27,8 @@
 #include "activate.h"
 #include "str_list.h"
 #include "defaults.h"
+#include "lvm-exec.h"
+#include "errors.h"
 
 typedef enum {
 	PREFERRED,
@@ -3175,6 +3177,738 @@ int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
 	return lv_rename_update(cmd, lv, new_name, 1);
 }
 
+/*
+ * 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)
+{
+
+	if ( lp->ac_stripesize_value > STRIPE_SIZE_LIMIT * 2) {
+		log_error("Stripe size cannot be larger than %s",
+			  display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
+		return 0;
+	}
+
+	if (!(vg->fid->fmt->features & FMT_SEGMENTS))
+		log_warn("Varied stripesize not supported. Ignoring.");
+	else if (lp->ac_stripesize_value > (uint64_t) vg->extent_size * 2) {
+		log_error("Reducing stripe size %s to maximum, "
+			  "physical extent size %s",
+			  display_size(cmd,lp->ac_stripesize_value),
+			  display_size(cmd, (uint64_t) vg->extent_size));
+		lp->stripe_size = vg->extent_size;
+	} else
+		lp->stripe_size = lp->ac_stripesize_value;
+
+	if (lp->stripe_size & (lp->stripe_size - 1)) {
+		log_error("Stripe size must be power of 2");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _request_confirmation(struct cmd_context *cmd,
+				 const struct volume_group *vg,
+				 const struct logical_volume *lv,
+				 const struct lvresize_params *lp)
+{
+	struct lvinfo info = { 0 };
+
+	if (!lv_info(cmd, lv, 0, &info, 1, 0) && driver_version(NULL, 0)) {
+		log_error("lv_info failed: aborting");
+		return 0;
+	}
+
+	if (lp->resizefs) {
+		if (!info.exists) {
+			log_error("Logical volume %s must be activated "
+				  "before resizing filesystem", lp->lv_name);
+			return 0;
+		}
+		return 1;
+	}
+
+	if (!info.exists)
+		return 1;
+
+	log_warn("WARNING: Reducing active%s logical volume to %s",
+		 info.open_count ? " and open" : "",
+		 display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
+
+	log_warn("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
+
+	if (!lp->ac_force) {
+		if (yes_no_prompt("Do you really want to reduce %s? [y/n]: ",
+				  lp->lv_name) == 'n') {
+			log_error("Logical volume %s NOT reduced", lp->lv_name);
+			return 0;
+		}
+		if (sigint_caught())
+			return 0;
+	}
+
+	return 1;
+}
+
+enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
+#define FSADM_CMD "fsadm"
+#define FSADM_CMD_MAX_ARGS 6
+#define FSADM_CHECK_FAILS_FOR_MOUNTED 3 /* shell exist status code */
+
+/*
+ * 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,
+		      const struct volume_group *vg,
+		      const struct lvresize_params *lp,
+		      enum fsadm_cmd_e fcmd,
+		      int *status)
+{
+	char lv_path[PATH_MAX];
+	char size_buf[SIZE_BUF];
+	const char *argv[FSADM_CMD_MAX_ARGS + 2];
+	unsigned i = 0;
+
+	argv[i++] = FSADM_CMD;
+
+	if (test_mode())
+		argv[i++] = "--dry-run";
+
+	if (verbose_level() >= _LOG_NOTICE)
+		argv[i++] = "--verbose";
+
+	if (lp->ac_force)
+		argv[i++] = "--force";
+
+	argv[i++] = (fcmd == FSADM_CMD_RESIZE) ? "resize" : "check";
+
+	if (status)
+		*status = -1;
+
+	if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir, lp->vg_name,
+			lp->lv_name) < 0) {
+		log_error("Couldn't create LV path for %s", lp->lv_name);
+		return 0;
+	}
+
+	argv[i++] = lv_path;
+
+	if (fcmd == FSADM_CMD_RESIZE) {
+		if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64 "K",
+				(uint64_t) lp->extents * vg->extent_size / 2) < 0) {
+			log_error("Couldn't generate new LV size string");
+			return 0;
+		}
+
+		argv[i++] = size_buf;
+	}
+
+	argv[i] = NULL;
+
+	return exec_cmd(cmd, argv, status, 1);
+}
+
+static int _adjust_policy_params(struct cmd_context *cmd,
+				 struct logical_volume *lv, struct lvresize_params *lp)
+{
+	percent_t percent;
+	int policy_threshold, policy_amount;
+
+	if (lv_is_thin_pool(lv)) {
+		policy_threshold =
+			find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG) * PERCENT_1;
+		policy_amount =
+			find_config_tree_int(cmd, activation_thin_pool_autoextend_percent_CFG);
+		if (!policy_amount && policy_threshold < PERCENT_100)
+                        return 0;
+	} else {
+		policy_threshold =
+			find_config_tree_int(cmd, activation_snapshot_autoextend_threshold_CFG) * PERCENT_1;
+		policy_amount =
+			find_config_tree_int(cmd, activation_snapshot_autoextend_percent_CFG);
+	}
+
+	if (policy_threshold >= PERCENT_100)
+		return 1; /* nothing to do */
+
+	if (lv_is_thin_pool(lv)) {
+		if (!lv_thin_pool_percent(lv, 1, &percent))
+			return_0;
+		if (percent > policy_threshold) {
+			/* FIXME: metadata resize support missing */
+			log_error("Resize for %s/%s is not yet supported.",
+				  lp->vg_name, lp->lv_name);
+			return ECMD_FAILED;
+		}
+
+		if (!lv_thin_pool_percent(lv, 0, &percent))
+			return_0;
+		if (!(PERCENT_0 < percent && percent <= PERCENT_100) ||
+		    percent <= policy_threshold)
+			return 1; /* nothing to do */
+	} else {
+		if (!lv_snapshot_percent(lv, &percent))
+			return_0;
+		if (!(PERCENT_0 < percent && percent < PERCENT_100) || percent <= policy_threshold)
+			return 1; /* nothing to do */
+	}
+
+	lp->extents = policy_amount;
+
+	return 1;
+}
+
+static uint32_t lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize)
+{
+	uint32_t s;
+	struct lv_segment *seg_mirr;
+
+	/* If segment mirrored, check if images are striped */
+	if (seg_is_mirrored(seg))
+		for (s = 0; s < seg->area_count; s++) {
+			if (seg_type(seg, s) != AREA_LV)
+				continue;
+			seg_mirr = first_seg(seg_lv(seg, s));
+
+			if (seg_is_striped(seg_mirr)) {
+				seg = seg_mirr;
+				break;
+			}
+		}
+
+
+	if (seg_is_striped(seg)) {
+		*stripesize = seg->stripe_size;
+		return seg->area_count;
+	}
+
+	*stripesize = 0;
+	return 0;
+}
+
+int lv_resize(struct cmd_context *cmd, struct volume_group *vg,
+		     struct lvresize_params *lp, struct dm_list *pvh)
+{
+	struct logical_volume *lv;
+	struct lvinfo info;
+	uint32_t stripesize_extents;
+	uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size;
+	uint32_t seg_mirrors = 0;
+	uint32_t extents_used;
+	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;
+	uint32_t sz, str;
+	int status;
+
+	/* does LV exist? */
+	if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
+		log_error("Logical volume %s not found in volume group %s",
+			  lp->lv_name, lp->vg_name);
+		return ECMD_FAILED;
+	}
+
+	if (lv_is_external_origin(lvl->lv)) {
+		/*
+		 * Since external-origin can be activated read-only,
+		 * there is no way to use extended areas.
+		 */
+		log_error("Cannot resize external origin \"%s\".", lvl->lv->name);
+		return EINVALID_CMD_LINE;
+	}
+
+	if (lvl->lv->status & (RAID_IMAGE | RAID_META)) {
+		log_error("Cannot resize a RAID %s directly",
+			  (lvl->lv->status & RAID_IMAGE) ? "image" :
+			  "metadata area");
+		return ECMD_FAILED;
+	}
+
+	if (lv_is_raid_with_tracking(lvl->lv)) {
+		log_error("Cannot resize %s while it is tracking a split image",
+			  lvl->lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lp->ac_stripes) {
+		if (vg->fid->fmt->features & FMT_SEGMENTS)
+			lp->stripes = lp->ac_stripes_value;
+		else
+			log_warn("Varied striping not supported. Ignoring.");
+	}
+
+	if (lp->ac_mirrors) {
+		if (vg->fid->fmt->features & FMT_SEGMENTS)
+			lp->mirrors = lp->ac_mirrors_value;
+		else
+			log_warn("Mirrors not supported. Ignoring.");
+	}
+
+	if (lp->ac_stripesize &&
+	    !_validate_stripesize(cmd, vg, lp))
+		return EINVALID_CMD_LINE;
+
+	lv = lvl->lv;
+
+	if (lp->ac_policy) {
+		if (!lv_is_cow(lv) &&
+		    !lv_is_thin_pool(lv)) {
+			log_error("Policy-based resize is supported only for snapshot and thin pool volumes.");
+			return ECMD_FAILED;
+		}
+		if (!_adjust_policy_params(cmd, lv, lp))
+			return ECMD_FAILED;
+	}
+
+	if (!lv_is_visible(lv)) {
+		log_error("Can't resize internal logical volume %s", lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & LOCKED) {
+		log_error("Can't resize locked LV %s", lv->name);
+		return ECMD_FAILED;
+	}
+
+	if (lv->status & CONVERTING) {
+		log_error("Can't resize %s while lvconvert in progress", lv->name);
+		return ECMD_FAILED;
+	}
+
+	alloc = (alloc_policy_t)(lp->ac_alloc)?lp->ac_alloc: lv->alloc;
+
+	/*
+	 * First adjust to an exact multiple of extent size.
+	 * When extending by a relative amount we round that amount up.
+	 * When reducing by a relative amount we remove at most that amount.
+	 * When changing to an absolute size, we round that size up.
+	 */
+	if (lp->size) {
+		if (lp->size % vg->extent_size) {
+			if (lp->sign == SIGN_MINUS)
+				lp->size -= lp->size % vg->extent_size;
+			else
+				lp->size += vg->extent_size -
+				    (lp->size % vg->extent_size);
+
+			log_print_unless_silent("Rounding size to boundary between physical extents: %s",
+						display_size(cmd, lp->size));
+		}
+
+		lp->extents = lp->size / vg->extent_size;
+	}
+
+	switch(lp->percent) {
+		case PERCENT_VG:
+			lp->extents = percent_of_extents(lp->extents, vg->extent_count,
+							 (lp->sign != SIGN_MINUS));
+			break;
+		case PERCENT_FREE:
+			lp->extents = percent_of_extents(lp->extents, vg->free_count,
+							 (lp->sign != SIGN_MINUS));
+			break;
+		case PERCENT_LV:
+			lp->extents = percent_of_extents(lp->extents, lv->le_count,
+							 (lp->sign != SIGN_MINUS));
+			break;
+		case PERCENT_PVS:
+			if (lp->argc) {
+				pv_extent_count = pv_list_extents_free(pvh);
+				lp->extents = percent_of_extents(lp->extents, pv_extent_count,
+								 (lp->sign != SIGN_MINUS));
+			} else
+				lp->extents = percent_of_extents(lp->extents, vg->extent_count,
+								 (lp->sign != SIGN_MINUS));
+			break;
+		case PERCENT_ORIGIN:
+			if (!lv_is_cow(lv)) {
+				log_error("Specified LV does not have an origin LV.");
+				return EINVALID_CMD_LINE;
+			}
+			lp->extents = percent_of_extents(lp->extents, origin_from_cow(lv)->le_count,
+							 (lp->sign != SIGN_MINUS));
+			break;
+		case PERCENT_NONE:
+			break;
+	}
+
+	if (lp->sign == SIGN_PLUS) {
+		if (lp->extents >= (MAX_EXTENT_COUNT - lv->le_count)) {
+			log_error("Unable to extend %s by %u extents, exceeds limit (%u).",
+				  lp->lv_name, lv->le_count, MAX_EXTENT_COUNT);
+			return EINVALID_CMD_LINE;
+		}
+		lp->extents += lv->le_count;
+	}
+
+	if (lp->sign == SIGN_MINUS) {
+		if (lp->extents >= lv->le_count) {
+			log_error("Unable to reduce %s below 1 extent",
+				  lp->lv_name);
+			return EINVALID_CMD_LINE;
+		}
+
+		lp->extents = lv->le_count - lp->extents;
+	}
+
+	if (!lp->extents) {
+		log_error("New size of 0 not permitted");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (lp->extents == lv->le_count) {
+		if (lp->ac_policy)
+			return ECMD_PROCESSED; /* Nothing to do. */
+		if (!lp->resizefs) {
+			log_error("New size (%d extents) matches existing size "
+				  "(%d extents)", lp->extents, lv->le_count);
+			return EINVALID_CMD_LINE;
+		}
+		lp->resize = LV_EXTEND; /* lets pretend zero size extension */
+	}
+
+	seg_size = lp->extents - lv->le_count;
+
+	/* Use segment type of last segment */
+	dm_list_iterate_items(seg, &lv->segments) {
+		lp->segtype = seg->segtype;
+	}
+
+	/* FIXME Support LVs with mixed segment types */
+	if (lp->segtype != get_segtype_from_string(cmd, (lp->ac_type)?lp->ac_type:lp->segtype->name)) {
+		log_error("VolumeType does not match (%s)", lp->segtype->name);
+		return EINVALID_CMD_LINE;
+	}
+
+	/* If extending, find mirrors of last segment */
+	if ((lp->extents > lv->le_count)) {
+		/*
+		 * Has the user specified that they would like the additional
+		 * extents of a mirror not to have an initial sync?
+		 */
+		if (seg_is_mirrored(first_seg(lv)) && lp->ac_no_sync)
+			lv->status |= LV_NOTSYNCED;
+
+		dm_list_iterate_back_items(mirr_seg, &lv->segments) {
+			if (seg_is_mirrored(mirr_seg))
+				seg_mirrors = lv_mirror_count(mirr_seg->lv);
+			else
+				seg_mirrors = 0;
+			break;
+		}
+
+		if (!lp->ac_mirrors && seg_mirrors) {
+			log_print_unless_silent("Extending %" PRIu32 " mirror images.",
+						seg_mirrors);
+			lp->mirrors = seg_mirrors;
+		}
+		if ((lp->ac_mirrors || seg_mirrors) &&
+		    (lp->mirrors != seg_mirrors)) {
+			log_error("Cannot vary number of mirrors in LV yet.");
+			return EINVALID_CMD_LINE;
+		}
+
+		if (seg_mirrors && !strcmp(mirr_seg->segtype->name, "raid10")) {
+			lp->stripes = mirr_seg->area_count / seg_mirrors;
+			lp->stripe_size = mirr_seg->stripe_size;
+		}
+	}
+
+	/* If extending, find stripes, stripesize & size of last segment */
+	if ((lp->extents > lv->le_count) &&
+	    !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size)) &&
+	    strcmp(mirr_seg->segtype->name, "raid10")) {
+		/* FIXME Don't assume mirror seg will always be AREA_LV */
+		/* FIXME We will need to support resize for metadata LV as well,
+		 *       and data LV could be any type (i.e. mirror)) */
+		dm_list_iterate_items(seg, seg_mirrors ? &seg_lv(mirr_seg, 0)->segments :
+				      lv_is_thin_pool(lv) ? &seg_lv(first_seg(lv), 0)->segments : &lv->segments) {
+			/* Allow through "striped" and RAID 4/5/6/10 */
+			if (!seg_is_striped(seg) &&
+			    (!seg_is_raid(seg) || seg_is_mirrored(seg)) &&
+			    strcmp(seg->segtype->name, "raid10"))
+				continue;
+
+			sz = seg->stripe_size;
+			str = seg->area_count - lp->segtype->parity_devs;
+
+			if ((seg_stripesize && seg_stripesize != sz &&
+			     sz && !lp->stripe_size) ||
+			    (seg_stripes && seg_stripes != str && !lp->stripes)) {
+				log_error("Please specify number of "
+					  "stripes (-i) and stripesize (-I)");
+				return EINVALID_CMD_LINE;
+			}
+
+			seg_stripesize = sz;
+			seg_stripes = str;
+		}
+
+		if (!lp->stripes)
+			lp->stripes = seg_stripes;
+		else if (seg_is_raid(first_seg(lv)) &&
+			 (lp->stripes != seg_stripes)) {
+			log_error("Unable to extend \"%s\" segment type with different number of stripes.", first_seg(lv)->segtype->ops->name(first_seg(lv)));
+			return ECMD_FAILED;
+		}
+
+		if (!lp->stripe_size && lp->stripes > 1) {
+			if (seg_stripesize) {
+				log_print_unless_silent("Using stripesize of last segment %s",
+							display_size(cmd, (uint64_t) seg_stripesize));
+				lp->stripe_size = seg_stripesize;
+			} else {
+				lp->stripe_size =
+					find_config_tree_int(cmd, metadata_stripesize_CFG) * 2;
+				log_print_unless_silent("Using default stripesize %s",
+							display_size(cmd, (uint64_t) lp->stripe_size));
+			}
+		}
+	}
+
+	/* If reducing, find stripes, stripesize & size of last segment */
+	if (lp->extents < lv->le_count) {
+		extents_used = 0;
+
+		if (lp->stripes || lp->stripe_size || lp->mirrors)
+			log_error("Ignoring stripes, stripesize and mirrors "
+				  "arguments when reducing");
+
+		dm_list_iterate_items(seg, &lv->segments) {
+			seg_extents = seg->len;
+
+			/* Check for underlying stripe sizes */
+			seg_stripes = lvseg_get_stripes(seg, &seg_stripesize);
+
+			if (seg_is_mirrored(seg))
+				seg_mirrors = lv_mirror_count(seg->lv);
+			else
+				seg_mirrors = 0;
+
+			if (lp->extents <= extents_used + seg_extents)
+				break;
+
+			extents_used += seg_extents;
+		}
+
+		seg_size = lp->extents - extents_used;
+		lp->stripe_size = seg_stripesize;
+		lp->stripes = seg_stripes;
+		lp->mirrors = seg_mirrors;
+	}
+
+	if (lp->stripes > 1 && !lp->stripe_size) {
+		log_error("Stripesize for striped segment should not be 0!");
+		return EINVALID_CMD_LINE;
+	}
+
+	if (lp->stripes > 1) {
+		if (lp->stripe_size < STRIPE_SIZE_MIN) {
+			log_error("Invalid stripe size %s",
+				  display_size(cmd, (uint64_t) lp->stripe_size));
+			return EINVALID_CMD_LINE;
+		}
+
+		if (!(stripesize_extents = lp->stripe_size / vg->extent_size))
+			stripesize_extents = 1;
+
+		size_rest = seg_size % (lp->stripes * stripesize_extents);
+		/* Round toward the original size. */
+		if (size_rest &&
+		    ((lp->extents < lv->le_count) ||
+		     !lp->percent ||
+		     (vg->free_count >= (lp->extents - lv->le_count - size_rest +
+					 (lp->stripes * stripesize_extents))))) {
+			log_print_unless_silent("Rounding size (%d extents) up to stripe "
+						"boundary size for segment (%d extents)",
+						lp->extents, lp->extents - size_rest +
+						(lp->stripes * stripesize_extents));
+			lp->extents = lp->extents - size_rest +
+				      (lp->stripes * stripesize_extents);
+		} else if (size_rest) {
+			log_print_unless_silent("Rounding size (%d extents) down to stripe "
+						"boundary size for segment (%d extents)",
+						lp->extents, lp->extents - size_rest);
+			lp->extents = lp->extents - size_rest;
+		}
+	}
+
+	if (lp->extents < lv->le_count) {
+		if (lp->resize == LV_EXTEND) {
+			log_error("New size given (%d extents) not larger "
+				  "than existing size (%d extents)",
+				  lp->extents, lv->le_count);
+			return EINVALID_CMD_LINE;
+		}
+		lp->resize = LV_REDUCE;
+	} else if (lp->extents > lv->le_count) {
+		if (lp->resize == LV_REDUCE) {
+			log_error("New size given (%d extents) not less than "
+				  "existing size (%d extents)", lp->extents,
+				  lv->le_count);
+			return EINVALID_CMD_LINE;
+		}
+		lp->resize = LV_EXTEND;
+	} else if (lp->extents == lv->le_count) {
+		if (lp->ac_policy)
+			return ECMD_PROCESSED; /* Nothing to do. */
+		if (!lp->resizefs) {
+			log_error("New size (%d extents) matches existing size "
+				  "(%d extents)", lp->extents, lv->le_count);
+			return EINVALID_CMD_LINE;
+		}
+		lp->resize = LV_EXTEND;
+	}
+
+	if (lv_is_origin(lv)) {
+		if (lp->resize == LV_REDUCE) {
+			log_error("Snapshot origin volumes cannot be reduced "
+				  "in size yet.");
+			return ECMD_FAILED;
+		}
+
+		if (lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) {
+			log_error("Snapshot origin volumes can be resized "
+				  "only while inactive: try lvchange -an");
+			return ECMD_FAILED;
+		}
+	}
+
+	if (lv_is_thin_pool(lv)) {
+		if (lp->resize == LV_REDUCE) {
+			log_error("Thin pool volumes cannot be reduced in size yet.");
+			return ECMD_FAILED;
+		}
+
+		if (lp->resizefs) {
+			log_warn("Thin pool volumes do not have filesystem.");
+			lp->resizefs = 0;
+		}
+	}
+
+	if ((lp->resize == LV_REDUCE) && lp->argc)
+		log_warn("Ignoring PVs on command line when reducing");
+
+	/* Request confirmation before operations that are often mistakes. */
+	if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
+	    !_request_confirmation(cmd, vg, lv, lp)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	if (lp->resizefs) {
+		if (!lp->nofsck &&
+		    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_CHECK, &status)) {
+			if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
+				log_error("Filesystem check failed.");
+				return ECMD_FAILED;
+			}
+			/* some filesystems supports online resize */
+		}
+
+		if ((lp->resize == LV_REDUCE) &&
+		    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL)) {
+			log_error("Filesystem resize failed.");
+			return ECMD_FAILED;
+		}
+	}
+
+	if (!archive(vg)) {
+		stack;
+		return ECMD_FAILED;
+	}
+
+	log_print_unless_silent("%sing logical volume %s to %s",
+				(lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
+				lp->lv_name,
+				display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
+
+	if (lp->resize == LV_REDUCE) {
+		if (!lv_reduce(lv, lv->le_count - lp->extents)) {
+			stack;
+			return ECMD_FAILED;
+		}
+	} else if ((lp->extents > lv->le_count) && /* Ensure we extend */
+		   !lv_extend(lv, lp->segtype,
+			      lp->stripes, lp->stripe_size,
+			      lp->mirrors, first_seg(lv)->region_size,
+			      lp->extents - lv->le_count, NULL,
+			      pvh, alloc)) {
+		stack;
+		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;
+	}
+
+	return ECMD_PROCESSED;
+}
+
 char *generate_lv_name(struct volume_group *vg, const char *format,
 		       char *buffer, size_t len)
 {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index a4ffe26..c8621ab 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -422,6 +422,49 @@ struct pvcreate_params {
 	struct pvcreate_restorable_params rp;
 };
 
+struct lvresize_params {
+	const char *vg_name;
+	const char *lv_name;
+
+	uint32_t stripes;
+	uint32_t stripe_size;
+	uint32_t mirrors;
+
+	const struct segment_type *segtype;
+
+	/* size */
+	uint32_t extents;
+	uint64_t size;
+	sign_t sign;
+	percent_type_t percent;
+
+	enum {
+		LV_ANY = 0,
+		LV_REDUCE = 1,
+		LV_EXTEND = 2
+	} resize;
+
+	int resizefs;
+	int nofsck;
+
+	int argc;
+	char **argv;
+
+	/* Arg counts & values */
+	unsigned ac_policy;
+	unsigned ac_stripes;
+	uint32_t ac_stripes_value;
+	unsigned ac_mirrors;
+	uint32_t ac_mirrors_value;
+	unsigned ac_stripesize;
+	uint64_t ac_stripesize_value;
+	unsigned ac_alloc;
+	unsigned ac_no_sync;
+	unsigned ac_force;
+
+	const char *ac_type;
+};
+
 struct physical_volume *pvcreate_single(struct cmd_context *cmd,
 					const char *pv_name,
 					struct pvcreate_params *pp,
@@ -468,6 +511,9 @@ int vgs_are_compatible(struct cmd_context *cmd,
 		       struct volume_group *vg_to);
 uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname);
 
+int lv_resize(struct cmd_context *cmd, struct volume_group *vg,
+		     struct lvresize_params *lp, struct dm_list *pvh);
+
 /*
  * Return a handle to VG metadata.
  */
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 4d11c16..aafd153 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -15,183 +15,6 @@
 
 #include "tools.h"
 
-#define SIZE_BUF 128
-
-struct lvresize_params {
-	const char *vg_name;
-	const char *lv_name;
-
-	uint32_t stripes;
-	uint32_t stripe_size;
-	uint32_t mirrors;
-
-	const struct segment_type *segtype;
-
-	/* size */
-	uint32_t extents;
-	uint64_t size;
-	sign_t sign;
-	percent_type_t percent;
-
-	enum {
-		LV_ANY = 0,
-		LV_REDUCE = 1,
-		LV_EXTEND = 2
-	} resize;
-
-	int resizefs;
-	int nofsck;
-
-	int argc;
-	char **argv;
-
-	/* Arg counts & values */
-	unsigned ac_policy;
-	unsigned ac_stripes;
-	uint32_t ac_stripes_value;
-	unsigned ac_mirrors;
-	uint32_t ac_mirrors_value;
-	unsigned ac_stripesize;
-	uint64_t ac_stripesize_value;
-	unsigned ac_alloc;
-	unsigned ac_no_sync;
-	unsigned ac_force;
-
-	const char *ac_type;
-};
-
-static int _validate_stripesize(struct cmd_context *cmd,
-				const struct volume_group *vg,
-				struct lvresize_params *lp)
-{
-
-	if ( lp->ac_stripesize_value > STRIPE_SIZE_LIMIT * 2) {
-		log_error("Stripe size cannot be larger than %s",
-			  display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
-		return 0;
-	}
-
-	if (!(vg->fid->fmt->features & FMT_SEGMENTS))
-		log_warn("Varied stripesize not supported. Ignoring.");
-	else if (lp->ac_stripesize_value > (uint64_t) vg->extent_size * 2) {
-		log_error("Reducing stripe size %s to maximum, "
-			  "physical extent size %s",
-			  display_size(cmd,lp->ac_stripesize_value),
-			  display_size(cmd, (uint64_t) vg->extent_size));
-		lp->stripe_size = vg->extent_size;
-	} else
-		lp->stripe_size = lp->ac_stripesize_value;
-
-	if (lp->stripe_size & (lp->stripe_size - 1)) {
-		log_error("Stripe size must be power of 2");
-		return 0;
-	}
-
-	return 1;
-}
-
-static int _request_confirmation(struct cmd_context *cmd,
-				 const struct volume_group *vg,
-				 const struct logical_volume *lv,
-				 const struct lvresize_params *lp)
-{
-	struct lvinfo info = { 0 };
-
-	if (!lv_info(cmd, lv, 0, &info, 1, 0) && driver_version(NULL, 0)) {
-		log_error("lv_info failed: aborting");
-		return 0;
-	}
-
-	if (lp->resizefs) {
-		if (!info.exists) {
-			log_error("Logical volume %s must be activated "
-				  "before resizing filesystem", lp->lv_name);
-			return 0;
-		}
-		return 1;
-	}
-
-	if (!info.exists)
-		return 1;
-
-	log_warn("WARNING: Reducing active%s logical volume to %s",
-		 info.open_count ? " and open" : "",
-		 display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
-
-	log_warn("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
-
-	if (!lp->ac_force) {
-		if (yes_no_prompt("Do you really want to reduce %s? [y/n]: ",
-				  lp->lv_name) == 'n') {
-			log_error("Logical volume %s NOT reduced", lp->lv_name);
-			return 0;
-		}
-		if (sigint_caught())
-			return 0;
-	}
-
-	return 1;
-}
-
-enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
-#define FSADM_CMD "fsadm"
-#define FSADM_CMD_MAX_ARGS 6
-#define FSADM_CHECK_FAILS_FOR_MOUNTED 3 /* shell exist status code */
-
-/*
- * 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,
-		      const struct volume_group *vg,
-		      const struct lvresize_params *lp,
-		      enum fsadm_cmd_e fcmd,
-		      int *status)
-{
-	char lv_path[PATH_MAX];
-	char size_buf[SIZE_BUF];
-	const char *argv[FSADM_CMD_MAX_ARGS + 2];
-	unsigned i = 0;
-
-	argv[i++] = FSADM_CMD;
-
-	if (test_mode())
-		argv[i++] = "--dry-run";
-
-	if (verbose_level() >= _LOG_NOTICE)
-		argv[i++] = "--verbose";
-
-	if (lp->ac_force)
-		argv[i++] = "--force";
-
-	argv[i++] = (fcmd == FSADM_CMD_RESIZE) ? "resize" : "check";
-
-	if (status)
-		*status = -1;
-
-	if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir, lp->vg_name,
-			lp->lv_name) < 0) {
-		log_error("Couldn't create LV path for %s", lp->lv_name);
-		return 0;
-	}
-
-	argv[i++] = lv_path;
-
-	if (fcmd == FSADM_CMD_RESIZE) {
-		if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64 "K",
-				(uint64_t) lp->extents * vg->extent_size / 2) < 0) {
-			log_error("Couldn't generate new LV size string");
-			return 0;
-		}
-
-		argv[i++] = size_buf;
-	}
-
-	argv[i] = NULL;
-
-	return exec_cmd(cmd, argv, status, 1);
-}
-
 static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
 			    struct lvresize_params *lp)
 {
@@ -326,600 +149,6 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
 	return 1;
 }
 
-static int _adjust_policy_params(struct cmd_context *cmd,
-				 struct logical_volume *lv, struct lvresize_params *lp)
-{
-	percent_t percent;
-	int policy_threshold, policy_amount;
-
-	if (lv_is_thin_pool(lv)) {
-		policy_threshold =
-			find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG) * PERCENT_1;
-		policy_amount =
-			find_config_tree_int(cmd, activation_thin_pool_autoextend_percent_CFG);
-		if (!policy_amount && policy_threshold < PERCENT_100)
-                        return 0;
-	} else {
-		policy_threshold =
-			find_config_tree_int(cmd, activation_snapshot_autoextend_threshold_CFG) * PERCENT_1;
-		policy_amount =
-			find_config_tree_int(cmd, activation_snapshot_autoextend_percent_CFG);
-	}
-
-	if (policy_threshold >= PERCENT_100)
-		return 1; /* nothing to do */
-
-	if (lv_is_thin_pool(lv)) {
-		if (!lv_thin_pool_percent(lv, 1, &percent))
-			return_0;
-		if (percent > policy_threshold) {
-			/* FIXME: metadata resize support missing */
-			log_error("Resize for %s/%s is not yet supported.",
-				  lp->vg_name, lp->lv_name);
-			return ECMD_FAILED;
-		}
-
-		if (!lv_thin_pool_percent(lv, 0, &percent))
-			return_0;
-		if (!(PERCENT_0 < percent && percent <= PERCENT_100) ||
-		    percent <= policy_threshold)
-			return 1; /* nothing to do */
-	} else {
-		if (!lv_snapshot_percent(lv, &percent))
-			return_0;
-		if (!(PERCENT_0 < percent && percent < PERCENT_100) || percent <= policy_threshold)
-			return 1; /* nothing to do */
-	}
-
-	lp->extents = policy_amount;
-
-	return 1;
-}
-
-static uint32_t lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize)
-{
-	uint32_t s;
-	struct lv_segment *seg_mirr;
-
-	/* If segment mirrored, check if images are striped */
-	if (seg_is_mirrored(seg))
-		for (s = 0; s < seg->area_count; s++) {
-			if (seg_type(seg, s) != AREA_LV)
-				continue;
-			seg_mirr = first_seg(seg_lv(seg, s));
-
-			if (seg_is_striped(seg_mirr)) {
-				seg = seg_mirr;
-				break;
-			}
-		}
-
-
-	if (seg_is_striped(seg)) {
-		*stripesize = seg->stripe_size;
-		return seg->area_count;
-	}
-
-	*stripesize = 0;
-	return 0;
-}
-
-static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
-		     struct lvresize_params *lp, struct dm_list *pvh)
-{
-	struct logical_volume *lv;
-	struct lvinfo info;
-	uint32_t stripesize_extents;
-	uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size;
-	uint32_t seg_mirrors = 0;
-	uint32_t extents_used;
-	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;
-	uint32_t sz, str;
-	int status;
-
-	/* does LV exist? */
-	if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
-		log_error("Logical volume %s not found in volume group %s",
-			  lp->lv_name, lp->vg_name);
-		return ECMD_FAILED;
-	}
-
-	if (lv_is_external_origin(lvl->lv)) {
-		/*
-		 * Since external-origin can be activated read-only,
-		 * there is no way to use extended areas.
-		 */
-		log_error("Cannot resize external origin \"%s\".", lvl->lv->name);
-		return EINVALID_CMD_LINE;
-	}
-
-	if (lvl->lv->status & (RAID_IMAGE | RAID_META)) {
-		log_error("Cannot resize a RAID %s directly",
-			  (lvl->lv->status & RAID_IMAGE) ? "image" :
-			  "metadata area");
-		return ECMD_FAILED;
-	}
-
-	if (lv_is_raid_with_tracking(lvl->lv)) {
-		log_error("Cannot resize %s while it is tracking a split image",
-			  lvl->lv->name);
-		return ECMD_FAILED;
-	}
-
-	if (lp->ac_stripes) {
-		if (vg->fid->fmt->features & FMT_SEGMENTS)
-			lp->stripes = lp->ac_stripes_value;
-		else
-			log_warn("Varied striping not supported. Ignoring.");
-	}
-
-	if (lp->ac_mirrors) {
-		if (vg->fid->fmt->features & FMT_SEGMENTS)
-			lp->mirrors = lp->ac_mirrors_value;
-		else
-			log_warn("Mirrors not supported. Ignoring.");
-	}
-
-	if (lp->ac_stripesize &&
-	    !_validate_stripesize(cmd, vg, lp))
-		return EINVALID_CMD_LINE;
-
-	lv = lvl->lv;
-
-	if (lp->ac_policy) {
-		if (!lv_is_cow(lv) &&
-		    !lv_is_thin_pool(lv)) {
-			log_error("Policy-based resize is supported only for snapshot and thin pool volumes.");
-			return ECMD_FAILED;
-		}
-		if (!_adjust_policy_params(cmd, lv, lp))
-			return ECMD_FAILED;
-	}
-
-	if (!lv_is_visible(lv)) {
-		log_error("Can't resize internal logical volume %s", lv->name);
-		return ECMD_FAILED;
-	}
-
-	if (lv->status & LOCKED) {
-		log_error("Can't resize locked LV %s", lv->name);
-		return ECMD_FAILED;
-	}
-
-	if (lv->status & CONVERTING) {
-		log_error("Can't resize %s while lvconvert in progress", lv->name);
-		return ECMD_FAILED;
-	}
-
-	alloc = (alloc_policy_t)(lp->ac_alloc)?lp->ac_alloc: lv->alloc;
-
-	/*
-	 * First adjust to an exact multiple of extent size.
-	 * When extending by a relative amount we round that amount up.
-	 * When reducing by a relative amount we remove at most that amount.
-	 * When changing to an absolute size, we round that size up.
-	 */
-	if (lp->size) {
-		if (lp->size % vg->extent_size) {
-			if (lp->sign == SIGN_MINUS)
-				lp->size -= lp->size % vg->extent_size;
-			else
-				lp->size += vg->extent_size -
-				    (lp->size % vg->extent_size);
-
-			log_print_unless_silent("Rounding size to boundary between physical extents: %s",
-						display_size(cmd, lp->size));
-		}
-
-		lp->extents = lp->size / vg->extent_size;
-	}
-
-	switch(lp->percent) {
-		case PERCENT_VG:
-			lp->extents = percent_of_extents(lp->extents, vg->extent_count,
-							 (lp->sign != SIGN_MINUS));
-			break;
-		case PERCENT_FREE:
-			lp->extents = percent_of_extents(lp->extents, vg->free_count,
-							 (lp->sign != SIGN_MINUS));
-			break;
-		case PERCENT_LV:
-			lp->extents = percent_of_extents(lp->extents, lv->le_count,
-							 (lp->sign != SIGN_MINUS));
-			break;
-		case PERCENT_PVS:
-			if (lp->argc) {
-				pv_extent_count = pv_list_extents_free(pvh);
-				lp->extents = percent_of_extents(lp->extents, pv_extent_count,
-								 (lp->sign != SIGN_MINUS));
-			} else
-				lp->extents = percent_of_extents(lp->extents, vg->extent_count,
-								 (lp->sign != SIGN_MINUS));
-			break;
-		case PERCENT_ORIGIN:
-			if (!lv_is_cow(lv)) {
-				log_error("Specified LV does not have an origin LV.");
-				return EINVALID_CMD_LINE;
-			}
-			lp->extents = percent_of_extents(lp->extents, origin_from_cow(lv)->le_count,
-							 (lp->sign != SIGN_MINUS));
-			break;
-		case PERCENT_NONE:
-			break;
-	}
-
-	if (lp->sign == SIGN_PLUS) {
-		if (lp->extents >= (MAX_EXTENT_COUNT - lv->le_count)) {
-			log_error("Unable to extend %s by %u extents, exceeds limit (%u).",
-				  lp->lv_name, lv->le_count, MAX_EXTENT_COUNT);
-			return EINVALID_CMD_LINE;
-		}
-		lp->extents += lv->le_count;
-	}
-
-	if (lp->sign == SIGN_MINUS) {
-		if (lp->extents >= lv->le_count) {
-			log_error("Unable to reduce %s below 1 extent",
-				  lp->lv_name);
-			return EINVALID_CMD_LINE;
-		}
-
-		lp->extents = lv->le_count - lp->extents;
-	}
-
-	if (!lp->extents) {
-		log_error("New size of 0 not permitted");
-		return EINVALID_CMD_LINE;
-	}
-
-	if (lp->extents == lv->le_count) {
-		if (lp->ac_policy)
-			return ECMD_PROCESSED; /* Nothing to do. */
-		if (!lp->resizefs) {
-			log_error("New size (%d extents) matches existing size "
-				  "(%d extents)", lp->extents, lv->le_count);
-			return EINVALID_CMD_LINE;
-		}
-		lp->resize = LV_EXTEND; /* lets pretend zero size extension */
-	}
-
-	seg_size = lp->extents - lv->le_count;
-
-	/* Use segment type of last segment */
-	dm_list_iterate_items(seg, &lv->segments) {
-		lp->segtype = seg->segtype;
-	}
-
-	/* FIXME Support LVs with mixed segment types */
-	if (lp->segtype != get_segtype_from_string(cmd, (lp->ac_type)?lp->ac_type:lp->segtype->name)) {
-		log_error("VolumeType does not match (%s)", lp->segtype->name);
-		return EINVALID_CMD_LINE;
-	}
-
-	/* If extending, find mirrors of last segment */
-	if ((lp->extents > lv->le_count)) {
-		/*
-		 * Has the user specified that they would like the additional
-		 * extents of a mirror not to have an initial sync?
-		 */
-		if (seg_is_mirrored(first_seg(lv)) && lp->ac_no_sync)
-			lv->status |= LV_NOTSYNCED;
-
-		dm_list_iterate_back_items(mirr_seg, &lv->segments) {
-			if (seg_is_mirrored(mirr_seg))
-				seg_mirrors = lv_mirror_count(mirr_seg->lv);
-			else
-				seg_mirrors = 0;
-			break;
-		}
-
-		if (!lp->ac_mirrors && seg_mirrors) {
-			log_print_unless_silent("Extending %" PRIu32 " mirror images.",
-						seg_mirrors);
-			lp->mirrors = seg_mirrors;
-		}
-		if ((lp->ac_mirrors || seg_mirrors) &&
-		    (lp->mirrors != seg_mirrors)) {
-			log_error("Cannot vary number of mirrors in LV yet.");
-			return EINVALID_CMD_LINE;
-		}
-
-		if (seg_mirrors && !strcmp(mirr_seg->segtype->name, "raid10")) {
-			lp->stripes = mirr_seg->area_count / seg_mirrors;
-			lp->stripe_size = mirr_seg->stripe_size;
-		}
-	}
-
-	/* If extending, find stripes, stripesize & size of last segment */
-	if ((lp->extents > lv->le_count) &&
-	    !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size)) &&
-	    strcmp(mirr_seg->segtype->name, "raid10")) {
-		/* FIXME Don't assume mirror seg will always be AREA_LV */
-		/* FIXME We will need to support resize for metadata LV as well,
-		 *       and data LV could be any type (i.e. mirror)) */
-		dm_list_iterate_items(seg, seg_mirrors ? &seg_lv(mirr_seg, 0)->segments :
-				      lv_is_thin_pool(lv) ? &seg_lv(first_seg(lv), 0)->segments : &lv->segments) {
-			/* Allow through "striped" and RAID 4/5/6/10 */
-			if (!seg_is_striped(seg) &&
-			    (!seg_is_raid(seg) || seg_is_mirrored(seg)) &&
-			    strcmp(seg->segtype->name, "raid10"))
-				continue;
-
-			sz = seg->stripe_size;
-			str = seg->area_count - lp->segtype->parity_devs;
-
-			if ((seg_stripesize && seg_stripesize != sz &&
-			     sz && !lp->stripe_size) ||
-			    (seg_stripes && seg_stripes != str && !lp->stripes)) {
-				log_error("Please specify number of "
-					  "stripes (-i) and stripesize (-I)");
-				return EINVALID_CMD_LINE;
-			}
-
-			seg_stripesize = sz;
-			seg_stripes = str;
-		}
-
-		if (!lp->stripes)
-			lp->stripes = seg_stripes;
-		else if (seg_is_raid(first_seg(lv)) &&
-			 (lp->stripes != seg_stripes)) {
-			log_error("Unable to extend \"%s\" segment type with different number of stripes.", first_seg(lv)->segtype->ops->name(first_seg(lv)));
-			return ECMD_FAILED;
-		}
-
-		if (!lp->stripe_size && lp->stripes > 1) {
-			if (seg_stripesize) {
-				log_print_unless_silent("Using stripesize of last segment %s",
-							display_size(cmd, (uint64_t) seg_stripesize));
-				lp->stripe_size = seg_stripesize;
-			} else {
-				lp->stripe_size =
-					find_config_tree_int(cmd, metadata_stripesize_CFG) * 2;
-				log_print_unless_silent("Using default stripesize %s",
-							display_size(cmd, (uint64_t) lp->stripe_size));
-			}
-		}
-	}
-
-	/* If reducing, find stripes, stripesize & size of last segment */
-	if (lp->extents < lv->le_count) {
-		extents_used = 0;
-
-		if (lp->stripes || lp->stripe_size || lp->mirrors)
-			log_error("Ignoring stripes, stripesize and mirrors "
-				  "arguments when reducing");
-
-		dm_list_iterate_items(seg, &lv->segments) {
-			seg_extents = seg->len;
-
-			/* Check for underlying stripe sizes */
-			seg_stripes = lvseg_get_stripes(seg, &seg_stripesize);
-
-			if (seg_is_mirrored(seg))
-				seg_mirrors = lv_mirror_count(seg->lv);
-			else
-				seg_mirrors = 0;
-
-			if (lp->extents <= extents_used + seg_extents)
-				break;
-
-			extents_used += seg_extents;
-		}
-
-		seg_size = lp->extents - extents_used;
-		lp->stripe_size = seg_stripesize;
-		lp->stripes = seg_stripes;
-		lp->mirrors = seg_mirrors;
-	}
-
-	if (lp->stripes > 1 && !lp->stripe_size) {
-		log_error("Stripesize for striped segment should not be 0!");
-		return EINVALID_CMD_LINE;
-	}
-
-	if (lp->stripes > 1) {
-		if (lp->stripe_size < STRIPE_SIZE_MIN) {
-			log_error("Invalid stripe size %s",
-				  display_size(cmd, (uint64_t) lp->stripe_size));
-			return EINVALID_CMD_LINE;
-		}
-
-		if (!(stripesize_extents = lp->stripe_size / vg->extent_size))
-			stripesize_extents = 1;
-
-		size_rest = seg_size % (lp->stripes * stripesize_extents);
-		/* Round toward the original size. */
-		if (size_rest &&
-		    ((lp->extents < lv->le_count) ||
-		     !lp->percent ||
-		     (vg->free_count >= (lp->extents - lv->le_count - size_rest +
-					 (lp->stripes * stripesize_extents))))) {
-			log_print_unless_silent("Rounding size (%d extents) up to stripe "
-						"boundary size for segment (%d extents)",
-						lp->extents, lp->extents - size_rest +
-						(lp->stripes * stripesize_extents));
-			lp->extents = lp->extents - size_rest +
-				      (lp->stripes * stripesize_extents);
-		} else if (size_rest) {
-			log_print_unless_silent("Rounding size (%d extents) down to stripe "
-						"boundary size for segment (%d extents)",
-						lp->extents, lp->extents - size_rest);
-			lp->extents = lp->extents - size_rest;
-		}
-	}
-
-	if (lp->extents < lv->le_count) {
-		if (lp->resize == LV_EXTEND) {
-			log_error("New size given (%d extents) not larger "
-				  "than existing size (%d extents)",
-				  lp->extents, lv->le_count);
-			return EINVALID_CMD_LINE;
-		}
-		lp->resize = LV_REDUCE;
-	} else if (lp->extents > lv->le_count) {
-		if (lp->resize == LV_REDUCE) {
-			log_error("New size given (%d extents) not less than "
-				  "existing size (%d extents)", lp->extents,
-				  lv->le_count);
-			return EINVALID_CMD_LINE;
-		}
-		lp->resize = LV_EXTEND;
-	} else if (lp->extents == lv->le_count) {
-		if (lp->ac_policy)
-			return ECMD_PROCESSED; /* Nothing to do. */
-		if (!lp->resizefs) {
-			log_error("New size (%d extents) matches existing size "
-				  "(%d extents)", lp->extents, lv->le_count);
-			return EINVALID_CMD_LINE;
-		}
-		lp->resize = LV_EXTEND;
-	}
-
-	if (lv_is_origin(lv)) {
-		if (lp->resize == LV_REDUCE) {
-			log_error("Snapshot origin volumes cannot be reduced "
-				  "in size yet.");
-			return ECMD_FAILED;
-		}
-
-		if (lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) {
-			log_error("Snapshot origin volumes can be resized "
-				  "only while inactive: try lvchange -an");
-			return ECMD_FAILED;
-		}
-	}
-
-	if (lv_is_thin_pool(lv)) {
-		if (lp->resize == LV_REDUCE) {
-			log_error("Thin pool volumes cannot be reduced in size yet.");
-			return ECMD_FAILED;
-		}
-
-		if (lp->resizefs) {
-			log_warn("Thin pool volumes do not have filesystem.");
-			lp->resizefs = 0;
-		}
-	}
-
-	if ((lp->resize == LV_REDUCE) && lp->argc)
-		log_warn("Ignoring PVs on command line when reducing");
-
-	/* Request confirmation before operations that are often mistakes. */
-	if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
-	    !_request_confirmation(cmd, vg, lv, lp)) {
-		stack;
-		return ECMD_FAILED;
-	}
-
-	if (lp->resizefs) {
-		if (!lp->nofsck &&
-		    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_CHECK, &status)) {
-			if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
-				log_error("Filesystem check failed.");
-				return ECMD_FAILED;
-			}
-			/* some filesystems supports online resize */
-		}
-
-		if ((lp->resize == LV_REDUCE) &&
-		    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL)) {
-			log_error("Filesystem resize failed.");
-			return ECMD_FAILED;
-		}
-	}
-
-	if (!archive(vg)) {
-		stack;
-		return ECMD_FAILED;
-	}
-
-	log_print_unless_silent("%sing logical volume %s to %s",
-				(lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
-				lp->lv_name,
-				display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
-
-	if (lp->resize == LV_REDUCE) {
-		if (!lv_reduce(lv, lv->le_count - lp->extents)) {
-			stack;
-			return ECMD_FAILED;
-		}
-	} else if ((lp->extents > lv->le_count) && /* Ensure we extend */
-		   !lv_extend(lv, lp->segtype,
-			      lp->stripes, lp->stripe_size,
-			      lp->mirrors, first_seg(lv)->region_size,
-			      lp->extents - lv->le_count, NULL,
-			      pvh, alloc)) {
-		stack;
-		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;
-	}
-
-	return ECMD_PROCESSED;
-}
-
 int lvresize(struct cmd_context *cmd, int argc, char **argv)
 {
 	struct lvresize_params lp = { 0 };
@@ -946,7 +175,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
 		return ECMD_FAILED;
 	}
 
-	if (!(r = _lvresize(cmd, vg, &lp, pvh)))
+	if (!(r = lv_resize(cmd, vg, &lp, pvh)))
 		stack;
 
 	unlock_and_release_vg(cmd, vg, lp.vg_name);
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/19] lvm2app: Implement lv resize (v2)
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (4 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 05/19] lvm2app: Move core lv re-size code (v2) Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 07/19] lvm2app: Add function to retrieve list of PVs Tony Asleson
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Simplified version of lv resize.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/metadata/metadata-exported.h |  1 +
 liblvm/lvm2app.h                 |  2 --
 liblvm/lvm_lv.c                  | 19 ++++++++++++++++---
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index c8621ab..21ea86d 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
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 633b026..25778d1 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1374,8 +1374,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 4fbd06b..49306e6 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -318,9 +318,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 != lv_resize(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)
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/19] lvm2app: Add function to retrieve list of PVs
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (5 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 06/19] lvm2app: Implement lv resize (v2) Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 08/19] lvm2app: Implement lvm_pv_remove Tony Asleson
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

As locks are held, you need to call the included function
to release the memory and locks when done transversing the
list of physical volumes.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/metadata/metadata-exported.h |  12 +++-
 lib/metadata/metadata.c          |  81 +++++++++++++++------
 liblvm/lvm2app.h                 |  28 ++++++++
 liblvm/lvm_pv.c                  |  79 ++++++++++++++++++++
 python/liblvm.c                  | 152 ++++++++++++++++++++++++++++++++++++---
 5 files changed, 322 insertions(+), 30 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 21ea86d..4cc42bc 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -396,6 +396,11 @@ struct lv_list {
 	struct logical_volume *lv;
 };
 
+struct vg_list {
+	struct dm_list list;
+	struct volume_group *vg;
+};
+
 #define PV_PE_START_CALC ((uint64_t) -1) /* Calculate pe_start value */
 
 struct pvcreate_restorable_params {
@@ -483,7 +488,12 @@ struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vg_na
 struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
 				int warnings,
 				int scan_label_only);
-struct dm_list *get_pvs(struct cmd_context *cmd);
+
+#define get_pvs( cmd ) get_pvs_internal((cmd), NULL, NULL)
+#define get_pvs_perserve_vg( cmd, pv_list, vg_list ) get_pvs_internal((cmd), (pv_list), (vg_list))
+
+struct dm_list *get_pvs_internal(struct cmd_context *cmd,
+		struct dm_list *pvslist, struct dm_list *vgslist);
 
 /*
  * Add/remove LV to/from volume group
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index bde1cb0..cecf81c 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3667,7 +3667,8 @@ struct dm_list *get_vgids(struct cmd_context *cmd, int include_internal)
 	return lvmcache_get_vgids(cmd, include_internal);
 }
 
-static int _get_pvs(struct cmd_context *cmd, int warnings, struct dm_list **pvslist)
+static int _get_pvs(struct cmd_context *cmd, int warnings,
+		struct dm_list *pvslist, struct dm_list *vgslist)
 {
 	struct str_list *strl;
 	struct dm_list * uninitialized_var(results);
@@ -3677,18 +3678,11 @@ static int _get_pvs(struct cmd_context *cmd, int warnings, struct dm_list **pvsl
 	struct volume_group *vg;
 	int consistent = 0;
 	int old_pvmove;
+	struct vg_list *vgl_item = NULL;
+	int have_pv = 0;
 
 	lvmcache_label_scan(cmd, 0);
 
-	if (pvslist) {
-		if (!(results = dm_pool_alloc(cmd->mem, sizeof(*results)))) {
-			log_error("PV list allocation failed");
-			return 0;
-		}
-
-		dm_list_init(results);
-	}
-
 	/* Get list of VGs */
 	if (!(vgids = get_vgids(cmd, 1))) {
 		log_error("get_pvs: get_vgids failed");
@@ -3724,33 +3718,78 @@ static int _get_pvs(struct cmd_context *cmd, int warnings, struct dm_list **pvsl
 					release_vg(vg);
 					return 0;
 				}
-				dm_list_add(results, &pvl_copy->list);
+				/* If we are going to release the vg, don't store a pointer to
+				 * it in the pv structure.
+				 */
+				if (!vgslist) {
+					pvl_copy->pv->vg = NULL;
+				}
+				have_pv = 1;
+				dm_list_add(pvslist, &pvl_copy->list);
 			}
-		release_vg(vg);
+
+		/* In the case of the library we want to preserve the embedded volume
+		 * group as subsequent calls to retrieve data about the pv require it.
+		 */
+		if (!vgslist || have_pv == 0) {
+			release_vg(vg);
+		} else {
+			/* Add vg to list of vg objects that will be returned
+			 */
+			vgl_item = dm_pool_alloc(cmd->mem, sizeof(*vgl_item));
+			if (!vgl_item) {
+				log_error("VG list element allocation failed");
+				return 0;
+			}
+			vgl_item->vg = vg;
+			vg = NULL;
+			dm_list_add(vgslist, &vgl_item->list);
+		}
+		have_pv = 0;
 	}
 	init_pvmove(old_pvmove);
 
-	if (pvslist)
-		*pvslist = results;
-	else
+	if (!pvslist) {
 		dm_pool_free(cmd->mem, vgids);
-
+	}
 	return 1;
 }
 
-struct dm_list *get_pvs(struct cmd_context *cmd)
+/* Retrieve a list of all physical volumes.
+ * @param 	cmd			Command context
+ * @param	pvslist		Set to NULL if you want memory for list created,
+ * 						else valid memory
+ * @param	vgslist		Set to NULL if you need the pv structures to contain
+ * 						valid vg pointer.  This is the list of VGs
+ * @returns NULL on errors, else pvslist which will equal passes in value if
+ * 	supplied.
+ */
+struct dm_list *get_pvs_internal(struct cmd_context *cmd,
+					struct dm_list *pvslist, struct dm_list *vgslist)
 {
-	struct dm_list *results;
+	struct dm_list *results = pvslist;
 
-	if (!_get_pvs(cmd, 1, &results))
-		return NULL;
+	if (NULL == results) {
+		if (!(results = dm_pool_alloc(cmd->mem, sizeof(*results)))) {
+			log_error("PV list allocation failed");
+			return 0;
+		}
+
+		dm_list_init(results);
+	}
 
+	if (!_get_pvs(cmd, 1, results, vgslist)) {
+		if (NULL == pvslist) {
+			dm_pool_free(cmd->mem, results);
+		}
+		return NULL;
+	}
 	return results;
 }
 
 int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings)
 {
-	return _get_pvs(cmd, warnings, NULL);
+	return _get_pvs(cmd, warnings, NULL, NULL);
 }
 
 int pv_write(struct cmd_context *cmd __attribute__((unused)),
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 25778d1..260693c 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -543,6 +543,34 @@ vg_t lvm_vg_create(lvm_t libh, const char *vg_name);
 struct dm_list *lvm_vg_list_lvs(vg_t vg);
 
 /**
+ * Return a list of PV handles for all.
+ *
+ * \memberof lvm_t
+ *
+ * \param   libh
+ * Library handle retrieved from lvm_init
+ *
+ * \return
+ * A list of lvm_pv_list structures containing pv handles for all physical
+ * volumes. If no PVs exist or a global lock was unable to be obtained a
+ * NULL is returned.
+ */
+struct dm_list *lvm_list_pvs(lvm_t libh);
+
+/**
+ * Free the resources used by acquiring the pvlist.  This should be called as
+ * soon as possible after processing the needed information from the pv list as
+ * a global locks are held.
+ *
+ * \param	pvlist
+ * PV list to be freed
+ * 
+ * \return
+ * 0 on success, else -1 with library errno and text set.
+ */
+int lvm_list_pvs_free(struct dm_list *pvlist);
+
+/**
  * Return a list of PV handles for a given VG handle.
  *
  * \memberof vg_t
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 18b1069..9e99e7d 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -12,11 +12,14 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <stddef.h>
 #include "lib.h"
 #include "metadata.h"
 #include "lvm-string.h"
 #include "lvm_misc.h"
 #include "lvm2app.h"
+#include "locking.h"
+#include "toolcontext.h"
 
 const char *lvm_pv_get_uuid(const pv_t pv)
 {
@@ -60,6 +63,82 @@ struct lvm_property_value lvm_pvseg_get_property(const pvseg_t pvseg,
 	return get_property(NULL, NULL, NULL, NULL, pvseg, NULL, name);
 }
 
+
+#define address_of(p, t, m) ({                  \
+	const typeof( ((t *)0)->m ) *__mptr = (p);    \
+	(t *)( (char *)__mptr - offsetof(t,m) );})
+
+struct lvm_list_wrapper
+{
+	unsigned long magic;
+	struct dm_list pvslist;
+	struct dm_list vgslist;
+};
+
+
+struct dm_list *lvm_list_pvs(lvm_t libh)
+{
+	struct lvm_list_wrapper *rc = NULL;
+	struct cmd_context *cmd = (struct cmd_context *)libh;
+
+
+	rc = dm_pool_zalloc(cmd->mem, sizeof(*rc));
+	if (!rc) {
+		log_errno(ENOMEM, "Memory allocation fail for pv list.");
+		return NULL;
+	}
+
+	if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE)) {
+		log_errno(ENOLCK, "Unable to obtain global lock.");
+	} else {
+		dm_list_init(&rc->pvslist);
+		dm_list_init(&rc->vgslist);
+		if( !get_pvs_perserve_vg(cmd, &rc->pvslist, &rc->vgslist) ) {
+			dm_pool_free(cmd->mem, rc);
+			return NULL;
+		}
+		rc->magic = 0xF005BA11;
+	}
+
+	return &rc->pvslist;
+}
+
+int lvm_list_pvs_free(struct dm_list *pvlist)
+{
+	int rc = 0;
+	struct lvm_list_wrapper *to_delete = NULL;
+	struct vg_list *vgl = NULL;
+	struct vg_list *tmp_vgl = NULL;
+	struct pv_list *pvl = NULL;
+	struct pv_list *tmp_pvl = NULL;
+	struct cmd_context *cmd = NULL;
+
+	if (pvlist ) {
+		to_delete = address_of(pvlist, struct lvm_list_wrapper, pvslist);
+		if (to_delete->magic == 0xF005BA11) {
+
+			dm_list_iterate_items(vgl, &to_delete->vgslist) {
+				cmd = vgl->vg->cmd;
+				release_vg(vgl->vg);
+			}
+
+			dm_list_iterate_items(pvl, &to_delete->pvslist) {
+				free_pv_fid(pvl->pv);
+			}
+
+			unlock_vg(cmd, VG_GLOBAL);
+		} else {
+			log_errno(EINVAL, "Not a correct pvlist structure");
+			rc = -1;
+		}
+
+		to_delete->magic = 0xA5A5A5A5;
+		dm_pool_free(cmd->mem, to_delete);
+
+	}
+	return rc;
+}
+
 struct dm_list *lvm_pv_list_pvsegs(pv_t pv)
 {
 	struct dm_list *list;
diff --git a/python/liblvm.c b/python/liblvm.c
index 906825e..928cab0 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -34,6 +34,11 @@ typedef struct {
 
 typedef struct {
 	PyObject_HEAD
+	struct dm_list *pvslist;
+} pvslistobject;
+
+typedef struct {
+	PyObject_HEAD
 	lv_t lv;		/* lv handle */
 	vgobject *parent_vgobj;
 } lvobject;
@@ -42,6 +47,7 @@ typedef struct {
 	PyObject_HEAD
 	pv_t pv;		/* pv handle */
 	vgobject *parent_vgobj;
+	pvslistobject *parent_pvslistobj;
 } pvobject;
 
 typedef struct {
@@ -58,6 +64,7 @@ typedef struct {
 
 static PyTypeObject LibLVMvgType;
 static PyTypeObject LibLVMlvType;
+static PyTypeObject LibLVMpvlistType;
 static PyTypeObject LibLVMpvType;
 static PyTypeObject LibLVMlvsegType;
 static PyTypeObject LibLVMpvsegType;
@@ -153,6 +160,90 @@ liblvm_lvm_list_vg_uuids(void)
 }
 
 static PyObject *
+liblvm_lvm_pvlist_get(pvslistobject *pvsobj)
+{
+	struct lvm_pv_list *pvl;
+	PyObject * pytuple;
+	pvobject * pvobj;
+	int i = 0;
+
+	/* unlike other LVM api calls, if there are no results, we get NULL */
+	pvsobj->pvslist = lvm_list_pvs(libh);
+
+	if (!pvsobj->pvslist)
+		return Py_BuildValue("()");
+
+	pytuple = PyTuple_New(dm_list_size(pvsobj->pvslist));
+	if (!pytuple)
+		return NULL;
+
+	dm_list_iterate_items(pvl, pvsobj->pvslist) {
+		/* Create and initialize the object */
+		pvobj = PyObject_New(pvobject, &LibLVMpvType);
+		if (!pvobj) {
+			Py_DECREF(pytuple);
+			return NULL;
+		}
+
+		/* We don't have a parent vg object to be concerned about */
+		pvobj->parent_vgobj = NULL;
+		pvobj->parent_pvslistobj = pvsobj;
+		Py_INCREF(pvobj->parent_pvslistobj);
+
+		pvobj->pv = pvl->pv;
+		PyTuple_SET_ITEM(pytuple, i, (PyObject *) pvobj);
+		i++;
+	}
+
+	return pytuple;
+}
+
+static PyObject *
+liblvm_lvm_pvlist_put(pvslistobject *self)
+{
+	int rc = 0;
+	if (self->pvslist) {
+		rc = lvm_list_pvs_free(self->pvslist);
+
+		if ( 0 != rc ) {
+			PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+			return NULL;
+		}
+
+		self->pvslist = NULL;
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+	return NULL;
+}
+
+static PyObject *
+liblvm_pvlist_dealloc(pvslistobject *self)
+{
+	if (self->pvslist) {
+		liblvm_lvm_pvlist_put(self);
+	}
+
+	PyObject_Del(self);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+liblvm_lvm_list_pvs(void)
+{
+	pvslistobject *pvslistobj;
+
+	LVM_VALID();
+
+	if ((pvslistobj = PyObject_New(pvslistobject, &LibLVMpvlistType)) == NULL)
+			return NULL;
+
+	pvslistobj->pvslist = NULL;
+	return (PyObject *)pvslistobj;
+}
+
+static PyObject *
 liblvm_lvm_percent_to_float(PyObject *self, PyObject *arg)
 {
 	double converted;
@@ -360,6 +451,15 @@ liblvm_vg_dealloc(vgobject *self)
 		}							\
 	} while (0)
 
+#define PVSLIST_VALID(pvslistobject)			\
+	do {										\
+		LVM_VALID();							\
+		if (!pvslistobject->pvslist) {			\
+			PyErr_SetString(PyExc_UnboundLocalError, "PVS object invalid"); \
+			return NULL;						\
+		}										\
+	} while (0)
+
 static PyObject *
 liblvm_lvm_vg_close(vgobject *self)
 {
@@ -1030,7 +1130,16 @@ liblvm_lvm_pv_from_uuid(vgobject *self, PyObject *arg)
 static void
 liblvm_pv_dealloc(pvobject *self)
 {
-	Py_DECREF(self->parent_vgobj);
+	if (self->parent_vgobj) {
+		Py_DECREF(self->parent_vgobj);
+	}
+
+	if (self->parent_pvslistobj) {
+		Py_DECREF(self->parent_pvslistobj);
+	}
+
+	self->parent_vgobj = NULL;
+	self->parent_pvslistobj = NULL;
 	PyObject_Del(self);
 }
 
@@ -1337,19 +1446,23 @@ liblvm_lvm_lv_snapshot(lvobject *self, PyObject *args)
 
 	lvobj->parent_vgobj = self->parent_vgobj;
 	Py_INCREF(lvobj->parent_vgobj);
-
 	return (PyObject *)lvobj;
 }
 
 /* PV Methods */
 
-#define PV_VALID(pvobject)						\
-	do {								\
-		VG_VALID(pvobject->parent_vgobj);			\
-		if (!pvobject->pv) {					\
+#define PV_VALID(pvobject)								\
+	do {												\
+		if (pvobject->parent_vgobj) {					\
+			VG_VALID(pvobject->parent_vgobj);			\
+		}												\
+		if (pvobject->parent_pvslistobj) {				\
+			PVSLIST_VALID(pvobject->parent_pvslistobj);	\
+		}												\
+		if (!pvobject->pv) {							\
 			PyErr_SetString(PyExc_UnboundLocalError, "PV object invalid"); \
-			return NULL;					\
-		}							\
+			return NULL;								\
+		}												\
 	} while (0)
 
 static PyObject *
@@ -1550,6 +1663,7 @@ static PyMethodDef Liblvm_methods[] = {
 	{ "scan",		(PyCFunction)liblvm_lvm_scan, METH_NOARGS },
 	{ "listVgNames",	(PyCFunction)liblvm_lvm_list_vg_names, METH_NOARGS },
 	{ "listVgUuids",	(PyCFunction)liblvm_lvm_list_vg_uuids, METH_NOARGS },
+	{ "listPvs",		(PyCFunction)liblvm_lvm_list_pvs, METH_NOARGS },
 	{ "percentToFloat",	(PyCFunction)liblvm_lvm_percent_to_float, METH_VARARGS },
 	{ "vgNameFromPvid",	(PyCFunction)liblvm_lvm_vgname_from_pvid, METH_VARARGS },
 	{ "vgNameFromDevice",	(PyCFunction)liblvm_lvm_vgname_from_device, METH_VARARGS },
@@ -1613,6 +1727,15 @@ static PyMethodDef liblvm_lv_methods[] = {
 	{ NULL, NULL }		/* sentinel */
 };
 
+static PyMethodDef liblvm_pv_list_methods[] = {
+	/* pv list methods */
+	{ "__enter__", 	(PyCFunction)liblvm_lvm_pvlist_get, METH_VARARGS },
+	{ "__exit__", 	(PyCFunction)liblvm_lvm_pvlist_put, METH_VARARGS },
+	{ "open",		(PyCFunction)liblvm_lvm_pvlist_get, METH_VARARGS }, 
+	{ "close",		(PyCFunction)liblvm_lvm_pvlist_put, METH_VARARGS }, 
+	{ NULL, NULL }
+};
+
 static PyMethodDef liblvm_pv_methods[] = {
 	/* pv methods */
 	{ "getName",		(PyCFunction)liblvm_lvm_pv_get_name, METH_NOARGS },
@@ -1659,6 +1782,17 @@ static PyTypeObject LibLVMlvType = {
 	.tp_methods = liblvm_lv_methods,
 };
 
+static PyTypeObject LibLVMpvlistType = {
+	PyObject_HEAD_INIT(&PyType_Type)
+		.tp_name = "liblvm.Liblvm_pvlist",
+		.tp_basicsize = sizeof(pvslistobject),
+		.tp_new = PyType_GenericNew,
+		.tp_dealloc = (destructor)liblvm_pvlist_dealloc,
+		.tp_flags = Py_TPFLAGS_DEFAULT,
+		.tp_doc = "LVM Physical Volume list object",
+		.tp_methods = liblvm_pv_list_methods,
+};
+
 static PyTypeObject LibLVMpvType = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	.tp_name = "liblvm.Liblvm_pv",
@@ -1716,6 +1850,8 @@ initlvm(void)
 		return;
 	if (PyType_Ready(&LibLVMpvsegType) < 0)
 		return;
+	if (PyType_Ready(&LibLVMpvlistType) < 0)
+			return;
 
 	m = Py_InitModule3("lvm", Liblvm_methods, "Liblvm module");
 	if (m == NULL)
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/19] lvm2app: Implement lvm_pv_remove
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (6 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 07/19] lvm2app: Add function to retrieve list of PVs Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 09/19] python-lvm: Add bindings for lvm_pv_remove Tony Asleson
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Code move and changes to support calling code from
command line and from library interface.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/metadata/metadata.h |   4 ++
 lib/metadata/pv_manip.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++
 liblvm/lvm2app.h        |  16 +++++-
 liblvm/lvm_pv.c         |   8 +++
 tools/pvremove.c        | 135 +++---------------------------------------------
 5 files changed, 163 insertions(+), 130 deletions(-)

diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 4f504ed..74dcff7 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -341,6 +341,10 @@ int vg_validate(struct volume_group *vg);
 
 int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
 
+int pvremove_single(struct cmd_context *cmd, const char *pv_name,
+			   void *handle __attribute__((unused)), unsigned force_count,
+			   unsigned prompt);
+
 /* Manipulate PV structures */
 int pv_add(struct volume_group *vg, struct physical_volume *pv);
 int pv_remove(struct volume_group *vg, struct physical_volume *pv);
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index 4a65a3e..3823f76 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -19,6 +19,7 @@
 #include "toolcontext.h"
 #include "locking.h"
 #include "defaults.h"
+#include "lvmetad.h"
 
 static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
 					    struct physical_volume *pv,
@@ -542,3 +543,132 @@ int pv_resize(struct physical_volume *pv,
 
 	return 1;
 }
+
+const char _really_wipe[] =
+    "Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
+
+/*
+ * Decide whether it is "safe" to wipe the labels on this device.
+ * 0 indicates we may not.
+ */
+static int pvremove_check(struct cmd_context *cmd, const char *name,
+		unsigned force_count, unsigned prompt)
+{
+	struct physical_volume *pv;
+
+	/* FIXME Check partition type is LVM unless --force is given */
+
+	/* Is there a pv here already? */
+	/* If not, this is an error unless you used -f. */
+	if (!(pv = pv_read(cmd, name, 1, 0))) {
+		if (force_count)
+			return 1;
+		log_error("Physical Volume %s not found", name);
+		return 0;
+	}
+
+	/*
+	 * If a PV has no MDAs it may appear to be an
+	 * orphan until the metadata is read off
+	 * another PV in the same VG.  Detecting this
+	 * 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 (!scan_vgs_for_pvs(cmd, 0)) {
+			log_error("Rescan for PVs without metadata areas "
+				  "failed.");
+			goto bad;
+		}
+		free_pv_fid(pv);
+		if (!(pv = pv_read(cmd, name, 1, 0))) {
+			log_error("Failed to read physical volume %s", name);
+			goto bad;
+		}
+	}
+
+	/* orphan ? */
+	if (is_orphan(pv)) {
+		free_pv_fid(pv);
+		return 1;
+	}
+
+	/* Allow partial & exported VGs to be destroyed. */
+	/* we must have -ff to overwrite a non orphan */
+	if (force_count < 2) {
+		log_error("PV %s belongs to Volume Group %s so please use vgreduce first.", name, pv_vg_name(pv));
+		log_error("(If you are certain you need pvremove, then confirm by using --force twice.)");
+		goto bad;
+	}
+
+	/* prompt */
+	if (!prompt &&
+	    yes_no_prompt(_really_wipe, name, pv_vg_name(pv)) == 'n') {
+		log_error("%s: physical volume label not removed", name);
+		goto bad;
+	}
+
+	if (force_count) {
+		log_warn("WARNING: Wiping physical volume label from "
+			  "%s%s%s%s", name,
+			  !is_orphan(pv) ? " of volume group \"" : "",
+			  !is_orphan(pv) ? pv_vg_name(pv) : "",
+			  !is_orphan(pv) ? "\"" : "");
+	}
+
+	free_pv_fid(pv);
+	return 1;
+
+bad:
+	free_pv_fid(pv);
+	return 0;
+}
+
+int pvremove_single(struct cmd_context *cmd, const char *pv_name,
+			   void *handle __attribute__((unused)), unsigned force_count,
+			   unsigned prompt)
+{
+	struct device *dev;
+	int ret = ECMD_FAILED;
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	if (!pvremove_check(cmd, pv_name, force_count, prompt))
+		goto out;
+
+	if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
+		log_error("%s: Couldn't find device.  Check your filters?",
+			  pv_name);
+		goto out;
+	}
+
+	if (!dev_test_excl(dev)) {
+		/* FIXME Detect whether device-mapper is still using the device */
+		log_error("Can't open %s exclusively - not removing. "
+			  "Mounted filesystem?", dev_name(dev));
+		goto out;
+	}
+
+	/* Wipe existing label(s) */
+	if (!label_remove(dev)) {
+		log_error("Failed to wipe existing label(s) on %s", pv_name);
+		goto out;
+	}
+
+	if (!lvmetad_pv_gone_by_dev(dev, NULL))
+		goto_out;
+
+	log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
+				pv_name);
+
+	ret = ECMD_PROCESSED;
+
+out:
+	unlock_vg(cmd, VG_ORPHANS);
+
+	return ret;
+}
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 260693c..a92d4dd 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -553,14 +553,15 @@ struct dm_list *lvm_vg_list_lvs(vg_t vg);
  * \return
  * A list of lvm_pv_list structures containing pv handles for all physical
  * volumes. If no PVs exist or a global lock was unable to be obtained a
- * NULL is returned.
+ * NULL is returned.  Do not attempt to remove one of the PVs until after the
+ * call to lvm_list_pvs_free has been made.
  */
 struct dm_list *lvm_list_pvs(lvm_t libh);
 
 /**
  * Free the resources used by acquiring the pvlist.  This should be called as
  * soon as possible after processing the needed information from the pv list as
- * a global locks are held.
+ * a global lock is held.
  *
  * \param	pvlist
  * PV list to be freed
@@ -571,6 +572,17 @@ struct dm_list *lvm_list_pvs(lvm_t libh);
 int lvm_list_pvs_free(struct dm_list *pvlist);
 
 /**
+ *  Remove a physical volume.
+ *  Note: You cannot remove a PV while iterating through the list of PVs as
+ *  locks are held for the PV list.
+ *  \param	libh	Library handle
+ *  \param	pv_name	The physical volume name
+ *  \return
+ *  0 on success, else -1 with library errno and text set.
+ */
+int lvm_pv_remove(lvm_t libh, const char *pv_name);
+
+/**
  * Return a list of PV handles for a given VG handle.
  *
  * \memberof vg_t
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 9e99e7d..38b0126 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -75,6 +75,14 @@ struct lvm_list_wrapper
 	struct dm_list vgslist;
 };
 
+int lvm_pv_remove(lvm_t libh, const char *pv_name)
+{
+	struct cmd_context *cmd = (struct cmd_context *)libh;
+	if ( 1 != pvremove_single(cmd, pv_name, NULL, 0, 0)) {
+		return -1;
+	}
+	return 0;
+}
 
 struct dm_list *lvm_list_pvs(lvm_t libh)
 {
diff --git a/tools/pvremove.c b/tools/pvremove.c
index 823c069..798e91c 100644
--- a/tools/pvremove.c
+++ b/tools/pvremove.c
@@ -14,150 +14,29 @@
  */
 
 #include "tools.h"
+#include "metadata.h"
 
-const char _really_wipe[] =
-    "Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
-
-/*
- * Decide whether it is "safe" to wipe the labels on this device.
- * 0 indicates we may not.
- */
-static int pvremove_check(struct cmd_context *cmd, const char *name)
-{
-	struct physical_volume *pv;
-
-	/* FIXME Check partition type is LVM unless --force is given */
-
-	/* Is there a pv here already? */
-	/* If not, this is an error unless you used -f. */
-	if (!(pv = pv_read(cmd, name, 1, 0))) {
-		if (arg_count(cmd, force_ARG))
-			return 1;
-		log_error("Physical Volume %s not found", name);
-		return 0;
-	}
-
-	/*
-	 * If a PV has no MDAs it may appear to be an
-	 * orphan until the metadata is read off
-	 * another PV in the same VG.  Detecting this
-	 * 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 (!scan_vgs_for_pvs(cmd, 0)) {
-			log_error("Rescan for PVs without metadata areas "
-				  "failed.");
-			goto bad;
-		}
-		free_pv_fid(pv);
-		if (!(pv = pv_read(cmd, name, 1, 0))) {
-			log_error("Failed to read physical volume %s", name);
-			goto bad;
-		}
-	}
-
-	/* orphan ? */
-	if (is_orphan(pv)) {
-		free_pv_fid(pv);
-		return 1;
-	}
-
-	/* Allow partial & exported VGs to be destroyed. */
-	/* we must have -ff to overwrite a non orphan */
-	if (arg_count(cmd, force_ARG) < 2) {
-		log_error("PV %s belongs to Volume Group %s so please use vgreduce first.", name, pv_vg_name(pv));
-		log_error("(If you are certain you need pvremove, then confirm by using --force twice.)");
-		goto bad;
-	}
-
-	/* prompt */
-	if (!arg_count(cmd, yes_ARG) &&
-	    yes_no_prompt(_really_wipe, name, pv_vg_name(pv)) == 'n') {
-		log_error("%s: physical volume label not removed", name);
-		goto bad;
-	}
-
-	if (arg_count(cmd, force_ARG)) {
-		log_warn("WARNING: Wiping physical volume label from "
-			  "%s%s%s%s", name,
-			  !is_orphan(pv) ? " of volume group \"" : "",
-			  !is_orphan(pv) ? pv_vg_name(pv) : "",
-			  !is_orphan(pv) ? "\"" : "");
-	}
-
-	free_pv_fid(pv);
-	return 1;
-
-bad:
-	free_pv_fid(pv);
-	return 0;
-}
-
-static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
-			   void *handle __attribute__((unused)))
-{
-	struct device *dev;
-	int ret = ECMD_FAILED;
-
-	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
-		log_error("Can't get lock for orphan PVs");
-		return ECMD_FAILED;
-	}
-
-	if (!pvremove_check(cmd, pv_name))
-		goto out;
-
-	if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
-		log_error("%s: Couldn't find device.  Check your filters?",
-			  pv_name);
-		goto out;
-	}
-
-	if (!dev_test_excl(dev)) {
-		/* FIXME Detect whether device-mapper is still using the device */
-		log_error("Can't open %s exclusively - not removing. "
-			  "Mounted filesystem?", dev_name(dev));
-		goto out;
-	}
-
-	/* Wipe existing label(s) */
-	if (!label_remove(dev)) {
-		log_error("Failed to wipe existing label(s) on %s", pv_name);
-		goto out;
-	}
-
-	if (!lvmetad_pv_gone_by_dev(dev, NULL))
-		goto_out;
-
-	log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
-				pv_name);
-
-	ret = ECMD_PROCESSED;
-
-out:
-	unlock_vg(cmd, VG_ORPHANS);
-
-	return ret;
-}
 
 int pvremove(struct cmd_context *cmd, int argc, char **argv)
 {
 	int i, r;
 	int ret = ECMD_PROCESSED;
+	unsigned force_count;
+	unsigned prompt;
 
 	if (!argc) {
 		log_error("Please enter a physical volume path");
 		return EINVALID_CMD_LINE;
 	}
 
+	force_count = arg_count(cmd, force_ARG);
+	prompt = arg_count(cmd, yes_ARG);
+
 	for (i = 0; i < argc; i++) {
 		dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
-		r = pvremove_single(cmd, argv[i], NULL);
+		r = pvremove_single(cmd, argv[i], NULL, force_count, prompt);
 		if (r > ret)
 			ret = r;
 	}
-
 	return ret;
 }
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/19] python-lvm: Add bindings for lvm_pv_remove
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (7 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 08/19] lvm2app: Implement lvm_pv_remove Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 10/19] lvm2app: Set suppress to 1 Tony Asleson
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Method off of base lvm namespace "pvRemove".

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 python/liblvm.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/python/liblvm.c b/python/liblvm.c
index 928cab0..9d0d8f8 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -244,6 +244,25 @@ liblvm_lvm_list_pvs(void)
 }
 
 static PyObject *
+liblvm_lvm_pv_remove(PyObject *self, PyObject *arg)
+{
+	const char *pv_name;
+	LVM_VALID();
+
+	if (!PyArg_ParseTuple(arg, "s", &pv_name))
+			return NULL;
+
+	int rc = lvm_pv_remove(libh, pv_name);
+	if (0 != rc) {
+		PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+		return NULL;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
 liblvm_lvm_percent_to_float(PyObject *self, PyObject *arg)
 {
 	double converted;
@@ -1664,6 +1683,7 @@ static PyMethodDef Liblvm_methods[] = {
 	{ "listVgNames",	(PyCFunction)liblvm_lvm_list_vg_names, METH_NOARGS },
 	{ "listVgUuids",	(PyCFunction)liblvm_lvm_list_vg_uuids, METH_NOARGS },
 	{ "listPvs",		(PyCFunction)liblvm_lvm_list_pvs, METH_NOARGS },
+	{ "pvRemove",		(PyCFunction)liblvm_lvm_pv_remove, METH_VARARGS },
 	{ "percentToFloat",	(PyCFunction)liblvm_lvm_percent_to_float, METH_VARARGS },
 	{ "vgNameFromPvid",	(PyCFunction)liblvm_lvm_vgname_from_pvid, METH_VARARGS },
 	{ "vgNameFromDevice",	(PyCFunction)liblvm_lvm_vgname_from_device, METH_VARARGS },
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/19] lvm2app: Set suppress to 1
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (8 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 09/19] python-lvm: Add bindings for lvm_pv_remove Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 11/19] _get_pvs: Remove unused variable Tony Asleson
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Removes printing to stdout/stderr etc.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 liblvm/lvm_base.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/liblvm/lvm_base.c b/liblvm/lvm_base.c
index 53be709..67ed023 100644
--- a/liblvm/lvm_base.c
+++ b/liblvm/lvm_base.c
@@ -66,6 +66,12 @@ lvm_t lvm_init(const char *system_dir)
 	 */
 	cmd->cmd_line = "liblvm";
 
+	/*
+	 * Turn off writing to stderr etc., not sure if there is a better way
+	 * to do this?
+	 */
+	log_suppress(1);
+
 	return (lvm_t) cmd;
 }
 
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/19] _get_pvs: Remove unused variable
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (9 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 10/19] lvm2app: Set suppress to 1 Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 12/19] lib2app: Fix warnings in lvm_list_pvs_free Tony Asleson
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/metadata/metadata.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index cecf81c..92d0ffa 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3671,7 +3671,6 @@ static int _get_pvs(struct cmd_context *cmd, int warnings,
 		struct dm_list *pvslist, struct dm_list *vgslist)
 {
 	struct str_list *strl;
-	struct dm_list * uninitialized_var(results);
 	const char *vgname, *vgid;
 	struct pv_list *pvl, *pvl_copy;
 	struct dm_list *vgids;
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 12/19] lib2app: Fix warnings in lvm_list_pvs_free
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (10 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 11/19] _get_pvs: Remove unused variable Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 13/19] lib2app: Added PV create Tony Asleson
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 liblvm/lvm_pv.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 38b0126..568ab5b 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -116,9 +116,7 @@ int lvm_list_pvs_free(struct dm_list *pvlist)
 	int rc = 0;
 	struct lvm_list_wrapper *to_delete = NULL;
 	struct vg_list *vgl = NULL;
-	struct vg_list *tmp_vgl = NULL;
 	struct pv_list *pvl = NULL;
-	struct pv_list *tmp_pvl = NULL;
 	struct cmd_context *cmd = NULL;
 
 	if (pvlist ) {
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 13/19] lib2app: Added PV create.
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (11 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 12/19] lib2app: Fix warnings in lvm_list_pvs_free Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 14/19] python-lvm: Add pvCreate python method Tony Asleson
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 lib/metadata/metadata.h |  3 +++
 lib/metadata/pv_manip.c | 22 ++++++++++++++++++++++
 liblvm/lvm2app.h        | 10 ++++++++++
 liblvm/lvm_pv.c         | 26 ++++++++++++++++++++++++++
 tools/pvcreate.c        | 11 ++---------
 5 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 74dcff7..25a52af 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -345,6 +345,9 @@ int pvremove_single(struct cmd_context *cmd, const char *pv_name,
 			   void *handle __attribute__((unused)), unsigned force_count,
 			   unsigned prompt);
 
+int pvcreate_locked(struct cmd_context *cmd, const char *pv_name,
+					struct pvcreate_params *pp);
+
 /* Manipulate PV structures */
 int pv_add(struct volume_group *vg, struct physical_volume *pv);
 int pv_remove(struct volume_group *vg, struct physical_volume *pv);
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index 3823f76..894cf58 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -20,6 +20,8 @@
 #include "locking.h"
 #include "defaults.h"
 #include "lvmetad.h"
+#include "display.h"
+#include "label.h"
 
 static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
 					    struct physical_volume *pv,
@@ -672,3 +674,23 @@ out:
 
 	return ret;
 }
+
+int pvcreate_locked(struct cmd_context *cmd, const char *pv_name,
+		struct pvcreate_params *pp)
+{
+	int ret = ECMD_PROCESSED;
+
+	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
+		log_error("Can't get lock for orphan PVs");
+		return ECMD_FAILED;
+	}
+
+	if (!(pvcreate_single(cmd, pv_name, pp, 1))) {
+		stack;
+		ret = ECMD_FAILED;
+	}
+
+	unlock_vg(cmd, VG_ORPHANS);
+
+	return ret;
+}
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index a92d4dd..a397297 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -572,6 +572,16 @@ struct dm_list *lvm_list_pvs(lvm_t libh);
 int lvm_list_pvs_free(struct dm_list *pvlist);
 
 /**
+ *  Create a physical volume.
+ *  \param	libh	Library handle
+ *  \param	pv_name	The physical volume name
+ *  \param	size	Size of physical volume, 0 = use all available.
+ *  \return
+ *  0 on success, else -1 with library errno and text set.
+ */
+int lvm_pv_create(lvm_t libh, const char *pv_name, uint64_t size);
+
+/**
  *  Remove a physical volume.
  *  Note: You cannot remove a PV while iterating through the list of PVs as
  *  locks are held for the PV list.
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 568ab5b..8e0eb49 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -226,3 +226,29 @@ int lvm_pv_resize(const pv_t pv, uint64_t new_size)
 		return 0;
 	}
 }
+
+int lvm_pv_create(lvm_t libh, const char *pv_name, uint64_t size)
+{
+	int rc = -1;
+	struct pvcreate_params pp;
+	struct cmd_context *cmd = (struct cmd_context *)libh;
+	uint64_t size_sectors = size;
+
+	pvcreate_params_set_defaults(&pp);
+
+	if (size_sectors != 0 ) {
+		if( size_sectors % SECTOR_SIZE ) {
+			log_errno(EINVAL, "Size not a multiple of 512");
+					return -1;
+		}
+		size_sectors = size_sectors >> SECTOR_SHIFT;
+	}
+
+	pp.size = size_sectors;
+
+	if (ECMD_PROCESSED == pvcreate_locked(cmd, pv_name, &pp)) {
+		rc = 0;
+	}
+
+	return rc;
+}
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index da51eec..18ce077 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -15,6 +15,7 @@
 
 #include "tools.h"
 #include "metadata-exported.h"
+#include "metadata.h"
 
 /*
  * Intial sanity checking of recovery-related command-line arguments.
@@ -96,7 +97,6 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
 	int i;
 	int ret = ECMD_PROCESSED;
 	struct pvcreate_params pp;
-	struct physical_volume *pv;
 
 	pvcreate_params_set_defaults(&pp);
 
@@ -108,19 +108,12 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
 	}
 
 	for (i = 0; i < argc; i++) {
-		if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
-			log_error("Can't get lock for orphan PVs");
-			return ECMD_FAILED;
-		}
-
 		dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
 
-		if (!(pv = pvcreate_single(cmd, argv[i], &pp, 1))) {
-			stack;
+		if (ECMD_PROCESSED != pvcreate_locked(cmd, argv[i], &pp)) {
 			ret = ECMD_FAILED;
 		}
 
-		unlock_vg(cmd, VG_ORPHANS);
 		if (sigint_caught())
 			return ret;
 	}
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 14/19] python-lvm: Add pvCreate python method
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (12 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 13/19] lib2app: Added PV create Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 15/19] lvm2app: Add method to retrieve attr from lv Tony Asleson
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Added to base namespace.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 python/liblvm.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/python/liblvm.c b/python/liblvm.c
index 9d0d8f8..c76a3d0 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -263,6 +263,26 @@ liblvm_lvm_pv_remove(PyObject *self, PyObject *arg)
 }
 
 static PyObject *
+liblvm_lvm_pv_create(PyObject *self, PyObject *arg)
+{
+	const char *pv_name;
+	uint64_t size;
+	LVM_VALID();
+
+	if (!PyArg_ParseTuple(arg, "sl", &pv_name, &size))
+			return NULL;
+
+	int rc = lvm_pv_create(libh, pv_name, size);
+	if (0 != rc) {
+		PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+		return NULL;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
 liblvm_lvm_percent_to_float(PyObject *self, PyObject *arg)
 {
 	double converted;
@@ -1683,6 +1703,7 @@ static PyMethodDef Liblvm_methods[] = {
 	{ "listVgNames",	(PyCFunction)liblvm_lvm_list_vg_names, METH_NOARGS },
 	{ "listVgUuids",	(PyCFunction)liblvm_lvm_list_vg_uuids, METH_NOARGS },
 	{ "listPvs",		(PyCFunction)liblvm_lvm_list_pvs, METH_NOARGS },
+	{ "pvCreate",		(PyCFunction)liblvm_lvm_pv_create, METH_VARARGS },
 	{ "pvRemove",		(PyCFunction)liblvm_lvm_pv_remove, METH_VARARGS },
 	{ "percentToFloat",	(PyCFunction)liblvm_lvm_percent_to_float, METH_VARARGS },
 	{ "vgNameFromPvid",	(PyCFunction)liblvm_lvm_vgname_from_pvid, METH_VARARGS },
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 15/19] lvm2app: Add method to retrieve attr from lv.
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (13 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 14/19] python-lvm: Add pvCreate python method Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 16/19] python-lvm: Add method to retrieve lv attr Tony Asleson
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 liblvm/lvm2app.h | 16 ++++++++++++++++
 liblvm/lvm_lv.c  |  5 +++++
 2 files changed, 21 insertions(+)

diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index a397297..17f7382 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1216,6 +1216,22 @@ const char *lvm_lv_get_uuid(const lv_t lv);
 const char *lvm_lv_get_name(const lv_t lv);
 
 /**
+ * Get the attributes of a logical volume.
+ *
+ * \memberof lv_t
+ *
+ * The memory allocated for the name is tied to the vg_t handle and will be
+ * released when lvm_vg_close() is called.
+ *
+ * \param   lv
+ * Logical volume handle.
+ *
+ * \return
+ * Copy of the attributes for the logical volume
+ */
+const char *lvm_lv_get_attr(const lv_t lv);
+
+/**
  * Get the current size in bytes of a logical volume.
  *
  * \memberof lv_t
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 49306e6..38813ea 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -57,6 +57,11 @@ const char *lvm_lv_get_name(const lv_t lv)
 			       NAME_LEN+1);
 }
 
+const char *lvm_lv_get_attr(const lv_t lv)
+{
+	return lv_attr_dup(lv->vg->vgmem, lv);
+}
+
 struct lvm_property_value lvm_lv_get_property(const lv_t lv, const char *name)
 {
 	return get_property(NULL, NULL, lv, NULL, NULL, NULL, name);
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 16/19] python-lvm: Add method to retrieve lv attr.
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (14 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 15/19] lvm2app: Add method to retrieve attr from lv Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 17/19] lvm2app: Add function to retrieve the origin Tony Asleson
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 python/liblvm.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/python/liblvm.c b/python/liblvm.c
index c76a3d0..96e94d4 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1193,6 +1193,13 @@ liblvm_pv_dealloc(pvobject *self)
 		}							\
 	} while (0)
 
+static PyObject *
+liblvm_lvm_lv_get_attr(lvobject *self)
+{
+	LV_VALID(self);
+
+	return Py_BuildValue("s", lvm_lv_get_attr(self->lv));
+}
 
 static PyObject *
 liblvm_lvm_lv_get_name(lvobject *self)
@@ -1749,6 +1756,7 @@ static PyMethodDef liblvm_vg_methods[] = {
 
 static PyMethodDef liblvm_lv_methods[] = {
 	/* lv methods */
+	{ "getAttr",		(PyCFunction)liblvm_lvm_lv_get_attr, METH_NOARGS },
 	{ "getName",		(PyCFunction)liblvm_lvm_lv_get_name, METH_NOARGS },
 	{ "getUuid",		(PyCFunction)liblvm_lvm_lv_get_uuid, METH_NOARGS },
 	{ "activate",		(PyCFunction)liblvm_lvm_lv_activate, METH_NOARGS },
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 17/19] lvm2app: Add function to retrieve the origin.
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (15 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 16/19] python-lvm: Add method to retrieve lv attr Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 18/19] python-lvm: Added lv method getOrigin Tony Asleson
  2013-05-08 22:45 ` [PATCH 19/19] python-lvm: Bindings for thin pool, thin lv creation V3 Tony Asleson
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 liblvm/lvm2app.h | 16 ++++++++++++++++
 liblvm/lvm_lv.c  |  5 +++++
 2 files changed, 21 insertions(+)

diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 17f7382..bb63844 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1232,6 +1232,22 @@ const char *lvm_lv_get_name(const lv_t lv);
 const char *lvm_lv_get_attr(const lv_t lv);
 
 /**
+ * Get the origin of a snapshot.
+ *
+ * \memberof lv_t
+ *
+ * The memory allocated for the name is tied to the vg_t handle and will be
+ * released when lvm_vg_close() is called.
+ *
+ * \param   lv
+ * Logical volume handle.
+ *
+ * \return
+ * Null if the logical volume is not a snapshot, else origin name.
+ */
+const char *lvm_lv_get_origin(const lv_t lv);
+
+/**
  * Get the current size in bytes of a logical volume.
  *
  * \memberof lv_t
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 38813ea..494ed27 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -62,6 +62,11 @@ const char *lvm_lv_get_attr(const lv_t lv)
 	return lv_attr_dup(lv->vg->vgmem, lv);
 }
 
+const char *lvm_lv_get_origin(const lv_t lv)
+{
+	return lv_origin_dup(lv->vg->vgmem, lv);
+}
+
 struct lvm_property_value lvm_lv_get_property(const lv_t lv, const char *name)
 {
 	return get_property(NULL, NULL, lv, NULL, NULL, NULL, name);
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 18/19] python-lvm: Added lv method getOrigin
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (16 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 17/19] lvm2app: Add function to retrieve the origin Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  2013-05-08 22:45 ` [PATCH 19/19] python-lvm: Bindings for thin pool, thin lv creation V3 Tony Asleson
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 python/liblvm.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/python/liblvm.c b/python/liblvm.c
index 96e94d4..09892ca 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1202,6 +1202,14 @@ liblvm_lvm_lv_get_attr(lvobject *self)
 }
 
 static PyObject *
+liblvm_lvm_lv_get_origin(lvobject *self)
+{
+	LV_VALID(self);
+
+	return Py_BuildValue("s", lvm_lv_get_origin(self->lv));
+}
+
+static PyObject *
 liblvm_lvm_lv_get_name(lvobject *self)
 {
 	LV_VALID(self);
@@ -1758,6 +1766,7 @@ static PyMethodDef liblvm_lv_methods[] = {
 	/* lv methods */
 	{ "getAttr",		(PyCFunction)liblvm_lvm_lv_get_attr, METH_NOARGS },
 	{ "getName",		(PyCFunction)liblvm_lvm_lv_get_name, METH_NOARGS },
+	{ "getOrigin",		(PyCFunction)liblvm_lvm_lv_get_origin, METH_NOARGS },
 	{ "getUuid",		(PyCFunction)liblvm_lvm_lv_get_uuid, METH_NOARGS },
 	{ "activate",		(PyCFunction)liblvm_lvm_lv_activate, METH_NOARGS },
 	{ "deactivate",		(PyCFunction)liblvm_lvm_lv_deactivate, METH_NOARGS },
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 19/19] python-lvm: Bindings for thin pool, thin lv creation V3
  2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
                   ` (17 preceding siblings ...)
  2013-05-08 22:45 ` [PATCH 18/19] python-lvm: Added lv method getOrigin Tony Asleson
@ 2013-05-08 22:45 ` Tony Asleson
  18 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-08 22:45 UTC (permalink / raw)
  To: lvm-devel

V2: Bug fix.
V3: Use updated property interface, add constants for discard.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
---
 python/liblvm.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/python/liblvm.c b/python/liblvm.c
index 09892ca..d30b647 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1032,6 +1032,109 @@ liblvm_lvm_vg_create_lv_linear(vgobject *self, PyObject *args)
 	return (PyObject *)lvobj;
 }
 
+static PyObject *
+liblvm_lvm_vg_create_lv_thinpool(vgobject *self, PyObject *args)
+{
+	const char *pool_name;
+	uint64_t size = 0;
+	uint32_t chunk_size = 0;
+	uint64_t meta_size = 0;
+	int skip_zero = 0;
+	lvm_thin_discards_t discard = LVM_THIN_DISCARDS_PASSDOWN;
+	lvobject *lvobj;
+	lv_create_params_t lvp = NULL;
+	struct lvm_property_value prop_value;
+
+	VG_VALID(self);
+
+	if (!PyArg_ParseTuple(args, "sK|kKii", &pool_name, &size, &chunk_size,
+			&meta_size, &discard, &skip_zero)) {
+		return NULL;
+	}
+
+	if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
+		return NULL;
+
+	/* Initialize the parent ptr in case lv create fails and we dealloc lvobj */
+	lvobj->parent_vgobj = NULL;
+
+	lvp = lvm_lv_params_create_thin_pool(self->vg, pool_name, size, chunk_size,
+				meta_size, discard);
+
+	if (lvp) {
+		if (skip_zero) {
+			prop_value = lvm_lv_params_get_property(lvp, "skip_zero");
+
+			if (prop_value.is_valid) {
+				prop_value.value.integer = 1;
+
+				if( -1 == lvm_lv_params_set_property(lvp, "skip_zero",
+						&prop_value)) {
+					PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+					Py_DECREF(lvobj);
+					return NULL;
+				}
+			}
+		}
+
+		if ((lvobj->lv = lvm_lv_create(lvp)) == NULL) {
+			PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+			Py_DECREF(lvobj);
+			return NULL;
+		}
+	} else {
+		PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+				Py_DECREF(lvobj);
+				return NULL;
+	}
+
+	lvobj->parent_vgobj = self;
+	Py_INCREF(lvobj->parent_vgobj);
+
+	return (PyObject *)lvobj;
+}
+
+static PyObject *
+liblvm_lvm_vg_create_lv_thin(vgobject *self, PyObject *args)
+{
+	const char *pool_name;
+	const char *lv_name;
+	uint64_t size = 0;
+	lvobject *lvobj;
+	lv_create_params_t lvp = NULL;
+
+	VG_VALID(self);
+
+	if (!PyArg_ParseTuple(args, "ssK", &pool_name, &lv_name, &size)) {
+		return NULL;
+	}
+
+	if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
+		return NULL;
+
+	/* Initialize the parent ptr in case lv create fails and we dealloc lvobj */
+	lvobj->parent_vgobj = NULL;
+
+	lvp = lvm_lv_params_create_thin(self->vg, pool_name, lv_name,size);
+
+	if (lvp) {
+		if ((lvobj->lv = lvm_lv_create(lvp)) == NULL) {
+			PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+			Py_DECREF(lvobj);
+			return NULL;
+		}
+	} else {
+		PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+				Py_DECREF(lvobj);
+				return NULL;
+	}
+
+	lvobj->parent_vgobj = self;
+	Py_INCREF(lvobj->parent_vgobj);
+
+	return (PyObject *)lvobj;
+}
+
 static void
 liblvm_lv_dealloc(lvobject *self)
 {
@@ -1759,6 +1862,8 @@ static PyMethodDef liblvm_vg_methods[] = {
 	{ "pvFromUuid", 	(PyCFunction)liblvm_lvm_pv_from_uuid, METH_VARARGS },
 	{ "getTags",		(PyCFunction)liblvm_lvm_vg_get_tags, METH_NOARGS },
 	{ "createLvLinear",	(PyCFunction)liblvm_lvm_vg_create_lv_linear, METH_VARARGS },
+	{ "createLvThinpool", (PyCFunction)liblvm_lvm_vg_create_lv_thinpool, METH_VARARGS },
+	{ "createLvThin", 	(PyCFunction)liblvm_lvm_vg_create_lv_thin, METH_VARARGS },
 	{ NULL, NULL }		/* sentinel */
 };
 
@@ -1915,6 +2020,22 @@ initlvm(void)
 	if (m == NULL)
 		return;
 
+
+	if (-1 == PyModule_AddIntConstant(m, "THIN_DISCARDS_IGNORE",
+										LVM_THIN_DISCARDS_IGNORE)) {
+		return;
+	}
+
+	if (-1 == PyModule_AddIntConstant(m, "THIN_DISCARDS_NO_PASSDOWN",
+											LVM_THIN_DISCARDS_NO_PASSDOWN)) {
+		return;
+	}
+
+	if ( -1 == PyModule_AddIntConstant(m, "THIN_DISCARDS_PASSDOWN",
+											LVM_THIN_DISCARDS_PASSDOWN)) {
+		return;
+	}
+
 	LibLVMError = PyErr_NewException("Liblvm.LibLVMError",
 					 NULL, NULL);
 	if (LibLVMError) {
-- 
1.8.1.4



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/19] lvm2app: Move core lv re-size code (v2)
  2013-05-08 22:45 ` [PATCH 05/19] lvm2app: Move core lv re-size code (v2) Tony Asleson
@ 2013-05-09  7:13   ` Zdenek Kabelac
  2013-05-09 13:55     ` Tony Asleson
  0 siblings, 1 reply; 22+ messages in thread
From: Zdenek Kabelac @ 2013-05-09  7:13 UTC (permalink / raw)
  To: lvm-devel

Dne 9.5.2013 00:45, Tony Asleson napsal(a):
> Moved to allow use from command line and for library use.
>
> Signed-off-by: Tony Asleson <tasleson@redhat.com>
> ---
>   lib/metadata/lv_manip.c          | 734 +++++++++++++++++++++++++++++++++++++
>   lib/metadata/metadata-exported.h |  46 +++
>   tools/lvresize.c                 | 773 +--------------------------------------
>   3 files changed, 781 insertions(+), 772 deletions(-)
>
> diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
> index 42e0fab..587cbd2 100644
> --- a/lib/metadata/lv_manip.c
> +++ b/lib/metadata/lv_manip.c
> @@ -27,6 +27,8 @@
>   #include "activate.h"
>   #include "str_list.h"
>   #include "defaults.h"
> +#include "lvm-exec.h"
> +#include "errors.h"
>

This '/tools' error from   '/lib'  needs some solution.

Currently /lib reports  1 success, 0 error - and potential error state is
returned via some other mechanism (i.e. setting struct member...)

On the other hand the lvm2app is seriously missing error reporting - since
the user of this API is usually not seeing typical lvm2 log_error messages.

Zdenek



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 05/19] lvm2app: Move core lv re-size code (v2)
  2013-05-09  7:13   ` Zdenek Kabelac
@ 2013-05-09 13:55     ` Tony Asleson
  0 siblings, 0 replies; 22+ messages in thread
From: Tony Asleson @ 2013-05-09 13:55 UTC (permalink / raw)
  To: lvm-devel

On 05/09/2013 02:13 AM, Zdenek Kabelac wrote:
> Dne 9.5.2013 00:45, Tony Asleson napsal(a):
>> Moved to allow use from command line and for library use.
>>
>> Signed-off-by: Tony Asleson <tasleson@redhat.com>
>> ---
>>   lib/metadata/lv_manip.c          | 734
>> +++++++++++++++++++++++++++++++++++++
>>   lib/metadata/metadata-exported.h |  46 +++
>>   tools/lvresize.c                 | 773
>> +--------------------------------------
>>   3 files changed, 781 insertions(+), 772 deletions(-)
>>
>> diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
>> index 42e0fab..587cbd2 100644
>> --- a/lib/metadata/lv_manip.c
>> +++ b/lib/metadata/lv_manip.c
>> @@ -27,6 +27,8 @@
>>   #include "activate.h"
>>   #include "str_list.h"
>>   #include "defaults.h"
>> +#include "lvm-exec.h"
>> +#include "errors.h"
>>
> 
> This '/tools' error from   '/lib'  needs some solution.
> 
> Currently /lib reports  1 success, 0 error - and potential error state is
> returned via some other mechanism (i.e. setting struct member...)
> 
> On the other hand the lvm2app is seriously missing error reporting - since
> the user of this API is usually not seeing typical lvm2 log_error messages.

I have been getting the error message text back to the caller, but the
error codes are lacking.  These changes are yet to come.

-Tony



^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-05-09 13:55 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-08 22:45 [PATCH 00/19] Looking for reviews Tony Asleson
2013-05-08 22:45 ` [PATCH 01/19] lvm2app: Add thin and thin pool lv creation V4 Tony Asleson
2013-05-08 22:45 ` [PATCH 02/19] lvm2app: Implementation of pv resize (v6) Tony Asleson
2013-05-08 22:45 ` [PATCH 03/19] lvm2app: Move percent_of_extents to lvm-percent.[h|c] Tony Asleson
2013-05-08 22:45 ` [PATCH 04/19] lvm2app: Rework argument handling for lv resize Tony Asleson
2013-05-08 22:45 ` [PATCH 05/19] lvm2app: Move core lv re-size code (v2) Tony Asleson
2013-05-09  7:13   ` Zdenek Kabelac
2013-05-09 13:55     ` Tony Asleson
2013-05-08 22:45 ` [PATCH 06/19] lvm2app: Implement lv resize (v2) Tony Asleson
2013-05-08 22:45 ` [PATCH 07/19] lvm2app: Add function to retrieve list of PVs Tony Asleson
2013-05-08 22:45 ` [PATCH 08/19] lvm2app: Implement lvm_pv_remove Tony Asleson
2013-05-08 22:45 ` [PATCH 09/19] python-lvm: Add bindings for lvm_pv_remove Tony Asleson
2013-05-08 22:45 ` [PATCH 10/19] lvm2app: Set suppress to 1 Tony Asleson
2013-05-08 22:45 ` [PATCH 11/19] _get_pvs: Remove unused variable Tony Asleson
2013-05-08 22:45 ` [PATCH 12/19] lib2app: Fix warnings in lvm_list_pvs_free Tony Asleson
2013-05-08 22:45 ` [PATCH 13/19] lib2app: Added PV create Tony Asleson
2013-05-08 22:45 ` [PATCH 14/19] python-lvm: Add pvCreate python method Tony Asleson
2013-05-08 22:45 ` [PATCH 15/19] lvm2app: Add method to retrieve attr from lv Tony Asleson
2013-05-08 22:45 ` [PATCH 16/19] python-lvm: Add method to retrieve lv attr Tony Asleson
2013-05-08 22:45 ` [PATCH 17/19] lvm2app: Add function to retrieve the origin Tony Asleson
2013-05-08 22:45 ` [PATCH 18/19] python-lvm: Added lv method getOrigin Tony Asleson
2013-05-08 22:45 ` [PATCH 19/19] python-lvm: Bindings for thin pool, thin lv creation V3 Tony Asleson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.