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.
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;
}
/* 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;
}
void lvmcache_destroy(void)
{
+ log_verbose("Wiping internal VG cache");
+
_has_scanned = 0;
if (_vgid_hash) {
#include "lvm-types.h"
#include "btree.h"
#include "filter.h"
+#include "filter-persistent.h"
#include <unistd.h>
#include <sys/param.h>
};
_cache.has_scanned = 1;
+ init_full_scan_done(1);
}
int dev_cache_has_scanned(void)
{
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;
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;
{
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);
size_t len;
char vgnamebuf[NAME_LEN + 2];
struct raw_locn *rlocn;
+ struct lvmcache_info *info;
rlocn = mdah->raw_locns;
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] == '{')) {
rlocn++;
}
+ error:
+ if ((info = info_from_pvid(dev_area->dev->pvid)))
+ lvmcache_update_vgname(info, ORPHAN);
+
return NULL;
}
}
if (!(rlocn = _vg_posn(fid, area, vgname))) {
- stack;
+ log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
goto out;
}
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 &&
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;
}
}
}
- 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;
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;
_pvmove = level;
}
+void init_full_scan_done(int level)
+{
+ _full_scan_done = level;
+}
+
void init_ignorelockingfailure(int level)
{
_ignorelockingfailure = level;
return _pvmove;
}
+int full_scan_done()
+{
+ return _full_scan_done;
+}
+
int ignorelockingfailure()
{
return _ignorelockingfailure;
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);
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);
}
}
- /* 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);
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);
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))) {
/* 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");
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");
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...");