]> sourceware.org Git - lvm2.git/commitdiff
Improve detection of external changes affecting internal cache.
authorAlasdair Kergon <agk@redhat.com>
Mon, 21 Mar 2005 22:40:35 +0000 (22:40 +0000)
committerAlasdair Kergon <agk@redhat.com>
Mon, 21 Mar 2005 22:40:35 +0000 (22:40 +0000)
14 files changed:
WHATS_NEW
lib/cache/lvmcache.c
lib/device/dev-cache.c
lib/filters/filter-persistent.c
lib/format_text/format-text.c
lib/label/label.c
lib/log/log.c
lib/log/log.h
lib/metadata/metadata.c
tools/lvmcmdline.c
tools/polldaemon.c
tools/pvcreate.c
tools/pvscan.c
tools/vgscan.c

index 6845e178d4ab1bed3947b647263ead2523451737..cc9e30b22967156c934b18d5dceb01e58b3b859f 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.01.08 - 
 ================================
+  Improve detection of external changes affecting internal cache.
   Add 'already in device cache' debug message.
   Add -a to pvdisplay -C.
   Avoid rmdir opendir error messsages when dir was already removed.
index 43ccf4e887bf6bfaef794c6ef1a5cc3a274dadf5..3173f4641fb012076f23a0b49c616fb118d12d6a 100644 (file)
@@ -104,10 +104,30 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
 const struct format_type *fmt_from_vgname(const char *vgname)
 {
        struct lvmcache_vginfo *vginfo;
+       struct label *label;
+       struct list *ih, *devh, *tmp;
+       struct list devs;
+       struct device_list *devl;
 
        if (!(vginfo = vginfo_from_vgname(vgname)))
                return NULL;
 
+       /* This function is normally called before reading metadata so
+        * we check cached labels here. Unfortunately vginfo is volatile. */
+       list_init(&devs);
+       list_iterate(ih, &vginfo->infos) {
+               devl = malloc(sizeof(*devl));
+               devl->dev = list_item(ih, struct lvmcache_info)->dev;
+               list_add(&devs, &devl->list);
+       }
+
+       list_iterate_safe(devh, tmp, &devs) {
+               devl = list_item(devh, struct device_list);
+               label_read(devl->dev, &label);
+               list_del(&devl->list);
+               free(devl);
+       }
+
        return vginfo->fmt;
 }
 
@@ -403,6 +423,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
        /* FIXME Check consistency of list! */
        vginfo->fmt = info->fmt;
 
+       log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
+                 *vgname ? "in VG " : "orphaned", vgname);
+
        return 1;
 }
 
@@ -551,6 +574,8 @@ static void _lvmcache_destroy_lockname(int present)
 
 void lvmcache_destroy(void)
 {
+       log_verbose("Wiping internal VG cache");
+
        _has_scanned = 0;
 
        if (_vgid_hash) {
index cf301212d6efd1aaf01aa8dd8d83504f1f3c544b..cafd837ae213f4d3001762b8eca8a2588a7092f7 100644 (file)
@@ -21,6 +21,7 @@
 #include "lvm-types.h"
 #include "btree.h"
 #include "filter.h"
+#include "filter-persistent.h"
 
 #include <unistd.h>
 #include <sys/param.h>
@@ -368,6 +369,7 @@ static void _full_scan(int dev_scan)
        };
 
        _cache.has_scanned = 1;
+       init_full_scan_done(1);
 }
 
 int dev_cache_has_scanned(void)
@@ -379,15 +381,14 @@ void dev_cache_scan(int do_scan)
 {
        if (!do_scan)
                _cache.has_scanned = 1;
-       else {
-               _cache.has_scanned = 0;
+       else
                _full_scan(1);
-       }
 }
 
 int dev_cache_init(void)
 {
        _cache.names = NULL;
+       _cache.has_scanned = 0;
 
        if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
                stack;
@@ -549,7 +550,14 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
                return NULL;
        }
 
-       _full_scan(dev_scan);
+
+       if (dev_scan) {
+               /* Flag gets reset between each command */
+               if (!full_scan_done())
+                       persistent_filter_wipe(f); /* Calls _full_scan(1) */
+       } else
+               _full_scan(0);
+
        di->current = btree_first(_cache.devices);
        di->filter = f;
 
