[lvm-devel] [PATCH 3/7] Add cache_vg

Zdenek Kabelac zkabelac at redhat.com
Tue Jul 19 13:43:54 UTC 2011


Signed-off-by: Zdenek Kabelac <zkabelac at redhat.com>
---
 WHATS_NEW               |    2 ++
 lib/cache/lvmcache.c    |   24 ++++++++++++++++++++----
 lib/cache/lvmcache.h    |    1 +
 lib/metadata/metadata.c |    6 ++++++
 lib/metadata/vg.c       |   17 ++++++++++++++++-
 lib/metadata/vg.h       |    3 +++
 6 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/WHATS_NEW b/WHATS_NEW
index fb26132..732ece0 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,7 @@
 Version 2.02.87 - 
 ===============================
+  Cache and share generated VG structs.
+  Add ref count to struct volume_group and use release_vg instead of free_vg.
 
 Version 2.02.86 - 8th July 2011
 ===============================
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index a2d6aa1..c9c3220 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -90,6 +90,10 @@ static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
 	}
 
 	log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
+
+	release_vg(vginfo->cached_vg);
+
+	vginfo->cached_vg = NULL;
 }
 
 /*
@@ -662,6 +666,12 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
 	    (!precommitted && vginfo->precommitted && !critical_section()))
 		return NULL;
 
+	/*
+	 * Use already-cached VG struct when available
+	 */
+	if ((vg = vginfo->cached_vg))
+		goto out;	
+
 	fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
 	fic.context.vg_ref.vg_name = vginfo->vgname;
 	fic.context.vg_ref.vg_id = vgid;
@@ -678,13 +688,19 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
 	if (!(vg = import_vg_from_config_tree(vginfo->cft, fid)))
 		goto_bad;
 
-	log_debug("Using cached %smetadata for VG %s.",
-		  vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
+	/*
+	 * Cache VG struct for potential reuse
+	 */
+	vginfo->cached_vg = vg;
+
+out:
+	increment_vg_holders(vg);
+	log_debug("Using cached %smetadata for VG %s with %u holder(s).",
+		  vginfo->precommitted ? "pre-committed" : "", vginfo->vgname, vg->holders);
 
 	return vg;
 
 bad:
-	release_vg(vg);
 	_free_cached_vgmetadata(vginfo);
 	return NULL;
 }
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 9aafff5..5f0a4d0 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -50,6 +50,7 @@ struct lvmcache_vginfo {
 	char *vgmetadata;	/* Copy of VG metadata as format_text string */
 	struct config_tree *cft; /* Config tree created from vgmetadata */
 				/* Lifetime is directly tied to vgmetadata */
+	struct volume_group *cached_vg;
 	unsigned precommitted;	/* Is vgmetadata live or precommitted? */
 };
 
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 6401207..35770bf 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -866,6 +866,12 @@ static struct volume_group *_vg_make_handle(struct cmd_context *cmd,
 					    struct volume_group *vg,
 					    uint32_t failure)
 {
+	/* Never return a shared VG struct for a failure */
+	if (vg && vg->holders > 1 && failure != SUCCESS) {
+		release_vg(vg);
+		vg = NULL;
+	}
+
 	if (!vg && !(vg = alloc_vg("vg_make_handle", cmd, NULL)))
 		return_NULL;
 
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index ef88a4d..08b78af 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -42,6 +42,7 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
 	vg->cmd = cmd;
 	vg->vgmem = vgmem;
 	vg->alloc = ALLOC_NORMAL;
+	vg->holders = 1;
 
 	dm_list_init(&vg->pvs);
 	dm_list_init(&vg->pvs_to_create);
@@ -49,9 +50,18 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
 	dm_list_init(&vg->tags);
 	dm_list_init(&vg->removed_pvs);
 
+	log_debug("Allocated VG %s with 1 holder at %p.", vg->name, vg);
+
 	return vg;
 }
 
+void increment_vg_holders(struct volume_group *vg)
+{
+	vg->holders++;
+
+	log_debug("Incrementing VG %s holder(s) to %d at %p.", vg->name, vg->holders, vg);
+}
+
 static void _free_vg(struct volume_group *vg)
 {
 	vg_set_fid(vg, NULL);
@@ -62,6 +72,8 @@ static void _free_vg(struct volume_group *vg)
 		return;
 	}
 
+	log_debug("Freeing VG %s at %p.", vg->name, vg);
+
 	dm_pool_destroy(vg->vgmem);
 }
 
@@ -70,7 +82,10 @@ void release_vg(struct volume_group *vg)
 	if (!vg)
 		return;
 
-	_free_vg(vg);
+	log_debug("Releasing VG %s with %d holder(s) at %p.", vg->name, vg->holders, vg);
+
+	if (!--vg->holders)
+		_free_vg(vg);
 }
 
 char *vg_fmt_dup(const struct volume_group *vg)
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index a3dc218..9366e0f 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -41,6 +41,7 @@ struct volume_group {
 	struct cmd_context *cmd;
 	struct dm_pool *vgmem;
 	struct format_instance *fid;
+	unsigned holders;
 	struct dm_list *cmd_vgs;/* List of wanted/locked and opened VGs */
 	uint32_t cmd_missing_vgs;/* Flag marks missing VG */
 	uint32_t seqno;		/* Metadata sequence number */
@@ -111,6 +112,8 @@ struct volume_group {
 struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
 			      const char *vg_name);
 
+void increment_vg_holders(struct volume_group *vg);
+
 /*
  * release_vg() must be called on every struct volume_group allocated
  * by vg_create() or vg_read_internal() to free it when no longer required.
-- 
1.7.6




More information about the lvm-devel mailing list