[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [lvm-devel] [PATCH] (1/2) new library interface for vg_read



I'm attaching a hopefully more-correct version of the two patches, with the
split moved. Sorry for slipping the "later today" to "tomorrow"...

Tue Dec 16 12:33:34 CET 2008  Petr Rockai <me mornfall net>
  * Library portions of vg_read patches.
diff -rN -p -u old-lvmlib-c/lib/metadata/metadata.c new-lvmlib-c/lib/metadata/metadata.c
--- old-lvmlib-c/lib/metadata/metadata.c	2008-12-16 13:27:01.130811860 +0100
+++ new-lvmlib-c/lib/metadata/metadata.c	2008-12-16 13:27:01.450810562 +0100
@@ -224,8 +224,8 @@ int get_pv_from_vg_by_id(const struct fo
 	struct pv_list *pvl;
 	int consistent = 0;
 
-	if (!(vg = vg_read(fmt->cmd, vg_name, vgid, &consistent))) {
-		log_error("get_pv_from_vg_by_id: vg_read failed to read VG %s",
+	if (!(vg = vg_read_internal(fmt->cmd, vg_name, vgid, &consistent))) {
+		log_error("get_pv_from_vg_by_id: vg_read_internal failed to read VG %s",
 			  vg_name);
 		return 0;
 	}
@@ -503,7 +503,7 @@ struct volume_group *vg_create(struct cm
 		return_NULL;
 
 	/* is this vg name already in use ? */
-	if (vg_read(cmd, vg_name, NULL, &consistent)) {
+	if (vg_read_internal(cmd, vg_name, NULL, &consistent)) {
 		log_err("A volume group called '%s' already exists.", vg_name);
 		goto bad;
 	}
@@ -1684,12 +1684,12 @@ int vg_missing_pv_count(const vg_t *vg)
 	return ret;
 }
 
-/* Caller sets consistent to 1 if it's safe for vg_read to correct
+/* Caller sets consistent to 1 if it's safe for vg_read_internal to correct
  * inconsistent metadata on disk (i.e. the VG write lock is held).
  * This guarantees only consistent metadata is returned.
  * If consistent is 0, caller must check whether consistent == 1 on return
  * and take appropriate action if it isn't (e.g. abort; get write lock
- * and call vg_read again).
+ * and call vg_read_internal again).
  *
  * If precommitted is set, use precommitted metadata if present.
  *
@@ -1716,7 +1716,7 @@ static struct volume_group *_vg_read(str
 
 	if (is_orphan_vg(vgname)) {
 		if (use_precommitted) {
-			log_error("Internal error: vg_read requires vgname "
+			log_error("Internal error: vg_read_internal requires vgname "
 				  "with pre-commit.");
 			return NULL;
 		}
@@ -1974,7 +1974,7 @@ static struct volume_group *_vg_read(str
 	return correct_vg;
 }
 
-struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
+struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vgname,
 			     const char *vgid, int *consistent)
 {
 	struct volume_group *vg;
@@ -2002,7 +2002,7 @@ struct volume_group *vg_read(struct cmd_
 
 /* This is only called by lv_from_lvid, which is only called from
  * activate.c so we know the appropriate VG lock is already held and
- * the vg_read is therefore safe.
+ * the vg_read_internal is therefore safe.
  */
 static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
 					    const char *vgid,
@@ -2034,7 +2034,7 @@ static struct volume_group *_vg_read_by_
 	if (memlock())
 		return NULL;
 
-	/* FIXME Need a genuine read by ID here - don't vg_read by name! */
+	/* FIXME Need a genuine read by ID here - don't vg_read_internal by name! */
 	/* FIXME Disabled vgrenames while active for now because we aren't
 	 *       allowed to do a full scan here any more. */
 
@@ -2218,7 +2218,7 @@ static int _get_pvs(struct cmd_context *
 			stack;
 			continue;
 		}
-		if (!(vg = vg_read(cmd, vgname, vgid, &consistent))) {
+		if (!(vg = vg_read_internal(cmd, vgname, vgid, &consistent))) {
 			stack;
 			continue;
 		}
@@ -2388,77 +2388,242 @@ int pv_analyze(struct cmd_context *cmd, 
  * 0 - fail
  * 1 - success
  */
-int vg_check_status(const struct volume_group *vg, uint32_t status)
+static uint32_t _vg_check_status(const struct volume_group *vg, uint32_t status)
 {
+	uint32_t ret = 0;
 	if ((status & CLUSTERED) &&
 	    (vg_is_clustered(vg)) && !locking_is_clustered() &&
 	    !lockingfailed()) {
 		log_error("Skipping clustered volume group %s", vg->name);
-		return 0;
+		ret |= FAILED_CLUSTERED;
 	}
 
 	if ((status & EXPORTED_VG) &&
 	    (vg->status & EXPORTED_VG)) {
 		log_error("Volume group %s is exported", vg->name);
-		return 0;
+		ret |= FAILED_EXPORTED;
 	}
 
 	if ((status & LVM_WRITE) &&
 	    !(vg->status & LVM_WRITE)) {
 		log_error("Volume group %s is read-only", vg->name);
-		return 0;
+		ret |= FAILED_READ_ONLY;
 	}
+
 	if ((status & RESIZEABLE_VG) &&
 	    !(vg->status & RESIZEABLE_VG)) {
 		log_error("Volume group %s is not resizeable.", vg->name);
-		return 0;
+		ret |= FAILED_RESIZEABLE;
 	}
 
+	return ret;
+}
+
+uint32_t vg_check_status(const struct volume_group *vg, uint32_t status)
+{
+	return !_vg_check_status(vg, status);
+}
+
+uint32_t vg_read_error(vg_t *vg) {
+	if (!vg)
+		return FAILED_ALLOCATION;
+	if (vg->read_failed & EXISTENCE_CHECK)
+		return vg->read_failed & ~(EXISTENCE_CHECK | FAILED_NOTFOUND);
+	return vg->read_failed;
+}
+
+/* Returns true if the volume group already exists. If unsure, it will return
+   true (it might exist, but we are not sure, as the read failed for some
+   other reason). */
+
+uint32_t vg_exists(vg_t *vg) {
+	if (!vg)
+		return 1;
+	log_error("vg_exists: %d != %d?", vg->read_failed, FAILED_NOTFOUND | EXISTENCE_CHECK);
+	if (vg->read_failed == (FAILED_NOTFOUND | EXISTENCE_CHECK))
+		return 0;
 	return 1;
 }
 
+static vg_t *_vg_make_handle(struct cmd_context *cmd,
+			     struct volume_group *vg,
+			     uint32_t failure)
+{
+	if (!vg)
+		if (!(vg = dm_pool_zalloc(cmd->mem, sizeof(*vg))))
+			return_NULL;
+	vg->read_failed = failure;
+	return vg;
+}
+
+/*
+ * High-level read-for-update function.
+ * On failure:
+ *  - out of memory: NULL is returned
+ *  - other: a volume group with "failed" field set to nonzero is returned
+ *
+ * Failures:
+ *  - metadata inconsistent and automatic correction failed: FAILED_INCONSISTENT
+ *  - VG is read-only: FAILED_READ_ONLY
+ *  - VG is EXPORTED, unless flags has ALLOW_EXPORTED: FAILED_EXPORTED
+ *  - VG is not RESIZEABLE, unless flags has ALLOW_NONRESIZEABLE:
+ *    FAILED_RESIZEABLE
+ *  - locking failed: FAILED_LOCKING
+ *
+ * On failures, all locks are released, unless KEEP_LOCK has been supplied.
+ *
+ * If EXISTENCE_CHECK is set in flags, if the VG exists, a non-NULL struct
+ * volume_group will be returned every time, but if it has INCONSISTENT_VG set,
+ * the other fields will be uninitialized. You *have to* check for
+ * INCONSISTENT_VG if passing EXISTENCE_CHECK. You also *must not* use it if it
+ * has INCONSISTENT_VG set.
+ */
+vg_t *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
+			 const char *vgid, uint32_t flags)
+{
+	return vg_read(cmd, vg_name, vgid, flags | READ_FOR_UPDATE);
+}
+
+/*
+ * FIXME we want vg_read to attempt automatic recovery after acquiring a
+ * temporary write lock -- if that fails, we bail out as usual, with failed &
+ * FAILED_INCONSISTENT. If it works, we are good to go. Code that's been in
+ * toollib just set lock type to LCK_WRITE and called vg_read_internal with
+ * *consistent = 1.
+ */
+vg_t *vg_read(struct cmd_context *cmd, const char *vg_name,
+	      const char *vgid, uint32_t flags)
+{
+	uint32_t status = CLUSTERED;
+	uint32_t lock = LCK_VG_READ;
+
+	if (flags & READ_FOR_UPDATE) {
+		status |= EXPORTED_VG | LVM_WRITE;
+		lock = LCK_VG_WRITE;
+	}
+
+	if (flags & ALLOW_EXPORTED)
+		status &= ~EXPORTED_VG;
+
+	if (flags & REQUIRE_RESIZEABLE)
+		status |= RESIZEABLE_VG;
+
+	if (flags & NONBLOCKING_LOCK)
+		lock |= LCK_NONBLOCK;
+
+	return vg_lock_and_read(cmd, vg_name, vgid, lock, status, flags);
+}
+
+static vg_t *_recover_vg(struct cmd_context *cmd, const char *lock, const char *vg_name,
+			 const char *vgid, uint32_t lock_flags )
+{
+	int consistent = 1;
+	struct volume_group *vg;
+
+	lock_flags &= ~LCK_TYPE_MASK;
+	lock_flags |= LCK_WRITE;
+
+	unlock_vg(cmd, lock);
+
+	dev_close_all();
+
+	if (!lock_vol(cmd, lock, lock_flags))
+		return_NULL;
+
+	if (!(vg = vg_read_internal(cmd, vg_name, vgid, &consistent)))
+		return_NULL;
+	if (!consistent)
+		return_NULL;
+	return vg;
+}
+
 /*
  * vg_lock_and_read - consolidate vg locking, reading, and status flag checking
  *
+ * misc_flags:
+ *  ALLOW_INCONSISTENT: disable autocorrection
+ *  
+ * Setting ALLOW_INCONSISTENT might give you inconsistent metadata. You will
+ * *still* get FAILED_INCONSISTENT in case the metadata has *really* been
+ * inconsistent. However, you still get the latest version of metadata in VG.
+ *
+ *
+ *
  * Returns:
- * NULL - failure
- * non-NULL - success; volume group handle
+ * Use vg_read_error(vg) to determine the result. Nonzero vg_read_error(vg)
+ * means there were problems reading the volume group.
+ * Zero value means that the VG is open and appropriate locks are held.
  */
 vg_t *vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
 		       const char *vgid,
 		       uint32_t lock_flags, uint32_t status_flags,
 		       uint32_t misc_flags)
 {
-	struct volume_group *vg;
+	struct volume_group *vg = 0;
+	const char *lock;
 	int consistent = 1;
+	int consistent_in;
+	uint32_t failure = 0;
 
-	if (!(misc_flags & CORRECT_INCONSISTENT))
-		consistent = 0;
+	if (misc_flags & ALLOW_INCONSISTENT || !(lock_flags & LCK_WRITE))
+	consistent = 0;
 
-	if (!validate_name(vg_name)) {
+	if (!validate_name(vg_name) && !is_orphan_vg(vg_name)) {
 		log_error("Volume group name %s has invalid characters",
 			  vg_name);
 		return NULL;
 	}
 
-	if (!lock_vol(cmd, vg_name, lock_flags)) {
-		log_error("Can't get lock for %s", vg_name);
-		return NULL;
+	lock = (misc_flags & ORPHAN_LOCK ? VG_ORPHANS : vg_name);
+	if (!(misc_flags & DISABLE_LOCK)) {
+		if (!lock_vol(cmd, lock, lock_flags)) {
+			log_error("Can't get lock for %s", vg_name);
+			return _vg_make_handle(cmd, vg, FAILED_LOCKING);
+		}
 	}
 
-	if (!(vg = vg_read(cmd, vg_name, vgid, &consistent)) ||
-	    ((misc_flags & FAIL_INCONSISTENT) && !consistent)) {
-		log_error("Volume group \"%s\" not found", vg_name);
-		unlock_vg(cmd, vg_name);
-		return NULL;
+	if (misc_flags & ORPHAN_LOCK)
+		status_flags &= ~LVM_WRITE;
+
+	if (misc_flags & EXISTENCE_CHECK)
+		consistent = 0;
+
+	consistent_in = consistent;
+
+	/* If consistent == 1, we get NULL here if correction fails. */
+	if (!(vg = vg_read_internal(cmd, vg_name, vgid, &consistent))) {
+		if (consistent_in && !consistent) {
+			log_error("Volume group \"%s\" inconsistent.", vg_name);
+			failure |= FAILED_INCONSISTENT;
+			goto_bad;
+		}
+		if (!(misc_flags & EXISTENCE_CHECK))
+			log_error("Volume group \"%s\" not found", vg_name);
+		failure |= FAILED_NOTFOUND | (misc_flags & EXISTENCE_CHECK);
+		goto_bad;
 	}
 
-	if (!vg_check_status(vg, status_flags)) {
-		unlock_vg(cmd, vg_name);
-		return NULL;
+	/* consistent == 0 when VG is not found, but failed == FAILED_NOTFOUND */
+	if (!consistent && !failure) {
+		vg = _recover_vg(cmd, lock, vg_name, vgid, lock_flags);
+		if (!vg) {
+			log_error("Recovery of volume group \"%s\" failed.",
+			  vg_name);
+			failure |= FAILED_INCONSISTENT;
+			goto_bad;
+		}
 	}
 
-	return vg;
+	failure |= _vg_check_status(vg, status_flags);
+	if (failure)
+		goto_bad;
+
+	return _vg_make_handle(cmd, vg, failure);
+ bad:
+	if (failure != (FAILED_NOTFOUND | EXISTENCE_CHECK))
+		if (!(misc_flags & KEEP_LOCK) && !(misc_flags & DISABLE_LOCK))
+			unlock_vg(cmd, lock);
+	return _vg_make_handle(cmd, vg, failure);
 }
 
 /*
diff -rN -p -u old-lvmlib-c/lib/metadata/metadata-exported.h new-lvmlib-c/lib/metadata/metadata-exported.h
--- old-lvmlib-c/lib/metadata/metadata-exported.h	2008-12-16 13:27:01.130811860 +0100
+++ new-lvmlib-c/lib/metadata/metadata-exported.h	2008-12-16 13:27:01.450810562 +0100
@@ -76,7 +76,7 @@ struct pv_segment;
 						   written out in metadata*/
 
 //#define POSTORDER_FLAG	0x02000000U /* Not real flags, reserved for
-//#define POSTORDER_OPEN_FLAG	0x04000000U    temporary use inside vg_read. */
+//#define POSTORDER_OPEN_FLAG	0x04000000U    temporary use inside vg_read_internal. */
 
 #define LVM_READ              	0x00000100U	/* LV VG */
 #define LVM_WRITE             	0x00000200U	/* LV VG */
@@ -99,6 +99,32 @@ struct pv_segment;
 #define CORRECT_INCONSISTENT    0x00000001U /* Correct inconsistent metadata */
 #define FAIL_INCONSISTENT       0x00000002U /* Fail if metadata inconsistent */
 
+/* vg_read and vg_read_for_update flags */
+#define ALLOW_INCONSISTENT 0x1
+#define ALLOW_EXPORTED 0x2
+#define REQUIRE_RESIZEABLE 0x4
+#define EXISTENCE_CHECK 0x8
+
+#define NONBLOCKING_LOCK 0x100
+#define KEEP_LOCK 0x200
+#define DISABLE_LOCK 0x400
+#define ORPHAN_LOCK 0x800
+
+#define READ_FOR_UPDATE 0x1000
+
+/* vg's "read_failed" field */
+#define FAILED_INCONSISTENT 0x1
+#define FAILED_LOCKING 0x2
+#define FAILED_NOTFOUND 0x4
+// 0x8 is left out for EXISTENCE_CHECK
+
+#define FAILED_READ_ONLY 0x10
+#define FAILED_EXPORTED 0x20
+#define FAILED_RESIZEABLE 0x40
+#define FAILED_CLUSTERED 0x80
+
+#define FAILED_ALLOCATION 0x100
+
 /* Mirror conversion type flags */
 #define MIRROR_BY_SEG		0x00000001U	/* segment-by-segment mirror */
 #define MIRROR_BY_LV		0x00000002U	/* mirror using whole mimage LVs */
@@ -197,6 +223,8 @@ struct volume_group {
 	char *system_id;
 
 	uint32_t status;
+	uint32_t read_failed;
+
 	alloc_policy_t alloc;
 
 	uint32_t extent_size;
@@ -328,7 +356,7 @@ struct lv_list {
 int vg_write(struct volume_group *vg);
 int vg_commit(struct volume_group *vg);
 int vg_revert(struct volume_group *vg);
-struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
+struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vg_name,
 			     const char *vgid, int *consistent);
 struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
 				struct dm_list *mdas, uint64_t *label_sector,
@@ -348,11 +376,20 @@ int is_orphan(const pv_t *pv);
 int vgs_are_compatible(struct cmd_context *cmd,
 		       struct volume_group *vg_from,
 		       struct volume_group *vg_to);
+
 vg_t *vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
 		       const char *vgid,
 		       uint32_t lock_flags, uint32_t status_flags,
 		       uint32_t misc_flags);
 
+uint32_t vg_read_error(vg_t *vg);
+uint32_t vg_exists(vg_t *vg);
+vg_t *vg_read(struct cmd_context *cmd, const char *vg_name,
+	      const char *vgid, uint32_t flags);
+
+vg_t *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
+			 const char *vgid, uint32_t flags);
+
 /* pe_start and pe_end relate to any existing data so that new metadata
 * areas can avoid overlap */
 pv_t *pv_create(const struct cmd_context *cmd,
@@ -501,7 +538,7 @@ int vg_add_snapshot(const char *name,
 
 int vg_remove_snapshot(struct logical_volume *cow);
 
-int vg_check_status(const struct volume_group *vg, uint32_t status);
+uint32_t vg_check_status(const struct volume_group *vg, uint32_t status);
 
 /*
 * Mirroring functions
diff -rN -p -u old-lvmlib-c/lib/metadata/metadata.h new-lvmlib-c/lib/metadata/metadata.h
--- old-lvmlib-c/lib/metadata/metadata.h	2008-12-16 13:27:01.114811014 +0100
+++ new-lvmlib-c/lib/metadata/metadata.h	2008-12-16 13:27:01.406809578 +0100
@@ -68,12 +68,13 @@
 //						   written out in metadata*/
 
 #define POSTORDER_FLAG		0x02000000U /* Not real flags, reserved for  */
-#define POSTORDER_OPEN_FLAG	0x04000000U /* temporary use inside vg_read. */
+#define POSTORDER_OPEN_FLAG	0x04000000U /* temporary use inside vg_read_internal. */
 
 //#define LVM_READ              	0x00000100U	/* LV VG */
 //#define LVM_WRITE             	0x00000200U	/* LV VG */
 //#define CLUSTERED         	0x00000400U	/* VG */
 #define SHARED            	0x00000800U	/* VG */
+//#define INCONSISTENT_VG         0x00001000U	/* VG */
 
 /* Format features flags */
 //#define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
diff -rN -p -u old-lvmlib-c/tools/pvresize.c new-lvmlib-c/tools/pvresize.c
--- old-lvmlib-c/tools/pvresize.c	2008-12-16 13:27:01.114811014 +0100
+++ new-lvmlib-c/tools/pvresize.c	2008-12-16 13:27:01.446811520 +0100
@@ -62,7 +62,7 @@ static int _pv_resize_single(struct cmd_
 			return 0;
 		}
 
-		if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
+		if (!(vg = vg_read_internal(cmd, vg_name, NULL, &consistent))) {
 			unlock_vg(cmd, vg_name);
 			log_error("Unable to find volume group of \"%s\"",
 				  pv_name);
diff -rN -p -u old-lvmlib-c/tools/toollib.c new-lvmlib-c/tools/toollib.c
--- old-lvmlib-c/tools/toollib.c	2008-12-16 13:27:01.114811014 +0100
+++ new-lvmlib-c/tools/toollib.c	2008-12-16 13:27:01.442810313 +0100
@@ -347,7 +347,7 @@ int process_each_lv(struct cmd_context *
 			consistent = 1;
 		else
 			consistent = 0;
-		if (!(vg = vg_read(cmd, vgname, NULL, &consistent)) || !consistent) {
+		if (!(vg = vg_read_internal(cmd, vgname, NULL, &consistent)) || !consistent) {
 			unlock_vg(cmd, vgname);
 			if (!vg)
 				log_error("Volume group \"%s\" "
@@ -489,7 +489,7 @@ static int _process_one_vg(struct cmd_co
 	}
 
 	log_verbose("Finding volume group \"%s\"", vg_name);
-	if (!(vg = vg_read(cmd, vg_name, vgid, &consistent))) {
+	if (!(vg = vg_read_internal(cmd, vg_name, vgid, &consistent))) {
 		log_error("Volume group \"%s\" not found", vg_name);
 		unlock_vg(cmd, vg_name);
 		return ECMD_FAILED;
@@ -776,7 +776,7 @@ int process_each_pv(struct cmd_context *
 					log_error("Can't lock %s: skipping", sll->str);
 					continue;
 				}
-				if (!(vg = vg_read(cmd, sll->str, NULL, &consistent))) {
+				if (!(vg = vg_read_internal(cmd, sll->str, NULL, &consistent))) {
 					log_error("Volume group \"%s\" not found", sll->str);
 					unlock_vg(cmd, sll->str);
 					ret_max = ECMD_FAILED;
@@ -1199,7 +1199,7 @@ struct volume_group *recover_vg(struct c
 		return NULL;
 	}
 
-	return vg_read(cmd, vgname, NULL, &consistent);
+	return vg_read_internal(cmd, vgname, NULL, &consistent);
 }
 
 int apply_lvname_restrictions(const char *name)
diff -rN -p -u old-lvmlib-c/tools/vgreduce.c new-lvmlib-c/tools/vgreduce.c
--- old-lvmlib-c/tools/vgreduce.c	2008-12-16 13:27:01.114811014 +0100
+++ new-lvmlib-c/tools/vgreduce.c	2008-12-16 13:27:01.434810763 +0100
@@ -426,7 +426,7 @@ static int _vgreduce_single(struct cmd_c
 	vg->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv);
 	vg->extent_count -= pv_pe_count(pv);
 
-	if(!(orphan_vg = vg_read(cmd, vg->fid->fmt->orphan_vg_name, NULL, &consistent)) ||
+	if(!(orphan_vg = vg_read_internal(cmd, vg->fid->fmt->orphan_vg_name, NULL, &consistent)) ||
 	   !consistent) {
 		log_error("Unable to read existing orphan PVs");
 		unlock_vg(cmd, VG_ORPHANS);
@@ -520,7 +520,7 @@ int vgreduce(struct cmd_context *cmd, in
 		return ECMD_FAILED;
 	}
 
-	if ((!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent)
+	if ((!(vg = vg_read_internal(cmd, vg_name, NULL, &consistent)) || !consistent)
 	    && !repairing) {
 		log_error("Volume group \"%s\" doesn't exist", vg_name);
 		unlock_vg(cmd, vg_name);
@@ -541,7 +541,7 @@ int vgreduce(struct cmd_context *cmd, in
 		}
 
 		consistent = !arg_count(cmd, force_ARG);
-		if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
+		if (!(vg = vg_read_internal(cmd, vg_name, NULL, &consistent))) {
 			log_error("Volume group \"%s\" not found", vg_name);
 			unlock_vg(cmd, vg_name);
 			return ECMD_FAILED;
diff -rN -p -u old-lvmlib-c/tools/vgrename.c new-lvmlib-c/tools/vgrename.c
--- old-lvmlib-c/tools/vgrename.c	2008-12-16 13:27:01.114811014 +0100
+++ new-lvmlib-c/tools/vgrename.c	2008-12-16 13:27:01.434810763 +0100
@@ -75,7 +75,7 @@ static int vg_rename_path(struct cmd_con
 		return 0;
 	}
 
-	if (!(vg = vg_read(cmd, vg_name_old, vgid, &consistent)) || !consistent) {
+	if (!(vg = vg_read_internal(cmd, vg_name_old, vgid, &consistent)) || !consistent) {
 		log_error("Volume group %s %s%s%snot found.", vg_name_old,
 		vgid ? "(" : "", vgid ? vgid : "", vgid ? ") " : "");
 		unlock_vg(cmd, vg_name_old);
@@ -107,7 +107,7 @@ static int vg_rename_path(struct cmd_con
 	}
 
 	consistent = 0;
-	if ((vg_new = vg_read(cmd, vg_name_new, NULL, &consistent))) {
+	if ((vg_new = vg_read_internal(cmd, vg_name_new, NULL, &consistent))) {
 		log_error("New volume group \"%s\" already exists",
 			  vg_name_new);
 		goto error;
diff -rN -p -u old-lvmlib-c/tools/vgsplit.c new-lvmlib-c/tools/vgsplit.c
--- old-lvmlib-c/tools/vgsplit.c	2008-12-16 13:27:01.114811014 +0100
+++ new-lvmlib-c/tools/vgsplit.c	2008-12-16 13:27:01.430808997 +0100
@@ -334,7 +334,7 @@ int vgsplit(struct cmd_context *cmd, int
 	}
 
 	consistent = 0;
-	if ((vg_to = vg_read(cmd, vg_name_to, NULL, &consistent))) {
+	if ((vg_to = vg_read_internal(cmd, vg_name_to, NULL, &consistent))) {
 		existing_vg = 1;
 		if (new_vg_option_specified(cmd)) {
 			log_error("Volume group \"%s\" exists, but new VG "
@@ -451,7 +451,7 @@ int vgsplit(struct cmd_context *cmd, int
 	 */
 	consistent = 1;
 	if (!test_mode() &&
-	    (!(vg_to = vg_read(cmd, vg_name_to, NULL, &consistent)) ||
+	    (!(vg_to = vg_read_internal(cmd, vg_name_to, NULL, &consistent)) ||
 	     !consistent)) {
 		log_error("Volume group \"%s\" became inconsistent: please "
 			  "fix manually", vg_name_to);

Tue Dec 16 12:45:35 CET 2008  Petr Rockai <me mornfall net>
  * Non-library portions of the vg_read patches.
diff -rN -p -u old-lvmlib-c/daemons/clvmd/lvm-functions.c new-lvmlib-c/daemons/clvmd/lvm-functions.c
--- old-lvmlib-c/daemons/clvmd/lvm-functions.c	2008-12-16 13:26:43.526811283 +0100
+++ new-lvmlib-c/daemons/clvmd/lvm-functions.c	2008-12-16 13:26:43.550808467 +0100
@@ -711,7 +711,7 @@ void lvm_do_backup(const char *vgname)
 
 	DEBUGLOG("Triggering backup of VG metadata for %s. suspended=%d\n", vgname, suspended);
 
-	vg = vg_read(cmd, vgname, NULL /*vgid*/, &consistent);
+	vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, &consistent);
 	if (vg) {
 		if (consistent)
 			check_current_backup(vg);
diff -rN -p -u old-lvmlib-c/lib/metadata/metadata.c new-lvmlib-c/lib/metadata/metadata.c
--- old-lvmlib-c/lib/metadata/metadata.c	2008-12-16 13:26:43.526811283 +0100
+++ new-lvmlib-c/lib/metadata/metadata.c	2008-12-16 13:26:43.802808860 +0100
@@ -332,7 +332,7 @@ static int remove_lvs_in_vg(struct cmd_c
 
 /* FIXME: remove redundant vg_name */
 int vg_remove_single(struct cmd_context *cmd, const char *vg_name,
-		     struct volume_group *vg, int consistent,
+		     struct volume_group *vg,
 		     force_t force __attribute((unused)))
 {
 	struct physical_volume *pv;
@@ -340,7 +340,7 @@ int vg_remove_single(struct cmd_context 
 	unsigned lv_count;
 	int ret = 1;
 
-	if (!vg || !consistent || vg_missing_pv_count(vg)) {
+	if (vg_read_error(vg) || vg_missing_pv_count(vg)) {
 		log_error("Volume group \"%s\" not found, is inconsistent "
 			  "or has PVs missing.", vg_name);
 		log_error("Consider vgreduce --removemissing if metadata "
diff -rN -p -u old-lvmlib-c/lib/metadata/metadata-exported.h new-lvmlib-c/lib/metadata/metadata-exported.h
--- old-lvmlib-c/lib/metadata/metadata-exported.h	2008-12-16 13:26:43.526811283 +0100
+++ new-lvmlib-c/lib/metadata/metadata-exported.h	2008-12-16 13:26:43.790808522 +0100
@@ -415,7 +415,7 @@ struct volume_group *vg_create(struct cm
 			       int pv_count, char **pv_names);
 int vg_remove(struct volume_group *vg);
 int vg_remove_single(struct cmd_context *cmd, const char *vg_name,
-		     struct volume_group *vg, int consistent,
+		     struct volume_group *vg,
 		     force_t force);
 int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
 	      const char *new_name);
diff -rN -p -u old-lvmlib-c/tools/lvchange.c new-lvmlib-c/tools/lvchange.c
--- old-lvmlib-c/tools/lvchange.c	2008-12-16 13:26:43.526811283 +0100
+++ new-lvmlib-c/tools/lvchange.c	2008-12-16 13:26:43.682808832 +0100
@@ -731,6 +731,6 @@ int lvchange(struct cmd_context *cmd, in
 		return EINVALID_CMD_LINE;
 	}
 
-	return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
+	return process_each_lv(cmd, argc, argv, READ_FOR_UPDATE, NULL,
 			       &lvchange_single);
 }
diff -rN -p -u old-lvmlib-c/tools/lvconvert.c new-lvmlib-c/tools/lvconvert.c
--- old-lvmlib-c/tools/lvconvert.c	2008-12-16 13:26:43.526811283 +0100
+++ new-lvmlib-c/tools/lvconvert.c	2008-12-16 13:26:43.662811319 +0100
@@ -240,10 +240,8 @@ static struct volume_group *_get_lvconve
 {
 	dev_close_all();
 
-        return vg_lock_and_read(cmd, extract_vgname(cmd, lv_name),
-				NULL, LCK_VG_WRITE,
- 				CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				CORRECT_INCONSISTENT | FAIL_INCONSISTENT);
+        return vg_read_for_update(cmd, extract_vgname(cmd, lv_name),
+				  NULL, 0);
 }
 
 static struct logical_volume *_get_lvconvert_lv(struct cmd_context *cmd __attribute((unused)),
@@ -746,9 +744,8 @@ int lvconvert(struct cmd_context * cmd, 
 
 	log_verbose("Checking for existing volume group \"%s\"", lp.vg_name);
 
-	if (!(vg = vg_lock_and_read(cmd, lp.vg_name, NULL, LCK_VG_WRITE,
-				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				    CORRECT_INCONSISTENT)))
+	vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
 
 	if (!(lvl = find_lv_in_vg(vg, lp.lv_name))) {
diff -rN -p -u old-lvmlib-c/tools/lvcreate.c new-lvmlib-c/tools/lvcreate.c
--- old-lvmlib-c/tools/lvcreate.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/lvcreate.c	2008-12-16 13:26:43.682808832 +0100
@@ -896,9 +896,8 @@ int lvcreate(struct cmd_context *cmd, in
 		return EINVALID_CMD_LINE;
 
 	log_verbose("Finding volume group \"%s\"", lp.vg_name);
-	if (!(vg = vg_lock_and_read(cmd, lp.vg_name, NULL, LCK_VG_WRITE,
-				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				    CORRECT_INCONSISTENT)))
+	vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
 
 	if (!_lvcreate(cmd, vg, &lp))
diff -rN -p -u old-lvmlib-c/tools/lvdisplay.c new-lvmlib-c/tools/lvdisplay.c
--- old-lvmlib-c/tools/lvdisplay.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/lvdisplay.c	2008-12-16 13:26:43.678808813 +0100
@@ -54,6 +54,6 @@ int lvdisplay(struct cmd_context *cmd, i
 		return EINVALID_CMD_LINE;
 	}
 
-	return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+	return process_each_lv(cmd, argc, argv, 0, NULL,
 			       &_lvdisplay_single);
 }
diff -rN -p -u old-lvmlib-c/tools/lvremove.c new-lvmlib-c/tools/lvremove.c
--- old-lvmlib-c/tools/lvremove.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/lvremove.c	2008-12-16 13:26:43.686808503 +0100
@@ -33,6 +33,6 @@ int lvremove(struct cmd_context *cmd, in
 
 	cmd->handles_missing_pvs = 1;
 
-	return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
+	return process_each_lv(cmd, argc, argv, READ_FOR_UPDATE, NULL,
 			       &lvremove_single);
 }
diff -rN -p -u old-lvmlib-c/tools/lvrename.c new-lvmlib-c/tools/lvrename.c
--- old-lvmlib-c/tools/lvrename.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/lvrename.c	2008-12-16 13:26:43.678808813 +0100
@@ -101,9 +101,8 @@ int lvrename(struct cmd_context *cmd, in
 	}
 
 	log_verbose("Checking for existing volume group \"%s\"", vg_name);
-	if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_WRITE,
-				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				    CORRECT_INCONSISTENT)))
+	vg = vg_read_for_update(cmd, vg_name, NULL, 0);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
 
 	if (!(lvl = find_lv_in_vg(vg, lv_name_old))) {
diff -rN -p -u old-lvmlib-c/tools/lvresize.c new-lvmlib-c/tools/lvresize.c
--- old-lvmlib-c/tools/lvresize.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/lvresize.c	2008-12-16 13:26:43.678808813 +0100
@@ -661,9 +661,8 @@ int lvresize(struct cmd_context *cmd, in
 		return EINVALID_CMD_LINE;
 
 	log_verbose("Finding volume group %s", lp.vg_name);
-	if (!(vg = vg_lock_and_read(cmd, lp.vg_name, NULL, LCK_VG_WRITE,
-				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				    CORRECT_INCONSISTENT))) {
+	vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
+	if (vg_read_error(vg)) {
 		stack;
 		return ECMD_FAILED;
 	}
diff -rN -p -u old-lvmlib-c/tools/lvscan.c new-lvmlib-c/tools/lvscan.c
--- old-lvmlib-c/tools/lvscan.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/lvscan.c	2008-12-16 13:26:43.682808832 +0100
@@ -80,6 +80,6 @@ int lvscan(struct cmd_context *cmd, int 
 		return EINVALID_CMD_LINE;
 	}
 
-	return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+	return process_each_lv(cmd, argc, argv, 0, NULL,
 			       &lvscan_single);
 }
diff -rN -p -u old-lvmlib-c/tools/polldaemon.c new-lvmlib-c/tools/polldaemon.c
--- old-lvmlib-c/tools/polldaemon.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/polldaemon.c	2008-12-16 13:26:43.666809383 +0100
@@ -147,7 +147,8 @@ static int _wait_for_single_mirror(struc
 		}
 
 		/* Locks the (possibly renamed) VG again */
-		if (!(vg = parms->poll_fns->get_copy_vg(cmd, name))) {
+		vg = parms->poll_fns->get_copy_vg(cmd, name);
+		if (vg_read_error(vg)) {
 			log_error("ABORTING: Can't reread VG for %s", name);
 			/* What more could we do here? */
 			return 0;
@@ -174,7 +175,7 @@ static int _wait_for_single_mirror(struc
 }
 
 static int _poll_vg(struct cmd_context *cmd, const char *vgname,
-		    struct volume_group *vg, int consistent, void *handle)
+		    struct volume_group *vg, void *handle)
 {
 	struct daemon_parms *parms = (struct daemon_parms *) handle;
 	struct lv_list *lvl;
@@ -182,18 +183,7 @@ static int _poll_vg(struct cmd_context *
 	const char *name;
 	int finished;
 
-	if (!vg) {
-		log_error("Couldn't read volume group %s", vgname);
-		return ECMD_FAILED;
-	}
-
-	if (!consistent) {
-		log_error("Volume Group %s inconsistent - skipping", vgname);
-		/* FIXME Should we silently recover it here or not? */
-		return ECMD_FAILED;
-	}
-
-	if (!vg_check_status(vg, EXPORTED_VG))
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
 
 	dm_list_iterate_items(lvl, &vg->lvs) {
@@ -218,7 +208,7 @@ static void _poll_for_all_vgs(struct cmd
 {
 	while (1) {
 		parms->outstanding_count = 0;
-		process_each_vg(cmd, 0, NULL, LCK_VG_WRITE, 1, parms, _poll_vg);
+		process_each_vg(cmd, 0, NULL, READ_FOR_UPDATE, parms, _poll_vg);
 		if (!parms->outstanding_count)
 			break;
 		sleep(parms->interval);
diff -rN -p -u old-lvmlib-c/tools/pvchange.c new-lvmlib-c/tools/pvchange.c
--- old-lvmlib-c/tools/pvchange.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/pvchange.c	2008-12-16 13:26:43.686808503 +0100
@@ -56,9 +56,8 @@ static int _pvchange_single(struct cmd_c
 
 		log_verbose("Finding volume group %s of physical volume %s",
 			    vg_name, pv_name);
-		if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_WRITE,
-					    CLUSTERED | EXPORTED_VG | LVM_WRITE,
-					    CORRECT_INCONSISTENT)))
+		vg = vg_read_for_update(cmd, vg_name, NULL, 0);
+		if (vg_read_error(vg))
 			return_0;
 
 		if (!(pvl = find_pv_in_vg(vg, pv_name))) {
diff -rN -p -u old-lvmlib-c/tools/pvdisplay.c new-lvmlib-c/tools/pvdisplay.c
--- old-lvmlib-c/tools/pvdisplay.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/pvdisplay.c	2008-12-16 13:26:43.690808522 +0100
@@ -28,10 +28,11 @@ static int _pvdisplay_single(struct cmd_
 
 	if (!is_orphan(pv) && !vg) {
 		vg_name = pv_vg_name(pv);
-		if (!(vg = vg_lock_and_read(cmd, vg_name, (char *)&pv->vgid,
-					    LCK_VG_READ, CLUSTERED, 0))) {
+		vg = vg_read(cmd, vg_name, (char *)&pv->vgid, 0);
+		if (vg_read_error(vg)) {
 		 	log_error("Skipping volume group %s", vg_name);
-			/* FIXME If CLUSTERED should return ECMD_PROCESSED here */
+			if (vg_read_error(vg) == FAILED_CLUSTERED)
+				return ECMD_PROCESSED;
 		 	return ECMD_FAILED;
 	 	}
 
diff -rN -p -u old-lvmlib-c/tools/pvmove.c new-lvmlib-c/tools/pvmove.c
--- old-lvmlib-c/tools/pvmove.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/pvmove.c	2008-12-16 13:26:43.670808983 +0100
@@ -89,16 +89,9 @@ static const char *_extract_lvname(struc
 
 static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
 {
-	struct volume_group *vg;
-
 	dev_close_all();
 
-	if (!(vg = vg_lock_and_read(cmd, vgname, NULL, LCK_VG_WRITE,
-				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				    CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
-		 return NULL;
-
-	return vg;
+	return vg_read_for_update(cmd, vgname, NULL, 0);
 }
 
 /* Create list of PVs for allocation of replacement extents */
@@ -382,7 +375,8 @@ static int _set_up_pvmove(struct cmd_con
 	/* Read VG */
 	log_verbose("Finding volume group \"%s\"", pv_vg_name(pv));
 
-	if (!(vg = _get_vg(cmd, pv_vg_name(pv)))) {
+	vg = _get_vg(cmd, pv_vg_name(pv));
+	if (vg_read_error(vg)) {
 		stack;
 		return ECMD_FAILED;
 	}
diff -rN -p -u old-lvmlib-c/tools/pvresize.c new-lvmlib-c/tools/pvresize.c
--- old-lvmlib-c/tools/pvresize.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/pvresize.c	2008-12-16 13:26:43.662811319 +0100
@@ -29,7 +29,6 @@ static int _pv_resize_single(struct cmd_
 			     const uint64_t new_size)
 {
 	struct pv_list *pvl;
-	int consistent = 1;
 	uint64_t size = 0;
 	uint32_t new_pe_count = 0;
 	struct dm_list mdas;
@@ -57,22 +56,10 @@ static int _pv_resize_single(struct cmd_
 	} else {
 		vg_name = pv_vg_name(pv);
 
-		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
-			log_error("Can't get lock for %s", pv_vg_name(pv));
-			return 0;
-		}
-
-		if (!(vg = vg_read_internal(cmd, vg_name, NULL, &consistent))) {
-			unlock_vg(cmd, vg_name);
-			log_error("Unable to find volume group of \"%s\"",
-				  pv_name);
-			return 0;
-		}
+		vg = vg_read_for_update(cmd, vg_name, NULL, 0);
 
-		if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE)) {
-			unlock_vg(cmd, vg_name);
+		if (vg_read_error(vg))
 			return 0;
-		}
 
 		if (!(pvl = find_pv_in_vg(vg, pv_name))) {
 			unlock_vg(cmd, vg_name);
diff -rN -p -u old-lvmlib-c/tools/reporter.c new-lvmlib-c/tools/reporter.c
--- old-lvmlib-c/tools/reporter.c	2008-12-16 13:26:43.522811962 +0100
+++ new-lvmlib-c/tools/reporter.c	2008-12-16 13:26:43.666809383 +0100
@@ -18,12 +18,10 @@
 
 static int _vgs_single(struct cmd_context *cmd __attribute((unused)),
 		       const char *vg_name, struct volume_group *vg,
-		       int consistent __attribute((unused)), void *handle)
+		       void *handle)
 {
-	if (!vg) {
-		log_error("Volume group %s not found", vg_name);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
-	}
 
 	if (!report_object(handle, vg, NULL, NULL, NULL, NULL))
 		return ECMD_FAILED;
@@ -125,8 +123,8 @@ static int _pvs_single(struct cmd_contex
 	if (is_pv(pv) && !is_orphan(pv) && !vg) {
 		vg_name = pv_vg_name(pv);
 
-		if (!(vg = vg_lock_and_read(cmd, vg_name, (char *)&pv->vgid,
-					    LCK_VG_READ, CLUSTERED, 0))) {
+		vg = vg_read(cmd, vg_name, (char *)&pv->vgid, 0);
+		if (vg_read_error(vg)) {
 			log_error("Skipping volume group %s", vg_name);
 			return ECMD_FAILED;
 		}
@@ -157,26 +155,20 @@ out:
 
 static int _pvs_in_vg(struct cmd_context *cmd, const char *vg_name,
 		      struct volume_group *vg,
-		      int consistent __attribute((unused)),
 		      void *handle)
 {
-	if (!vg) {
-		log_error("Volume group %s not found", vg_name);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
-	}
 
 	return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvs_single);
 }
 
 static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
 			 struct volume_group *vg,
-			 int consistent __attribute((unused)),
 			 void *handle)
 {
-	if (!vg) {
-		log_error("Volume group %s not found", vg_name);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
-	}
 
 	return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvsegs_single);
 }
@@ -349,23 +341,23 @@ static int _report(struct cmd_context *c
 
 	switch (report_type) {
 	case LVS:
-		r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
+		r = process_each_lv(cmd, argc, argv, 0, report_handle,
 				    &_lvs_single);
 		break;
 	case VGS:
-		r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
-				    report_handle, &_vgs_single);
+		r = process_each_vg(cmd, argc, argv, 0, report_handle,
+				    &_vgs_single);
 		break;
 	case PVS:
 		if (args_are_pvs)
 			r = process_each_pv(cmd, argc, argv, NULL, LCK_VG_READ,
 					    report_handle, &_pvs_single);
 		else
-			r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+			r = process_each_vg(cmd, argc, argv, 0,
 					    report_handle, &_pvs_in_vg);
 		break;
 	case SEGS:
-		r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
+		r = process_each_lv(cmd, argc, argv, 0, report_handle,
 				    &_lvsegs_single);
 		break;
 	case PVSEGS:
@@ -373,7 +365,7 @@ static int _report(struct cmd_context *c
 			r = process_each_pv(cmd, argc, argv, NULL, LCK_VG_READ,
 					    report_handle, &_pvsegs_single);
 		else
-			r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
+			r = process_each_vg(cmd, argc, argv, 0,
 					    report_handle, &_pvsegs_in_vg);
 		break;
 	}
diff -rN -p -u old-lvmlib-c/tools/toollib.c new-lvmlib-c/tools/toollib.c
--- old-lvmlib-c/tools/toollib.c	2008-12-16 13:26:43.518820602 +0100
+++ new-lvmlib-c/tools/toollib.c	2008-12-16 13:26:43.690808522 +0100
@@ -217,7 +217,7 @@ int process_each_lv_in_vg(struct cmd_con
 }
 
 int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
-		    uint32_t lock_type, void *handle,
+		    uint32_t flags, void *handle,
 		    int (*process_single) (struct cmd_context * cmd,
 					   struct logical_volume * lv,
 					   void *handle))
@@ -225,7 +225,6 @@ int process_each_lv(struct cmd_context *
 	int opt = 0;
 	int ret_max = ECMD_PROCESSED;
 	int ret = 0;
-	int consistent;
 
 	struct dm_list *tags_arg;
 	struct dm_list *vgnames;	/* VGs to process */
@@ -339,38 +338,10 @@ int process_each_lv(struct cmd_context *
 		vgname = strl->str;
 		if (is_orphan_vg(vgname))
 			continue;	/* FIXME Unnecessary? */
-		if (!lock_vol(cmd, vgname, lock_type)) {
-			log_error("Can't lock %s: skipping", vgname);
-			continue;
-		}
-		if (lock_type & LCK_WRITE)
-			consistent = 1;
-		else
-			consistent = 0;
-		if (!(vg = vg_read_internal(cmd, vgname, NULL, &consistent)) || !consistent) {
-			unlock_vg(cmd, vgname);
-			if (!vg)
-				log_error("Volume group \"%s\" "
-					  "not found", vgname);
-			else {
-				if (!vg_check_status(vg, CLUSTERED)) {
-					if (ret_max < ECMD_FAILED)
-						ret_max = ECMD_FAILED;
-					continue;
-				}
-				log_error("Volume group \"%s\" "
-					  "inconsistent", vgname);
-			}
 
-			if (!vg || !(vg = recover_vg(cmd, vgname, lock_type))) {
-				if (ret_max < ECMD_FAILED)
-					ret_max = ECMD_FAILED;
-				continue;
-			}
-		}
+		vg = vg_read(cmd, vgname, NULL, flags);
 
-		if (!vg_check_status(vg, CLUSTERED)) {
-			unlock_vg(cmd, vgname);
+		if (vg_read_error(vg)) {
 			if (ret_max < ECMD_FAILED)
 				ret_max = ECMD_FAILED;
 			continue;
@@ -427,8 +398,8 @@ int process_each_segment_in_pv(struct cm
 	if (!vg && !is_orphan(pv)) {
 		vg_name = pv_vg_name(pv);
 
-		if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_READ,
-					    CLUSTERED, 0))) {
+		vg = vg_read(cmd, vg_name, NULL, 0);
+		if (vg_read_error(vg)) {
 			log_error("Skipping volume group %s", vg_name);
 			return ECMD_FAILED;
 		}
@@ -473,32 +444,18 @@ int process_each_segment_in_lv(struct cm
 static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
 			   const char *vgid,
 			   struct dm_list *tags, struct dm_list *arg_vgnames,
-			   uint32_t lock_type, int consistent, void *handle,
+			   uint32_t flags, void *handle,
 			   int ret_max,
 			   int (*process_single) (struct cmd_context * cmd,
 						  const char *vg_name,
 						  struct volume_group * vg,
-						  int consistent, void *handle))
+						  void *handle))
 {
 	struct volume_group *vg;
 	int ret = 0;
 
-	if (!lock_vol(cmd, vg_name, lock_type)) {
-		log_error("Can't lock volume group %s: skipping", vg_name);
-		return ret_max;
-	}
-
 	log_verbose("Finding volume group \"%s\"", vg_name);
-	if (!(vg = vg_read_internal(cmd, vg_name, vgid, &consistent))) {
-		log_error("Volume group \"%s\" not found", vg_name);
-		unlock_vg(cmd, vg_name);
-		return ECMD_FAILED;
-	}
-
-	if (!vg_check_status(vg, CLUSTERED)) {
-		unlock_vg(cmd, vg_name);
-		return ECMD_FAILED;
-	}
+	vg = vg_read(cmd, vg_name, vgid, flags);
 
 	if (!dm_list_empty(tags)) {
 		/* Only process if a tag matches or it's on arg_vgnames */
@@ -509,7 +466,7 @@ static int _process_one_vg(struct cmd_co
 		}
 	}
 
-	if ((ret = process_single(cmd, vg_name, vg, consistent,
+	if ((ret = process_single(cmd, vg_name, vg,
 				  handle)) > ret_max) {
 		ret_max = ret;
 	}
@@ -520,11 +477,11 @@ static int _process_one_vg(struct cmd_co
 }
 
 int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
-		    uint32_t lock_type, int consistent, void *handle,
+		    uint32_t flags, void *handle,
 		    int (*process_single) (struct cmd_context * cmd,
 					   const char *vg_name,
 					   struct volume_group * vg,
-					   int consistent, void *handle))
+					   void *handle))
 {
 	int opt = 0;
 	int ret_max = ECMD_PROCESSED;
@@ -587,7 +544,7 @@ int process_each_vg(struct cmd_context *
 				continue;
 			ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
 						  &arg_vgnames,
-					  	  lock_type, consistent, handle,
+					  	  flags, handle,
 					  	  ret_max, process_single);
 			if (sigint_caught())
 				return ret_max;
@@ -599,7 +556,7 @@ int process_each_vg(struct cmd_context *
 				continue;	/* FIXME Unnecessary? */
 			ret_max = _process_one_vg(cmd, vg_name, NULL, &tags,
 						  &arg_vgnames,
-					  	  lock_type, consistent, handle,
+					  	  flags, handle,
 					  	  ret_max, process_single);
 			if (sigint_caught())
 				return ret_max;
@@ -1178,30 +1135,6 @@ struct dm_list *clone_pv_list(struct dm_
 	return r;
 }
 
-/*
- * Attempt metadata recovery
- */
-struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
-				uint32_t lock_type)
-{
-	int consistent = 1;
-
-	/* Don't attempt automatic recovery without proper locking */
-	if (lockingfailed())
-		return NULL;
-
-	lock_type &= ~LCK_TYPE_MASK;
-	lock_type |= LCK_WRITE;
-
-	if (!lock_vol(cmd, vgname, lock_type)) {
-		log_error("Can't lock %s for metadata recovery: skipping",
-			  vgname);
-		return NULL;
-	}
-
-	return vg_read_internal(cmd, vgname, NULL, &consistent);
-}
-
 int apply_lvname_restrictions(const char *name)
 {
 	if (!strncmp(name, "snapshot", 8)) {
diff -rN -p -u old-lvmlib-c/tools/toollib.h new-lvmlib-c/tools/toollib.h
--- old-lvmlib-c/tools/toollib.h	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/toollib.h	2008-12-16 13:26:43.690808522 +0100
@@ -27,11 +27,11 @@ struct volume_group *recover_vg(struct c
 				uint32_t lock_type);
 
 int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
-		    uint32_t lock_type, int consistent, void *handle,
+		    uint32_t flags, void *handle,
 		    int (*process_single) (struct cmd_context * cmd,
 					   const char *vg_name,
 					   struct volume_group * vg,
-					   int consistent, void *handle));
+					   void *handle));
 
 int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
 		    struct volume_group *vg, uint32_t lock_type, void *handle,
@@ -49,7 +49,7 @@ int process_each_segment_in_pv(struct cm
 						      void *handle));
 
 int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
-		    uint32_t lock_type, void *handle,
+		    uint32_t flags, void *handle,
 		    int (*process_single) (struct cmd_context * cmd,
 					   struct logical_volume * lv,
 					   void *handle));
diff -rN -p -u old-lvmlib-c/tools/vgcfgbackup.c new-lvmlib-c/tools/vgcfgbackup.c
--- old-lvmlib-c/tools/vgcfgbackup.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgcfgbackup.c	2008-12-16 13:26:43.674808444 +0100
@@ -48,19 +48,14 @@ static char *_expand_filename(const char
 }
 
 static int vg_backup_single(struct cmd_context *cmd, const char *vg_name,
-			    struct volume_group *vg, int consistent,
+			    struct volume_group *vg,
 			    void *handle)
 {
 	char **last_filename = (char **)handle;
 	char *filename;
 
-	if (!vg) {
-		log_error("Volume group \"%s\" not found", vg_name);
+	if (vg_read_error(vg) && !vg_read_error(vg) == FAILED_INCONSISTENT)
 		return ECMD_FAILED;
-	}
-
-	if (!consistent)
-		log_error("WARNING: Volume group \"%s\" inconsistent", vg_name);
 
 	if (arg_count(cmd, file_ARG)) {
 		if (!(filename = _expand_filename(arg_value(cmd, file_ARG),
@@ -72,7 +67,7 @@ static int vg_backup_single(struct cmd_c
 		if (!backup_to_file(filename, vg->cmd->cmd_line, vg))
 			return ECMD_FAILED;
 	} else {
-		if (!consistent) {
+		if (vg_read_error(vg) == FAILED_INCONSISTENT) {
 			log_error("No backup taken: specify filename with -f "
 				  "to backup an inconsistent VG");
 			stack;
@@ -98,7 +93,7 @@ int vgcfgbackup(struct cmd_context *cmd,
 
 	init_pvmove(1);
 
-	ret = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, &last_filename,
+	ret = process_each_vg(cmd, argc, argv, 0, &last_filename,
 			      &vg_backup_single);
 
 	dm_free(last_filename);
diff -rN -p -u old-lvmlib-c/tools/vgchange.c new-lvmlib-c/tools/vgchange.c
--- old-lvmlib-c/tools/vgchange.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgchange.c	2008-12-16 13:26:43.682808832 +0100
@@ -511,28 +511,13 @@ static int _vgchange_uuid(struct cmd_con
 }
 
 static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
-			   struct volume_group *vg, int consistent,
+			   struct volume_group *vg,
 			   void *handle __attribute((unused)))
 {
 	int r = ECMD_FAILED;
 
-	if (!vg) {
-		log_error("Unable to find volume group \"%s\"", vg_name);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
-	}
-
-	if (!consistent) {
-		unlock_vg(cmd, vg_name);
-		dev_close_all();
-		log_error("Volume group \"%s\" inconsistent", vg_name);
-		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
-			return ECMD_FAILED;
-	}
-
-	if (!(vg_status(vg) & LVM_WRITE) && !arg_count(cmd, available_ARG)) {
-		log_error("Volume group \"%s\" is read-only", vg->name);
-		return ECMD_FAILED;
-	}
 
 	if (vg_status(vg) & EXPORTED_VG) {
 		log_error("Volume group \"%s\" is exported", vg_name);
@@ -620,6 +605,6 @@ int vgchange(struct cmd_context *cmd, in
 
 	return process_each_vg(cmd, argc, argv,
 			       (arg_count(cmd, available_ARG)) ?
-			       LCK_VG_READ : LCK_VG_WRITE, 0, NULL,
+			       0 : READ_FOR_UPDATE, NULL,
 			       &vgchange_single);
 }
diff -rN -p -u old-lvmlib-c/tools/vgck.c new-lvmlib-c/tools/vgck.c
--- old-lvmlib-c/tools/vgck.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgck.c	2008-12-16 13:26:43.686808503 +0100
@@ -17,27 +17,14 @@
 
 static int vgck_single(struct cmd_context *cmd __attribute((unused)),
 		       const char *vg_name,
-		       struct volume_group *vg, int consistent,
+		       struct volume_group *vg,
 		       void *handle __attribute((unused)))
 {
-	if (!vg) {
-		log_error("Volume group \"%s\" not found", vg_name);
-		return ECMD_FAILED;
-	}
-
-	if (!consistent) {
-		log_error("Volume group \"%s\" inconsistent", vg_name);
-		return ECMD_FAILED;
-	}
-
-	if (!vg_check_status(vg, EXPORTED_VG))
-		return ECMD_FAILED;
-
 	return ECMD_PROCESSED;
 }
 
 int vgck(struct cmd_context *cmd, int argc, char **argv)
 {
-	return process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+	return process_each_vg(cmd, argc, argv, 0, NULL,
 			       &vgck_single);
 }
diff -rN -p -u old-lvmlib-c/tools/vgconvert.c new-lvmlib-c/tools/vgconvert.c
--- old-lvmlib-c/tools/vgconvert.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgconvert.c	2008-12-16 13:26:43.670808983 +0100
@@ -16,7 +16,7 @@
 #include "tools.h"
 
 static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
-			    struct volume_group *vg, int consistent,
+			    struct volume_group *vg,
 			    void *handle __attribute((unused)))
 {
 	struct physical_volume *pv, *existing_pv;
@@ -32,20 +32,7 @@ static int vgconvert_single(struct cmd_c
 	struct lvinfo info;
 	int active = 0;
 
-	if (!vg) {
-		log_error("Unable to find volume group \"%s\"", vg_name);
-		return ECMD_FAILED;
-	}
-
-	if (!consistent) {
-		unlock_vg(cmd, vg_name);
-		dev_close_all();
-		log_error("Volume group \"%s\" inconsistent", vg_name);
-		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
-			return ECMD_FAILED;
-	}
-
-	if (!vg_check_status(vg, LVM_WRITE | EXPORTED_VG))
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
 
 	if (vg->fid->fmt == cmd->fmt) {
@@ -233,6 +220,6 @@ int vgconvert(struct cmd_context *cmd, i
 		return EINVALID_CMD_LINE;
 	}
 
-	return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 0, NULL,
+	return process_each_vg(cmd, argc, argv, READ_FOR_UPDATE, NULL,
 			       &vgconvert_single);
 }
diff -rN -p -u old-lvmlib-c/tools/vgdisplay.c new-lvmlib-c/tools/vgdisplay.c
--- old-lvmlib-c/tools/vgdisplay.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgdisplay.c	2008-12-16 13:26:43.678808813 +0100
@@ -16,17 +16,12 @@
 #include "tools.h"
 
 static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
-			    struct volume_group *vg, int consistent,
+			    struct volume_group *vg,
 			    void *handle __attribute((unused)))
 {
 	/* FIXME Do the active check here if activevolumegroups_ARG ? */
-	if (!vg) {
-		log_error("Volume group \"%s\" doesn't exist", vg_name);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
-	}
-
-	if (!consistent)
-		log_error("WARNING: Volume group \"%s\" inconsistent", vg_name);
 
 	vg_check_status(vg, EXPORTED_VG);
 
@@ -98,8 +93,7 @@ int vgdisplay(struct cmd_context *cmd, i
 	}
 **********/
 
-	return process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
-			       vgdisplay_single);
+	return process_each_vg(cmd, argc, argv, 0, NULL, vgdisplay_single);
 
 /******** FIXME Need to count number processed
 	  Add this to process_each_vg if arg_count(cmd,activevolumegroups_ARG) ?
diff -rN -p -u old-lvmlib-c/tools/vgexport.c new-lvmlib-c/tools/vgexport.c
--- old-lvmlib-c/tools/vgexport.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgexport.c	2008-12-16 13:26:43.674808444 +0100
@@ -17,25 +17,14 @@
 
 static int vgexport_single(struct cmd_context *cmd __attribute((unused)),
 			   const char *vg_name,
-			   struct volume_group *vg, int consistent,
+			   struct volume_group *vg,
 			   void *handle __attribute((unused)))
 {
 	struct pv_list *pvl;
 	struct physical_volume *pv;
 
-	if (!vg) {
-		log_error("Unable to find volume group \"%s\"", vg_name);
+	if (vg_read_error(vg))
 		goto error;
-	}
-
-	if (!consistent) {
-		log_error("Volume group %s inconsistent", vg_name);
-		goto error;
-	}
-
-	if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE)) {
-		goto error;
-	}
 
 	if (lvs_in_vg_activated(vg)) {
 		log_error("Volume group \"%s\" has active logical volumes",
@@ -78,6 +67,6 @@ int vgexport(struct cmd_context *cmd, in
 		return ECMD_FAILED;
 	}
 
-	return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 1, NULL,
+	return process_each_vg(cmd, argc, argv, READ_FOR_UPDATE, NULL,
 			       &vgexport_single);
 }
diff -rN -p -u old-lvmlib-c/tools/vgextend.c new-lvmlib-c/tools/vgextend.c
--- old-lvmlib-c/tools/vgextend.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgextend.c	2008-12-16 13:26:43.682808832 +0100
@@ -41,11 +41,10 @@ int vgextend(struct cmd_context *cmd, in
 	}
 
 	log_verbose("Checking for volume group \"%s\"", vg_name);
-	if (!(vg = vg_lock_and_read(cmd, vg_name, NULL, LCK_VG_WRITE | LCK_NONBLOCK,
-				    CLUSTERED | EXPORTED_VG |
-				    LVM_WRITE | RESIZEABLE_VG,
-				    CORRECT_INCONSISTENT | FAIL_INCONSISTENT))) {
-		 unlock_vg(cmd, VG_ORPHANS);
+	vg = vg_read_for_update(cmd, vg_name, NULL,
+				REQUIRE_RESIZEABLE | NONBLOCKING_LOCK);
+	if (vg_read_error(vg)) {
+		unlock_vg(cmd, VG_ORPHANS);
 		return ECMD_FAILED;
 	 }
 /********** FIXME
diff -rN -p -u old-lvmlib-c/tools/vgimport.c new-lvmlib-c/tools/vgimport.c
--- old-lvmlib-c/tools/vgimport.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgimport.c	2008-12-16 13:26:43.670808983 +0100
@@ -17,17 +17,14 @@
 
 static int vgimport_single(struct cmd_context *cmd __attribute((unused)),
 			   const char *vg_name,
-			   struct volume_group *vg, int consistent,
+			   struct volume_group *vg,
 			   void *handle __attribute((unused)))
 {
 	struct pv_list *pvl;
 	struct physical_volume *pv;
 
-	if (!vg || !consistent) {
-		log_error("Unable to find exported volume group \"%s\"",
-			  vg_name);
+	if (vg_read_error(vg))
 		goto error;
-	}
 
 	if (!(vg_status(vg) & EXPORTED_VG)) {
 		log_error("Volume group \"%s\" is not exported", vg_name);
@@ -74,6 +71,7 @@ int vgimport(struct cmd_context *cmd, in
 		return ECMD_FAILED;
 	}
 
-	return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 1, NULL,
+	return process_each_vg(cmd, argc, argv,
+			       READ_FOR_UPDATE | ALLOW_EXPORTED, NULL,
 			       &vgimport_single);
 }
diff -rN -p -u old-lvmlib-c/tools/vgmerge.c new-lvmlib-c/tools/vgmerge.c
--- old-lvmlib-c/tools/vgmerge.c	2008-12-16 13:26:43.514810945 +0100
+++ new-lvmlib-c/tools/vgmerge.c	2008-12-16 13:26:43.674808444 +0100
@@ -27,16 +27,14 @@ static int _vgmerge_single(struct cmd_co
 	}
 
 	log_verbose("Checking for volume group \"%s\"", vg_name_to);
-	if (!(vg_to = vg_lock_and_read(cmd, vg_name_to, NULL, LCK_VG_WRITE,
-				       CLUSTERED | EXPORTED_VG | LVM_WRITE,
-				       CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
+	vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0);
+	if (vg_read_error(vg_to))
 		 return ECMD_FAILED;
 
 	log_verbose("Checking for volume group \"%s\"", vg_name_from);
-	if (!(vg_from = vg_lock_and_read(cmd, vg_name_from, NULL,
-					 LCK_VG_WRITE | LCK_NONBLOCK,
-					 CLUSTERED | EXPORTED_VG | LVM_WRITE,
-					 CORRECT_INCONSISTENT | FAIL_INCONSISTENT))) {
+	vg_from = vg_read_for_update(cmd, vg_name_from, NULL,
+				     NONBLOCKING_LOCK);
+	if (vg_read_error(vg_from)) {
 		unlock_vg(cmd, vg_name_to);
 		return ECMD_FAILED;
 	}
diff -rN -p -u old-lvmlib-c/tools/vgmknodes.c new-lvmlib-c/tools/vgmknodes.c
--- old-lvmlib-c/tools/vgmknodes.c	2008-12-16 13:26:43.510810785 +0100
+++ new-lvmlib-c/tools/vgmknodes.c	2008-12-16 13:26:43.670808983 +0100
@@ -28,7 +28,7 @@ int vgmknodes(struct cmd_context *cmd, i
 {
 	int r;
 
-	r = process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+	r = process_each_lv(cmd, argc, argv, 0, NULL,
 			    &_vgmknodes_single);
 
 	if (!lv_mknodes(cmd, NULL) && (r < ECMD_FAILED))
diff -rN -p -u old-lvmlib-c/tools/vgreduce.c new-lvmlib-c/tools/vgreduce.c
--- old-lvmlib-c/tools/vgreduce.c	2008-12-16 13:26:43.510810785 +0100
+++ new-lvmlib-c/tools/vgreduce.c	2008-12-16 13:26:43.686808503 +0100
@@ -382,7 +382,6 @@ static int _vgreduce_single(struct cmd_c
 {
 	struct pv_list *pvl;
 	struct volume_group *orphan_vg;
-	int consistent = 1;
 	const char *name = pv_dev_name(pv);
 
 	if (pv_pe_alloc_count(pv)) {
@@ -396,17 +395,10 @@ static int _vgreduce_single(struct cmd_c
 		return ECMD_FAILED;
 	}
 
-	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE | LCK_NONBLOCK)) {
-		log_error("Can't get lock for orphan PVs");
-		return ECMD_FAILED;
-	}
-
 	pvl = find_pv_in_vg(vg, name);
 
-	if (!archive(vg)) {
-		unlock_vg(cmd, VG_ORPHANS);
+	if (!archive(vg))
 		return ECMD_FAILED;
-	}
 
 	log_verbose("Removing \"%s\" from volume group \"%s\"", name, vg->name);
 
@@ -426,12 +418,11 @@ static int _vgreduce_single(struct cmd_c
 	vg->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv);
 	vg->extent_count -= pv_pe_count(pv);
 
-	if(!(orphan_vg = vg_read_internal(cmd, vg->fid->fmt->orphan_vg_name, NULL, &consistent)) ||
-	   !consistent) {
-		log_error("Unable to read existing orphan PVs");
-		unlock_vg(cmd, VG_ORPHANS);
+	orphan_vg = vg_read_for_update(cmd, vg->fid->fmt->orphan_vg_name,
+				       NULL, NONBLOCKING_LOCK | ORPHAN_LOCK);
+
+	if (vg_read_error(orphan_vg))
 		return ECMD_FAILED;
-	}
 
 	if (!vg_split_mdas(cmd, vg, orphan_vg) || !vg->pv_count) {
 		log_error("Cannot remove final metadata area on \"%s\" from \"%s\"",
@@ -468,7 +459,6 @@ int vgreduce(struct cmd_context *cmd, in
 	struct volume_group *vg;
 	char *vg_name;
 	int ret = 1;
-	int consistent = 1;
 	int fixed = 1;
 	int repairing = arg_count(cmd, removemissing_ARG);
 
@@ -515,41 +505,37 @@ int vgreduce(struct cmd_context *cmd, in
 	}
 
 	log_verbose("Finding volume group \"%s\"", vg_name);
-	if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
-		log_error("Can't get lock for %s", vg_name);
-		return ECMD_FAILED;
-	}
 
-	if ((!(vg = vg_read_internal(cmd, vg_name, NULL, &consistent)) || !consistent)
-	    && !repairing) {
-		log_error("Volume group \"%s\" doesn't exist", vg_name);
-		unlock_vg(cmd, vg_name);
+	vg = vg_read_for_update(cmd, vg_name, NULL, ALLOW_EXPORTED);
+	if (vg_read_error(vg) == FAILED_ALLOCATION ||
+	    vg_read_error(vg) == FAILED_NOTFOUND)
 		return ECMD_FAILED;
-	}
 
-	if (vg && !vg_check_status(vg, CLUSTERED)) {
-		unlock_vg(cmd, vg_name);
+	/* FIXME We want to allow read-only VGs to be changed here? */
+	if (vg_read_error(vg) && vg_read_error(vg) != FAILED_READ_ONLY
+	    && !arg_count(cmd, removemissing_ARG))
 		return ECMD_FAILED;
-	}
 
 	if (repairing) {
-		if (vg && consistent && !vg_missing_pv_count(vg)) {
+		if (!vg_read_error(vg) && !vg_missing_pv_count(vg)) {
 			log_error("Volume group \"%s\" is already consistent",
 				  vg_name);
 			unlock_vg(cmd, vg_name);
 			return ECMD_PROCESSED;
 		}
 
-		consistent = !arg_count(cmd, force_ARG);
-		if (!(vg = vg_read_internal(cmd, vg_name, NULL, &consistent))) {
-			log_error("Volume group \"%s\" not found", vg_name);
-			unlock_vg(cmd, vg_name);
-			return ECMD_FAILED;
-		}
-		if (!vg_check_status(vg, CLUSTERED)) {
+		log_verbose("Trying to open VG %s for recovery...", vg_name);
+
+		vg = vg_read_for_update(cmd, vg_name, NULL,
+					ALLOW_INCONSISTENT | DISABLE_LOCK
+					| ALLOW_EXPORTED);
+
+		if (vg_read_error(vg) && vg_read_error(vg) != FAILED_READ_ONLY
+		    && vg_read_error(vg) != FAILED_INCONSISTENT) {
 			unlock_vg(cmd, vg_name);
 			return ECMD_FAILED;
 		}
+
 		if (!archive(vg)) {
 			unlock_vg(cmd, vg_name);
 			return ECMD_FAILED;
diff -rN -p -u old-lvmlib-c/tools/vgremove.c new-lvmlib-c/tools/vgremove.c
--- old-lvmlib-c/tools/vgremove.c	2008-12-16 13:26:43.510810785 +0100
+++ new-lvmlib-c/tools/vgremove.c	2008-12-16 13:26:43.686808503 +0100
@@ -16,10 +16,10 @@
 #include "tools.h"
 
 static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
-			   struct volume_group *vg, int consistent,
+			   struct volume_group *vg,
 			   void *handle __attribute((unused)))
 {
-	if (!vg_remove_single(cmd, vg_name, vg, consistent,
+	if (!vg_remove_single(cmd, vg_name, vg,
 			      arg_count(cmd, force_ARG)))
 		return ECMD_FAILED;
 
@@ -41,7 +41,7 @@ int vgremove(struct cmd_context *cmd, in
 	}
 
 	ret = process_each_vg(cmd, argc, argv,
-			      LCK_VG_WRITE | LCK_NONBLOCK, 1,
+			      READ_FOR_UPDATE | NONBLOCKING_LOCK,
 			      NULL, &vgremove_single);
 
 	unlock_vg(cmd, VG_ORPHANS);
diff -rN -p -u old-lvmlib-c/tools/vgrename.c new-lvmlib-c/tools/vgrename.c
--- old-lvmlib-c/tools/vgrename.c	2008-12-16 13:26:43.510810785 +0100
+++ new-lvmlib-c/tools/vgrename.c	2008-12-16 13:26:43.686808503 +0100
@@ -20,7 +20,6 @@ static int vg_rename_path(struct cmd_con
 {
 	char *dev_dir;
 	struct id id;
-	int consistent = 1;
 	int match = 0;
 	int found_id = 0;
 	struct dm_list *vgids;
@@ -70,25 +69,11 @@ static int vg_rename_path(struct cmd_con
 	} else
 		vgid = NULL;
 
-	if (!lock_vol(cmd, vg_name_old, LCK_VG_WRITE)) {
-		log_error("Can't get lock for %s", vg_name_old);
-		return 0;
-	}
-
-	if (!(vg = vg_read_internal(cmd, vg_name_old, vgid, &consistent)) || !consistent) {
-		log_error("Volume group %s %s%s%snot found.", vg_name_old,
-		vgid ? "(" : "", vgid ? vgid : "", vgid ? ") " : "");
-		unlock_vg(cmd, vg_name_old);
-		return 0;
-	}
-
-	if (!vg_check_status(vg, CLUSTERED | LVM_WRITE)) {
-		unlock_vg(cmd, vg_name_old);
-		return 0;
-	}
-
-	/* Don't return failure for EXPORTED_VG */
-	vg_check_status(vg, EXPORTED_VG);
+	/* FIXME we used to print an error about EXPORTED, but proceeded
+	   nevertheless. */
+	vg = vg_read_for_update(cmd, vg_name_old, vgid, ALLOW_EXPORTED);
+	if (vg_read_error(vg))
+		return_0;
 
 	if (lvs_in_vg_activated_by_uuid_only(vg)) {
 		unlock_vg(cmd, vg_name_old);
@@ -100,14 +85,13 @@ static int vg_rename_path(struct cmd_con
 
 	log_verbose("Checking for new volume group \"%s\"", vg_name_new);
 
-	if (!lock_vol(cmd, vg_name_new, LCK_VG_WRITE | LCK_NONBLOCK)) {
-		unlock_vg(cmd, vg_name_old);
-		log_error("Can't get lock for %s", vg_name_new);
-		return 0;
-	}
+	vg_new = vg_read_for_update(cmd, vg_name_new, NULL, KEEP_LOCK |
+				    EXISTENCE_CHECK | NONBLOCKING_LOCK);
+
+	if (vg_read_error(vg_new))
+	    goto error;
 
-	consistent = 0;
-	if ((vg_new = vg_read_internal(cmd, vg_name_new, NULL, &consistent))) {
+	if (vg_exists(vg_new)) {
 		log_error("New volume group \"%s\" already exists",
 			  vg_name_new);
 		goto error;
diff -rN -p -u old-lvmlib-c/tools/vgscan.c new-lvmlib-c/tools/vgscan.c
--- old-lvmlib-c/tools/vgscan.c	2008-12-16 13:26:43.510810785 +0100
+++ new-lvmlib-c/tools/vgscan.c	2008-12-16 13:26:43.682808832 +0100
@@ -16,22 +16,11 @@
 #include "tools.h"
 
 static int vgscan_single(struct cmd_context *cmd, const char *vg_name,
-			 struct volume_group *vg, int consistent,
+			 struct volume_group *vg,
 			 void *handle __attribute((unused)))
 {
-	if (!vg) {
-		log_error("Volume group \"%s\" not found", vg_name);
+	if (vg_read_error(vg))
 		return ECMD_FAILED;
-	}
-
-	if (!consistent) {
-		unlock_vg(cmd, vg_name);
-		dev_close_all();
-		log_error("Volume group \"%s\" inconsistent", vg_name);
-		/* Don't allow partial switch to this program */
-		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
-			return ECMD_FAILED;
-	}
 
 	log_print("Found %svolume group \"%s\" using metadata type %s",
 		  (vg_status(vg) & EXPORTED_VG) ? "exported " : "", vg_name,
@@ -61,8 +50,7 @@ int vgscan(struct cmd_context *cmd, int 
 
 	log_print("Reading all physical volumes.  This may take a while...");
 
-	maxret = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
-				 &vgscan_single);
+	maxret = process_each_vg(cmd, argc, argv, 0, NULL, &vgscan_single);
 
 	if (arg_count(cmd, mknodes_ARG)) {
 		ret = vgmknodes(cmd, argc, argv);
diff -rN -p -u old-lvmlib-c/tools/vgsplit.c new-lvmlib-c/tools/vgsplit.c
--- old-lvmlib-c/tools/vgsplit.c	2008-12-16 13:26:43.506809439 +0100
+++ new-lvmlib-c/tools/vgsplit.c	2008-12-16 13:26:43.670808983 +0100
@@ -320,21 +320,20 @@ int vgsplit(struct cmd_context *cmd, int
 	}
 
 	log_verbose("Checking for volume group \"%s\"", vg_name_from);
-	if (!(vg_from = vg_lock_and_read(cmd, vg_name_from, NULL, LCK_VG_WRITE,
-				       CLUSTERED | EXPORTED_VG |
-				       RESIZEABLE_VG | LVM_WRITE,
-				       CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
-		 return ECMD_FAILED;
+	vg_from = vg_read_for_update(cmd, vg_name_from, NULL,
+				     REQUIRE_RESIZEABLE);
+	if (vg_read_error(vg_from))
+		return ECMD_FAILED;
 
 	log_verbose("Checking for new volume group \"%s\"", vg_name_to);
-	if (!lock_vol(cmd, vg_name_to, LCK_VG_WRITE | LCK_NONBLOCK)) {
-		log_error("Can't get lock for %s", vg_name_to);
-		unlock_vg(cmd, vg_name_from);
-		return ECMD_FAILED;
-	}
+	vg_to = vg_read_for_update(cmd, vg_name_to, NULL, REQUIRE_RESIZEABLE |
+				   NONBLOCKING_LOCK | KEEP_LOCK |
+				   EXISTENCE_CHECK);
+
+	if (vg_read_error(vg_to))
+		goto_bad;
 
-	consistent = 0;
-	if ((vg_to = vg_read_internal(cmd, vg_name_to, NULL, &consistent))) {
+	if (vg_exists(vg_to)) {
 		existing_vg = 1;
 		if (new_vg_option_specified(cmd)) {
 			log_error("Volume group \"%s\" exists, but new VG "
@@ -450,12 +449,14 @@ int vgsplit(struct cmd_context *cmd, int
 	 * Finally, remove the EXPORTED flag from the new VG and write it out.
 	 */
 	consistent = 1;
-	if (!test_mode() &&
-	    (!(vg_to = vg_read_internal(cmd, vg_name_to, NULL, &consistent)) ||
-	     !consistent)) {
-		log_error("Volume group \"%s\" became inconsistent: please "
-			  "fix manually", vg_name_to);
-		goto_bad;
+	if (!test_mode()) {
+		vg_to = vg_read_for_update(cmd, vg_name_to, NULL,
+					   DISABLE_LOCK | ALLOW_EXPORTED);
+		if (vg_read_error(vg_to)) {
+			log_error("Volume group \"%s\" became inconsistent: "
+				  "please fix manually", vg_name_to);
+			goto_bad;
+		}
 	}
 
 	vg_to->status &= ~EXPORTED_VG;

Yours,
   Petr.

-- 
Peter Rockai | me()mornfall!net | prockai()redhat!com
 http://blog.mornfall.net | http://web.mornfall.net

"In My Egotistical Opinion, most people's C programs should be
 indented six feet downward and covered with dirt."
     -- Blair P. Houghton on the subject of C program indentation

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]