index 7b94b95ce9b3d1f9e4aed482b23ec43b68b50e9d..0666156b86edaee9fa92ba7efed4a7d3292e0301 100644 (file)
@@ -53,7 +53,9 @@ int persistent_filter_wipe(struct dev_filter *f)
 {
        struct pfilter *pf = (struct pfilter *) f->private;
 
+       log_verbose("Wiping cache of LVM-capable devices");
        hash_wipe(pf->devices);
+
        /* Trigger complete device scan */
        dev_cache_scan(1);
 
index 1f9006029c0ba78a8ebe2f11c8da1de5489189c2..0676921c9aaeca63e447570c357bec10577954de 100644 (file)
@@ -188,6 +188,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
        size_t len;
        char vgnamebuf[NAME_LEN + 2];
        struct raw_locn *rlocn;
+       struct lvmcache_info *info;
 
        rlocn = mdah->raw_locns;
 
@@ -196,7 +197,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
                if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
                              sizeof(vgnamebuf), vgnamebuf)) {
                        stack;
-                       return NULL;
+                       goto error;
                }
                if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
                    (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
@@ -205,6 +206,10 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
                rlocn++;
        }
 
+      error:
+       if ((info = info_from_pvid(dev_area->dev->pvid)))
+               lvmcache_update_vgname(info, ORPHAN);
+
        return NULL;
 }
 
@@ -264,7 +269,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
        }
 
        if (!(rlocn = _vg_posn(fid, area, vgname))) {
-               stack;
+               log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
                goto out;
        }
 
@@ -1183,8 +1188,8 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
                return 1;
        }
 
-       /* Perform full scan and try again */
-       if (!memlock()) {
+       /* Perform full scan (just the first time) and try again */
+       if (!memlock() && !full_scan_done()) {
                lvmcache_label_scan(fmt->cmd, 2);
 
                if (info->vginfo && info->vginfo->vgname &&
index 9d6dd685e36bd2e89d4fc811aeae54e5535bb838..beda8e970aa7afe2375257b64072b1d648854e16 100644 (file)
@@ -117,12 +117,17 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
        struct labeller_i *li;
        struct labeller *r = NULL;
        struct label_header *lh;
+       struct lvmcache_info *info;
        uint64_t sector;
        int found = 0;
        char readbuf[LABEL_SCAN_SIZE];
 
        if (!dev_open(dev)) {
                stack;
+
+               if ((info = info_from_pvid(dev->pvid)))
+                       lvmcache_update_vgname(info, ORPHAN);
+
                return NULL;
        }
 
@@ -182,10 +187,13 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
                }
        }
 
-       if (!found)
+      out:
+       if (!found) {
+               if ((info = info_from_pvid(dev->pvid)))
+                       lvmcache_update_vgname(info, ORPHAN);
                log_very_verbose("%s: No label detected", dev_name(dev));
+       }
 
-      out:
        if (!dev_close(dev))
                stack;
 
index 61677b5ca1a595f5a94b07028632c99957a18a53..2b0d70545a75c173cab2dbe74e9d14349df400c3 100644 (file)
@@ -30,6 +30,7 @@ static int _test = 0;
 static int _partial = 0;
 static int _md_filtering = 0;
 static int _pvmove = 0;
+static int _full_scan_done = 0;        /* Restrict to one full scan during each cmd */
 static int _debug_level = 0;
 static int _syslog = 0;
 static int _log_to_file = 0;
@@ -149,6 +150,11 @@ void init_pvmove(int level)
        _pvmove = level;
 }
 
+void init_full_scan_done(int level)
+{
+       _full_scan_done = level;
+}
+
 void init_ignorelockingfailure(int level)
 {
        _ignorelockingfailure = level;
@@ -203,6 +209,11 @@ int pvmove_mode()
        return _pvmove;
 }
 
+int full_scan_done()
+{
+       return _full_scan_done;
+}
+
 int ignorelockingfailure()
 {
        return _ignorelockingfailure;
index 8d552d107d3cfe1e8cee56cedb587006ef010173..bcb358fdc2a4a826cd78a743432ce763a9fd21d1 100644 (file)
@@ -65,6 +65,7 @@ void init_test(int level);
 void init_partial(int level);
 void init_md_filtering(int level);
 void init_pvmove(int level);
+void init_full_scan_done(int level);
 void init_debug(int level);
 void init_cmd_name(int status);
 void init_msg_prefix(const char *prefix);
@@ -78,6 +79,7 @@ int test_mode(void);
 int partial_mode(void);
 int md_filtering(void);
 int pvmove_mode(void);
+int full_scan_done(void);
 int debug_level(void);
 int ignorelockingfailure(void);
 int security_level(void);
index 9a6351be20b3627fb479ec42f1162990fbe8d2f3..d7a3a8be266d2edd41fc3d841e7d6624ea87692b 100644 (file)
@@ -687,10 +687,46 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
                }
        }
 
