mirror of
git://sourceware.org/git/lvm2.git
synced 2025-02-10 17:57:54 +03:00
Merge branch 'master' of git+ssh://sourceware.org/git/lvm2
This commit is contained in:
commit
3b02b35c3e
2
lib/cache/lvmcache.c
vendored
2
lib/cache/lvmcache.c
vendored
@ -1320,7 +1320,7 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const
|
||||
/* FIXME: should we also rescan unused_duplicate_devs for devs
|
||||
being rescanned here and then repeat resolving the duplicates? */
|
||||
|
||||
label_scan_devs(cmd, &devs);
|
||||
label_scan_devs(cmd, cmd->filter, &devs);
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
|
||||
log_warn("VG info not found after rescan of %s", vgname);
|
||||
|
2
lib/cache/lvmetad.c
vendored
2
lib/cache/lvmetad.c
vendored
@ -1878,7 +1878,7 @@ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct v
|
||||
*/
|
||||
log_debug_lvmetad("Rescan VG %s scanning data from devs in previous metadata.", vg->name);
|
||||
|
||||
label_scan_devs(cmd, &pvs_scan);
|
||||
label_scan_devs(cmd, cmd->full_filter, &pvs_scan);
|
||||
|
||||
/*
|
||||
* Check if any pvs_scan entries are no longer PVs.
|
||||
|
@ -1144,7 +1144,7 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
|
||||
/* md component filter. Optional, non-critical. */
|
||||
if (find_config_tree_bool(cmd, devices_md_component_detection_CFG, NULL)) {
|
||||
init_md_filtering(1);
|
||||
if ((filters[nr_filt] = md_filter_create(cmd->dev_types)))
|
||||
if ((filters[nr_filt] = md_filter_create(cmd, cmd->dev_types)))
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,7 @@ struct cmd_context {
|
||||
unsigned pvscan_cache_single:1;
|
||||
unsigned can_use_one_scan:1;
|
||||
unsigned is_clvmd:1;
|
||||
unsigned use_full_md_check:1;
|
||||
|
||||
/*
|
||||
* Filtering.
|
||||
|
@ -1378,6 +1378,7 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||
struct stat buf;
|
||||
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
int info_available = 0;
|
||||
int ret = 1;
|
||||
|
||||
if (d && (d->flags & DEV_REGULAR))
|
||||
return d;
|
||||
@ -1405,10 +1406,25 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||
}
|
||||
}
|
||||
|
||||
if (!d || (f && !(d->flags & DEV_REGULAR) && !(f->passes_filter(f, d))))
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
if (d && (d->flags & DEV_REGULAR))
|
||||
return d;
|
||||
|
||||
if (f && !(d->flags & DEV_REGULAR)) {
|
||||
ret = f->passes_filter(f, d);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("get device by name defer filter %s", dev_name(d));
|
||||
d->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (f && !(d->flags & DEV_REGULAR) && !ret)
|
||||
return NULL;
|
||||
|
||||
log_debug_devs("%s: Using device (%d:%d)", dev_name(d), (int) MAJOR(d->dev), (int) MINOR(d->dev));
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -1435,6 +1451,7 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
|
||||
const char *sysfs_dir;
|
||||
struct stat info;
|
||||
struct device *d = _dev_cache_seek_devt(dev);
|
||||
int ret;
|
||||
|
||||
if (d && (d->flags & DEV_REGULAR))
|
||||
return d;
|
||||
@ -1450,8 +1467,8 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
|
||||
}
|
||||
|
||||
if (lstat(path, &info)) {
|
||||
log_debug("No sysfs entry for %d:%d.",
|
||||
(int)MAJOR(dev), (int)MINOR(dev));
|
||||
log_debug("No sysfs entry for %d:%d errno %d at %s.",
|
||||
(int)MAJOR(dev), (int)MINOR(dev), errno, path);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -1460,8 +1477,27 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
|
||||
d = _dev_cache_seek_devt(dev);
|
||||
}
|
||||
|
||||
return (d && (!f || (d->flags & DEV_REGULAR) ||
|
||||
f->passes_filter(f, d))) ? d : NULL;
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
if (d->flags & DEV_REGULAR)
|
||||
return d;
|
||||
|
||||
if (!f)
|
||||
return d;
|
||||
|
||||
ret = f->passes_filter(f, d);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("get device by number defer filter %s", dev_name(d));
|
||||
d->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return d;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dev_iter *dev_iter_create(struct dev_filter *f, int unused)
|
||||
@ -1497,13 +1533,27 @@ static struct device *_iter_next(struct dev_iter *iter)
|
||||
|
||||
struct device *dev_iter_get(struct dev_iter *iter)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
int ret;
|
||||
|
||||
while (iter->current) {
|
||||
struct device *d = _iter_next(iter);
|
||||
if (!iter->filter || (d->flags & DEV_REGULAR) ||
|
||||
iter->filter->passes_filter(iter->filter, d)) {
|
||||
log_debug_devs("%s: Using device (%d:%d)", dev_name(d), (int) MAJOR(d->dev), (int) MINOR(d->dev));
|
||||
return d;
|
||||
ret = 1;
|
||||
|
||||
f = iter->filter;
|
||||
|
||||
if (f && !(d->flags & DEV_REGULAR)) {
|
||||
ret = f->passes_filter(f, d);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("get device by iter defer filter %s", dev_name(d));
|
||||
d->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f || (d->flags & DEV_REGULAR) || ret)
|
||||
return d;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -358,11 +358,11 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
|
||||
dev->size = *size;
|
||||
dev->size_seqno = _dev_size_seqno;
|
||||
|
||||
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||
|
||||
if (do_close && !dev_close(dev))
|
||||
log_sys_error("close", name);
|
||||
|
||||
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -18,27 +18,22 @@
|
||||
#define LUKS_SIGNATURE "LUKS\xba\xbe"
|
||||
#define LUKS_SIGNATURE_SIZE 6
|
||||
|
||||
int dev_is_luks(struct device *dev, uint64_t *offset_found)
|
||||
int dev_is_luks(struct device *dev, uint64_t *offset_found, int full)
|
||||
{
|
||||
char buf[LUKS_SIGNATURE_SIZE];
|
||||
int ret = -1;
|
||||
|
||||
if (!dev_open_readonly(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
if (!scan_bcache)
|
||||
return -EAGAIN;
|
||||
|
||||
if (offset_found)
|
||||
*offset_found = 0;
|
||||
|
||||
if (!dev_read(dev, 0, LUKS_SIGNATURE_SIZE, DEV_IO_SIGNATURES, buf))
|
||||
if (!dev_read_bytes(dev, 0, LUKS_SIGNATURE_SIZE, buf))
|
||||
goto_out;
|
||||
|
||||
ret = memcmp(buf, LUKS_SIGNATURE, LUKS_SIGNATURE_SIZE) ? 0 : 1;
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -37,9 +37,12 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
|
||||
uint32_t md_magic;
|
||||
|
||||
/* Version 1 is little endian; version 0.90.0 is machine endian */
|
||||
if (dev_read(dev, sb_offset, sizeof(uint32_t), DEV_IO_SIGNATURES, &md_magic) &&
|
||||
((md_magic == MD_SB_MAGIC) ||
|
||||
((MD_SB_MAGIC != xlate32(MD_SB_MAGIC)) && (md_magic == xlate32(MD_SB_MAGIC)))))
|
||||
|
||||
if (!dev_read_bytes(dev, sb_offset, sizeof(uint32_t), &md_magic))
|
||||
return_0;
|
||||
|
||||
if ((md_magic == MD_SB_MAGIC) ||
|
||||
((MD_SB_MAGIC != xlate32(MD_SB_MAGIC)) && (md_magic == xlate32(MD_SB_MAGIC))))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@ -109,11 +112,14 @@ static int _udev_dev_is_md(struct device *dev)
|
||||
/*
|
||||
* Returns -1 on error
|
||||
*/
|
||||
static int _native_dev_is_md(struct device *dev, uint64_t *offset_found)
|
||||
static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int full)
|
||||
{
|
||||
int ret = 1;
|
||||
md_minor_version_t minor;
|
||||
uint64_t size, sb_offset;
|
||||
int ret;
|
||||
|
||||
if (!scan_bcache)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
@ -123,38 +129,67 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found)
|
||||
if (size < MD_RESERVED_SECTORS * 2)
|
||||
return 0;
|
||||
|
||||
if (!dev_open_readonly(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
/*
|
||||
* Old md versions locate the magic number at the end of the device.
|
||||
* Those checks can't be satisfied with the initial bcache data, and
|
||||
* would require an extra read i/o at the end of every device. Issuing
|
||||
* an extra read to every device in every command, just to check for
|
||||
* the old md format is a bad tradeoff. It's also not a big issue if
|
||||
* one happens to exist and we don't filter it out.
|
||||
*
|
||||
* When "full" is set, we check a the start and end of the device for
|
||||
* md magic numbers. When "full" is not set, we only check at the
|
||||
* start of the device for the magic numbers. We decide for each
|
||||
* command if it should do a full check (cmd->use_full_md_check),
|
||||
* and set it for commands that could possibly write to an md dev
|
||||
* (pvcreate/vgcreate/vgextend).
|
||||
*/
|
||||
if (!full) {
|
||||
sb_offset = 0;
|
||||
if (_dev_has_md_magic(dev, sb_offset)) {
|
||||
log_debug_devs("Found md magic number at offset 0 of %s.", dev_name(dev));
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sb_offset = 8 << SECTOR_SHIFT;
|
||||
if (_dev_has_md_magic(dev, sb_offset)) {
|
||||
log_debug_devs("Found md magic number at offset %d of %s.", (int)sb_offset, dev_name(dev));
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check if it is an md component device. */
|
||||
/* Version 0.90.0 */
|
||||
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
|
||||
if (_dev_has_md_magic(dev, sb_offset))
|
||||
if (_dev_has_md_magic(dev, sb_offset)) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
minor = MD_MINOR_VERSION_MIN;
|
||||
/* Version 1, try v1.0 -> v1.2 */
|
||||
do {
|
||||
sb_offset = _v1_sb_offset(size, minor);
|
||||
if (_dev_has_md_magic(dev, sb_offset))
|
||||
if (_dev_has_md_magic(dev, sb_offset)) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
} while (++minor <= MD_MINOR_VERSION_MAX);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
if (ret && offset_found)
|
||||
*offset_found = sb_offset;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dev_is_md(struct device *dev, uint64_t *offset_found)
|
||||
int dev_is_md(struct device *dev, uint64_t *offset_found, int full)
|
||||
{
|
||||
|
||||
/*
|
||||
@ -163,7 +198,7 @@ int dev_is_md(struct device *dev, uint64_t *offset_found)
|
||||
* information is not in udev db.
|
||||
*/
|
||||
if ((dev->ext.src == DEV_EXT_NONE) || offset_found)
|
||||
return _native_dev_is_md(dev, offset_found);
|
||||
return _native_dev_is_md(dev, offset_found, full);
|
||||
|
||||
if (dev->ext.src == DEV_EXT_UDEV)
|
||||
return _udev_dev_is_md(dev);
|
||||
|
@ -35,19 +35,17 @@ static int _swap_detect_signature(const char *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_is_swap(struct device *dev, uint64_t *offset_found)
|
||||
int dev_is_swap(struct device *dev, uint64_t *offset_found, int full)
|
||||
{
|
||||
char buf[10];
|
||||
uint64_t size;
|
||||
unsigned page;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
if (!scan_bcache)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!dev_open_readonly(dev)) {
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
@ -60,8 +58,7 @@ int dev_is_swap(struct device *dev, uint64_t *offset_found)
|
||||
continue;
|
||||
if (size < (page >> SECTOR_SHIFT))
|
||||
break;
|
||||
if (!dev_read(dev, page - SIGNATURE_SIZE,
|
||||
SIGNATURE_SIZE, DEV_IO_SIGNATURES, buf)) {
|
||||
if (!dev_read_bytes(dev, page - SIGNATURE_SIZE, SIGNATURE_SIZE, buf)) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
@ -73,9 +70,6 @@ int dev_is_swap(struct device *dev, uint64_t *offset_found)
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ static int _has_partition_table(struct device *dev)
|
||||
uint16_t magic;
|
||||
} __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
|
||||
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(buf), DEV_IO_SIGNATURES, &buf))
|
||||
if (!dev_read_bytes(dev, UINT64_C(0), sizeof(buf), &buf))
|
||||
return_0;
|
||||
|
||||
/* FIXME Check for other types of partition table too */
|
||||
@ -434,6 +434,9 @@ static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!scan_bcache)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!_is_partitionable(dt, dev))
|
||||
return 0;
|
||||
|
||||
@ -441,17 +444,8 @@ static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
|
||||
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
|
||||
return 1;
|
||||
|
||||
if (!dev_open_readonly_quiet(dev)) {
|
||||
log_debug_devs("%s: failed to open device, considering device "
|
||||
"is partitioned", dev_name(dev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = _has_partition_table(dev);
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -750,12 +744,12 @@ out:
|
||||
|
||||
static int _wipe_signature(struct device *dev, const char *type, const char *name,
|
||||
int wipe_len, int yes, force_t force, int *wiped,
|
||||
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found))
|
||||
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found, int full))
|
||||
{
|
||||
int wipe;
|
||||
uint64_t offset_found;
|
||||
|
||||
wipe = signature_detection_fn(dev, &offset_found);
|
||||
wipe = signature_detection_fn(dev, &offset_found, 1);
|
||||
if (wipe == -1) {
|
||||
log_error("Fatal error while trying to detect %s on %s.",
|
||||
type, name);
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "device.h"
|
||||
#include "display.h"
|
||||
#include "label.h"
|
||||
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
@ -56,9 +57,9 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
|
||||
int major_is_scsi_device(struct dev_types *dt, int major);
|
||||
|
||||
/* Signature/superblock recognition with position returned where found. */
|
||||
int dev_is_md(struct device *dev, uint64_t *sb);
|
||||
int dev_is_swap(struct device *dev, uint64_t *signature);
|
||||
int dev_is_luks(struct device *dev, uint64_t *signature);
|
||||
int dev_is_md(struct device *dev, uint64_t *sb, int full);
|
||||
int dev_is_swap(struct device *dev, uint64_t *signature, int full);
|
||||
int dev_is_luks(struct device *dev, uint64_t *signature, int full);
|
||||
int dasd_is_cdl_formatted(struct device *dev);
|
||||
int udev_dev_is_mpath_component(struct device *dev);
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
#define DEV_NOT_O_NOATIME 0x00000400 /* Don't use O_NOATIME */
|
||||
#define DEV_IN_BCACHE 0x00000800 /* dev fd is open and used in bcache */
|
||||
#define DEV_BCACHE_EXCL 0x00001000 /* bcache_fd should be open EXCL */
|
||||
#define DEV_FILTER_AFTER_SCAN 0x00002000 /* apply filter after bcache has data */
|
||||
#define DEV_FILTER_OUT_SCAN 0x00004000 /* filtered out during label scan */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
|
@ -15,14 +15,19 @@
|
||||
|
||||
#include "lib.h"
|
||||
#include "filter.h"
|
||||
#include "device.h"
|
||||
|
||||
static int _and_p(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
struct dev_filter **filters;
|
||||
int ret;
|
||||
|
||||
for (filters = (struct dev_filter **) f->private; *filters; ++filters)
|
||||
if (!(*filters)->passes_filter(*filters, dev))
|
||||
for (filters = (struct dev_filter **) f->private; *filters; ++filters) {
|
||||
ret = (*filters)->passes_filter(*filters, dev);
|
||||
|
||||
if (!ret)
|
||||
return 0; /* No 'stack': a filter, not an error. */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -20,15 +20,21 @@
|
||||
|
||||
#define MSG_SKIPPING "%s: Skipping md component device"
|
||||
|
||||
static int _ignore_md(struct dev_filter *f __attribute__((unused)),
|
||||
struct device *dev)
|
||||
static int _ignore_md(struct device *dev, int full)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!md_filtering())
|
||||
return 1;
|
||||
|
||||
ret = dev_is_md(dev, NULL);
|
||||
ret = dev_is_md(dev, NULL, full);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* let pass, call again after scan */
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
log_debug_devs("filter md deferred %s", dev_name(dev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
if (dev->ext.src == DEV_EXT_NONE)
|
||||
@ -48,6 +54,18 @@ static int _ignore_md(struct dev_filter *f __attribute__((unused)),
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _ignore_md_lite(struct dev_filter *f __attribute__((unused)),
|
||||
struct device *dev)
|
||||
{
|
||||
return _ignore_md(dev, 0);
|
||||
}
|
||||
|
||||
static int _ignore_md_full(struct dev_filter *f __attribute__((unused)),
|
||||
struct device *dev)
|
||||
{
|
||||
return _ignore_md(dev, 1);
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
if (f->use_count)
|
||||
@ -56,7 +74,7 @@ static void _destroy(struct dev_filter *f)
|
||||
dm_free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *md_filter_create(struct dev_types *dt)
|
||||
struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *dt)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
@ -65,7 +83,18 @@ struct dev_filter *md_filter_create(struct dev_types *dt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _ignore_md;
|
||||
/*
|
||||
* FIXME: for commands that want a full md check (pvcreate, vgcreate,
|
||||
* vgextend), we do an extra read at the end of every device that the
|
||||
* filter looks at. This isn't necessary; we only need to do the full
|
||||
* md check on the PVs that these commands are trying to use.
|
||||
*/
|
||||
|
||||
if (cmd->use_full_md_check)
|
||||
f->passes_filter = _ignore_md_full;
|
||||
else
|
||||
f->passes_filter = _ignore_md_lite;
|
||||
|
||||
f->destroy = _destroy;
|
||||
f->use_count = 0;
|
||||
f->private = dt;
|
||||
|
@ -21,8 +21,18 @@
|
||||
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
struct dev_types *dt = (struct dev_types *) f->private;
|
||||
int ret;
|
||||
|
||||
if (dev_is_partitioned(dt, dev)) {
|
||||
ret = dev_is_partitioned(dt, dev);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* let pass, call again after scan */
|
||||
log_debug_devs("filter partitioned deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (dev->ext.src == DEV_EXT_NONE)
|
||||
log_debug_devs(MSG_SKIPPING, dev_name(dev));
|
||||
else
|
||||
|
@ -26,6 +26,30 @@ struct pfilter {
|
||||
struct dev_types *dt;
|
||||
};
|
||||
|
||||
/*
|
||||
* The persistent filter is filter layer that sits above the other filters and
|
||||
* caches the final result of those other filters. When a device is first
|
||||
* checked against filters, it will not be in this cache, so this filter will
|
||||
* pass the device down to the other filters to check it. The other filters
|
||||
* will run and either include the device (good/pass) or exclude the device
|
||||
* (bad/fail). That good or bad result propagates up through this filter which
|
||||
* saves the result. The next time some code checks the filters against the
|
||||
* device, this persistent/cache filter is checked first. This filter finds
|
||||
* the previous result in its cache and returns it without reevaluating the
|
||||
* other real filters.
|
||||
*
|
||||
* FIXME: a cache like this should not be needed. The fact it's needed is a
|
||||
* symptom of code that should be fixed to not reevaluate filters multiple
|
||||
* times. A device should be checked against the filter once, and then not
|
||||
* need to be checked again. With scanning now controlled, we could probably
|
||||
* do this.
|
||||
*
|
||||
* FIXME: "persistent" isn't a great name for this caching filter. This filter
|
||||
* at one time saved its cache results to a file, which is how it got the name.
|
||||
* That .cache file does not work well, causes problems, and is no longer used
|
||||
* by default. The old code for it should be removed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The hash table holds one of these two states
|
||||
* against each entry.
|
||||
@ -264,27 +288,51 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
void *l = dm_hash_lookup(pf->devices, dev_name(dev));
|
||||
struct dm_str_list *sl;
|
||||
int pass = 1;
|
||||
|
||||
/* Cached BAD? */
|
||||
/* Cached bad, skip dev */
|
||||
if (l == PF_BAD_DEVICE) {
|
||||
log_debug_devs("%s: Skipping (cached)", dev_name(dev));
|
||||
log_debug_devs("%s: filter cache skipping (cached bad)", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test dm devices every time, so cache them as GOOD. */
|
||||
if (MAJOR(dev->dev) == pf->dt->device_mapper_major) {
|
||||
if (!l)
|
||||
dm_list_iterate_items(sl, &dev->aliases)
|
||||
if (!dm_hash_insert(pf->devices, sl->str, PF_GOOD_DEVICE)) {
|
||||
log_error("Failed to hash device to filter.");
|
||||
return 0;
|
||||
}
|
||||
return pf->real->passes_filter(pf->real, dev);
|
||||
/* Cached good, use dev */
|
||||
if (l == PF_GOOD_DEVICE) {
|
||||
log_debug_devs("%s: filter cache using (cached good)", dev_name(dev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Uncached */
|
||||
/* Uncached, check filters and cache the result */
|
||||
if (!l) {
|
||||
l = pf->real->passes_filter(pf->real, dev) ? PF_GOOD_DEVICE : PF_BAD_DEVICE;
|
||||
dev->flags &= ~DEV_FILTER_AFTER_SCAN;
|
||||
|
||||
pass = pf->real->passes_filter(pf->real, dev);
|
||||
|
||||
if (!pass) {
|
||||
/*
|
||||
* A device that does not pass one filter is excluded
|
||||
* even if the result of another filter is deferred,
|
||||
* because the deferred result won't change the exclude.
|
||||
*/
|
||||
l = PF_BAD_DEVICE;
|
||||
|
||||
} else if ((pass == -EAGAIN) || (dev->flags & DEV_FILTER_AFTER_SCAN)) {
|
||||
/*
|
||||
* When the filter result is deferred, we let the device
|
||||
* pass for now, but do not cache the result. We need to
|
||||
* rerun the filters later. At that point the final result
|
||||
* will be cached.
|
||||
*/
|
||||
log_debug_devs("filter cache deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
pass = 1;
|
||||
goto out;
|
||||
|
||||
} else if (pass) {
|
||||
l = PF_GOOD_DEVICE;
|
||||
}
|
||||
|
||||
log_debug_devs("filter caching %s %s", pass ? "good" : "bad", dev_name(dev));
|
||||
|
||||
dm_list_iterate_items(sl, &dev->aliases)
|
||||
if (!dm_hash_insert(pf->devices, sl->str, l)) {
|
||||
@ -292,8 +340,8 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (l == PF_BAD_DEVICE) ? 0 : 1;
|
||||
out:
|
||||
return pass;
|
||||
}
|
||||
|
||||
static void _persistent_destroy(struct dev_filter *f)
|
||||
|
@ -26,14 +26,16 @@ static int _ignore_signature(struct dev_filter *f __attribute__((unused)),
|
||||
char buf[BUFSIZE];
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_open_readonly(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
if (!scan_bcache) {
|
||||
/* let pass, call again after scan */
|
||||
log_debug_devs("filter signature deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(buf, 0, BUFSIZE);
|
||||
|
||||
if (!dev_read(dev, 0, BUFSIZE, DEV_IO_SIGNATURES, buf)) {
|
||||
if (!dev_read_bytes(dev, 0, BUFSIZE, buf)) {
|
||||
log_debug_devs("%s: Skipping: error in signature detection",
|
||||
dev_name(dev));
|
||||
ret = 0;
|
||||
@ -54,8 +56,6 @@ static int _ignore_signature(struct dev_filter *f __attribute__((unused)),
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
dev_close(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -27,12 +27,6 @@ static int _native_check_pv_min_size(struct device *dev)
|
||||
uint64_t size;
|
||||
int ret = 0;
|
||||
|
||||
/* Check it's accessible */
|
||||
if (!dev_open_readonly_quiet(dev)) {
|
||||
log_debug_devs("%s: Skipping: open failed", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check it's not too small */
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
log_debug_devs("%s: Skipping: dev_get_size failed", dev_name(dev));
|
||||
@ -47,9 +41,6 @@ static int _native_check_pv_min_size(struct device *dev)
|
||||
|
||||
ret = 1;
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct dev_filter **filters);
|
||||
|
||||
struct dev_filter *lvm_type_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *md_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *dt);
|
||||
struct dev_filter *fwraid_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *mpath_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *partitioned_filter_create(struct dev_types *dt);
|
||||
|
@ -328,13 +328,44 @@ static struct labeller *_find_lvm_header(struct device *dev,
|
||||
* beyond the range of the scanned block, then additional reads
|
||||
* are performed in the processing functions to get that data.
|
||||
*/
|
||||
static int _process_block(struct device *dev, struct block *bb, int *is_lvm_device)
|
||||
static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
|
||||
struct device *dev, struct block *bb, int *is_lvm_device)
|
||||
{
|
||||
char label_buf[LABEL_SIZE] __attribute__((aligned(8)));
|
||||
struct label *label = NULL;
|
||||
struct labeller *labeller;
|
||||
uint64_t sector;
|
||||
int ret = 0;
|
||||
int pass;
|
||||
|
||||
/*
|
||||
* The device may have signatures that exclude it from being processed.
|
||||
* If filters were applied before bcache data was available, some
|
||||
* filters may have deferred their check until the point where bcache
|
||||
* data had been read (here). They set this flag to indicate that the
|
||||
* filters should be retested now that data from the device is ready.
|
||||
*/
|
||||
if (cmd && (dev->flags & DEV_FILTER_AFTER_SCAN)) {
|
||||
dev->flags &= ~DEV_FILTER_AFTER_SCAN;
|
||||
|
||||
log_debug_devs("Scan filtering %s", dev_name(dev));
|
||||
|
||||
pass = f->passes_filter(f, dev);
|
||||
|
||||
if ((pass == -EAGAIN) || (dev->flags & DEV_FILTER_AFTER_SCAN)) {
|
||||
/* Shouldn't happen */
|
||||
dev->flags &= ~DEV_FILTER_OUT_SCAN;
|
||||
log_debug_devs("Scan filter should not be deferred %s", dev_name(dev));
|
||||
pass = 1;
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
log_very_verbose("%s: Not processing filtered", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_OUT_SCAN;
|
||||
*is_lvm_device = 0;
|
||||
goto_out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the data sector containing the label and copies into label_buf.
|
||||
@ -460,7 +491,8 @@ static int _scan_dev_close(struct device *dev)
|
||||
* its info is removed from lvmcache.
|
||||
*/
|
||||
|
||||
static int _scan_list(struct dm_list *devs, int *failed)
|
||||
static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
struct dm_list *devs, int *failed)
|
||||
{
|
||||
struct dm_list wait_devs;
|
||||
struct dm_list done_devs;
|
||||
@ -471,6 +503,7 @@ static int _scan_list(struct dm_list *devs, int *failed)
|
||||
int scan_process_errors = 0;
|
||||
int scan_failed_count = 0;
|
||||
int rem_prefetches;
|
||||
int submit_count;
|
||||
int scan_failed;
|
||||
int is_lvm_device;
|
||||
int error;
|
||||
@ -483,6 +516,7 @@ static int _scan_list(struct dm_list *devs, int *failed)
|
||||
|
||||
scan_more:
|
||||
rem_prefetches = bcache_max_prefetches(scan_bcache);
|
||||
submit_count = 0;
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, devs) {
|
||||
|
||||
@ -510,11 +544,14 @@ static int _scan_list(struct dm_list *devs, int *failed)
|
||||
bcache_prefetch(scan_bcache, devl->dev->bcache_fd, 0);
|
||||
|
||||
rem_prefetches--;
|
||||
submit_count++;
|
||||
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(&wait_devs, &devl->list);
|
||||
}
|
||||
|
||||
log_debug_devs("Scanning submitted %d reads", submit_count);
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &wait_devs) {
|
||||
bb = NULL;
|
||||
error = 0;
|
||||
@ -530,7 +567,7 @@ static int _scan_list(struct dm_list *devs, int *failed)
|
||||
} else {
|
||||
log_debug_devs("Processing data from device %s fd %d block %p", dev_name(devl->dev), devl->dev->bcache_fd, bb);
|
||||
|
||||
ret = _process_block(devl->dev, bb, &is_lvm_device);
|
||||
ret = _process_block(cmd, f, devl->dev, bb, &is_lvm_device);
|
||||
|
||||
if (!ret && is_lvm_device) {
|
||||
log_debug_devs("Scan failed to process %s", dev_name(devl->dev));
|
||||
@ -666,7 +703,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
_scan_list(&all_devs, NULL);
|
||||
_scan_list(cmd, cmd->full_filter, &all_devs, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -679,7 +716,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
* without a lock.)
|
||||
*/
|
||||
|
||||
int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs)
|
||||
int label_scan_devs(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
@ -697,7 +734,7 @@ int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs)
|
||||
}
|
||||
}
|
||||
|
||||
_scan_list(devs, NULL);
|
||||
_scan_list(cmd, f, devs, NULL);
|
||||
|
||||
/* FIXME: this function should probably fail if any devs couldn't be scanned */
|
||||
|
||||
@ -721,7 +758,7 @@ int label_scan_devs_excl(struct dm_list *devs)
|
||||
devl->dev->flags |= DEV_BCACHE_EXCL;
|
||||
}
|
||||
|
||||
_scan_list(devs, &failed);
|
||||
_scan_list(NULL, NULL, devs, &failed);
|
||||
|
||||
if (failed)
|
||||
return 0;
|
||||
@ -750,7 +787,7 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv
|
||||
|
||||
lv_info(cmd, lv, 0, &lvinfo, 0, 0);
|
||||
devt = MKDEV(lvinfo.major, lvinfo.minor);
|
||||
if ((dev = dev_cache_get_by_devt(devt, cmd->filter)))
|
||||
if ((dev = dev_cache_get_by_devt(devt, NULL)))
|
||||
label_scan_invalidate(dev);
|
||||
}
|
||||
|
||||
@ -764,9 +801,8 @@ void label_scan_drop(struct cmd_context *cmd)
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
|
||||
if (!(iter = dev_iter_create(NULL, 0)))
|
||||
return;
|
||||
}
|
||||
|
||||
while ((dev = dev_iter_get(iter))) {
|
||||
if (_in_bcache(dev))
|
||||
@ -818,7 +854,7 @@ int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector
|
||||
_scan_dev_close(dev);
|
||||
}
|
||||
|
||||
_scan_list(&one_dev, &failed);
|
||||
_scan_list(NULL, NULL, &one_dev, &failed);
|
||||
|
||||
/*
|
||||
* FIXME: this ugliness of returning a pointer to the label is
|
||||
|
@ -103,7 +103,7 @@ void label_destroy(struct label *label);
|
||||
extern struct bcache *scan_bcache;
|
||||
|
||||
int label_scan(struct cmd_context *cmd);
|
||||
int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs);
|
||||
int label_scan_devs(struct cmd_context *cmd, struct dev_filter *f, struct dm_list *devs);
|
||||
int label_scan_devs_excl(struct dm_list *devs);
|
||||
void label_scan_invalidate(struct device *dev);
|
||||
void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
|
||||
|
@ -723,7 +723,7 @@ int pv_resize_single(struct cmd_context *cmd,
|
||||
const uint64_t new_size,
|
||||
int yes);
|
||||
|
||||
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
|
||||
int pv_analyze(struct cmd_context *cmd, struct device *dev,
|
||||
uint64_t label_sector);
|
||||
|
||||
/* FIXME: move internal to library */
|
||||
|
@ -5059,30 +5059,19 @@ static int _analyze_mda(struct metadata_area *mda, void *baton)
|
||||
* 0 - fail
|
||||
* 1 - success
|
||||
*/
|
||||
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
|
||||
int pv_analyze(struct cmd_context *cmd, struct device *dev,
|
||||
uint64_t label_sector)
|
||||
{
|
||||
struct label *label;
|
||||
struct device *dev;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
dev = dev_cache_get(pv_name, cmd->filter);
|
||||
if (!dev) {
|
||||
log_error("Device %s %s.", pv_name, dev_cache_filtered_reason(pv_name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* First, scan for LVM labels.
|
||||
*/
|
||||
if (!label_read(dev, &label, label_sector)) {
|
||||
log_error("Could not find LVM label on %s",
|
||||
pv_name);
|
||||
if (!(label = lvmcache_get_dev_label(dev))) {
|
||||
log_error("Could not find LVM label on %s", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Found label on %s, sector %"PRIu64", type=%.8s",
|
||||
pv_name, label->sector, label->type);
|
||||
dev_name(dev), label->sector, label->type);
|
||||
|
||||
/*
|
||||
* Next, loop through metadata areas
|
||||
|
@ -297,16 +297,17 @@ static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_quiet(dev))
|
||||
return 0;
|
||||
|
||||
if (!dev_write(dev, UINT64_C(0), sizeof(log_header), DEV_IO_LV, &log_header)) {
|
||||
log_error("Failed to write log header to %s.", name);
|
||||
dev_close_immediate(dev);
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Failed to open %s/%s to write log header.", lv->vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_close_immediate(dev);
|
||||
if (!dev_write_bytes(dev, UINT64_C(0), sizeof(log_header), &log_header)) {
|
||||
log_error("Failed to write log header to %s.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
label_scan_invalidate(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -97,6 +97,9 @@ int lvmdiskscan(struct cmd_context *cmd, int argc __attribute__((unused)),
|
||||
if (arg_is_set(cmd, lvmpartition_ARG))
|
||||
log_warn("WARNING: only considering LVM devices");
|
||||
|
||||
/* Call before using dev_iter which uses filters which want bcache data. */
|
||||
label_scan(cmd);
|
||||
|
||||
max_len = _get_max_dev_name_len(cmd->full_filter);
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
|
||||
@ -104,8 +107,6 @@ int lvmdiskscan(struct cmd_context *cmd, int argc __attribute__((unused)),
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
label_scan(cmd);
|
||||
|
||||
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
||||
if (lvmcache_has_dev_info(dev)) {
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
|
48
tools/pvck.c
48
tools/pvck.c
@ -17,27 +17,51 @@
|
||||
|
||||
int pvck(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct dm_list devs;
|
||||
struct device_list *devl;
|
||||
struct device *dev;
|
||||
const char *pv_name;
|
||||
uint64_t labelsector;
|
||||
int i;
|
||||
int ret_max = ECMD_PROCESSED;
|
||||
|
||||
/* FIXME: validate cmdline options */
|
||||
/* FIXME: what does the cmdline look like? */
|
||||
|
||||
label_scan_setup_bcache();
|
||||
labelsector = arg_uint64_value(cmd, labelsector_ARG, UINT64_C(0));
|
||||
|
||||
if (labelsector) {
|
||||
/* FIXME: see label_read_sector */
|
||||
log_error("TODO: reading label from non-zero sector");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
dm_list_init(&devs);
|
||||
|
||||
/*
|
||||
* Use what's on the cmdline directly, and avoid calling into
|
||||
* some of the other infrastructure functions, so as to avoid
|
||||
* hitting some of the lvmcache behavior, scanning other devices,
|
||||
* etc.
|
||||
*/
|
||||
for (i = 0; i < argc; i++) {
|
||||
/* FIXME: warning and/or check if in use? */
|
||||
log_verbose("Scanning %s", argv[i]);
|
||||
|
||||
dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
|
||||
if (!pv_analyze(cmd, argv[i],
|
||||
arg_uint64_value(cmd, labelsector_ARG, UINT64_C(0)))) {
|
||||
|
||||
pv_name = argv[i];
|
||||
|
||||
dev = dev_cache_get(pv_name, cmd->filter);
|
||||
|
||||
if (!dev) {
|
||||
log_error("Device %s %s.", pv_name, dev_cache_filtered_reason(pv_name));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(devl = dm_zalloc(sizeof(*devl))))
|
||||
continue;
|
||||
|
||||
devl->dev = dev;
|
||||
dm_list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
label_scan_setup_bcache();
|
||||
label_scan_devs(cmd, cmd->filter, &devs);
|
||||
|
||||
dm_list_iterate_items(devl, &devs) {
|
||||
if (!pv_analyze(cmd, devl->dev, labelsector)) {
|
||||
stack;
|
||||
ret_max = ECMD_FAILED;
|
||||
}
|
||||
|
@ -147,6 +147,9 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
pp.pv_count = argc;
|
||||
pp.pv_names = argv;
|
||||
|
||||
/* Check for old md signatures at the end of devices. */
|
||||
cmd->use_full_md_check = 1;
|
||||
|
||||
/*
|
||||
* Needed to change the set of orphan PVs.
|
||||
* (disable afterward to prevent process_each_pv from doing
|
||||
|
@ -439,6 +439,9 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
||||
cmd->pvscan_cache_single = 1;
|
||||
}
|
||||
|
||||
/* Creates a list of dev names from /dev, sysfs, etc; does not read any. */
|
||||
dev_cache_scan();
|
||||
|
||||
dm_list_init(&single_devs);
|
||||
|
||||
while (argc--) {
|
||||
@ -455,7 +458,11 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
||||
ret = ECMD_FAILED;
|
||||
}
|
||||
} else {
|
||||
/* Add device path to lvmetad. */
|
||||
/*
|
||||
* Scan device. This dev could still be
|
||||
* removed from lvmetad below if it doesn't
|
||||
* pass other filters.
|
||||
*/
|
||||
log_debug("Scanning dev %s for lvmetad cache.", pv_name);
|
||||
|
||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
||||
@ -476,7 +483,11 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
||||
if (!_lvmetad_clear_dev(devno, major, minor))
|
||||
remove_errors++;
|
||||
} else {
|
||||
/* Add major:minor to lvmetad. */
|
||||
/*
|
||||
* Scan device. This dev could still be
|
||||
* removed from lvmetad below if it doesn't
|
||||
* pass other filters.
|
||||
*/
|
||||
log_debug("Scanning dev %d:%d for lvmetad cache.", major, minor);
|
||||
|
||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
||||
@ -493,11 +504,23 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!dm_list_empty(&single_devs)) {
|
||||
dev_cache_scan();
|
||||
label_scan_devs(cmd, &single_devs);
|
||||
label_scan_devs(cmd, cmd->lvmetad_filter, &single_devs);
|
||||
|
||||
dm_list_iterate_items(devl, &single_devs) {
|
||||
if (!lvmetad_pvscan_single(cmd, devl->dev, &found_vgnames, &pp.changed_vgnames))
|
||||
dev = devl->dev;
|
||||
|
||||
if (dev->flags & DEV_FILTER_OUT_SCAN) {
|
||||
log_debug("Removing dev %s from lvmetad cache after scan.", dev_name(dev));
|
||||
if (!_lvmetad_clear_dev(dev->dev, MAJOR(dev->dev), MINOR(dev->dev)))
|
||||
remove_errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Devices that exist and pass the lvmetad filter
|
||||
* are added to lvmetad.
|
||||
*/
|
||||
if (!lvmetad_pvscan_single(cmd, dev, &found_vgnames, &pp.changed_vgnames))
|
||||
add_errors++;
|
||||
}
|
||||
}
|
||||
@ -539,10 +562,22 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!dm_list_empty(&single_devs)) {
|
||||
dev_cache_scan();
|
||||
label_scan_devs(cmd, &single_devs);
|
||||
label_scan_devs(cmd, cmd->lvmetad_filter, &single_devs);
|
||||
|
||||
dm_list_iterate_items(devl, &single_devs) {
|
||||
dev = devl->dev;
|
||||
|
||||
if (dev->flags & DEV_FILTER_OUT_SCAN) {
|
||||
log_debug("Removing dev %s from lvmetad cache after scan.", dev_name(dev));
|
||||
if (!_lvmetad_clear_dev(dev->dev, MAJOR(dev->dev), MINOR(dev->dev)))
|
||||
remove_errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Devices that exist and pass the lvmetad filter
|
||||
* are added to lvmetad.
|
||||
*/
|
||||
if (!lvmetad_pvscan_single(cmd, devl->dev, &found_vgnames, &pp.changed_vgnames))
|
||||
add_errors++;
|
||||
}
|
||||
|
@ -65,6 +65,9 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
return_ECMD_FAILED;
|
||||
cmd->lockd_gl_disable = 1;
|
||||