mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-10 16:58:47 +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 -
|
Version 2.01.08 -
|
||||||
================================
|
================================
|
||||||
|
Improve detection of external changes affecting internal cache.
|
||||||
Add 'already in device cache' debug message.
|
Add 'already in device cache' debug message.
|
||||||
Add -a to pvdisplay -C.
|
Add -a to pvdisplay -C.
|
||||||
Avoid rmdir opendir error messsages when dir was already removed.
|
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)
|
const struct format_type *fmt_from_vgname(const char *vgname)
|
||||||
{
|
{
|
||||||
struct lvmcache_vginfo *vginfo;
|
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)))
|
if (!(vginfo = vginfo_from_vgname(vgname)))
|
||||||
return NULL;
|
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;
|
return vginfo->fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +423,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
|||||||
/* FIXME Check consistency of list! */
|
/* FIXME Check consistency of list! */
|
||||||
vginfo->fmt = info->fmt;
|
vginfo->fmt = info->fmt;
|
||||||
|
|
||||||
|
log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
|
||||||
|
*vgname ? "in VG " : "orphaned", vgname);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,6 +574,8 @@ static void _lvmcache_destroy_lockname(int present)
|
|||||||
|
|
||||||
void lvmcache_destroy(void)
|
void lvmcache_destroy(void)
|
||||||
{
|
{
|
||||||
|
log_verbose("Wiping internal VG cache");
|
||||||
|
|
||||||
_has_scanned = 0;
|
_has_scanned = 0;
|
||||||
|
|
||||||
if (_vgid_hash) {
|
if (_vgid_hash) {
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "lvm-types.h"
|
#include "lvm-types.h"
|
||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "filter-persistent.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -368,6 +369,7 @@ static void _full_scan(int dev_scan)
|
|||||||
};
|
};
|
||||||
|
|
||||||
_cache.has_scanned = 1;
|
_cache.has_scanned = 1;
|
||||||
|
init_full_scan_done(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_has_scanned(void)
|
int dev_cache_has_scanned(void)
|
||||||
@ -379,15 +381,14 @@ void dev_cache_scan(int do_scan)
|
|||||||
{
|
{
|
||||||
if (!do_scan)
|
if (!do_scan)
|
||||||
_cache.has_scanned = 1;
|
_cache.has_scanned = 1;
|
||||||
else {
|
else
|
||||||
_cache.has_scanned = 0;
|
|
||||||
_full_scan(1);
|
_full_scan(1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_init(void)
|
int dev_cache_init(void)
|
||||||
{
|
{
|
||||||
_cache.names = NULL;
|
_cache.names = NULL;
|
||||||
|
_cache.has_scanned = 0;
|
||||||
|
|
||||||
if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
|
if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
|
||||||
stack;
|
stack;
|
||||||
@ -549,7 +550,14 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
|
|||||||
return NULL;
|
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->current = btree_first(_cache.devices);
|
||||||
di->filter = f;
|
di->filter = f;
|
||||||
|
|
||||||
|
@ -53,7 +53,9 @@ int persistent_filter_wipe(struct dev_filter *f)
|
|||||||
{
|
{
|
||||||
struct pfilter *pf = (struct pfilter *) f->private;
|
struct pfilter *pf = (struct pfilter *) f->private;
|
||||||
|
|
||||||
|
log_verbose("Wiping cache of LVM-capable devices");
|
||||||
hash_wipe(pf->devices);
|
hash_wipe(pf->devices);
|
||||||
|
|
||||||
/* Trigger complete device scan */
|
/* Trigger complete device scan */
|
||||||
dev_cache_scan(1);
|
dev_cache_scan(1);
|
||||||
|
|
||||||
|
@ -188,6 +188,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
|||||||
size_t len;
|
size_t len;
|
||||||
char vgnamebuf[NAME_LEN + 2];
|
char vgnamebuf[NAME_LEN + 2];
|
||||||
struct raw_locn *rlocn;
|
struct raw_locn *rlocn;
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
rlocn = mdah->raw_locns;
|
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,
|
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||||
sizeof(vgnamebuf), vgnamebuf)) {
|
sizeof(vgnamebuf), vgnamebuf)) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
|
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
|
||||||
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
|
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
|
||||||
@ -205,6 +206,10 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
|||||||
rlocn++;
|
rlocn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
if ((info = info_from_pvid(dev_area->dev->pvid)))
|
||||||
|
lvmcache_update_vgname(info, ORPHAN);
|
||||||
|
|
||||||
return NULL;
|
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))) {
|
if (!(rlocn = _vg_posn(fid, area, vgname))) {
|
||||||
stack;
|
log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,8 +1188,8 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform full scan and try again */
|
/* Perform full scan (just the first time) and try again */
|
||||||
if (!memlock()) {
|
if (!memlock() && !full_scan_done()) {
|
||||||
lvmcache_label_scan(fmt->cmd, 2);
|
lvmcache_label_scan(fmt->cmd, 2);
|
||||||
|
|
||||||
if (info->vginfo && info->vginfo->vgname &&
|
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_i *li;
|
||||||
struct labeller *r = NULL;
|
struct labeller *r = NULL;
|
||||||
struct label_header *lh;
|
struct label_header *lh;
|
||||||
|
struct lvmcache_info *info;
|
||||||
uint64_t sector;
|
uint64_t sector;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
char readbuf[LABEL_SCAN_SIZE];
|
char readbuf[LABEL_SCAN_SIZE];
|
||||||
|
|
||||||
if (!dev_open(dev)) {
|
if (!dev_open(dev)) {
|
||||||
stack;
|
stack;
|
||||||
|
|
||||||
|
if ((info = info_from_pvid(dev->pvid)))
|
||||||
|
lvmcache_update_vgname(info, ORPHAN);
|
||||||
|
|
||||||
return NULL;
|
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:
|
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))
|
if (!dev_close(dev))
|
||||||
stack;
|
stack;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ static int _test = 0;
|
|||||||
static int _partial = 0;
|
static int _partial = 0;
|
||||||
static int _md_filtering = 0;
|
static int _md_filtering = 0;
|
||||||
static int _pvmove = 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 _debug_level = 0;
|
||||||
static int _syslog = 0;
|
static int _syslog = 0;
|
||||||
static int _log_to_file = 0;
|
static int _log_to_file = 0;
|
||||||
@ -149,6 +150,11 @@ void init_pvmove(int level)
|
|||||||
_pvmove = level;
|
_pvmove = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init_full_scan_done(int level)
|
||||||
|
{
|
||||||
|
_full_scan_done = level;
|
||||||
|
}
|
||||||
|
|
||||||
void init_ignorelockingfailure(int level)
|
void init_ignorelockingfailure(int level)
|
||||||
{
|
{
|
||||||
_ignorelockingfailure = level;
|
_ignorelockingfailure = level;
|
||||||
@ -203,6 +209,11 @@ int pvmove_mode()
|
|||||||
return _pvmove;
|
return _pvmove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int full_scan_done()
|
||||||
|
{
|
||||||
|
return _full_scan_done;
|
||||||
|
}
|
||||||
|
|
||||||
int ignorelockingfailure()
|
int ignorelockingfailure()
|
||||||
{
|
{
|
||||||
return _ignorelockingfailure;
|
return _ignorelockingfailure;
|
||||||
|
@ -65,6 +65,7 @@ void init_test(int level);
|
|||||||
void init_partial(int level);
|
void init_partial(int level);
|
||||||
void init_md_filtering(int level);
|
void init_md_filtering(int level);
|
||||||
void init_pvmove(int level);
|
void init_pvmove(int level);
|
||||||
|
void init_full_scan_done(int level);
|
||||||
void init_debug(int level);
|
void init_debug(int level);
|
||||||
void init_cmd_name(int status);
|
void init_cmd_name(int status);
|
||||||
void init_msg_prefix(const char *prefix);
|
void init_msg_prefix(const char *prefix);
|
||||||
@ -78,6 +79,7 @@ int test_mode(void);
|
|||||||
int partial_mode(void);
|
int partial_mode(void);
|
||||||
int md_filtering(void);
|
int md_filtering(void);
|
||||||
int pvmove_mode(void);
|
int pvmove_mode(void);
|
||||||
|
int full_scan_done(void);
|
||||||
int debug_level(void);
|
int debug_level(void);
|
||||||
int ignorelockingfailure(void);
|
int ignorelockingfailure(void);
|
||||||
int security_level(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) {
|
if (!correct_vg) {
|
||||||
stack;
|
inconsistent = 0;
|
||||||
return NULL;
|
|
||||||
|
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);
|
lvmcache_update_vg(correct_vg);
|
||||||
|
@ -753,6 +753,7 @@ static void _apply_settings(struct cmd_context *cmd)
|
|||||||
init_debug(cmd->current_settings.debug);
|
init_debug(cmd->current_settings.debug);
|
||||||
init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
|
init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
|
||||||
init_test(cmd->current_settings.test);
|
init_test(cmd->current_settings.test);
|
||||||
|
init_full_scan_done(0);
|
||||||
|
|
||||||
init_msg_prefix(cmd->default_settings.msg_prefix);
|
init_msg_prefix(cmd->default_settings.msg_prefix);
|
||||||
init_cmd_name(cmd->default_settings.cmd_name);
|
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) {
|
while (!finished) {
|
||||||
/* FIXME Also needed in vg/lvchange -ay? */
|
/* FIXME Also needed in vg/lvchange -ay? */
|
||||||
/* FIXME Use alarm for regular intervals instead */
|
/* FIXME Use alarm for regular intervals instead */
|
||||||
if (parms->interval && !parms->aborting)
|
if (parms->interval && !parms->aborting) {
|
||||||
sleep(parms->interval);
|
sleep(parms->interval);
|
||||||
|
/* Devices might have changed while we slept */
|
||||||
|
init_full_scan_done(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Locks the (possibly renamed) VG again */
|
/* Locks the (possibly renamed) VG again */
|
||||||
if (!(vg = parms->poll_fns->get_copy_vg(cmd, name))) {
|
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? */
|
/* Is there an md superblock here? */
|
||||||
if (!dev && md_filtering()) {
|
if (!dev && md_filtering()) {
|
||||||
unlock_vg(cmd, "");
|
unlock_vg(cmd, "");
|
||||||
log_verbose("Wiping cache of LVM-capable devices");
|
|
||||||
persistent_filter_wipe(cmd->filter);
|
persistent_filter_wipe(cmd->filter);
|
||||||
log_verbose("Wiping internal cache");
|
|
||||||
lvmcache_destroy();
|
lvmcache_destroy();
|
||||||
|
|
||||||
init_md_filtering(0);
|
init_md_filtering(0);
|
||||||
if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
|
if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
|
||||||
log_error("Can't get lock for orphan PVs");
|
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) ?
|
arg_count(cmd, exported_ARG) ?
|
||||||
"of exported volume group(s)" : "in no volume group");
|
"of exported volume group(s)" : "in no volume group");
|
||||||
|
|
||||||
log_verbose("Wiping cache of LVM-capable devices");
|
|
||||||
persistent_filter_wipe(cmd->filter);
|
persistent_filter_wipe(cmd->filter);
|
||||||
|
|
||||||
log_verbose("Wiping internal cache");
|
|
||||||
lvmcache_destroy();
|
lvmcache_destroy();
|
||||||
|
|
||||||
log_verbose("Walking through all physical volumes");
|
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;
|
return EINVALID_CMD_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose("Wiping cache of LVM-capable devices");
|
|
||||||
persistent_filter_wipe(cmd->filter);
|
persistent_filter_wipe(cmd->filter);
|
||||||
|
|
||||||
log_verbose("Wiping internal cache");
|
|
||||||
lvmcache_destroy();
|
lvmcache_destroy();
|
||||||
|
|
||||||
log_print("Reading all physical volumes. This may take a while...");
|
log_print("Reading all physical volumes. This may take a while...");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user