mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Improve detection of external changes affecting internal cache.
This commit is contained in:
parent
162d85b97b
commit
e5b836d2d6
@ -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.
|
||||
|
25
lib/cache/lvmcache.c
vendored
25
lib/cache/lvmcache.c
vendored
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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)
|
||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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))) {
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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...");
|
||||
|
Loading…
Reference in New Issue
Block a user