mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-11 20:58:50 +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
|
/* FIXME: should we also rescan unused_duplicate_devs for devs
|
||||||
being rescanned here and then repeat resolving the duplicates? */
|
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))) {
|
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
|
||||||
log_warn("VG info not found after rescan of %s", vgname);
|
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);
|
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.
|
* 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. */
|
/* md component filter. Optional, non-critical. */
|
||||||
if (find_config_tree_bool(cmd, devices_md_component_detection_CFG, NULL)) {
|
if (find_config_tree_bool(cmd, devices_md_component_detection_CFG, NULL)) {
|
||||||
init_md_filtering(1);
|
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++;
|
nr_filt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,7 @@ struct cmd_context {
|
|||||||
unsigned pvscan_cache_single:1;
|
unsigned pvscan_cache_single:1;
|
||||||
unsigned can_use_one_scan:1;
|
unsigned can_use_one_scan:1;
|
||||||
unsigned is_clvmd:1;
|
unsigned is_clvmd:1;
|
||||||
|
unsigned use_full_md_check:1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Filtering.
|
* Filtering.
|
||||||
|
@ -1378,6 +1378,7 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
|||||||
struct stat buf;
|
struct stat buf;
|
||||||
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
|
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||||
int info_available = 0;
|
int info_available = 0;
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
if (d && (d->flags & DEV_REGULAR))
|
if (d && (d->flags & DEV_REGULAR))
|
||||||
return d;
|
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;
|
return NULL;
|
||||||
|
|
||||||
log_debug_devs("%s: Using device (%d:%d)", dev_name(d), (int) MAJOR(d->dev), (int) MINOR(d->dev));
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1435,6 +1451,7 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
|
|||||||
const char *sysfs_dir;
|
const char *sysfs_dir;
|
||||||
struct stat info;
|
struct stat info;
|
||||||
struct device *d = _dev_cache_seek_devt(dev);
|
struct device *d = _dev_cache_seek_devt(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (d && (d->flags & DEV_REGULAR))
|
if (d && (d->flags & DEV_REGULAR))
|
||||||
return d;
|
return d;
|
||||||
@ -1450,8 +1467,8 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lstat(path, &info)) {
|
if (lstat(path, &info)) {
|
||||||
log_debug("No sysfs entry for %d:%d.",
|
log_debug("No sysfs entry for %d:%d errno %d at %s.",
|
||||||
(int)MAJOR(dev), (int)MINOR(dev));
|
(int)MAJOR(dev), (int)MINOR(dev), errno, path);
|
||||||
return NULL;
|
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);
|
d = _dev_cache_seek_devt(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (d && (!f || (d->flags & DEV_REGULAR) ||
|
if (!d)
|
||||||
f->passes_filter(f, d))) ? d : NULL;
|
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)
|
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 device *dev_iter_get(struct dev_iter *iter)
|
||||||
{
|
{
|
||||||
|
struct dev_filter *f;
|
||||||
|
int ret;
|
||||||
|
|
||||||
while (iter->current) {
|
while (iter->current) {
|
||||||
struct device *d = _iter_next(iter);
|
struct device *d = _iter_next(iter);
|
||||||
if (!iter->filter || (d->flags & DEV_REGULAR) ||
|
ret = 1;
|
||||||
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));
|
f = iter->filter;
|
||||||
return d;
|
|
||||||
|
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;
|
return NULL;
|
||||||
|
@ -358,11 +358,11 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
|
|||||||
dev->size = *size;
|
dev->size = *size;
|
||||||
dev->size_seqno = _dev_size_seqno;
|
dev->size_seqno = _dev_size_seqno;
|
||||||
|
|
||||||
|
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||||
|
|
||||||
if (do_close && !dev_close(dev))
|
if (do_close && !dev_close(dev))
|
||||||
log_sys_error("close", name);
|
log_sys_error("close", name);
|
||||||
|
|
||||||
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,27 +18,22 @@
|
|||||||
#define LUKS_SIGNATURE "LUKS\xba\xbe"
|
#define LUKS_SIGNATURE "LUKS\xba\xbe"
|
||||||
#define LUKS_SIGNATURE_SIZE 6
|
#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];
|
char buf[LUKS_SIGNATURE_SIZE];
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (!dev_open_readonly(dev)) {
|
if (!scan_bcache)
|
||||||
stack;
|
return -EAGAIN;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset_found)
|
if (offset_found)
|
||||||
*offset_found = 0;
|
*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;
|
goto_out;
|
||||||
|
|
||||||
ret = memcmp(buf, LUKS_SIGNATURE, LUKS_SIGNATURE_SIZE) ? 0 : 1;
|
ret = memcmp(buf, LUKS_SIGNATURE, LUKS_SIGNATURE_SIZE) ? 0 : 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,12 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
|
|||||||
uint32_t md_magic;
|
uint32_t md_magic;
|
||||||
|
|
||||||
/* Version 1 is little endian; version 0.90.0 is machine endian */
|
/* 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) ||
|
if (!dev_read_bytes(dev, sb_offset, sizeof(uint32_t), &md_magic))
|
||||||
((MD_SB_MAGIC != xlate32(MD_SB_MAGIC)) && (md_magic == xlate32(MD_SB_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 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -109,11 +112,14 @@ static int _udev_dev_is_md(struct device *dev)
|
|||||||
/*
|
/*
|
||||||
* Returns -1 on error
|
* 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;
|
md_minor_version_t minor;
|
||||||
uint64_t size, sb_offset;
|
uint64_t size, sb_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!scan_bcache)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
if (!dev_get_size(dev, &size)) {
|
if (!dev_get_size(dev, &size)) {
|
||||||
stack;
|
stack;
|
||||||
@ -123,38 +129,67 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found)
|
|||||||
if (size < MD_RESERVED_SECTORS * 2)
|
if (size < MD_RESERVED_SECTORS * 2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!dev_open_readonly(dev)) {
|
/*
|
||||||
stack;
|
* Old md versions locate the magic number at the end of the device.
|
||||||
return -1;
|
* 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. */
|
/* Check if it is an md component device. */
|
||||||
/* Version 0.90.0 */
|
/* Version 0.90.0 */
|
||||||
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
|
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;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
minor = MD_MINOR_VERSION_MIN;
|
minor = MD_MINOR_VERSION_MIN;
|
||||||
/* Version 1, try v1.0 -> v1.2 */
|
/* Version 1, try v1.0 -> v1.2 */
|
||||||
do {
|
do {
|
||||||
sb_offset = _v1_sb_offset(size, minor);
|
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;
|
goto out;
|
||||||
|
}
|
||||||
} while (++minor <= MD_MINOR_VERSION_MAX);
|
} while (++minor <= MD_MINOR_VERSION_MAX);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
|
|
||||||
if (ret && offset_found)
|
if (ret && offset_found)
|
||||||
*offset_found = sb_offset;
|
*offset_found = sb_offset;
|
||||||
|
|
||||||
return ret;
|
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.
|
* information is not in udev db.
|
||||||
*/
|
*/
|
||||||
if ((dev->ext.src == DEV_EXT_NONE) || offset_found)
|
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)
|
if (dev->ext.src == DEV_EXT_UDEV)
|
||||||
return _udev_dev_is_md(dev);
|
return _udev_dev_is_md(dev);
|
||||||
|
@ -35,19 +35,17 @@ static int _swap_detect_signature(const char *buf)
|
|||||||
return 0;
|
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];
|
char buf[10];
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
unsigned page;
|
unsigned page;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!dev_get_size(dev, &size)) {
|
if (!scan_bcache)
|
||||||
stack;
|
return -EAGAIN;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dev_open_readonly(dev)) {
|
if (!dev_get_size(dev, &size)) {
|
||||||
stack;
|
stack;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -60,8 +58,7 @@ int dev_is_swap(struct device *dev, uint64_t *offset_found)
|
|||||||
continue;
|
continue;
|
||||||
if (size < (page >> SECTOR_SHIFT))
|
if (size < (page >> SECTOR_SHIFT))
|
||||||
break;
|
break;
|
||||||
if (!dev_read(dev, page - SIGNATURE_SIZE,
|
if (!dev_read_bytes(dev, page - SIGNATURE_SIZE, SIGNATURE_SIZE, buf)) {
|
||||||
SIGNATURE_SIZE, DEV_IO_SIGNATURES, buf)) {
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -73,9 +70,6 @@ int dev_is_swap(struct device *dev, uint64_t *offset_found)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ static int _has_partition_table(struct device *dev)
|
|||||||
uint16_t magic;
|
uint16_t magic;
|
||||||
} __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
|
} __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;
|
return_0;
|
||||||
|
|
||||||
/* FIXME Check for other types of partition table too */
|
/* 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;
|
int r;
|
||||||
|
|
||||||
|
if (!scan_bcache)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
if (!_is_partitionable(dt, dev))
|
if (!_is_partitionable(dt, dev))
|
||||||
return 0;
|
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))
|
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
|
||||||
return 1;
|
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);
|
r = _has_partition_table(dev);
|
||||||
|
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,12 +744,12 @@ out:
|
|||||||
|
|
||||||
static int _wipe_signature(struct device *dev, const char *type, const char *name,
|
static int _wipe_signature(struct device *dev, const char *type, const char *name,
|
||||||
int wipe_len, int yes, force_t force, int *wiped,
|
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;
|
int wipe;
|
||||||
uint64_t offset_found;
|
uint64_t offset_found;
|
||||||
|
|
||||||
wipe = signature_detection_fn(dev, &offset_found);
|
wipe = signature_detection_fn(dev, &offset_found, 1);
|
||||||
if (wipe == -1) {
|
if (wipe == -1) {
|
||||||
log_error("Fatal error while trying to detect %s on %s.",
|
log_error("Fatal error while trying to detect %s on %s.",
|
||||||
type, name);
|
type, name);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "label.h"
|
||||||
|
|
||||||
#define NUMBER_OF_MAJORS 4096
|
#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);
|
int major_is_scsi_device(struct dev_types *dt, int major);
|
||||||
|
|
||||||
/* Signature/superblock recognition with position returned where found. */
|
/* Signature/superblock recognition with position returned where found. */
|
||||||
int dev_is_md(struct device *dev, uint64_t *sb);
|
int dev_is_md(struct device *dev, uint64_t *sb, int full);
|
||||||
int dev_is_swap(struct device *dev, uint64_t *signature);
|
int dev_is_swap(struct device *dev, uint64_t *signature, int full);
|
||||||
int dev_is_luks(struct device *dev, uint64_t *signature);
|
int dev_is_luks(struct device *dev, uint64_t *signature, int full);
|
||||||
int dasd_is_cdl_formatted(struct device *dev);
|
int dasd_is_cdl_formatted(struct device *dev);
|
||||||
int udev_dev_is_mpath_component(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_NOT_O_NOATIME 0x00000400 /* Don't use O_NOATIME */
|
||||||
#define DEV_IN_BCACHE 0x00000800 /* dev fd is open and used in bcache */
|
#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_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.
|
* Support for external device info.
|
||||||
|
@ -15,14 +15,19 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
static int _and_p(struct dev_filter *f, struct device *dev)
|
static int _and_p(struct dev_filter *f, struct device *dev)
|
||||||
{
|
{
|
||||||
struct dev_filter **filters;
|
struct dev_filter **filters;
|
||||||
|
int ret;
|
||||||
|
|
||||||
for (filters = (struct dev_filter **) f->private; *filters; ++filters)
|
for (filters = (struct dev_filter **) f->private; *filters; ++filters) {
|
||||||
if (!(*filters)->passes_filter(*filters, dev))
|
ret = (*filters)->passes_filter(*filters, dev);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
return 0; /* No 'stack': a filter, not an error. */
|
return 0; /* No 'stack': a filter, not an error. */
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,21 @@
|
|||||||
|
|
||||||
#define MSG_SKIPPING "%s: Skipping md component device"
|
#define MSG_SKIPPING "%s: Skipping md component device"
|
||||||
|
|
||||||
static int _ignore_md(struct dev_filter *f __attribute__((unused)),
|
static int _ignore_md(struct device *dev, int full)
|
||||||
struct device *dev)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!md_filtering())
|
if (!md_filtering())
|
||||||
return 1;
|
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 (ret == 1) {
|
||||||
if (dev->ext.src == DEV_EXT_NONE)
|
if (dev->ext.src == DEV_EXT_NONE)
|
||||||
@ -48,6 +54,18 @@ static int _ignore_md(struct dev_filter *f __attribute__((unused)),
|
|||||||
return 1;
|
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)
|
static void _destroy(struct dev_filter *f)
|
||||||
{
|
{
|
||||||
if (f->use_count)
|
if (f->use_count)
|
||||||
@ -56,7 +74,7 @@ static void _destroy(struct dev_filter *f)
|
|||||||
dm_free(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;
|
struct dev_filter *f;
|
||||||
|
|
||||||
@ -65,7 +83,18 @@ struct dev_filter *md_filter_create(struct dev_types *dt)
|
|||||||
return NULL;
|
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->destroy = _destroy;
|
||||||
f->use_count = 0;
|
f->use_count = 0;
|
||||||
f->private = dt;
|
f->private = dt;
|
||||||
|
@ -21,8 +21,18 @@
|
|||||||
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
|
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
|
||||||
{
|
{
|
||||||
struct dev_types *dt = (struct dev_types *) f->private;
|
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)
|
if (dev->ext.src == DEV_EXT_NONE)
|
||||||
log_debug_devs(MSG_SKIPPING, dev_name(dev));
|
log_debug_devs(MSG_SKIPPING, dev_name(dev));
|
||||||
else
|
else
|
||||||
|
@ -26,6 +26,30 @@ struct pfilter {
|
|||||||
struct dev_types *dt;
|
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
|
* The hash table holds one of these two states
|
||||||
* against each entry.
|
* 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;
|
struct pfilter *pf = (struct pfilter *) f->private;
|
||||||
void *l = dm_hash_lookup(pf->devices, dev_name(dev));
|
void *l = dm_hash_lookup(pf->devices, dev_name(dev));
|
||||||
struct dm_str_list *sl;
|
struct dm_str_list *sl;
|
||||||
|
int pass = 1;
|
||||||
|
|
||||||
/* Cached BAD? */
|
/* Cached bad, skip dev */
|
||||||
if (l == PF_BAD_DEVICE) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test dm devices every time, so cache them as GOOD. */
|
/* Cached good, use dev */
|
||||||
if (MAJOR(dev->dev) == pf->dt->device_mapper_major) {
|
if (l == PF_GOOD_DEVICE) {
|
||||||
if (!l)
|
log_debug_devs("%s: filter cache using (cached good)", dev_name(dev));
|
||||||
dm_list_iterate_items(sl, &dev->aliases)
|
return 1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Uncached */
|
/* Uncached, check filters and cache the result */
|
||||||
if (!l) {
|
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)
|
dm_list_iterate_items(sl, &dev->aliases)
|
||||||
if (!dm_hash_insert(pf->devices, sl->str, l)) {
|
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 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
return (l == PF_BAD_DEVICE) ? 0 : 1;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _persistent_destroy(struct dev_filter *f)
|
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];
|
char buf[BUFSIZE];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!dev_open_readonly(dev)) {
|
if (!scan_bcache) {
|
||||||
stack;
|
/* let pass, call again after scan */
|
||||||
return -1;
|
log_debug_devs("filter signature deferred %s", dev_name(dev));
|
||||||
|
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(buf, 0, BUFSIZE);
|
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",
|
log_debug_devs("%s: Skipping: error in signature detection",
|
||||||
dev_name(dev));
|
dev_name(dev));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -54,8 +56,6 @@ static int _ignore_signature(struct dev_filter *f __attribute__((unused)),
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dev_close(dev);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,12 +27,6 @@ static int _native_check_pv_min_size(struct device *dev)
|
|||||||
uint64_t size;
|
uint64_t size;
|
||||||
int ret = 0;
|
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 */
|
/* Check it's not too small */
|
||||||
if (!dev_get_size(dev, &size)) {
|
if (!dev_get_size(dev, &size)) {
|
||||||
log_debug_devs("%s: Skipping: dev_get_size failed", dev_name(dev));
|
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;
|
ret = 1;
|
||||||
out:
|
out:
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
|
|
||||||
return ret;
|
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 *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 *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 *fwraid_filter_create(struct dev_types *dt);
|
||||||
struct dev_filter *mpath_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);
|
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
|
* beyond the range of the scanned block, then additional reads
|
||||||
* are performed in the processing functions to get that data.
|
* 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)));
|
char label_buf[LABEL_SIZE] __attribute__((aligned(8)));
|
||||||
struct label *label = NULL;
|
struct label *label = NULL;
|
||||||
struct labeller *labeller;
|
struct labeller *labeller;
|
||||||
uint64_t sector;
|
uint64_t sector;
|
||||||
int ret = 0;
|
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.
|
* 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.
|
* 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 wait_devs;
|
||||||
struct dm_list done_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_process_errors = 0;
|
||||||
int scan_failed_count = 0;
|
int scan_failed_count = 0;
|
||||||
int rem_prefetches;
|
int rem_prefetches;
|
||||||
|
int submit_count;
|
||||||
int scan_failed;
|
int scan_failed;
|
||||||
int is_lvm_device;
|
int is_lvm_device;
|
||||||
int error;
|
int error;
|
||||||
@ -483,6 +516,7 @@ static int _scan_list(struct dm_list *devs, int *failed)
|
|||||||
|
|
||||||
scan_more:
|
scan_more:
|
||||||
rem_prefetches = bcache_max_prefetches(scan_bcache);
|
rem_prefetches = bcache_max_prefetches(scan_bcache);
|
||||||
|
submit_count = 0;
|
||||||
|
|
||||||
dm_list_iterate_items_safe(devl, devl2, devs) {
|
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);
|
bcache_prefetch(scan_bcache, devl->dev->bcache_fd, 0);
|
||||||
|
|
||||||
rem_prefetches--;
|
rem_prefetches--;
|
||||||
|
submit_count++;
|
||||||
|
|
||||||
dm_list_del(&devl->list);
|
dm_list_del(&devl->list);
|
||||||
dm_list_add(&wait_devs, &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) {
|
dm_list_iterate_items_safe(devl, devl2, &wait_devs) {
|
||||||
bb = NULL;
|
bb = NULL;
|
||||||
error = 0;
|
error = 0;
|
||||||
@ -530,7 +567,7 @@ static int _scan_list(struct dm_list *devs, int *failed)
|
|||||||
} else {
|
} else {
|
||||||
log_debug_devs("Processing data from device %s fd %d block %p", dev_name(devl->dev), devl->dev->bcache_fd, bb);
|
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) {
|
if (!ret && is_lvm_device) {
|
||||||
log_debug_devs("Scan failed to process %s", dev_name(devl->dev));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_scan_list(&all_devs, NULL);
|
_scan_list(cmd, cmd->full_filter, &all_devs, NULL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -679,7 +716,7 @@ int label_scan(struct cmd_context *cmd)
|
|||||||
* without a lock.)
|
* 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;
|
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 */
|
/* 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;
|
devl->dev->flags |= DEV_BCACHE_EXCL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_scan_list(devs, &failed);
|
_scan_list(NULL, NULL, devs, &failed);
|
||||||
|
|
||||||
if (failed)
|
if (failed)
|
||||||
return 0;
|
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);
|
lv_info(cmd, lv, 0, &lvinfo, 0, 0);
|
||||||
devt = MKDEV(lvinfo.major, lvinfo.minor);
|
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);
|
label_scan_invalidate(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,9 +801,8 @@ void label_scan_drop(struct cmd_context *cmd)
|
|||||||
struct dev_iter *iter;
|
struct dev_iter *iter;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
|
if (!(iter = dev_iter_create(NULL, 0)))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
while ((dev = dev_iter_get(iter))) {
|
while ((dev = dev_iter_get(iter))) {
|
||||||
if (_in_bcache(dev))
|
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_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
|
* 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;
|
extern struct bcache *scan_bcache;
|
||||||
|
|
||||||
int label_scan(struct cmd_context *cmd);
|
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);
|
int label_scan_devs_excl(struct dm_list *devs);
|
||||||
void label_scan_invalidate(struct device *dev);
|
void label_scan_invalidate(struct device *dev);
|
||||||
void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
|
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,
|
const uint64_t new_size,
|
||||||
int yes);
|
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);
|
uint64_t label_sector);
|
||||||
|
|
||||||
/* FIXME: move internal to library */
|
/* FIXME: move internal to library */
|
||||||
|
@ -5059,30 +5059,19 @@ static int _analyze_mda(struct metadata_area *mda, void *baton)
|
|||||||
* 0 - fail
|
* 0 - fail
|
||||||
* 1 - success
|
* 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)
|
uint64_t label_sector)
|
||||||
{
|
{
|
||||||
struct label *label;
|
struct label *label;
|
||||||
struct device *dev;
|
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
dev = dev_cache_get(pv_name, cmd->filter);
|
if (!(label = lvmcache_get_dev_label(dev))) {
|
||||||
if (!dev) {
|
log_error("Could not find LVM label on %s", dev_name(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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_print("Found label on %s, sector %"PRIu64", type=%.8s",
|
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
|
* Next, loop through metadata areas
|
||||||
|
@ -297,16 +297,17 @@ static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev_open_quiet(dev))
|
if (!label_scan_open(dev)) {
|
||||||
return 0;
|
log_error("Failed to open %s/%s to write log header.", lv->vg->name, lv->name);
|
||||||
|
|
||||||
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);
|
|
||||||
return 0;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,9 @@ int lvmdiskscan(struct cmd_context *cmd, int argc __attribute__((unused)),
|
|||||||
if (arg_is_set(cmd, lvmpartition_ARG))
|
if (arg_is_set(cmd, lvmpartition_ARG))
|
||||||
log_warn("WARNING: only considering LVM devices");
|
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);
|
max_len = _get_max_dev_name_len(cmd->full_filter);
|
||||||
|
|
||||||
if (!(iter = dev_iter_create(cmd->full_filter, 0))) {
|
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;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
label_scan(cmd);
|
|
||||||
|
|
||||||
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
||||||
if (lvmcache_has_dev_info(dev)) {
|
if (lvmcache_has_dev_info(dev)) {
|
||||||
if (!dev_get_size(dev, &size)) {
|
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)
|
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 i;
|
||||||
int ret_max = ECMD_PROCESSED;
|
int ret_max = ECMD_PROCESSED;
|
||||||
|
|
||||||
/* FIXME: validate cmdline options */
|
/* FIXME: validate cmdline options */
|
||||||
/* FIXME: what does the cmdline look like? */
|
/* 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++) {
|
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);
|
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;
|
stack;
|
||||||
ret_max = ECMD_FAILED;
|
ret_max = ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,9 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
pp.pv_count = argc;
|
pp.pv_count = argc;
|
||||||
pp.pv_names = argv;
|
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.
|
* Needed to change the set of orphan PVs.
|
||||||
* (disable afterward to prevent process_each_pv from doing
|
* (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;
|
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);
|
dm_list_init(&single_devs);
|
||||||
|
|
||||||
while (argc--) {
|
while (argc--) {
|
||||||
@ -455,7 +458,11 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
ret = ECMD_FAILED;
|
ret = ECMD_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
log_debug("Scanning dev %s for lvmetad cache.", pv_name);
|
||||||
|
|
||||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
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))
|
if (!_lvmetad_clear_dev(devno, major, minor))
|
||||||
remove_errors++;
|
remove_errors++;
|
||||||
} else {
|
} 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);
|
log_debug("Scanning dev %d:%d for lvmetad cache.", major, minor);
|
||||||
|
|
||||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
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)) {
|
if (!dm_list_empty(&single_devs)) {
|
||||||
dev_cache_scan();
|
label_scan_devs(cmd, cmd->lvmetad_filter, &single_devs);
|
||||||
label_scan_devs(cmd, &single_devs);
|
|
||||||
|
|
||||||
dm_list_iterate_items(devl, &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++;
|
add_errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,10 +562,22 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dm_list_empty(&single_devs)) {
|
if (!dm_list_empty(&single_devs)) {
|
||||||
dev_cache_scan();
|
label_scan_devs(cmd, cmd->lvmetad_filter, &single_devs);
|
||||||
label_scan_devs(cmd, &single_devs);
|
|
||||||
|
|
||||||
dm_list_iterate_items(devl, &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))
|
if (!lvmetad_pvscan_single(cmd, devl->dev, &found_vgnames, &pp.changed_vgnames))
|
||||||
add_errors++;
|
add_errors++;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,9 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
return_ECMD_FAILED;
|
return_ECMD_FAILED;
|
||||||
cmd->lockd_gl_disable = 1;
|
cmd->lockd_gl_disable = 1;
|
||||||
|
|
||||||
|
/* Check for old md signatures at the end of devices. */
|
||||||
|
cmd->use_full_md_check = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the VG name already exists. This should be done before
|
* Check if the VG name already exists. This should be done before
|
||||||
* creating PVs on any of the devices.
|
* creating PVs on any of the devices.
|
||||||
|
@ -154,6 +154,9 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
|
|||||||
/* pvcreate within vgextend cannot be forced. */
|
/* pvcreate within vgextend cannot be forced. */
|
||||||
pp->force = 0;
|
pp->force = 0;
|
||||||
|
|
||||||
|
/* Check for old md signatures at the end of devices. */
|
||||||
|
cmd->use_full_md_check = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Needed to change the set of orphan PVs.
|
* Needed to change the set of orphan PVs.
|
||||||
* (disable afterward to prevent process_each_pv from doing
|
* (disable afterward to prevent process_each_pv from doing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user