summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/cache/lvmcache.c41
-rw-r--r--lib/cache/lvmcache.h5
-rw-r--r--lib/metadata/metadata.c6
-rw-r--r--lib/metadata/vg.c10
-rw-r--r--lib/metadata/vg.h1
5 files changed, 59 insertions, 4 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 43ed1f46..59f060db 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,8 @@ static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
}
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
+
+ release_vg(vginfo->cached_vg);
}
/*
@@ -662,6 +664,10 @@ 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;
@@ -677,17 +683,44 @@ 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 reuse */
+ vginfo->cached_vg = vg;
+ vginfo->holders = 1;
+ vginfo->vg_use_count = 0;
+ vg->vginfo = vginfo;
+
+out:
+ vginfo->holders++;
+ vginfo->vg_use_count++;
+ log_debug("Using cached %smetadata for VG %s with %u holder(s).",
+ vginfo->precommitted ? "pre-committed " : "",
+ vginfo->vgname, vginfo->holders);
return vg;
bad:
- release_vg(vg);
_free_cached_vgmetadata(vginfo);
return NULL;
}
+int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
+{
+ log_debug("VG %s decrementing %d holder(s) at %p.",
+ vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg);
+
+ if (--vginfo->holders)
+ return 0;
+
+ if (vginfo->vg_use_count > 1)
+ log_debug("VG %s reused %d times.",
+ vginfo->cached_vg->name, vginfo->vg_use_count);
+
+ vginfo->cached_vg->vginfo = NULL;
+ vginfo->cached_vg = NULL;
+
+ return 1;
+}
+
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
int include_internal)
{
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 9aafff5a..2cf02362 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -50,6 +50,9 @@ 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 holders;
+ unsigned vg_use_count; /* Counter of vg reusage */
unsigned precommitted; /* Is vgmetadata live or precommitted? */
};
@@ -93,6 +96,8 @@ int lvmcache_verify_lock_order(const char *vgname);
/* Queries */
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
+/* Decrement and test if there are still vg holders in vginfo. */
+int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 0383e546..69955f6b 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 cached VG structure for a failure */
+ if (vg && vg->vginfo && 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 ef88a4d3..7aaea3e3 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -18,6 +18,7 @@
#include "display.h"
#include "activate.h"
#include "toolcontext.h"
+#include "lvmcache.h"
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
const char *vg_name)
@@ -49,6 +50,8 @@ 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 at %p.", vg->name, vg);
+
return vg;
}
@@ -62,6 +65,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,6 +75,11 @@ void release_vg(struct volume_group *vg)
if (!vg)
return;
+ /* Check if there are any vginfo holders */
+ if (vg->vginfo &&
+ !vginfo_holders_dec_and_test_for_zero(vg->vginfo))
+ return;
+
_free_vg(vg);
}
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index 52488880..9c21f37e 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;
+ struct lvmcache_vginfo *vginfo;
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 */