]> sourceware.org Git - lvm2.git/commitdiff
Rely upon internally-cached PV labels while corresponding VG lock is held.
authorAlasdair Kergon <agk@redhat.com>
Tue, 29 Jan 2008 23:45:48 +0000 (23:45 +0000)
committerAlasdair Kergon <agk@redhat.com>
Tue, 29 Jan 2008 23:45:48 +0000 (23:45 +0000)
WHATS_NEW
lib/cache/lvmcache.c
lib/cache/lvmcache.h
lib/device/dev-io.c
lib/format_text/archiver.c
lib/format_text/format-text.c
lib/label/label.c
lib/report/report.c

index e4e392fe77232d1db882f8085b08ebe08ed7a1f5..5daf18e2542109ef84348362990a6a7f1fc5dfb7 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.33 -
 ===================================
+  Rely upon internally-cached PV labels while corresponding VG lock is held.
 
 Version 2.02.32 - 29th January 2008
 ===================================
index 7ceac094b3fda04af1183f48849b8912a697b3b2..63e7c37eace1b9c655718259ce48e277fe9d5f57 100644 (file)
@@ -49,6 +49,41 @@ int lvmcache_init(void)
        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()) {
@@ -59,6 +94,8 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)
        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++;
 }
 
@@ -72,7 +109,8 @@ int vgname_is_locked(const char *vgname)
 
 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 */
@@ -182,7 +220,22 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
        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)));
@@ -196,6 +249,9 @@ struct lvmcache_info *info_from_pvid(const char *pvid)
        if (!(info = dm_hash_lookup(_pvid_hash, id)))
                return NULL;
 
+       if (valid_only && !_info_is_valid(info))
+               return NULL;
+
        return info;
 }
 
@@ -344,7 +400,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
        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))
@@ -355,7 +411,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *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))
@@ -369,7 +425,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *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))
@@ -645,6 +701,8 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
        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;
 
@@ -716,7 +774,7 @@ int lvmcache_update_vg(struct volume_group *vg)
        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))
@@ -743,8 +801,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
        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;
index 43b4ae3be825c6457e337e2a66c6781622509bf3..bdda2f0a4158943bafdc080bc2100cb3f29adbca 100644 (file)
@@ -86,7 +86,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
 struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
                                           const char *vgid);
 struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
-struct lvmcache_info *info_from_pvid(const char *pvid);
+struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
 const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
 struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
 int vgs_locked(void);
index 54ae88e58ed2cc2e178a48e4fc72eea1279a74bd..b2b476726a5c604395d7c2e03d641f1143914d9f 100644 (file)
@@ -523,7 +523,7 @@ static int _dev_close(struct device *dev, int immediate)
        /* Close unless device is known to belong to a locked VG */
        if (immediate ||
            (dev->open_count < 1 && 
-            (!(info = info_from_pvid(dev->pvid)) ||
+            (!(info = info_from_pvid(dev->pvid, 0)) ||
              !info->vginfo ||
              !vgname_is_locked(info->vginfo->vgname))))
                _close(dev);
index 9aa803b04d179c2b6065f7e2f31aadff26bc2ca5..c736727ecabb84bc4aeaed05a475b5b956549fd0 100644 (file)
@@ -305,7 +305,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
        /* Add any metadata areas on the PVs */
        list_iterate_items(pvl, &vg->pvs) {
                pv = pvl->pv;
-               if (!(info = info_from_pvid(pv->dev->pvid))) {
+               if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
                        log_error("PV %s missing from cache",
                                  pv_dev_name(pv));
                        return 0;
index c83d7a821d48de77441d3fe6b367ff3ccba3b6d9..0783c14167196c57fd1cc0644ee538fd8d65f433 100644 (file)
@@ -391,7 +391,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
        }
 
       error:
-       if ((info = info_from_pvid(dev_area->dev->pvid)))
+       if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
                lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
 
        return NULL;
@@ -1610,7 +1610,7 @@ static int _text_pv_setup(const struct format_type *fmt,
        /* If new vg, add any further mdas on this PV to the fid's mda list */
        if (vg) {
                /* Iterate through all mdas on this PV */
-               if ((info = info_from_pvid(pv->dev->pvid))) {
+               if ((info = info_from_pvid(pv->dev->pvid, 0))) {
                        pvmdas = &info->mdas;
                        list_iterate_items(mda, pvmdas) {
                                mda_count++;
index f08dfe30bc3a55f35cd460ac39cd17f3b86e5cf6..e0454d01511ee6fef3c0f765700ed7ec02301023 100644 (file)
@@ -179,7 +179,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
 
       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));
@@ -260,7 +260,6 @@ int label_remove(struct device *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)
 {
@@ -270,10 +269,16 @@ int label_read(struct device *dev, struct label **result,
        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);
 
@@ -353,7 +358,7 @@ int label_verify(struct device *dev)
        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);
 
index af73259a5ae7725d427bbc3530ebc8918ed193bc..291e223de6f1ad14116cab9f4730248b49244492 100644 (file)
@@ -840,7 +840,7 @@ static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
        uint32_t count;
        const char *pvid = (const char *)(&((struct id *) data)->uuid);
 
-       info = info_from_pvid(pvid);
+       info = info_from_pvid(pvid, 0);
        count = info ? list_size(&info->mdas) : 0;
 
        return _uint32_disp(rh, mem, field, &count, private);
@@ -867,7 +867,7 @@ static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
        const char *pvid = (const char *)(&((struct id *) data)->uuid);
        struct metadata_area *mda;
 
-       info = info_from_pvid(pvid);
+       info = info_from_pvid(pvid, 0);
 
        list_iterate_items(mda, &info->mdas) {
                if (!mda->ops->mda_free_sectors)
This page took 0.056818 seconds and 5 git commands to generate.