mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-12 07:33:16 +03:00
Compare commits
17 Commits
v2_03_15
...
dev-dct-de
Author | SHA1 | Date | |
---|---|---|---|
|
07338325e5 | ||
|
ac1f4bbbfd | ||
|
6144dac897 | ||
|
96c99d647e | ||
|
ec2119bedd | ||
|
d4a0816a58 | ||
|
fa7b67eeeb | ||
|
4fd76de4b6 | ||
|
d2e7a05573 | ||
|
c2679f76e5 | ||
|
6ffb150f30 | ||
|
6626adb467 | ||
|
d59382c772 | ||
|
61f23fe15e | ||
|
13122bcc33 | ||
|
f83b3962c1 | ||
|
8dccc2314e |
@@ -1 +1 @@
|
||||
1.02.183 (2022-02-07)
|
||||
1.02.185-git (2022-02-07)
|
||||
|
@@ -1,3 +1,6 @@
|
||||
Version 2.03.16 -
|
||||
====================================
|
||||
|
||||
Version 2.03.15 - 07th February 2022
|
||||
====================================
|
||||
Remove service based autoactivation. global/event_activation = 0 is NOOP.
|
||||
|
@@ -1,3 +1,6 @@
|
||||
Version 1.02.185 -
|
||||
=====================================
|
||||
|
||||
Version 1.02.183 - 07th February 2022
|
||||
=====================================
|
||||
Unmangle UUIDs for DM_DEVICE_LIST ioctl.
|
||||
|
@@ -1151,16 +1151,11 @@ global {
|
||||
# lvdisplay_shows_full_device_path = 0
|
||||
|
||||
# Configuration option global/event_activation.
|
||||
# Activate LVs based on system-generated device events.
|
||||
# When a PV appears on the system, a system-generated uevent triggers
|
||||
# the lvm2-pvscan service which runs the pvscan --cache -aay command.
|
||||
# If the new PV completes a VG, pvscan autoactivates LVs in the VG.
|
||||
# When event_activation is disabled, the lvm2-activation services are
|
||||
# generated and run at fixed points during system startup. These
|
||||
# services run vgchange -aay to autoactivate LVs in VGs that happen
|
||||
# to be present at that point in time.
|
||||
# See the --setautoactivation option or the auto_activation_volume_list
|
||||
# setting to configure autoactivation for specific VGs or LVs.
|
||||
# Disable event based autoactivation commands.
|
||||
# WARNING: setting this to zero may cause machine startup to fail.
|
||||
# Previously, setting this to zero would enable static autoactivation
|
||||
# services (via the lvm2-activation-generator), but the autoactivation
|
||||
# services and generator have been removed.
|
||||
# This configuration option has an automatic default value.
|
||||
# event_activation = 1
|
||||
|
||||
|
@@ -107,6 +107,8 @@ static struct dm_task *_setup_task_run(int task, struct dm_info *info,
|
||||
int with_flush,
|
||||
int query_inactive)
|
||||
{
|
||||
char vsn[80];
|
||||
unsigned maj, min;
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = dm_task_create(task)))
|
||||
@@ -142,7 +144,11 @@ static struct dm_task *_setup_task_run(int task, struct dm_info *info,
|
||||
case DM_DEVICE_TARGET_MSG:
|
||||
return dmt; /* TARGET_MSG needs more local tweaking before task_run() */
|
||||
case DM_DEVICE_LIST:
|
||||
if (!dm_task_set_newuuid(dmt, " ")) // new uuid has no meaning here
|
||||
/* Use 'newuuid' only with DM version that supports it */
|
||||
if (driver_version(vsn, sizeof(vsn)) &&
|
||||
(sscanf(vsn, "%u.%u", &maj, &min) == 2) &&
|
||||
(maj == 4 ? min >= 19 : maj > 4) &&
|
||||
!dm_task_set_newuuid(dmt, " ")) // new uuid has no meaning here
|
||||
log_warn("WARNING: Failed to query uuid with LIST.");
|
||||
break;
|
||||
default:
|
||||
@@ -198,7 +204,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
|
||||
/* If kernel's type isn't an exact match is it compatible? */
|
||||
(!segtype->ops->target_status_compatible ||
|
||||
!segtype->ops->target_status_compatible(target_name))) {
|
||||
log_warn(INTERNAL_ERROR "WARNING: Segment type %s found does not match expected type %s for %s.",
|
||||
log_warn("WARNING: Detected %s segment type does not match expected type %s for %s.",
|
||||
target_name, segtype->name, display_lvname(seg_status->seg->lv));
|
||||
return 0;
|
||||
}
|
||||
@@ -2248,6 +2254,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
{
|
||||
char *dlid, *name;
|
||||
struct dm_info info, info2;
|
||||
const struct dm_active_device *dev;
|
||||
|
||||
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
|
||||
return_0;
|
||||
@@ -2256,15 +2263,20 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_0;
|
||||
|
||||
if (!dm->cmd->disable_dm_devs &&
|
||||
dm->cmd->cache_dm_devs &&
|
||||
!dm_device_list_find_by_uuid(dm->cmd->cache_dm_devs, dlid, NULL)) {
|
||||
log_debug("Cached as not present %s.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_info(dm->cmd, name, dlid, 1, 0, 0, &info, NULL, NULL))
|
||||
dm->cmd->cache_dm_devs) {
|
||||
if (!dm_device_list_find_by_uuid(dm->cmd->cache_dm_devs, dlid, &dev)) {
|
||||
log_debug("Cached as not present %s.", name);
|
||||
return 1;
|
||||
}
|
||||
info = (struct dm_info) {
|
||||
.exists = 1,
|
||||
.major = dev->major,
|
||||
.minor = dev->minor,
|
||||
};
|
||||
log_debug("Cached as present %s %s (%d:%d).",
|
||||
name, dlid, info.major, info.minor);
|
||||
} else if (!_info(dm->cmd, name, dlid, 0, 0, 0, &info, NULL, NULL))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* For top level volumes verify that existing device match
|
||||
* requested major/minor and that major/minor pair is available for use
|
||||
@@ -2935,6 +2947,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
|
||||
/* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */
|
||||
for (s = start_area; s < areas; s++) {
|
||||
|
||||
/* FIXME: dev_name() does not return NULL! It needs to check if dm_list_empty(&dev->aliases)
|
||||
but this knot of logic is too complex to pull apart without careful deconstruction. */
|
||||
|
||||
if ((seg_type(seg, s) == AREA_PV &&
|
||||
(!seg_pvseg(seg, s) || !seg_pv(seg, s) || !seg_dev(seg, s) ||
|
||||
!(name = dev_name(seg_dev(seg, s))) || !*name ||
|
||||
@@ -2953,7 +2969,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
return_0;
|
||||
num_error_areas++;
|
||||
} else if (seg_type(seg, s) == AREA_PV) {
|
||||
if (!dm_tree_node_add_target_area(node, dev_name(seg_dev(seg, s)), NULL,
|
||||
struct device *dev = seg_dev(seg, s);
|
||||
name = dm_list_empty(&dev->aliases) ? NULL : dev_name(dev);
|
||||
|
||||
if (!dm_tree_node_add_target_area(node, name, NULL,
|
||||
(seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s)))))
|
||||
return_0;
|
||||
num_existing_areas++;
|
||||
|
@@ -522,7 +522,9 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
|
||||
if (!(dev->flags & DEV_REGULAR) || size2)
|
||||
use_plain_read = 0;
|
||||
|
||||
if (!(buf = zalloc(size + size2))) {
|
||||
/* Ensure there is extra '\0' after end of buffer since we pass
|
||||
* buffer to funtions like strtoll() */
|
||||
if (!(buf = zalloc(size + size2 + 1))) {
|
||||
log_error("Failed to allocate circular buffer.");
|
||||
return 0;
|
||||
}
|
||||
|
@@ -351,7 +351,7 @@ static int _add_alias(struct device *dev, const char *path, enum add_hash hash)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(path = dm_pool_strdup(_cache.mem, path)) ||
|
||||
if (!(path = _strdup(path)) ||
|
||||
!(sl = _zalloc(sizeof(*sl)))) {
|
||||
log_error("Failed to add allias to dev cache.");
|
||||
return 0;
|
||||
@@ -1162,6 +1162,17 @@ static int _insert(const char *path, const struct stat *info,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _drop_all_aliases(struct device *dev)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
|
||||
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
log_debug("Drop alias for %d:%d %s.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev), strl->str);
|
||||
dm_hash_remove(_cache.names, strl->str);
|
||||
dm_list_del(&strl->list);
|
||||
}
|
||||
}
|
||||
|
||||
void dev_cache_scan(struct cmd_context *cmd)
|
||||
{
|
||||
log_debug_devs("Creating list of system devices.");
|
||||
@@ -1371,59 +1382,6 @@ int dev_cache_add_dir(const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check cached device name is still valid before returning it */
|
||||
/* This should be a rare occurrence */
|
||||
/* set quiet if the cache is expected to be out-of-date */
|
||||
/* FIXME Make rest of code pass/cache struct device instead of dev_name */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||
{
|
||||
struct stat buf;
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
if ((dev->flags & DEV_REGULAR))
|
||||
return dev_name(dev);
|
||||
|
||||
while ((r = stat(name = dm_list_item(dev->aliases.n,
|
||||
struct dm_str_list)->str, &buf)) ||
|
||||
(buf.st_rdev != dev->dev)) {
|
||||
if (r < 0) {
|
||||
if (quiet)
|
||||
log_sys_debug("stat", name);
|
||||
else
|
||||
log_sys_error("stat", name);
|
||||
}
|
||||
if (quiet)
|
||||
log_debug_devs("Path %s no longer valid for device(%d,%d)",
|
||||
name, (int) MAJOR(dev->dev),
|
||||
(int) MINOR(dev->dev));
|
||||
else
|
||||
log_warn("Path %s no longer valid for device(%d,%d)",
|
||||
name, (int) MAJOR(dev->dev),
|
||||
(int) MINOR(dev->dev));
|
||||
|
||||
/* Remove the incorrect hash entry */
|
||||
dm_hash_remove(_cache.names, name);
|
||||
|
||||
/* Leave list alone if there isn't an alternative name */
|
||||
/* so dev_name will always find something to return. */
|
||||
/* Otherwise add the name to the correct device. */
|
||||
if (dm_list_size(&dev->aliases) > 1) {
|
||||
dm_list_del(dev->aliases.n);
|
||||
if (!r)
|
||||
_insert(name, &buf, 0, obtain_device_list_from_udev());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Scanning issues this inappropriately sometimes. */
|
||||
log_debug_devs("Aborting - please provide new pathname for what "
|
||||
"used to be %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev_name(dev);
|
||||
}
|
||||
|
||||
struct device *dev_hash_get(const char *name)
|
||||
{
|
||||
return (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
@@ -1452,26 +1410,23 @@ static void _remove_alias(struct device *dev, const char *name)
|
||||
* deactivated LV. Those old paths are all invalid and are dropped here.
|
||||
*/
|
||||
|
||||
static void _verify_aliases(struct device *dev, const char *newname)
|
||||
static void _verify_aliases(struct device *dev)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
struct stat st;
|
||||
|
||||
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
/* newname was just stat'd and added by caller */
|
||||
if (newname && !strcmp(strl->str, newname))
|
||||
continue;
|
||||
|
||||
if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
|
||||
log_debug("Drop invalid path %s for %d:%d (new path %s).",
|
||||
strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
|
||||
log_debug("Drop alias for %d:%d invalid path %s %d:%d.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev), strl->str,
|
||||
(int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev));
|
||||
dm_hash_remove(_cache.names, strl->str);
|
||||
dm_list_del(&strl->list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f, int existing)
|
||||
{
|
||||
struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
struct stat st;
|
||||
@@ -1485,13 +1440,18 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
if (dev && (dev->flags & DEV_REGULAR))
|
||||
return dev;
|
||||
|
||||
if (dev && dm_list_empty(&dev->aliases)) {
|
||||
/* shouldn't happen */
|
||||
log_warn("Ignoring dev with no valid paths for %s.", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The requested path is invalid, remove any dev-cache
|
||||
* info for it.
|
||||
* The requested path is invalid, remove any dev-cache info for it.
|
||||
*/
|
||||
if (stat(name, &st)) {
|
||||
if (dev) {
|
||||
log_print("Device path %s is invalid for %d:%d %s.",
|
||||
log_debug("Device path %s is invalid for %d:%d %s.",
|
||||
name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
|
||||
|
||||
dm_hash_remove(_cache.names, name);
|
||||
@@ -1499,11 +1459,17 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
_remove_alias(dev, name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
_verify_aliases(dev, NULL);
|
||||
_verify_aliases(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dev && dm_list_empty(&dev->aliases)) {
|
||||
/* shouldn't happen */
|
||||
log_warn("Ignoring dev with no valid paths for %s.", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!S_ISBLK(st.st_mode)) {
|
||||
log_debug("Not a block device %s.", name);
|
||||
return NULL;
|
||||
@@ -1514,26 +1480,41 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
* Remove incorrect info and then add new dev-cache entry.
|
||||
*/
|
||||
if (dev && (st.st_rdev != dev->dev)) {
|
||||
log_debug("Device path %s does not match %d:%d %s.",
|
||||
name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
|
||||
struct device *dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) st.st_rdev);
|
||||
|
||||
dm_hash_remove(_cache.names, name);
|
||||
/*
|
||||
* lvm commands create this condition when they
|
||||
* activate/deactivate LVs combined with creating new LVs.
|
||||
* The command does not purge dev structs when deactivating
|
||||
* an LV (which it probably should do), but the better
|
||||
* approach would be not using dev-cache at all for LVs.
|
||||
*/
|
||||
|
||||
_remove_alias(dev, name);
|
||||
log_debug("Dropping aliases for device entry %d:%d %s for new device %d:%d %s.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev),
|
||||
(int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev), name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
_verify_aliases(dev, NULL);
|
||||
_drop_all_aliases(dev);
|
||||
|
||||
/* Add new dev-cache entry next. */
|
||||
dev = NULL;
|
||||
}
|
||||
if (dev_by_devt) {
|
||||
log_debug("Dropping aliases for device entry %d:%d %s for new device %d:%d %s.",
|
||||
(int)MAJOR(dev_by_devt->dev), (int)MINOR(dev_by_devt->dev), dev_name(dev_by_devt),
|
||||
(int)MAJOR(st.st_rdev), (int)MINOR(st.st_rdev), name);
|
||||
|
||||
_drop_all_aliases(dev_by_devt);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* I think only lvm's own dm devs should be added here, so use
|
||||
* a warning to look for any other unknown cases.
|
||||
*/
|
||||
if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) {
|
||||
log_warn("WARNING: new device appeared %d:%d %s",
|
||||
(int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Either add a new struct dev for st_rdev and name,
|
||||
* or add name as a new alias for an existing struct dev
|
||||
* for st_rdev.
|
||||
*/
|
||||
if (!dev) {
|
||||
if (!_insert_dev(name, st.st_rdev))
|
||||
return_NULL;
|
||||
|
||||
@@ -1545,9 +1526,77 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_verify_aliases(dev, name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dev && dm_list_empty(&dev->aliases)) {
|
||||
/* shouldn't happen */
|
||||
log_warn("Ignoring dev with no valid paths for %s.", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dev && existing)
|
||||
return_NULL;
|
||||
|
||||
/*
|
||||
* This case should never be hit for a PV. It should only
|
||||
* happen when the command is opening a new LV it has created.
|
||||
* Add an arg to all callers indicating when the arg should be
|
||||
* new (for an LV) and not existing.
|
||||
* FIXME: fix this further by not using dev-cache struct devs
|
||||
* at all for new dm devs (LVs) that lvm uses. Make the
|
||||
* dev-cache contain only devs for PVs.
|
||||
* Places to fix that use a dev for LVs include:
|
||||
* . lv_resize opening lv to discard
|
||||
* . wipe_lv opening lv to zero it
|
||||
* . _extend_sanlock_lv opening lv to extend it
|
||||
* . _write_log_header opening lv to write header
|
||||
* Also, io to LVs should not go through bcache.
|
||||
* bcache should contain only labels and metadata
|
||||
* scanned from PVs.
|
||||
*/
|
||||
if (!dev) {
|
||||
/*
|
||||
* This case should only be used for new devices created by this
|
||||
* command (opening LVs it's created), so if a dev exists for the
|
||||
* dev_t referenced by the name, then drop all aliases for before
|
||||
* _insert_dev adds the new name. lvm commands actually hit this
|
||||
* fairly often when it uses some LV, deactivates the LV, then
|
||||
* creates some new LV which ends up with the same major:minor.
|
||||
* Without dropping the aliases, it's plausible that lvm commands
|
||||
* could end up using the wrong dm device.
|
||||
*/
|
||||
struct device *dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) st.st_rdev);
|
||||
if (dev_by_devt) {
|
||||
log_debug("Dropping aliases for %d:%d before adding new path %s.",
|
||||
(int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name);
|
||||
_drop_all_aliases(dev_by_devt);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* I think only lvm's own dm devs should be added here, so use
|
||||
* a warning to look for any other unknown cases.
|
||||
*/
|
||||
if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) {
|
||||
log_warn("WARNING: new device appeared %d:%d %s",
|
||||
(int)MAJOR(st.st_rdev), (int)(MINOR(st.st_rdev)), name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_insert_dev(name, st.st_rdev))
|
||||
return_NULL;
|
||||
|
||||
/* Get the struct dev that was just added. */
|
||||
dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
|
||||
if (!dev) {
|
||||
log_error("Failed to get device %s", name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
/*
|
||||
* The caller passed a filter if they only want the dev if it
|
||||
* passes filters.
|
||||
@@ -1577,63 +1626,23 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
|
||||
return dev;
|
||||
}
|
||||
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f, int *filtered)
|
||||
struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs_dir;
|
||||
struct stat info;
|
||||
struct device *d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
|
||||
int ret;
|
||||
return _dev_cache_get(cmd, name, f, 1);
|
||||
}
|
||||
|
||||
if (filtered)
|
||||
*filtered = 0;
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
{
|
||||
return _dev_cache_get(cmd, name, f, 0);
|
||||
}
|
||||
|
||||
if (!d) {
|
||||
sysfs_dir = dm_sysfs_dir();
|
||||
if (sysfs_dir && *sysfs_dir) {
|
||||
/* First check if dev is sysfs to avoid useless scan */
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
|
||||
sysfs_dir, (int)MAJOR(dev), (int)MINOR(dev)) < 0) {
|
||||
log_error("dm_snprintf partition failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lstat(path, &info)) {
|
||||
log_debug("No sysfs entry for %d:%d errno %d at %s.",
|
||||
(int)MAJOR(dev), (int)MINOR(dev), errno, path);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug_devs("Device num not found in dev_cache repeat dev_cache_scan for %d:%d",
|
||||
(int)MAJOR(dev), (int)MINOR(dev));
|
||||
dev_cache_scan(cmd);
|
||||
d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
|
||||
|
||||
if (!d)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (d->flags & DEV_REGULAR)
|
||||
return d;
|
||||
|
||||
if (!f)
|
||||
return d;
|
||||
|
||||
ret = f->passes_filter(cmd, f, d, NULL);
|
||||
|
||||
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;
|
||||
|
||||
if (filtered)
|
||||
*filtered = 1;
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt)
|
||||
{
|
||||
struct device *dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devt);
|
||||
|
||||
if (dev)
|
||||
return dev;
|
||||
log_debug_devs("No devno %d:%d in dev cache.", (int)MAJOR(devt), (int)MINOR(devt));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1703,8 +1712,10 @@ int dev_fd(struct device *dev)
|
||||
|
||||
const char *dev_name(const struct device *dev)
|
||||
{
|
||||
return (dev && dev->aliases.n) ? dm_list_item(dev->aliases.n, struct dm_str_list)->str :
|
||||
unknown_device_name();
|
||||
if (dev && dev->aliases.n && !dm_list_empty(&dev->aliases))
|
||||
return dm_list_item(dev->aliases.n, struct dm_str_list)->str;
|
||||
else
|
||||
return unknown_device_name();
|
||||
}
|
||||
|
||||
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt)
|
||||
|
@@ -53,8 +53,8 @@ int dev_cache_has_scanned(void);
|
||||
|
||||
int dev_cache_add_dir(const char *path);
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered);
|
||||
struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt);
|
||||
|
||||
struct device *dev_hash_get(const char *name);
|
||||
|
||||
|
@@ -58,6 +58,9 @@ static int _dev_get_size_file(struct device *dev, uint64_t *size)
|
||||
const char *name = dev_name(dev);
|
||||
struct stat info;
|
||||
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
return_0;
|
||||
|
||||
if (dev->size_seqno == _dev_size_seqno) {
|
||||
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
|
||||
name, dev->size);
|
||||
@@ -87,7 +90,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
|
||||
int do_close = 0;
|
||||
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
return 0;
|
||||
return_0;
|
||||
|
||||
if (dev->size_seqno == _dev_size_seqno) {
|
||||
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
|
||||
@@ -305,6 +308,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
if ((flags & O_EXCL))
|
||||
need_excl = 1;
|
||||
|
||||
if (dm_list_empty(&dev->aliases)) {
|
||||
/* shouldn't happen */
|
||||
log_print("Cannot open device %d:%d with no valid paths.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
return 0;
|
||||
}
|
||||
name = dev_name(dev);
|
||||
|
||||
if (dev->fd >= 0) {
|
||||
if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
|
||||
((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
|
||||
@@ -314,7 +324,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (dev->open_count && !need_excl)
|
||||
log_debug_devs("%s: Already opened read-only. Upgrading "
|
||||
"to read-write.", dev_name(dev));
|
||||
"to read-write.", name);
|
||||
|
||||
/* dev_close_immediate will decrement this */
|
||||
dev->open_count++;
|
||||
@@ -327,11 +337,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (critical_section())
|
||||
/* FIXME Make this log_error */
|
||||
log_verbose("dev_open(%s) called while suspended",
|
||||
dev_name(dev));
|
||||
|
||||
if (!(name = dev_name_confirmed(dev, quiet)))
|
||||
return_0;
|
||||
log_verbose("dev_open(%s) called while suspended", name);
|
||||
|
||||
#ifdef O_DIRECT_SUPPORT
|
||||
if (direct) {
|
||||
@@ -372,9 +378,9 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
}
|
||||
#endif
|
||||
if (quiet)
|
||||
log_sys_debug("open", name);
|
||||
log_debug("Failed to open device path %s (%d).", name, errno);
|
||||
else
|
||||
log_sys_error("open", name);
|
||||
log_error("Failed to open device path %s (%d).", name, errno);
|
||||
|
||||
dev->flags |= DEV_OPEN_FAILURE;
|
||||
return 0;
|
||||
@@ -415,10 +421,12 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||
|
||||
log_debug_devs("Opened %s %s%s%s", dev_name(dev),
|
||||
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
|
||||
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
|
||||
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
|
||||
if (!quiet) {
|
||||
log_debug_devs("Opened %s %s%s%s", name,
|
||||
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
|
||||
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
|
||||
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
|
||||
}
|
||||
|
||||
dev->flags &= ~DEV_OPEN_FAILURE;
|
||||
return 1;
|
||||
|
@@ -966,6 +966,9 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
|
||||
|
||||
/* TODO: Should we check for valid dev - _dev_is_valid(dev)? */
|
||||
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
goto_out;
|
||||
|
||||
if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) {
|
||||
log_error("Failed to create a new blkid probe for device %s.", dev_name(dev));
|
||||
goto out;
|
||||
|
@@ -40,6 +40,7 @@
|
||||
#define DEV_IS_NVME 0x00040000 /* set if dev is nvme */
|
||||
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */
|
||||
#define DEV_SCAN_FOUND_NOLABEL 0x00100000 /* label_scan read, passed filters, but no lvm label */
|
||||
#define DEV_SCAN_NOT_READ 0x00200000 /* label_scan not able to read dev */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
@@ -203,9 +204,6 @@ struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
struct dm_str_list *alias, int use_malloc);
|
||||
void dev_destroy_file(struct device *dev);
|
||||
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
||||
int dev_mpath_init(const char *config_wwids_file);
|
||||
void dev_mpath_exit(void);
|
||||
|
||||
|
@@ -347,6 +347,8 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
|
||||
}
|
||||
|
||||
else if (idtype == DEV_ID_TYPE_DEVNAME) {
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
goto_bad;
|
||||
if (!(idname = strdup(dev_name(dev))))
|
||||
goto_bad;
|
||||
return idname;
|
||||
@@ -955,6 +957,10 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
|
||||
if (!dev_get_partition_number(dev, &part))
|
||||
return_0;
|
||||
|
||||
/* Ensure valid dev_name(dev) below. */
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* When enable_devices_file=0 and pending_devices_file=1 we let
|
||||
* pvcreate/vgcreate add new du's to cmd->use_devices. These du's may
|
||||
@@ -1577,7 +1583,7 @@ void device_ids_match_device_list(struct cmd_context *cmd)
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
if (du->dev)
|
||||
continue;
|
||||
if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) {
|
||||
if (!(du->dev = dev_cache_get_existing(cmd, du->devname, NULL))) {
|
||||
log_warn("Device not found for %s.", du->devname);
|
||||
} else {
|
||||
/* Should we set dev->id? Which idtype? Use --deviceidtype? */
|
||||
@@ -1625,7 +1631,7 @@ void device_ids_match(struct cmd_context *cmd)
|
||||
* the du/dev pairs in preparation for using the filters.
|
||||
*/
|
||||
if (du->devname &&
|
||||
(dev = dev_cache_get(cmd, du->devname, NULL))) {
|
||||
(dev = dev_cache_get_existing(cmd, du->devname, NULL))) {
|
||||
/* On successful match, du, dev, and id are linked. */
|
||||
if (_match_du_to_dev(cmd, du, dev))
|
||||
continue;
|
||||
@@ -1746,6 +1752,13 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The matched device could not be read so we do not have
|
||||
* the PVID from disk and cannot verify the devices file entry.
|
||||
*/
|
||||
if (dev->flags & DEV_SCAN_NOT_READ)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* du and dev may have been matched, but the dev could still
|
||||
* have been excluded by other filters during label scan.
|
||||
@@ -1828,6 +1841,16 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
if (scanned_devs && !dev_in_device_list(dev, scanned_devs))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The matched device could not be read so we do not have
|
||||
* the PVID from disk and cannot verify the devices file entry.
|
||||
*/
|
||||
if (dev->flags & DEV_SCAN_NOT_READ)
|
||||
continue;
|
||||
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
continue;
|
||||
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
log_warn("Devices file %s is excluded by filter: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
@@ -2211,14 +2234,14 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
|
||||
dm_list_iterate_items(dil, &search_pvids) {
|
||||
char *dup_devname1, *dup_devname2, *dup_devname3;
|
||||
|
||||
if (!dil->dev) {
|
||||
if (!dil->dev || dm_list_empty(&dil->dev->aliases)) {
|
||||
not_found++;
|
||||
continue;
|
||||
}
|
||||
found++;
|
||||
|
||||
dev = dil->dev;
|
||||
devname = dev_name(dev);
|
||||
found++;
|
||||
|
||||
if (!(du = get_du_for_pvid(cmd, dil->pvid))) {
|
||||
/* shouldn't happen */
|
||||
|
@@ -2601,7 +2601,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
|
||||
fmt->ops = &_text_handler;
|
||||
fmt->name = FMT_TEXT_NAME;
|
||||
fmt->alias = FMT_TEXT_ALIAS;
|
||||
fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_TEXT_NAME);
|
||||
strncpy(fmt->orphan_vg_name, ORPHAN_VG_NAME(FMT_TEXT_NAME), sizeof(fmt->orphan_vg_name));
|
||||
fmt->features = FMT_SEGMENTS | FMT_TAGS | FMT_PRECOMMIT |
|
||||
FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
|
||||
FMT_UNLIMITED_STRIPESIZE | FMT_CONFIG_PROFILE |
|
||||
|
@@ -410,6 +410,7 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
|
||||
{
|
||||
struct lvmcache_vgsummary vgsummary;
|
||||
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
struct lvmcache_info *info;
|
||||
const struct format_type *fmt = labeller->fmt;
|
||||
struct label_header *lh = (struct label_header *) label_buf;
|
||||
@@ -433,6 +434,7 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
|
||||
pvhdr = (struct pv_header *) ((char *) label_buf + xlate32(lh->offset_xl));
|
||||
|
||||
memcpy(pvid, &pvhdr->pv_uuid, ID_LEN);
|
||||
strncpy(vgid, FMT_TEXT_ORPHAN_VG_NAME, ID_LEN);
|
||||
|
||||
/*
|
||||
* FIXME: stop adding the device to lvmcache initially as an orphan
|
||||
@@ -449,8 +451,8 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
|
||||
* Other reasons for lvmcache_add to return NULL are internal errors.
|
||||
*/
|
||||
if (!(info = lvmcache_add(cmd, labeller, pvid, dev, label_sector,
|
||||
FMT_TEXT_ORPHAN_VG_NAME,
|
||||
FMT_TEXT_ORPHAN_VG_NAME, 0, is_duplicate)))
|
||||
vgid,
|
||||
vgid, 0, is_duplicate)))
|
||||
return_0;
|
||||
|
||||
lvmcache_set_device_size(info, xlate64(pvhdr->device_size_xl));
|
||||
|
@@ -236,6 +236,7 @@ static int _touch_newhints(void)
|
||||
return_0;
|
||||
if (fclose(fp))
|
||||
stack;
|
||||
log_debug("newhints created");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -499,6 +500,8 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
|
||||
if (!(iter = dev_iter_create(NULL, 0)))
|
||||
return 0;
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
continue;
|
||||
if (!(hint = _find_hint_name(hints, dev_name(dev))))
|
||||
continue;
|
||||
|
||||
@@ -506,6 +509,19 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
|
||||
if (!hint->chosen)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* label_scan was unable to read the dev so we don't know its pvid.
|
||||
* Since we are unable to verify the hint is correct, it's possible
|
||||
* that the PVID is actually found on a different device, so don't
|
||||
* depend on hints. (This would also fail the following pvid check.)
|
||||
*/
|
||||
if (dev->flags & DEV_SCAN_NOT_READ) {
|
||||
log_debug("Uncertain hint for unread device %d:%d %s",
|
||||
major(hint->devt), minor(hint->devt), dev_name(dev));
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(dev->pvid, hint->pvid)) {
|
||||
log_debug("Invalid hint device %d:%d %s pvid %s had hint pvid %s",
|
||||
major(hint->devt), minor(hint->devt), dev_name(dev),
|
||||
|
@@ -687,6 +687,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, devs) {
|
||||
|
||||
devl->dev->flags &= ~DEV_SCAN_NOT_READ;
|
||||
|
||||
/*
|
||||
* If we prefetch more devs than blocks in the cache, then the
|
||||
* cache will wait for earlier reads to complete, toss the
|
||||
@@ -702,6 +704,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
log_debug_devs("Scan failed to open %s.", dev_name(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(&reopen_devs, &devl->list);
|
||||
devl->dev->flags |= DEV_SCAN_NOT_READ;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -725,6 +728,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
log_debug_devs("Scan failed to read %s.", dev_name(devl->dev));
|
||||
scan_read_errors++;
|
||||
scan_failed_count++;
|
||||
devl->dev->flags |= DEV_SCAN_NOT_READ;
|
||||
lvmcache_del_dev(devl->dev);
|
||||
if (bb)
|
||||
bcache_put(bb);
|
||||
@@ -1126,11 +1130,12 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||
* sure to find the device.
|
||||
*/
|
||||
if (try_dev_scan) {
|
||||
log_debug("Repeat dev cache scan to translate devnos.");
|
||||
dev_cache_scan(cmd);
|
||||
dm_list_iterate_items(po, &pvs_online) {
|
||||
if (po->dev)
|
||||
continue;
|
||||
if (!(po->dev = dev_cache_get_by_devt(cmd, po->devno, NULL, NULL))) {
|
||||
if (!(po->dev = dev_cache_get_by_devt(cmd, po->devno))) {
|
||||
log_error("No device found for %d:%d PVID %s",
|
||||
(int)MAJOR(po->devno), (int)MINOR(po->devno), po->pvid);
|
||||
goto bad;
|
||||
@@ -1389,6 +1394,10 @@ int label_scan(struct cmd_context *cmd)
|
||||
* filter", and this result needs to be cleared (wiped) so that the
|
||||
* complete set of filters (including those that require data) can be
|
||||
* checked in _process_block, where headers have been read.
|
||||
*
|
||||
* FIXME: devs that are filtered with data in _process_block
|
||||
* are not moved to the filtered_devs list like devs filtered
|
||||
* here without data. Does that have any effect?
|
||||
*/
|
||||
log_debug_devs("Filtering devices to scan (nodata)");
|
||||
|
||||
@@ -1714,7 +1723,7 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv
|
||||
if (lv_info(cmd, lv, 0, &lvinfo, 0, 0) && lvinfo.exists) {
|
||||
/* FIXME: Still unclear what is it supposed to find */
|
||||
devt = MKDEV(lvinfo.major, lvinfo.minor);
|
||||
if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
|
||||
if ((dev = dev_cache_get_by_devt(cmd, devt)))
|
||||
label_scan_invalidate(dev);
|
||||
}
|
||||
}
|
||||
@@ -1728,13 +1737,19 @@ void label_scan_invalidate_lvs(struct cmd_context *cmd, struct dm_list *lvs)
|
||||
struct lv_list *lvl;
|
||||
dev_t devt;
|
||||
|
||||
/*
|
||||
* FIXME: this is all unnecessary unless there are PVs stacked on LVs,
|
||||
* so we can skip all of this if scan_lvs=0.
|
||||
*/
|
||||
log_debug("invalidating devs for any pvs on lvs");
|
||||
|
||||
if (get_device_list(NULL, &devs, &devs_features)) {
|
||||
if (devs_features & DM_DEVICE_LIST_HAS_UUID) {
|
||||
dm_list_iterate_items(dm_dev, devs)
|
||||
if (dm_dev->uuid &&
|
||||
strncmp(dm_dev->uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1) == 0) {
|
||||
devt = MKDEV(dm_dev->major, dm_dev->minor);
|
||||
if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
|
||||
if ((dev = dev_cache_get_by_devt(cmd, devt)))
|
||||
label_scan_invalidate(dev);
|
||||
}
|
||||
/* ATM no further caching for any lvconvert command
|
||||
@@ -1871,10 +1886,24 @@ int label_scan_open_rw(struct device *dev)
|
||||
|
||||
int label_scan_reopen_rw(struct device *dev)
|
||||
{
|
||||
const char *name;
|
||||
int flags = 0;
|
||||
int prev_fd = dev->bcache_fd;
|
||||
int fd;
|
||||
|
||||
if (dm_list_empty(&dev->aliases)) {
|
||||
log_error("Cannot reopen rw device %d:%d with no valid paths di %d fd %d.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = dev_name(dev);
|
||||
if (!name || name[0] != '/') {
|
||||
log_error("Cannot reopen rw device %d:%d with no valid name di %d fd %d.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dev->flags & DEV_IN_BCACHE)) {
|
||||
if ((dev->bcache_fd != -1) || (dev->bcache_di != -1)) {
|
||||
/* shouldn't happen */
|
||||
@@ -1904,7 +1933,7 @@ int label_scan_reopen_rw(struct device *dev)
|
||||
flags |= O_NOATIME;
|
||||
flags |= O_RDWR;
|
||||
|
||||
fd = open(dev_name(dev), flags, 0777);
|
||||
fd = open(name, flags, 0777);
|
||||
if (fd < 0) {
|
||||
log_error("Failed to open rw %s errno %d di %d fd %d.",
|
||||
dev_name(dev), errno, dev->bcache_di, dev->bcache_fd);
|
||||
|
@@ -272,6 +272,8 @@ static void _lockd_retrive_vg_pv_list(struct volume_group *vg,
|
||||
|
||||
i = 0;
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases))
|
||||
continue;
|
||||
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
|
||||
if (!lock_pvs->path[i]) {
|
||||
log_error("Fail to allocate PV path for VG %s", vg->name);
|
||||
@@ -341,6 +343,8 @@ static void _lockd_retrive_lv_pv_list(struct volume_group *vg,
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (lv_is_on_pv(lv, pvl->pv)) {
|
||||
if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases))
|
||||
continue;
|
||||
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
|
||||
if (!lock_pvs->path[i]) {
|
||||
log_error("Fail to allocate PV path for LV %s/%s",
|
||||
|
@@ -371,7 +371,7 @@ struct format_type {
|
||||
struct labeller *labeller;
|
||||
const char *name;
|
||||
const char *alias;
|
||||
const char *orphan_vg_name;
|
||||
char orphan_vg_name[ID_LEN];
|
||||
struct volume_group *orphan_vg; /* Only one ever exists. */
|
||||
uint32_t features;
|
||||
void *library;
|
||||
|
@@ -2197,7 +2197,7 @@ static int _validate_lock_args_chars(const char *lock_args)
|
||||
|
||||
static int _validate_vg_lock_args(struct volume_group *vg)
|
||||
{
|
||||
if (!_validate_lock_args_chars(vg->lock_args)) {
|
||||
if (!vg->lock_args || !_validate_lock_args_chars(vg->lock_args)) {
|
||||
log_error(INTERNAL_ERROR "VG %s has invalid lock_args chars", vg->name);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1231,14 +1231,23 @@ int remove_mirrors_from_segments(struct logical_volume *lv,
|
||||
const char *get_pvmove_pvname_from_lv_mirr(const struct logical_volume *lv_mirr)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
struct device *dev;
|
||||
|
||||
dm_list_iterate_items(seg, &lv_mirr->segments) {
|
||||
if (!seg_is_mirrored(seg))
|
||||
continue;
|
||||
if (seg_type(seg, 0) == AREA_PV)
|
||||
return dev_name(seg_dev(seg, 0));
|
||||
if (seg_type(seg, 0) == AREA_LV)
|
||||
return dev_name(seg_dev(first_seg(seg_lv(seg, 0)), 0));
|
||||
if (seg_type(seg, 0) == AREA_PV) {
|
||||
dev = seg_dev(seg, 0);
|
||||
if (!dev || dm_list_empty(&dev->aliases))
|
||||
return NULL;
|
||||
return dev_name(dev);
|
||||
}
|
||||
if (seg_type(seg, 0) == AREA_LV) {
|
||||
dev = seg_dev(first_seg(seg_lv(seg, 0)), 0);
|
||||
if (!dev || dm_list_empty(&dev->aliases))
|
||||
return NULL;
|
||||
return dev_name(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@@ -152,6 +152,11 @@ static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
|
||||
struct pv_list *new_pvl = NULL, *pvl2;
|
||||
struct dm_list *pe_ranges;
|
||||
|
||||
if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases)) {
|
||||
log_error("Failed to create PV entry for missing device.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvname = pv_dev_name(pvl->pv);
|
||||
if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
|
||||
log_warn("WARNING: Physical volume %s not allocatable.", pvname);
|
||||
|
@@ -679,6 +679,11 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!pv->dev || dm_list_empty(&pv->dev->aliases)) {
|
||||
log_error("No device found for PV.");
|
||||
return r;
|
||||
}
|
||||
|
||||
log_debug("vgreduce_single VG %s PV %s", vg->name, pv_dev_name(pv));
|
||||
|
||||
if (pv_pe_alloc_count(pv)) {
|
||||
|
@@ -108,6 +108,7 @@ FIELD(LVS, lv, TIM, "RTime", lvid, 26, lvtimeremoved, lv_time_removed, "Removal
|
||||
FIELD(LVS, lv, STR, "Host", lvid, 10, lvhost, lv_host, "Creation host of the LV, if known.", 0)
|
||||
FIELD(LVS, lv, STR_LIST, "Modules", lvid, 0, modules, lv_modules, "Kernel device-mapper modules required for this LV.", 0)
|
||||
FIELD(LVS, lv, BIN, "Historical", lvid, 0, lvhistorical, lv_historical, "Set if the LV is historical.", 0)
|
||||
FIELD(LVS, lv, NUM, "WCacheBlkSize", lvid, 0, writecache_block_size, writecache_block_size, "The writecache block size", 0)
|
||||
/*
|
||||
* End of LVS type fields
|
||||
*/
|
||||
|
@@ -353,6 +353,8 @@ GET_PV_STR_PROPERTY_FN(pv_device_id_type, pv->device_id_type)
|
||||
#define _writecache_writeback_blocks_get prop_not_implemented_get
|
||||
#define _writecache_error_set prop_not_implemented_set
|
||||
#define _writecache_error_get prop_not_implemented_get
|
||||
#define _writecache_block_size_set prop_not_implemented_set
|
||||
#define _writecache_block_size_get prop_not_implemented_get
|
||||
|
||||
#define _vdo_operating_mode_set prop_not_implemented_set
|
||||
#define _vdo_operating_mode_get prop_not_implemented_get
|
||||
|
@@ -3346,6 +3346,26 @@ static int _integritymismatches_disp(struct dm_report *rh __attribute__((unused)
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
static int _writecache_block_size_disp(struct dm_report *rh __attribute__((unused)),
|
||||
struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data,
|
||||
void *private __attribute__((unused)))
|
||||
{
|
||||
struct logical_volume *lv = (struct logical_volume *) data;
|
||||
uint32_t bs = 0;
|
||||
|
||||
if (lv_is_writecache(lv)) {
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
bs = seg->writecache_block_size;
|
||||
}
|
||||
|
||||
if (!bs)
|
||||
return dm_report_field_int32(rh, field, &GET_TYPE_RESERVED_VALUE(num_undef_32));
|
||||
|
||||
return dm_report_field_uint32(rh, field, &bs);
|
||||
}
|
||||
|
||||
static int _datapercent_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
|
@@ -168,6 +168,11 @@ int id_write_format(const struct id *id, char *buffer, size_t size)
|
||||
|
||||
assert(ID_LEN == 32);
|
||||
|
||||
if (id->uuid[0] == '#') {
|
||||
(void) dm_strncpy(buffer, (char*)id->uuid, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* split into groups separated by dashes */
|
||||
if (size < (32 + 6 + 1)) {
|
||||
if (size > 0)
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h> /* help musl C */
|
||||
#include <pthread.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
@@ -61,8 +61,6 @@ and more, using a more compact and configurable output format.
|
||||
.br
|
||||
[ \fB--readonly\fP ]
|
||||
.br
|
||||
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
|
||||
.br
|
||||
[ \fB--segments\fP ]
|
||||
.br
|
||||
[ \fB--separator\fP \fIString\fP ]
|
||||
@@ -332,16 +330,6 @@ device-mapper kernel driver, so this option is unable to report whether
|
||||
or not LVs are actually in use.
|
||||
.
|
||||
.HP
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.br
|
||||
Overrides current output format for reports which is defined globally by
|
||||
the report/output_format setting in \fBlvm.conf\fP(5).
|
||||
\fBbasic\fP is the original format with columns and rows.
|
||||
If there is more than one report per command, each report is prefixed
|
||||
with the report name for identification. \fBjson\fP produces report
|
||||
output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
\fB--segments\fP
|
||||
.br
|
||||
.
|
||||
|
@@ -240,18 +240,59 @@ The writecache block size should be chosen to match the xfs sectsz value.
|
||||
It is also possible to specify a sector size of 4096 to mkfs.xfs when
|
||||
creating the file system. In this case the writecache block size of 4096
|
||||
can be used.
|
||||
.P
|
||||
The writecache block size is displayed by the command:
|
||||
.br
|
||||
lvs -o writecacheblocksize VG/LV
|
||||
.P
|
||||
.SS dm-writecache memory usage
|
||||
.P
|
||||
The amount of main system memory used by dm-writecache can be a factor
|
||||
when selecting the writecache cachevol size and the writecache block size.
|
||||
.P
|
||||
.IP \[bu] 2
|
||||
writecache block size 4096: each 100 GiB of writecache cachevol uses
|
||||
slighly over 2 GiB of system memory.
|
||||
.IP \[bu] 2
|
||||
writecache block size 512: each 100 GiB of writecache cachevol uses
|
||||
a little over 16 GiB of system memory.
|
||||
.
|
||||
.SS dm-writecache settings
|
||||
.
|
||||
Tunable parameters can be passed to the dm-writecache kernel module using
|
||||
the --cachesettings option when caching is started, e.g.
|
||||
To specify dm-writecache tunable settings on the command line, use:
|
||||
.br
|
||||
--cachesettings 'option=N' or
|
||||
.br
|
||||
--cachesettings 'option1=N option2=N ...'
|
||||
.P
|
||||
For example, --cachesettings 'high_watermark=90 writeback_jobs=4'.
|
||||
.P
|
||||
To include settings when caching is started, run:
|
||||
.P
|
||||
.nf
|
||||
# lvconvert --type writecache --cachevol fast \\
|
||||
--cachesettings 'high_watermark=N writeback_jobs=N' vg/main
|
||||
--cachesettings 'option=N' vg/main
|
||||
.fi
|
||||
.P
|
||||
Tunable options are:
|
||||
To change settings for an existing writecache, run:
|
||||
.P
|
||||
.nf
|
||||
# lvchange --cachesettings 'option=N' vg/main
|
||||
.fi
|
||||
.P
|
||||
To clear all settings that have been applied, run:
|
||||
.P
|
||||
.nf
|
||||
# lvchange --cachesettings '' vg/main
|
||||
.fi
|
||||
.P
|
||||
To view the settings that are applied to a writecache LV, run:
|
||||
.P
|
||||
.nf
|
||||
# lvs -o cachesettings vg/main
|
||||
.fi
|
||||
.P
|
||||
Tunable settings are:
|
||||
.
|
||||
.TP
|
||||
high_watermark = <percent>
|
||||
@@ -301,11 +342,14 @@ writecache. Adding cleaner=0 to the splitcache command will skip the
|
||||
cleaner mode, and any required flushing is performed in device suspend.
|
||||
|
||||
.SS dm-writecache using metadata profiles
|
||||
|
||||
Writecache allows to set a variety of options. Lots of these settings
|
||||
can be specified in lvm.conf or profile settings. You can prepare
|
||||
a number of different profiles in the \fI#DEFAULT_SYS_DIR#/profile\fP directory
|
||||
and just specify the metadata profile file name when writecaching LV.
|
||||
.
|
||||
In addition to specifying writecache settings on the command line, they
|
||||
can also be set in lvm.conf, or in a profile file, using the
|
||||
allocation/cache_settings/writecache config structure shown below.
|
||||
.P
|
||||
It's possible to prepare a number of different profile files in the
|
||||
\fI#DEFAULT_SYS_DIR#/profile\fP directory and specify the file name
|
||||
of the profile when starting writecache.
|
||||
.P
|
||||
.I Example
|
||||
.nf
|
||||
@@ -327,11 +371,10 @@ writeback_jobs=1024
|
||||
EOF
|
||||
.P
|
||||
|
||||
# lvcreate -an -L10G --name wcache vg /dev/fast_ssd
|
||||
# lvcreate --type writecache -L10G --name main --cachevol wcache \\
|
||||
# lvcreate -an -L10G --name fast vg /dev/fast_ssd
|
||||
# lvcreate --type writecache -L10G --name main --cachevol fast \\
|
||||
--metadataprofile cache_writecache vg /dev/slow_hdd
|
||||
.fi
|
||||
|
||||
.
|
||||
.SS dm-cache with separate data and metadata LVs
|
||||
.
|
||||
|
@@ -322,7 +322,8 @@ Find a device with the PVID and add the device to the devices file.
|
||||
.HP
|
||||
\fB--check\fP
|
||||
.br
|
||||
Check the content of the devices file.
|
||||
Checks the content of the devices file.
|
||||
Reports incorrect device names or PVIDs for entries.
|
||||
.
|
||||
.HP
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
|
@@ -61,8 +61,6 @@ and more, using a more compact and configurable output format.
|
||||
.br
|
||||
[ \fB--readonly\fP ]
|
||||
.br
|
||||
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
|
||||
.br
|
||||
[ \fB--separator\fP \fIString\fP ]
|
||||
.br
|
||||
[ \fB--shared\fP ]
|
||||
@@ -320,16 +318,6 @@ device-mapper kernel driver, so this option is unable to report whether
|
||||
or not LVs are actually in use.
|
||||
.
|
||||
.HP
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.br
|
||||
Overrides current output format for reports which is defined globally by
|
||||
the report/output_format setting in \fBlvm.conf\fP(5).
|
||||
\fBbasic\fP is the original format with columns and rows.
|
||||
If there is more than one report per command, each report is prefixed
|
||||
with the report name for identification. \fBjson\fP produces report
|
||||
output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.br
|
||||
Select objects for processing and reporting based on specified criteria.
|
||||
|
@@ -15,6 +15,8 @@ pvscan \(em List all physical volumes
|
||||
.P
|
||||
.ad l
|
||||
\fB-a\fP|\fB--activate\fP \fBy\fP|\fBn\fP|\fBay\fP
|
||||
.br
|
||||
\fB--autoactivation\fP \fIString\fP
|
||||
.br
|
||||
\fB--cache\fP
|
||||
.br
|
||||
@@ -91,59 +93,50 @@ like
|
||||
or
|
||||
.BR pvdisplay (8).
|
||||
.P
|
||||
When the --cache and -aay options are used, pvscan records which PVs are
|
||||
available on the system, and activates LVs in completed VGs. A VG is
|
||||
complete when pvscan sees that the final PV in the VG has appeared. This
|
||||
is used by event-based system startup (systemd, udev) to activate LVs.
|
||||
.P
|
||||
The four main variations of this are:
|
||||
When --cache is used, pvscan updates runtime lvm state on the system, or
|
||||
with -aay performs autoactivation.
|
||||
.P
|
||||
.B pvscan --cache
|
||||
.I device
|
||||
.P
|
||||
If device is present, lvm adds a record that the PV on device is online.
|
||||
If device is present, lvm records that the PV on device is online.
|
||||
If device is not present, lvm removes the online record for the PV.
|
||||
In most cases, the pvscan will only read the named devices.
|
||||
.P
|
||||
.B pvscan --cache -aay
|
||||
.IR device ...
|
||||
.P
|
||||
This begins by performing the same steps as above. Afterward, if the VG
|
||||
for the specified PV is complete, then pvscan will activate LVs in the VG
|
||||
(the same as vgchange -aay vgname would do.)
|
||||
pvscan only reads the named device.
|
||||
.P
|
||||
.B pvscan --cache
|
||||
.P
|
||||
This first clears all existing PV online records, then scans all devices
|
||||
on the system, adding PV online records for any PVs that are found.
|
||||
Updates the runtime state for all lvm devices.
|
||||
.P
|
||||
.B pvscan --cache -aay
|
||||
.I device
|
||||
.P
|
||||
Performs the --cache steps for the device, then checks if the VG using the
|
||||
device is complete. If so, LVs in the VG are autoactivated, the same as
|
||||
vgchange -aay vgname would do. (A device name may be replaced with major
|
||||
and minor numbers.)
|
||||
.P
|
||||
.B pvscan --cache -aay
|
||||
.P
|
||||
This begins by performing the same steps as pvscan --cache. Afterward, it
|
||||
activates LVs in any complete VGs.
|
||||
Performs the --cache steps for all devices, then autoactivates any complete VGs.
|
||||
.P
|
||||
To prevent devices from being scanned by pvscan --cache, add them
|
||||
to
|
||||
.BR lvm.conf (5)
|
||||
.B devices/global_filter.
|
||||
For more information, see:
|
||||
.br
|
||||
.B lvmconfig --withcomments devices/global_filter
|
||||
.B pvscan --cache --listvg|--listlvs
|
||||
.I device
|
||||
.P
|
||||
Auto-activation of VGs or LVs can be enabled/disabled using:
|
||||
.br
|
||||
Performs the --cache steps for the device, then prints the name of the VG
|
||||
using the device, or the names of LVs using the device. --checkcomplete
|
||||
is usually included to check if all PVs for the VG or LVs are online.
|
||||
When this command is called by a udev rule, the output must conform to
|
||||
udev rule specifications (see --udevoutput.) The udev rule will use the
|
||||
results to perform autoactivation.
|
||||
.P
|
||||
Autoactivation of VGs or LVs can be enabled/disabled using vgchange or
|
||||
lvchange with --setautoactivation y|n, or by adding names to
|
||||
.BR lvm.conf (5)
|
||||
.B activation/auto_activation_volume_list
|
||||
.P
|
||||
For more information, see:
|
||||
.br
|
||||
.B lvmconfig --withcomments activation/auto_activation_volume_list
|
||||
.P
|
||||
To disable auto-activation, explicitly set this list to an empty list,
|
||||
i.e. auto_activation_volume_list = [ ].
|
||||
.P
|
||||
When this setting is undefined (e.g. commented), then all LVs are
|
||||
auto-activated.
|
||||
See
|
||||
.BR lvmautoactivation (7)
|
||||
for more information about how pvscan is used for autoactivation.
|
||||
.
|
||||
.SH USAGE
|
||||
.
|
||||
@@ -215,6 +208,8 @@ Record that a PV is online and autoactivate the VG if complete.
|
||||
.br
|
||||
[ \fB--noudevsync\fP ]
|
||||
.br
|
||||
[ \fB--autoactivation\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
@@ -239,6 +234,8 @@ Record that a PV is online and list the VG using the PV.
|
||||
.br
|
||||
[ \fB--udevoutput\fP ]
|
||||
.br
|
||||
[ \fB--autoactivation\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
@@ -342,6 +339,14 @@ Auto-activate LVs in a VG when the PVs scanned have completed the VG.
|
||||
(Only \fBay\fP is applicable.)
|
||||
.
|
||||
.HP
|
||||
\fB--autoactivation\fP \fIString\fP
|
||||
.br
|
||||
Specify if autoactivation is being used from an event.
|
||||
This allows the command to apply settings that are specific
|
||||
to event activation, such as device scanning optimizations
|
||||
using pvs_online files created by event-based pvscans.
|
||||
.
|
||||
.HP
|
||||
\fB--cache\fP
|
||||
.br
|
||||
Scan one or more devices and record that they are online.
|
||||
|
@@ -24,6 +24,8 @@ vgchange \(em Change volume group attributes
|
||||
.nh
|
||||
\%\fBcontiguous\fP|\:\fBcling\fP|\:\fBcling_by_tags\fP|\:\fBnormal\fP|\:\fBanywhere\fP|\:\fBinherit\fP
|
||||
.hy
|
||||
.br
|
||||
\fB--autoactivation\fP \fIString\fP
|
||||
.br
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
@@ -286,6 +288,8 @@ Activate or deactivate LVs.
|
||||
.br
|
||||
[ \fB--poll\fP \fBy\fP|\fBn\fP ]
|
||||
.br
|
||||
[ \fB--autoactivation\fP \fIString\fP ]
|
||||
.br
|
||||
[ \fB--ignoremonitoring\fP ]
|
||||
.br
|
||||
[ \fB--noudevsync\fP ]
|
||||
@@ -516,6 +520,14 @@ which PVs the command will use for allocation.
|
||||
See \fBlvm\fP(8) for more information about allocation.
|
||||
.
|
||||
.HP
|
||||
\fB--autoactivation\fP \fIString\fP
|
||||
.br
|
||||
Specify if autoactivation is being used from an event.
|
||||
This allows the command to apply settings that are specific
|
||||
to event activation, such as device scanning optimizations
|
||||
using pvs_online files created by event-based pvscans.
|
||||
.
|
||||
.HP
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies if metadata should be backed up automatically after a change.
|
||||
|
@@ -58,8 +58,6 @@ and more, using a more compact and configurable output format.
|
||||
.br
|
||||
[ \fB--readonly\fP ]
|
||||
.br
|
||||
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
|
||||
.br
|
||||
[ \fB--shared\fP ]
|
||||
.br
|
||||
[ \fB--separator\fP \fIString\fP ]
|
||||
@@ -312,16 +310,6 @@ device-mapper kernel driver, so this option is unable to report whether
|
||||
or not LVs are actually in use.
|
||||
.
|
||||
.HP
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.br
|
||||
Overrides current output format for reports which is defined globally by
|
||||
the report/output_format setting in \fBlvm.conf\fP(5).
|
||||
\fBbasic\fP is the original format with columns and rows.
|
||||
If there is more than one report per command, each report is prefixed
|
||||
with the report name for identification. \fBjson\fP produces report
|
||||
output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.br
|
||||
Select objects for processing and reporting based on specified criteria.
|
||||
|
@@ -33,6 +33,8 @@ aux udev_wait
|
||||
ls -la "${LOOP}"*
|
||||
test -e "${LOOP}p1"
|
||||
|
||||
aux lvmconf 'devices/scan = "/dev"'
|
||||
|
||||
aux extend_filter "a|$LOOP|"
|
||||
aux extend_devices "$LOOP"
|
||||
|
||||
|
@@ -75,7 +75,7 @@ wait_lvm_activate() {
|
||||
local vgw=$1
|
||||
local wait=0
|
||||
|
||||
while systemctl status lvm-activate-$vgw | grep "active (running)" && test "$wait" -le 30; do
|
||||
while systemctl status lvm-activate-$vgw > /dev/null && test "$wait" -le 30; do
|
||||
sleep .2
|
||||
wait=$(( wait + 1 ))
|
||||
done
|
||||
@@ -382,7 +382,6 @@ lvcreate -l1 -an -n $lv1 $vg9
|
||||
lvcreate -l1 -an -n $lv2 $vg9
|
||||
|
||||
mdadm --stop "$mddev"
|
||||
systemctl stop lvm-activate-$vg9 || true
|
||||
_clear_online_files
|
||||
mdadm --assemble "$mddev" "$dev1" "$dev2"
|
||||
|
||||
@@ -405,17 +404,6 @@ mdadm --stop "$mddev"
|
||||
aux udev_wait
|
||||
wipe_all
|
||||
|
||||
systemctl stop lvm-activate-$vg1
|
||||
systemctl stop lvm-activate-$vg2
|
||||
systemctl stop lvm-activate-$vg3
|
||||
systemctl stop lvm-activate-$vg4
|
||||
systemctl stop lvm-activate-$vg5
|
||||
systemctl stop lvm-activate-$vg6
|
||||
systemctl stop lvm-activate-$vg7
|
||||
systemctl stop lvm-activate-$vg8
|
||||
systemctl stop lvm-activate-$vg9
|
||||
|
||||
|
||||
# no devices file, filter with symlink of PV
|
||||
# the pvscan needs to look at all dev names to
|
||||
# match the symlink in the filter with the
|
||||
@@ -439,7 +427,6 @@ udevadm trigger --settle -c add /sys/block/$BDEV1
|
||||
ls /dev/disk/by-id/lvm-pv-uuid-$OPVID1
|
||||
|
||||
vgchange -an $vg10
|
||||
systemctl stop lvm-activate-$vg10
|
||||
_clear_online_files
|
||||
|
||||
aux lvmconf "devices/filter = [ \"a|/dev/disk/by-id/lvm-pv-uuid-$OPVID1|\", \"r|.*|\" ]"
|
||||
|
@@ -19,6 +19,9 @@ _clear_online_files() {
|
||||
|
||||
aux prepare_devs 4
|
||||
|
||||
# skip rhel5 which doesn't seem to have /dev/mapper/LVMTESTpv1
|
||||
aux driver_at_least 4 15 || skip
|
||||
|
||||
DFDIR="$LVM_SYSTEM_DIR/devices"
|
||||
mkdir -p "$DFDIR" || true
|
||||
DF="$DFDIR/system.devices"
|
||||
|
@@ -222,6 +222,8 @@ vgextend $vg "$dev2"
|
||||
lvcreate -n $lv1 -l 8 -an $vg "$dev1"
|
||||
lvcreate -n $lv2 -l 4 -an $vg "$dev2"
|
||||
lvconvert --yes --type writecache --cachevol $lv2 --cachesettings "block_size=4096" $vg/$lv1
|
||||
lvs -o writecacheblocksize $vg/$lv1 |tee out
|
||||
grep 4096 out
|
||||
lvchange -ay $vg/$lv1
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" |tee out
|
||||
grep "sectsz=4096" out
|
||||
|
@@ -190,9 +190,9 @@ command-lines-input.h: $(srcdir)/command-lines.in Makefile
|
||||
$(Q) set -o pipefail && \
|
||||
( cat $(srcdir)/license.inc && \
|
||||
echo "/* Do not edit. This file is generated by the Makefile. */" && \
|
||||
echo -en "const char _command_input[] =\n\n\"" && \
|
||||
echo -en "static const char _command_input[] =\n\n\"" && \
|
||||
$(EGREP) -v '^#|\-\-\-|^$$' $(srcdir)/command-lines.in | $(AWK) 'BEGIN {ORS = "\\n\"\n\""} //' && \
|
||||
echo "\\n\";" \
|
||||
echo "\\n\\n\";" \
|
||||
) > $@
|
||||
|
||||
$(SOURCES:%.c=%.d) $(SOURCES2:%.c=%.d): command-lines-input.h command-count.h cmds.h
|
||||
|
13
tools/args.h
13
tools/args.h
@@ -862,12 +862,13 @@ arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0,
|
||||
"See \\fBlvmcache\\fP(7) for more information.\n")
|
||||
|
||||
arg(cachesettings_ARG, '\0', "cachesettings", string_VAL, ARG_GROUPABLE, 0,
|
||||
"Specifies tunable values for a cache LV in \"Key = Value\" form.\n"
|
||||
"Repeat this option to specify multiple values.\n"
|
||||
"(The default values should usually be adequate.)\n"
|
||||
"The special string value \\fBdefault\\fP switches\n"
|
||||
"settings back to their default kernel values and removes\n"
|
||||
"them from the list of settings stored in LVM metadata.\n"
|
||||
"Specifies tunable kernel options for dm-cache or dm-writecache LVs.\n"
|
||||
"Use the form 'option=value' or 'option1=value option2=value', or\n"
|
||||
"repeat --cachesettings for each option being set.\n"
|
||||
"These settings override the default kernel behaviors which are\n"
|
||||
"usually adequate. To remove cachesettings and revert to the default\n"
|
||||
"kernel behaviors, use --cachesettings 'default' for dm-cache or\n"
|
||||
"an empty string --cachesettings '' for dm-writecache.\n"
|
||||
"See \\fBlvmcache\\fP(7) for more information.\n")
|
||||
|
||||
arg(unconfigured_ARG, '\0', "unconfigured", 0, 0, 0,
|
||||
|
@@ -2549,7 +2549,7 @@ static const char *_man_long_opt_name(const char *cmdname, int opt_enum)
|
||||
}
|
||||
|
||||
if (strchr(long_opt, '[')) {
|
||||
for (i = 0; i < sizeof(long_opt_name) - 1; ++long_opt, ++i) {
|
||||
for (i = 0; *long_opt && i < sizeof(long_opt_name) - 1; ++long_opt, ++i) {
|
||||
if (i < (sizeof(long_opt_name) - 8))
|
||||
switch(*long_opt) {
|
||||
case '[':
|
||||
|
@@ -1488,7 +1488,7 @@ int process_each_label(struct cmd_context *cmd, int argc, char **argv,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(dev = dev_cache_get(cmd, argv[opt], cmd->filter))) {
|
||||
if (!(dev = dev_cache_get_existing(cmd, argv[opt], cmd->filter))) {
|
||||
log_error("Failed to find device "
|
||||
"\"%s\".", argv[opt]);
|
||||
ret_max = ECMD_FAILED;
|
||||
@@ -3925,7 +3925,7 @@ static int _get_arg_devices(struct cmd_context *cmd,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(dil->dev = dev_cache_get(cmd, sl->str, cmd->filter))) {
|
||||
if (!(dil->dev = dev_cache_get_existing(cmd, sl->str, cmd->filter))) {
|
||||
log_error("Cannot use %s: %s", sl->str, devname_error_reason(sl->str));
|
||||
ret_max = EINIT_FAILED;
|
||||
} else {
|
||||
@@ -5261,7 +5261,7 @@ int pvcreate_each_device(struct cmd_context *cmd,
|
||||
struct device *dev;
|
||||
|
||||
/* No filter used here */
|
||||
if (!(dev = dev_cache_get(cmd, pd->name, NULL))) {
|
||||
if (!(dev = dev_cache_get_existing(cmd, pd->name, NULL))) {
|
||||
log_error("No device found for %s.", pd->name);
|
||||
dm_list_del(&pd->list);
|
||||
dm_list_add(&pp->arg_fail, &pd->list);
|
||||
|
Reference in New Issue
Block a user