diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/cache/lvmcache.c | 41 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 5 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 6 | ||||
-rw-r--r-- | lib/metadata/vg.c | 10 | ||||
-rw-r--r-- | lib/metadata/vg.h | 1 |
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 */ |