[lvm-devel] [PATCH 2/3] Add VG refcount and cache created VG structure
Zdenek Kabelac
zkabelac at redhat.com
Wed Feb 23 13:52:16 UTC 2011
Imported VG from config tree is now cached in lvmcache_vginfo for
read-only code path..
Extended lvmcache_get_vg() with new parameter 'consistent'.
It passing information about how the metadata are going to be used.
For 'read-only' case it is == '0'.
VG structure has reference counter to support shared usage of VG.
(One copy is kept by cache - and 2nd is processed by the code and
released with free_vg()).
Sharing of 'write' MDA is not being made - after writting,
metadata cache is flushed and new data is read back and parsed again.
Signed-off-by: Zdenek Kabelac <zkabelac at redhat.com>
---
lib/cache/lvmcache.c | 53 +++++++++++++++++++++++++++++++----------------
lib/cache/lvmcache.h | 4 ++-
lib/metadata/metadata.c | 5 +++-
lib/metadata/vg.c | 1 +
lib/metadata/vg.h | 1 +
5 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 0a8693c..7c53b14 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -89,6 +89,11 @@ static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
vginfo->cft = NULL;
}
+ if (vginfo->vg) {
+ free_vg(vginfo->vg);
+ vginfo->vg = NULL;
+ }
+
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
}
@@ -624,7 +629,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
return r;
}
-struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
+struct volume_group *lvmcache_get_vg(const char *vgid, int consistent, unsigned precommitted)
{
struct lvmcache_vginfo *vginfo;
struct volume_group *vg;
@@ -653,25 +658,37 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
(!precommitted && vginfo->precommitted && !critical_section()))
return NULL;
- 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;
- if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic)))
- return_NULL;
+ if (vginfo->vg && (consistent == 0)) {
+ vg = vginfo->vg;
+ ++vg->refcount; /* Share with caller */
+ log_debug("Sharing VG %s (%d)", vginfo->vgname, vg->refcount);
+ } else {
+ 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;
+ if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic)))
+ return_NULL;
- /* Build config tree from vgmetadata, if not yet cached */
- if (!vginfo->cft &&
- !(vginfo->cft =
- create_config_tree_from_string(fid->fmt->cmd,
- vginfo->vgmetadata))) {
- _free_cached_vgmetadata(vginfo);
- return_NULL;
- }
+ /* Build config tree from vgmetadata, if not yet cached */
+ if (!vginfo->cft &&
+ !(vginfo->cft =
+ create_config_tree_from_string(fid->fmt->cmd,
+ vginfo->vgmetadata))) {
+ _free_cached_vgmetadata(vginfo);
+ return_NULL;
+ }
- if (!(vg = import_vg_from_config_tree(vginfo->cft, fid))) {
- _free_cached_vgmetadata(vginfo);
- return_NULL;
- }
+ if (!(vg = import_vg_from_config_tree(vginfo->cft, fid))) {
+ _free_cached_vgmetadata(vginfo);
+ return_NULL;
+ }
+
+ /* Cache only 'read-only' imported VG metadata */
+ if (consistent == 0) {
+ vginfo->vg = vg;
+ ++vg->refcount; /* Keep copy for cache */
+ }
+ }
log_debug("Using cached %smetadata for VG %s.",
vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 080f3b5..19ef423 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -49,6 +49,8 @@ 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 *vg; /* Cached parsed VG structure */
+ /* Lifetime is directly tied to vgmetadata */
unsigned precommitted; /* Is vgmetadata live or precommitted? */
};
@@ -120,7 +122,7 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
/* Returns cached volume group metadata. */
-struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
+struct volume_group *lvmcache_get_vg(const char *vgid, int consistent, unsigned precommitted);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index d75a1cf..563f0cb 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2860,7 +2860,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* Also return if use_precommitted is set due to the FIXME in
* the missing PV logic below.
*/
- if ((correct_vg = lvmcache_get_vg(vgid, precommitted)) &&
+ if ((correct_vg = lvmcache_get_vg(vgid, *consistent, precommitted)) &&
(use_precommitted || !*consistent || !(correct_vg->status & INCONSISTENT_VG))) {
if (!(correct_vg->status & INCONSISTENT_VG))
*consistent = 1;
@@ -3272,6 +3272,9 @@ void free_vg(struct volume_group *vg)
if (!vg)
return;
+ if (--vg->refcount)
+ return;
+
if (vg->cmd && vg->vgmem == vg->cmd->mem) {
log_error(INTERNAL_ERROR "global memory pool used for VG %s",
vg->name);
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index 392d23c..e21645c 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -31,6 +31,7 @@ struct volume_group *alloc_vg(struct cmd_context *cmd)
return NULL;
}
+ vg->refcount = 1;
vg->cmd = cmd;
vg->vgmem = vgmem;
vg->alloc = ALLOC_NORMAL;
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index c00fb74..ad6e071 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -37,6 +37,7 @@ struct volume_group {
struct format_instance *fid;
struct dm_list *cmd_vgs;/* List of wanted/locked and opened VGs */
uint32_t cmd_missing_vgs;/* Flag marks missing VG */
+ uint32_t refcount; /* Reference counter */
uint32_t seqno; /* Metadata sequence number */
alloc_policy_t alloc;
--
1.7.4.1
More information about the lvm-devel
mailing list