/*
* 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.
*
}
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
+
+ release_vg(vginfo->cached_vg);
}
/*
(!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;
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)
{
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? */
};
/* 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);
#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)
dm_list_init(&vg->tags);
dm_list_init(&vg->removed_pvs);
+ log_debug("Allocated VG %s at %p.", vg->name, vg);
+
return vg;
}
return;
}
+ log_debug("Freeing VG %s at %p.", vg->name, vg);
+
dm_pool_destroy(vg->vgmem);
}
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);
}