1
0
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:
Alasdair Kergon 2005-03-21 22:40:35 +00:00
parent 162d85b97b
commit e5b836d2d6
14 changed files with 119 additions and 23 deletions

View File

@ -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
View 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) {

View 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;

View 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);

View 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 &&

View 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)
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;

View 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;

View 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);

View 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);

View 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);

View 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))) {

View 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");

View 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");

View 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...");