-       /* Failed to find VG */
+       /* Failed to find VG where we expected it - full scan and retry */
        if (!correct_vg) {
-               stack;
-               return NULL;
+               inconsistent = 0;
+
+               lvmcache_label_scan(cmd, 2);
+               if (!(fmt = fmt_from_vgname(vgname))) {
+                       stack;
+                       return NULL;
+               }
+
+               /* create format instance with appropriate metadata area */
+               if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
+                       log_error("Failed to create format instance");
+                       return NULL;
+               }
+
+               /* Ensure contents of all metadata areas match - else recover */
+               list_iterate(mdah, &fid->metadata_areas) {
+                       mda = list_item(mdah, struct metadata_area);
+                       if (!(vg = mda->ops->vg_read(fid, vgname, mda))) {
+                               inconsistent = 1;
+                               continue;
+                       }
+                       if (!correct_vg) {
+                               correct_vg = vg;
+                               continue;
+                       }
+                       /* FIXME Also ensure contents same - checksums same? */
+                       if (correct_vg->seqno != vg->seqno) {
+                               inconsistent = 1;
+                               if (vg->seqno > correct_vg->seqno)
+                                       correct_vg = vg;
+                       }
+               }
+
+               /* Give up looking */
+               if (!correct_vg) {
+                       stack;
+                       return NULL;
+               }
        }
 
        lvmcache_update_vg(correct_vg);
index 35b9b336949572f1c512ac9613db8f270b839ba0..9cd79419125d70320d32ae77f9054b5a87c13b97 100644 (file)
@@ -753,6 +753,7 @@ static void _apply_settings(struct cmd_context *cmd)
        init_debug(cmd->current_settings.debug);
        init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
        init_test(cmd->current_settings.test);
+       init_full_scan_done(0);
 
        init_msg_prefix(cmd->default_settings.msg_prefix);
        init_cmd_name(cmd->default_settings.cmd_name);
index 88506902a195484148332e8bd3ed6b2080e1339b..7833e6ad23161f9f589eec0ebd37a425d7a0bf18 100644 (file)
@@ -138,8 +138,11 @@ static int _wait_for_single_mirror(struct cmd_context *cmd, const char *name,
        while (!finished) {
                /* FIXME Also needed in vg/lvchange -ay? */
                /* FIXME Use alarm for regular intervals instead */
-               if (parms->interval && !parms->aborting)
+               if (parms->interval && !parms->aborting) {
                        sleep(parms->interval);
+                       /* Devices might have changed while we slept */
+                       init_full_scan_done(0);
+               }
 
                /* Locks the (possibly renamed) VG again */
                if (!(vg = parms->poll_fns->get_copy_vg(cmd, name))) {
index fd3a8a39ae0bba0908baa32192ff527815eb5ab6..1bd40ac04145e5b0bdbcbb21716402d93ec3ffe2 100644 (file)
@@ -63,10 +63,10 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
        /* Is there an md superblock here? */
        if (!dev && md_filtering()) {
                unlock_vg(cmd, "");
-               log_verbose("Wiping cache of LVM-capable devices");
+
                persistent_filter_wipe(cmd->filter);
-               log_verbose("Wiping internal cache");
                lvmcache_destroy();
+
                init_md_filtering(0);
                if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
                        log_error("Can't get lock for orphan PVs");
index c7fc0de28d66b20879cea264b4da87c46addd3c4..bbe054d6f25b14fefd182cbb16ec8b81c71c321d 100644 (file)
@@ -123,10 +123,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
                          arg_count(cmd, exported_ARG) ?
                          "of exported volume group(s)" : "in no volume group");
 
-       log_verbose("Wiping cache of LVM-capable devices");
        persistent_filter_wipe(cmd->filter);
-
-       log_verbose("Wiping internal cache");
        lvmcache_destroy();
 
        log_verbose("Walking through all physical volumes");
index e1eb69f2495574817827ef861d5b2a4122df20f9..ced50a5afc0709ef6231f4297aa424f6bb371ef7 100644 (file)
@@ -48,10 +48,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
                return EINVALID_CMD_LINE;
        }
 
-       log_verbose("Wiping cache of LVM-capable devices");
        persistent_filter_wipe(cmd->filter);
-
-       log_verbose("Wiping internal cache");
        lvmcache_destroy();
 
        log_print("Reading all physical volumes.  This may take a while...");
This page took 0.050397 seconds and 5 git commands to generate.