return 1;
}
+static void _update_cache_info_lock_state(struct lvmcache_info *info, int locked)
+{
+ int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
+
+ /*
+ * Cache becomes invalid whenever lock state changes
+ */
+ if (was_locked != locked)
+ info->status |= CACHE_INVALID;
+
+ if (locked)
+ info->status |= CACHE_LOCKED;
+ else
+ info->status &= ~CACHE_LOCKED;
+}
+
+static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
+ int locked)
+{
+ struct lvmcache_info *info;
+
+ list_iterate_items(info, &vginfo->infos)
+ _update_cache_info_lock_state(info, locked);
+}
+
+static void _update_cache_lock_state(const char *vgname, int locked)
+{
+ struct lvmcache_vginfo *vginfo;
+
+ if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
+ return;
+
+ _update_cache_vginfo_lock_state(vginfo, locked);
+}
+
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
{
if (!_lock_hash && !lvmcache_init()) {
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
log_error("Cache locking failure for %s", vgname);
+ _update_cache_lock_state(vgname, 1);
+
_vgs_locked++;
}
void lvmcache_unlock_vgname(const char *vgname)
{
- /* FIXME: Clear all CACHE_LOCKED flags in this vg */
+ _update_cache_lock_state(vgname, 0);
+
dm_hash_remove(_lock_hash, vgname);
/* FIXME Do this per-VG */
return vgname;
}
-struct lvmcache_info *info_from_pvid(const char *pvid)
+static int _info_is_valid(struct lvmcache_info *info)
+{
+ if (info->status & CACHE_INVALID)
+ return 0;
+
+ if (!(info->status & CACHE_LOCKED))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * If valid_only is set, data will only be returned if the cached data is
+ * known still to be valid.
+ */
+struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
{
struct lvmcache_info *info;
char id[ID_LEN + 1] __attribute((aligned(8)));
if (!(info = dm_hash_lookup(_pvid_hash, id)))
return NULL;
+ if (valid_only && !_info_is_valid(info))
+ return NULL;
+
return info;
}
struct lvmcache_info *info;
/* Already cached ? */
- if ((info = info_from_pvid((char *) pvid))) {
+ if ((info = info_from_pvid((char *) pvid, 0))) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
lvmcache_label_scan(cmd, 0);
/* Try again */
- if ((info = info_from_pvid((char *) pvid))) {
+ if ((info = info_from_pvid((char *) pvid, 0))) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
lvmcache_label_scan(cmd, 2);
/* Try again */
- if ((info = info_from_pvid((char *) pvid))) {
+ if ((info = info_from_pvid((char *) pvid, 0))) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
info->vginfo = vginfo;
list_add(&vginfo->infos, &info->list);
+ _update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
+
/* FIXME Check consistency of list! */
vginfo->fmt = info->fmt;
list_iterate_items(pvl, &vg->pvs) {
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
- if ((info = info_from_pvid(pvid_s)) &&
+ if ((info = info_from_pvid(pvid_s, 0)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
strncpy(pvid_s, pvid, sizeof(pvid_s));
pvid_s[sizeof(pvid_s) - 1] = '\0';
- if (!(existing = info_from_pvid(pvid_s)) &&
- !(existing = info_from_pvid(dev->pvid))) {
+ if (!(existing = info_from_pvid(pvid_s, 0)) &&
+ !(existing = info_from_pvid(dev->pvid, 0))) {
if (!(label = label_create(labeller))) {
stack;
return NULL;
out:
if (!found) {
- if ((info = info_from_pvid(dev->pvid)))
+ if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);
log_very_verbose("%s: No label detected", dev_name(dev));
return r;
}
-/* FIXME Avoid repeated re-reading if cache lock held */
int label_read(struct device *dev, struct label **result,
uint64_t scan_sector)
{
struct lvmcache_info *info;
int r = 0;
+ if ((info = info_from_pvid(dev->pvid, 1))) {
+ log_debug("Using cached label for %s", dev_name(dev));
+ *result = info->label;
+ return 1;
+ }
+
if (!dev_open(dev)) {
stack;
- if ((info = info_from_pvid(dev->pvid)))
+ if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);
int r = 0;
if (!dev_open(dev)) {
- if ((info = info_from_pvid(dev->pvid)))
+ if ((info = info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
0, NULL);