mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-30 17:44:21 +03:00
Compare commits
1 Commits
dev-dct-vg
...
dev-dct-pv
Author | SHA1 | Date | |
---|---|---|---|
|
f59cb6632b |
@@ -1,7 +1,5 @@
|
||||
version 2.03.19 -
|
||||
====================================
|
||||
Do not reset SYSTEMD_READY variable in udev for PVs on MD and loop devices.
|
||||
Ensure udev is processing origin LV before its thick snapshots LVs.
|
||||
Fix and improve runtime memory size detection for VDO volumes.
|
||||
|
||||
version 2.03.18 - 22nd december 2022
|
||||
|
@@ -1,6 +1,5 @@
|
||||
Version 1.02.191 -
|
||||
=====================================
|
||||
Remove NAME="mapper/control" rule from 10-dm.rules to avoid udev warnings.
|
||||
|
||||
Version 1.02.189 - 22nd December 2022
|
||||
=====================================
|
||||
|
@@ -928,8 +928,8 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
start = now;
|
||||
now -= start;
|
||||
if (_debug_level)
|
||||
fprintf(stream, "[%2lld:%02lld] %8x:%-6s%s",
|
||||
(long long)now / 60, (long long)now % 60,
|
||||
fprintf(stream, "[%2ld:%02ld] %8x:%-6s%s",
|
||||
(long)now / 60, (long)now % 60,
|
||||
// TODO: Maybe use shorter ID
|
||||
// ((int)(pthread_self()) >> 6) & 0xffff,
|
||||
(int)pthread_self(), subsys,
|
||||
|
@@ -294,10 +294,6 @@ struct load_properties {
|
||||
unsigned send_messages;
|
||||
/* Skip suspending node's children, used when sending messages to thin-pool */
|
||||
int skip_suspend;
|
||||
|
||||
/* Suspend and Resume siblings after node activation with udev flags*/
|
||||
unsigned reactivate_siblings;
|
||||
uint16_t reactivate_udev_flags;
|
||||
};
|
||||
|
||||
/* Two of these used to join two nodes with uses and used_by. */
|
||||
@@ -2034,68 +2030,6 @@ static int _rename_conflict_exists(struct dm_tree_node *parent,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reactivation of sibling nodes
|
||||
*
|
||||
* Function is used when activating origin and its thick snapshots
|
||||
* to ensure udev is processing first the origin LV and all the
|
||||
* snapshot LVs are processed afterwards.
|
||||
*/
|
||||
static int _reactivate_siblings(struct dm_tree_node *dnode,
|
||||
const char *uuid_prefix,
|
||||
size_t uuid_prefix_len)
|
||||
{
|
||||
struct dm_tree_node *child;
|
||||
const char *uuid;
|
||||
void *handle = NULL;
|
||||
int r = 1;
|
||||
|
||||
/* Wait for udev before reactivating siblings */
|
||||
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
|
||||
stack;
|
||||
|
||||
dm_tree_set_cookie(dnode, 0);
|
||||
|
||||
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
|
||||
if (child->props.reactivate_siblings) {
|
||||
/* Skip 'leading' device in this group, marked with flag */
|
||||
child->props.reactivate_siblings = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(uuid = dm_tree_node_get_uuid(child))) {
|
||||
stack;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
|
||||
continue;
|
||||
|
||||
if (!_suspend_node(child->name, child->info.major, child->info.minor,
|
||||
child->dtree->skip_lockfs,
|
||||
child->dtree->no_flush, &child->info)) {
|
||||
log_error("Unable to suspend %s (" FMTu32
|
||||
":" FMTu32 ")", child->name,
|
||||
child->info.major, child->info.minor);
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
if (!_resume_node(child->name, child->info.major, child->info.minor,
|
||||
child->props.read_ahead, child->props.read_ahead_flags,
|
||||
&child->info, &child->dtree->cookie,
|
||||
child->props.reactivate_udev_flags, // use these flags
|
||||
child->info.suspended)) {
|
||||
log_error("Failed to suspend %s (" FMTu32
|
||||
":" FMTu32 ")", child->name,
|
||||
child->info.major, child->info.minor);
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_tree_activate_children(struct dm_tree_node *dnode,
|
||||
const char *uuid_prefix,
|
||||
size_t uuid_prefix_len)
|
||||
@@ -2106,7 +2040,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
|
||||
struct dm_tree_node *child = dnode;
|
||||
const char *name;
|
||||
const char *uuid;
|
||||
int priority, next_priority;
|
||||
int priority;
|
||||
|
||||
/* Activate children first */
|
||||
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
|
||||
@@ -2124,16 +2058,12 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
|
||||
}
|
||||
|
||||
handle = NULL;
|
||||
|
||||
for (priority = 0; priority < 3; priority++) {
|
||||
awaiting_peer_rename = 0;
|
||||
next_priority = 0;
|
||||
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
|
||||
if (priority != child->activation_priority) {
|
||||
if ((next_priority < child->activation_priority) &&
|
||||
(child->activation_priority > priority))
|
||||
next_priority = child->activation_priority;
|
||||
if (priority != child->activation_priority)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(uuid = dm_tree_node_get_uuid(child))) {
|
||||
stack;
|
||||
@@ -2188,16 +2118,9 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
|
||||
if (r && (child->props.send_messages > 1) &&
|
||||
!(r = _node_send_messages(child, uuid_prefix, uuid_prefix_len, 1)))
|
||||
stack;
|
||||
|
||||
/* Reactivate only for fresh activated origin */
|
||||
if (r && child->props.reactivate_siblings &&
|
||||
(!(r = _reactivate_siblings(dnode, uuid_prefix, uuid_prefix_len))))
|
||||
stack;
|
||||
}
|
||||
if (awaiting_peer_rename)
|
||||
priority--; /* redo priority level */
|
||||
else if (!next_priority)
|
||||
break; /* no more work, higher priority was not found in the chain */
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -3526,10 +3449,6 @@ int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
|
||||
/* Resume snapshot origins after new snapshots */
|
||||
dnode->activation_priority = 1;
|
||||
|
||||
if (!dnode->info.exists)
|
||||
/* Reactivate siblings for this origin after being resumed */
|
||||
dnode->props.reactivate_siblings = 1;
|
||||
|
||||
/*
|
||||
* Don't resume the origin immediately in case it is a non-trivial
|
||||
* target that must not be active more than once concurrently!
|
||||
@@ -3592,20 +3511,6 @@ static int _add_snapshot_target(struct dm_tree_node *node,
|
||||
/* Resume merging snapshot after snapshot-merge */
|
||||
seg->merge->activation_priority = 2;
|
||||
}
|
||||
} else if (!origin_node->info.exists) {
|
||||
/* Keep original udev_flags for reactivation. */
|
||||
node->props.reactivate_udev_flags = node->udev_flags;
|
||||
|
||||
/* Reactivation is needed if the origin's -real device is not in DM table.
|
||||
* For this case after the resume of its origin LV we resume its snapshots
|
||||
* with updated udev_flags to completely avoid udev scanning for the first resume.
|
||||
* Reactivation then resumes snapshots with original udev_flags.
|
||||
*/
|
||||
node->udev_flags |= DM_SUBSYSTEM_UDEV_FLAG0 |
|
||||
DM_UDEV_DISABLE_DISK_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_OTHER_RULES_FLAG;
|
||||
log_debug_activation("Using udev_flags 0x%x for activation of %s.",
|
||||
node->udev_flags, node->name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@@ -194,7 +194,6 @@ struct cmd_context {
|
||||
unsigned create_edit_devices_file:1; /* command expects to create and/or edit devices file */
|
||||
unsigned edit_devices_file:1; /* command expects to edit devices file */
|
||||
unsigned filter_deviceid_skip:1; /* don't use filter-deviceid */
|
||||
unsigned filter_regex_skip:1; /* don't use filter-regex */
|
||||
unsigned filter_regex_with_devices_file:1; /* use filter-regex even when devices file is enabled */
|
||||
unsigned filter_nodata_only:1; /* only use filters that do not require data from the dev */
|
||||
unsigned run_by_dmeventd:1; /* command is being run by dmeventd */
|
||||
@@ -208,7 +207,6 @@ struct cmd_context {
|
||||
unsigned udevoutput:1;
|
||||
unsigned online_vg_file_removed:1;
|
||||
unsigned disable_dm_devs:1; /* temporarily disable use of dm devs cache */
|
||||
unsigned filter_regex_set_preferred_name_disable:1; /* prevent dev_set_preferred_name */
|
||||
|
||||
/*
|
||||
* Devices and filtering.
|
||||
|
@@ -52,6 +52,7 @@ static struct {
|
||||
struct dm_regex *preferred_names_matcher;
|
||||
const char *dev_dir;
|
||||
|
||||
int preferred_names_disabled;
|
||||
int has_scanned;
|
||||
long st_dev;
|
||||
struct dm_list dirs;
|
||||
@@ -166,11 +167,19 @@ void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev)
|
||||
if (_cache.preferred_names_matcher)
|
||||
return;
|
||||
|
||||
if (_cache.preferred_names_disabled)
|
||||
return;
|
||||
|
||||
log_debug_devs("%s: New preferred name", sl->str);
|
||||
dm_list_del(&sl->list);
|
||||
dm_list_add_h(&dev->aliases, &sl->list);
|
||||
}
|
||||
|
||||
void dev_cache_disable_preferred_names(void)
|
||||
{
|
||||
_cache.preferred_names_disabled = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether path0 or path1 contains the subpath. The path that
|
||||
* *does not* contain the subpath wins (return 0 or 1). If both paths
|
||||
|
@@ -61,6 +61,8 @@ struct device *dev_hash_get(const char *name);
|
||||
|
||||
void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev);
|
||||
|
||||
void dev_cache_disable_preferred_names(void);
|
||||
|
||||
/*
|
||||
* Object for iterating through the cache.
|
||||
*/
|
||||
|
@@ -94,19 +94,6 @@ static int _get_crypt_path(dev_t lv_devt, char *lv_path, char *crypt_path)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lv_crypt_is_active(struct cmd_context *cmd, char *lv_path)
|
||||
{
|
||||
char crypt_path[PATH_MAX];
|
||||
struct stat st_lv;
|
||||
|
||||
if (stat(lv_path, &st_lv) < 0) {
|
||||
log_error("Failed to get LV path %s", lv_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _get_crypt_path(st_lv.st_rdev, lv_path, crypt_path);
|
||||
}
|
||||
|
||||
int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct fs_info *fsi, int include_mount)
|
||||
{
|
||||
@@ -162,7 +149,7 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
log_print("Checking crypt device %s on LV %s.",
|
||||
log_print("File system found on crypt device %s on LV %s.",
|
||||
crypt_path, display_lvname(lv));
|
||||
|
||||
if ((fd = open(crypt_path, O_RDONLY)) < 0) {
|
||||
@@ -227,116 +214,6 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype)
|
||||
{
|
||||
FILE *fp;
|
||||
char proc_line[PATH_MAX];
|
||||
char proc_fstype[FSTYPE_MAX];
|
||||
char proc_devpath[1024];
|
||||
char proc_mntpath[1024];
|
||||
char lv_mapper_path[1024];
|
||||
char mntent_mount_dir[1024];
|
||||
char *dm_name;
|
||||
struct stat st_lv;
|
||||
struct stat stme;
|
||||
FILE *fme = NULL;
|
||||
struct mntent *me;
|
||||
int renamed = 0;
|
||||
int found_dir = 0;
|
||||
int found_dev = 0;
|
||||
int dev_match, dir_match;
|
||||
|
||||
if (stat(lv_path, &st_lv) < 0) {
|
||||
log_error("Failed to get LV path %s", lv_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If LVs have been renamed while their file systems were mounted, then
|
||||
* inconsistencies appear in the device path and mount point info
|
||||
* provided by getmntent and /proc/mounts. If there's any
|
||||
* inconsistency or duplication of info for the LV name or the mount
|
||||
* point, then give up and don't try fs resize which is likely to fail
|
||||
* due to kernel problems where mounts reference old device names
|
||||
* causing fs resizing tools to fail.
|
||||
*/
|
||||
|
||||
if (!(fme = setmntent("/etc/mtab", "r")))
|
||||
return_0;
|
||||
|
||||
while ((me = getmntent(fme))) {
|
||||
if (strcmp(me->mnt_type, fstype))
|
||||
continue;
|
||||
if (me->mnt_dir[0] != '/')
|
||||
continue;
|
||||
if (me->mnt_fsname[0] != '/')
|
||||
continue;
|
||||
if (stat(me->mnt_dir, &stme) < 0)
|
||||
continue;
|
||||
if (stme.st_dev != st_lv.st_rdev)
|
||||
continue;
|
||||
strncpy(mntent_mount_dir, me->mnt_dir, PATH_MAX-1);
|
||||
}
|
||||
endmntent(fme);
|
||||
|
||||
if (!(dm_name = dm_build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
|
||||
return_0;
|
||||
|
||||
if ((dm_snprintf(lv_mapper_path, 1024, "%s/%s", dm_dir(), dm_name) < 0))
|
||||
return_0;
|
||||
|
||||
if (!(fp = fopen("/proc/mounts", "r")))
|
||||
return_0;
|
||||
|
||||
while (fgets(proc_line, sizeof(proc_line), fp)) {
|
||||
if (proc_line[0] != '/')
|
||||
continue;
|
||||
if (sscanf(proc_line, "%s %s %s", proc_devpath, proc_mntpath, proc_fstype) != 3)
|
||||
continue;
|
||||
if (strcmp(fstype, proc_fstype))
|
||||
continue;
|
||||
|
||||
dir_match = !strcmp(mntent_mount_dir, proc_mntpath);
|
||||
dev_match = !strcmp(lv_mapper_path, proc_devpath);
|
||||
|
||||
if (dir_match)
|
||||
found_dir++;
|
||||
if (dev_match)
|
||||
found_dev++;
|
||||
|
||||
if (dir_match != dev_match) {
|
||||
log_error("LV %s mounted at %s may have been renamed (from %s).",
|
||||
lv_mapper_path, proc_mntpath, proc_devpath);
|
||||
renamed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(fp))
|
||||
stack;
|
||||
|
||||
/*
|
||||
* Don't try resizing if:
|
||||
* - different device names apppear for the mount point
|
||||
* (LVs probably renamed while mounted), or
|
||||
* - the mount point for the LV appears multiple times, or
|
||||
* - the LV device is listed for multiple mounts.
|
||||
*/
|
||||
if (renamed) {
|
||||
log_error("File system resizing not supported: fs utilities do not support renamed devices.");
|
||||
return 1;
|
||||
}
|
||||
/* These two are likely detected as renamed, but include checks in case. */
|
||||
if (found_dir > 1) {
|
||||
log_error("File system resizing not supported: %s appears more than once in /proc/mounts.", mntent_mount_dir);
|
||||
return 1;
|
||||
}
|
||||
if (found_dev > 1) {
|
||||
log_error("File system resizing not supported: %s appears more than once in /proc/mounts.", lv_mapper_path);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FS_CMD_MAX_ARGS 16
|
||||
|
||||
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
|
@@ -48,8 +48,4 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
|
||||
uint64_t newsize_bytes, char *fsmode);
|
||||
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes_fs);
|
||||
|
||||
int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype);
|
||||
int lv_crypt_is_active(struct cmd_context *cmd, char *lv_path);
|
||||
|
||||
#endif
|
||||
|
@@ -161,9 +161,6 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
|
||||
if (cmd->enable_devices_list)
|
||||
return 1;
|
||||
|
||||
if (cmd->filter_regex_skip)
|
||||
return 1;
|
||||
|
||||
if (cmd->enable_devices_file && !cmd->filter_regex_with_devices_file) {
|
||||
/* can't warn in create_filter because enable_devices_file is set later */
|
||||
if (rf->config_filter && !rf->warned_filter) {
|
||||
@@ -182,7 +179,7 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
|
||||
|
||||
if (m >= 0) {
|
||||
if (dm_bit(rf->accept, m)) {
|
||||
if (!first && !cmd->filter_regex_set_preferred_name_disable)
|
||||
if (!first)
|
||||
dev_set_preferred_name(sl, dev);
|
||||
|
||||
return 1;
|
||||
@@ -253,48 +250,3 @@ struct dev_filter *regex_filter_create(const struct dm_config_value *patterns, i
|
||||
dm_pool_destroy(mem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _filter_contains_symlink(struct cmd_context *cmd, int filter_cfg)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
const struct dm_config_value *cv;
|
||||
const char *fname;
|
||||
|
||||
if ((cn = find_config_tree_array(cmd, filter_cfg, NULL))) {
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != DM_CFG_STRING)
|
||||
continue;
|
||||
if (!cv->v.str)
|
||||
continue;
|
||||
|
||||
fname = cv->v.str;
|
||||
|
||||
if (fname[0] != 'a')
|
||||
continue;
|
||||
|
||||
if (strstr(fname, "/dev/disk/"))
|
||||
return 1;
|
||||
if (strstr(fname, "/dev/mapper/"))
|
||||
return 1;
|
||||
|
||||
/* In case /dev/disk/by was omitted */
|
||||
if (strstr(fname, "lvm-pv-uuid"))
|
||||
return 1;
|
||||
if (strstr(fname, "dm-uuid"))
|
||||
return 1;
|
||||
if (strstr(fname, "wwn-"))
|
||||
return 1;
|
||||
if (strstr(fname, "pci-"))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regex_filter_contains_symlink(struct cmd_context *cmd)
|
||||
{
|
||||
return _filter_contains_symlink(cmd, devices_filter_CFG) ||
|
||||
_filter_contains_symlink(cmd, devices_global_filter_CFG);
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,4 @@ struct dev_filter *usable_filter_create(struct cmd_context *cmd, struct dev_type
|
||||
#define DEV_FILTERED_DEVICES_LIST 0x00001000
|
||||
#define DEV_FILTERED_IS_LV 0x00002000
|
||||
|
||||
int regex_filter_contains_symlink(struct cmd_context *cmd);
|
||||
|
||||
#endif /* _LVM_FILTER_H */
|
||||
|
@@ -219,7 +219,7 @@ static void _remove_expired(const char *dir, const char *vgname,
|
||||
|
||||
sum /= 1024 * 1024;
|
||||
if (sum > 128 || archives_size > 8192)
|
||||
log_print_unless_silent("Consider pruning %s VG archive with more then %u MiB in %u files (see archiving settings in lvm.conf).",
|
||||
log_print_unless_silent("Consider pruning %s VG archive with more then %u MiB in %u files (check archiving is needed in lvm.conf).",
|
||||
vgname, (unsigned)sum, archives_size);
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,6 @@
|
||||
#include "lib/format_text/layout.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/device/online.h"
|
||||
#include "lib/filters/filter.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -1100,20 +1099,6 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||
log_debug("Skipping device_id filtering due to devname ids.");
|
||||
}
|
||||
|
||||
/*
|
||||
* See corresponding code in pvscan. This function is used during
|
||||
* startup autoactivation when udev has not created all symlinks, so
|
||||
* regex filter containing symlinks doesn't work. pvscan has code
|
||||
* to properly check devs against the filter using DEVLINKS. The
|
||||
* pvscan will only create pvs_online files for devs that pass the
|
||||
* filter. We get devs from the pvs_online files, so we inherit the
|
||||
* regex filtering from pvscan and don't have to do it ourself.
|
||||
*/
|
||||
if (!cmd->enable_devices_file &&
|
||||
!cmd->enable_devices_list &&
|
||||
regex_filter_contains_symlink(cmd))
|
||||
cmd->filter_regex_skip = 1;
|
||||
|
||||
cmd->filter_nodata_only = 1;
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &devs) {
|
||||
@@ -1194,8 +1179,6 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||
if (relax_deviceid_filter)
|
||||
cmd->filter_deviceid_skip = 0;
|
||||
|
||||
cmd->filter_regex_skip = 0;
|
||||
|
||||
free_po_list(&pvs_online);
|
||||
|
||||
if (dm_list_empty(&devs)) {
|
||||
|
@@ -6939,13 +6939,6 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
log_error("File system not found for --resizefs or --fs options.");
|
||||
goto out;
|
||||
}
|
||||
if (!strcmp(fstype, "crypto_LUKS") && !lv_crypt_is_active(cmd, lv_path)) {
|
||||
log_error("LUKS dm-crypt device must be active for fs resize.");
|
||||
goto out;
|
||||
}
|
||||
/* FS utils will fail if LVs were renamed while mounted. */
|
||||
if (fs_mount_state_is_misnamed(cmd, lv_top, lv_path, fstype))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -3571,6 +3571,12 @@ static void _set_pv_device(struct format_instance *fid,
|
||||
if (!pv->dev)
|
||||
pv->status |= MISSING_PV;
|
||||
|
||||
/* is this correct? */
|
||||
if ((pv->status & MISSING_PV) && pv->dev && (pv_mda_used_count(pv) == 0)) {
|
||||
pv->status &= ~MISSING_PV;
|
||||
log_info("Found a previously MISSING PV %s with no MDAs.", pv_dev_name(pv));
|
||||
}
|
||||
|
||||
/* Fix up pv size if missing or impossibly large */
|
||||
if ((!pv->size || pv->size > (1ULL << 62)) && pv->dev) {
|
||||
if (!dev_get_size(pv->dev, &pv->size)) {
|
||||
@@ -4637,9 +4643,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
struct volume_group *vg, *vg_ret = NULL;
|
||||
struct metadata_area *mda, *mda2;
|
||||
unsigned use_precommitted = precommitted;
|
||||
struct device *mda_dev, *dev_ret = NULL;
|
||||
struct device *mda_dev, *dev_ret = NULL, *dev;
|
||||
struct cached_vg_fmtdata *vg_fmtdata = NULL; /* Additional format-specific data about the vg */
|
||||
struct pv_list *pvl;
|
||||
int found_old_metadata = 0;
|
||||
int found_md_component = 0;
|
||||
unsigned use_previous_vg;
|
||||
|
||||
log_debug_metadata("Reading VG %s %s", vgname ?: "<no name>", vgid ?: "<no vgid>");
|
||||
@@ -4858,6 +4866,46 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Usually md components are eliminated during label scan, or duplicate
|
||||
* resolution, but sometimes an md component can get through and be
|
||||
* detected in set_pv_device() (which will do an md component check if
|
||||
* the device/PV sizes don't match.) In this case we need to fix up
|
||||
* lvmcache to drop the component dev and fix up metadata_areas_in_use
|
||||
* to drop it also.
|
||||
*/
|
||||
if (found_md_component) {
|
||||
dm_list_iterate_items(pvl, &vg_ret->pvs) {
|
||||
if (!(dev = lvmcache_device_from_pv_id(cmd, &pvl->pv->id, NULL)))
|
||||
continue;
|
||||
|
||||
/* dev_is_md_component set this flag if it was found */
|
||||
if (!(dev->flags & DEV_IS_MD_COMPONENT))
|
||||
continue;
|
||||
|
||||
log_debug_metadata("Drop dev for MD component from cache %s.", dev_name(dev));
|
||||
lvmcache_del_dev(dev);
|
||||
|
||||
dm_list_iterate_items(mda, &fid->metadata_areas_in_use)
|
||||
if (mda_get_device(mda) == dev) {
|
||||
log_debug_metadata("Drop mda from MD component from mda list %s.", dev_name(dev));
|
||||
dm_list_del(&mda->list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* After dropping MD components there may be no remaining legitimate
|
||||
* devices for this VG.
|
||||
*/
|
||||
if (!lvmcache_vginfo_from_vgid(vgid)) {
|
||||
log_debug_metadata("VG %s not found on any remaining devices.", vgname);
|
||||
release_vg(vg_ret);
|
||||
vg_ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Correct the lvmcache representation of the VG using the metadata
|
||||
* that we have chosen above (vg_ret).
|
||||
|
@@ -184,19 +184,6 @@ system from booting. A custom systemd service could be written to run
|
||||
autoactivation during system startup, in which case disabling event
|
||||
autoactivation may be useful.
|
||||
.
|
||||
.SS lvm.conf filter
|
||||
.P
|
||||
Device symlinks from /dev/disk/ can be used in the lvm.conf filter to
|
||||
guard against changes in kernel device names. The /dev/disk/by-path/ or
|
||||
/dev/disk/by-id/ prefixes should be included in the filter names; these
|
||||
prefixes help lvm detect that symlink names are used. Filters containing
|
||||
symlinks require special matching by commands run in the lvm udev rule.
|
||||
.P
|
||||
Common symlinks, e.g. beginning with wwn-, scsi-, pci-, or lvm-pv-uuid-,
|
||||
are recommended. Uncommon or custom symlinks created by custom udev rules
|
||||
may be less reliable. If a custom udev rule creates symlinks used in the
|
||||
lvm filter, then the udev rule should be started prior to the lvm rule.
|
||||
.
|
||||
.SH EXAMPLES
|
||||
.P
|
||||
VG "vg" contains two PVs:
|
||||
|
@@ -262,17 +262,6 @@ umount "$mount_dir"
|
||||
lvchange -an $vg/$lv
|
||||
lvremove $vg/$lv
|
||||
|
||||
# lvextend|lvreduce, ext4, active, mounted, --fs resize, renamed LV
|
||||
lvcreate -n $lv -L 256M $vg
|
||||
mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
|
||||
mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
|
||||
lvrename $vg/$lv $vg/$lv2
|
||||
not lvextend --fs resize -L+32M $vg/$lv2
|
||||
not lvreduce --fs resize -L-32M $vg/$lv2
|
||||
umount "$mount_dir"
|
||||
lvchange -an $vg/$lv2
|
||||
lvremove $vg/$lv2
|
||||
|
||||
|
||||
#
|
||||
# lvextend, xfs
|
||||
|
@@ -28,12 +28,8 @@ lvs -a -o+devices
|
||||
# Fail one leg of each mirror LV.
|
||||
aux disable_dev "$dev1"
|
||||
|
||||
pvs -o+missing |tee out
|
||||
grep missing out |tee out2
|
||||
grep unknown out2
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial "partial"
|
||||
check vg_field $vg vg_missing_pv_count 1
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Cannot do normal activate of either LV with a failed leg.
|
||||
@@ -44,12 +40,8 @@ not lvchange -ay $vg/$lv2
|
||||
lvchange -ay --activationmode partial $vg/$lv1
|
||||
lvchange -ay --activationmode partial $vg/$lv2
|
||||
|
||||
pvs -o+missing |tee out
|
||||
grep missing out |tee out2
|
||||
grep unknown out2
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial "partial"
|
||||
check vg_field $vg vg_missing_pv_count 1
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Repair lv1 so it no longer uses failed dev.
|
||||
@@ -62,12 +54,8 @@ pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
pvs -o+missing |tee out
|
||||
grep missing out |tee out2
|
||||
grep unknown out2
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial "partial"
|
||||
check vg_field $vg vg_missing_pv_count 1
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Verify normal activation is possible of lv1 since it's
|
||||
@@ -80,12 +68,8 @@ vgchange -an $vg
|
||||
|
||||
aux enable_dev "$dev1"
|
||||
|
||||
pvs -o+missing |tee out
|
||||
grep missing out |tee out2
|
||||
grep "$dev1" out2
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial "partial"
|
||||
check vg_field $vg vg_missing_pv_count 1
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# TODO: check that lv2 has partial flag, lv1 does not
|
||||
@@ -98,6 +82,7 @@ pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
|
||||
# The missing pv restrictions still apply even after
|
||||
# the dev has reappeared since it has the MISSING flag.
|
||||
not lvchange -ay $vg/$lv2
|
||||
@@ -113,75 +98,52 @@ not lvcreate -l1 $vg
|
||||
# explicitly writes/fixes metadata.
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs -o+missing |tee out
|
||||
grep missing out |tee out2
|
||||
grep "$dev1" out2
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial "partial"
|
||||
check vg_field $vg vg_missing_pv_count 1
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Check that MISSING flag is still set in ondisk metadata since the
|
||||
# previously missing dev is still used by lv2.
|
||||
# Check that MISSING flag is still set in ondisk
|
||||
# metadata since the previously missing dev is still
|
||||
# used by lv2.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
# The missing pv restrictions still apply since it has the MISSING flag.
|
||||
|
||||
# The missing pv restrictions still apply since it
|
||||
# has the MISSING flag.
|
||||
not lvchange -ay $vg/$lv2
|
||||
not lvcreate -l1 $vg
|
||||
|
||||
lvchange -ay --activationmode partial $vg/$lv2
|
||||
|
||||
# Replace the missing leg of LV2 so no LV will be using the dev that was
|
||||
# missing. The MISSING_PV flag will not have been cleared from the
|
||||
# metadata yet; that will take another metadata update.
|
||||
# After repair, no more LVs will be using the previously
|
||||
# missing PV.
|
||||
lvconvert --repair --yes $vg/$lv2
|
||||
|
||||
lvs -a -o+devices | tee out
|
||||
not grep "$dev1" out
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# The MISSING_PV flag hasn't been cleared from the metadata yet, but now
|
||||
# that the PV is not used by any more LVs, that flag will be cleared from
|
||||
# the metadata in the next update.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
vgchange -an $vg
|
||||
|
||||
# Reporting commands run vg_read which sees MISSING_PV in the metadata,
|
||||
# but vg_read then sees the dev is no longer used by any LV, so vg_read
|
||||
# clears the MISSING_PV flag in the vg struct (not in the metadata) before
|
||||
# returning the vg struct to the caller. It's cleared in the vg struct so
|
||||
# that the limitations of having a missing PV are not applied to the
|
||||
# command. The caller sees/uses/reports the VG as having no missing PV,
|
||||
# even though the metadata still contains MISSING_PV. The MISSING_PV flag
|
||||
# is no longer needed in the metadata, but there has simply not been a
|
||||
# metadata update yet to clear it.
|
||||
# The message that's printed in this case is:
|
||||
# WARNING: VG %s has unused reappeared PV %s %s
|
||||
pvs -o+missing |tee out
|
||||
not grep missing out
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial ""
|
||||
check vg_field $vg vg_missing_pv_count 0
|
||||
# The next write of the metadata will clear the MISSING
|
||||
# flag in ondisk metadata because the previously missing
|
||||
# PV is no longer used by any LVs.
|
||||
|
||||
# Run any command that updates the metadata, and the MISSING_PV flag will
|
||||
# be cleared. Here just use lvcreate -l1, or we could use
|
||||
# vgck --updatemetadata.
|
||||
# Run a command to write ondisk metadata, which should clear
|
||||
# the MISSING flag, could also use vgck --updatemetadata vg.
|
||||
lvcreate -l1 $vg
|
||||
|
||||
# Now the MISSING flag is removed from the ondisk metadata.
|
||||
# Check that the MISSING flag is no longer set
|
||||
# in the ondisk metadata.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
not grep MISSING meta
|
||||
rm meta
|
||||
|
||||
# and commands continue to report no missing PV
|
||||
pvs -o+missing |tee out
|
||||
not grep missing out
|
||||
vgs -o+partial,missing_pv_count
|
||||
check vg_field $vg vg_partial ""
|
||||
check vg_field $vg vg_missing_pv_count 0
|
||||
|
||||
vgchange -an $vg
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
vgremove -ff $vg
|
||||
|
@@ -22,7 +22,7 @@ print_lvmlocal() {
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 5
|
||||
aux prepare_devs 1
|
||||
|
||||
SIDFILE="etc/lvm_test.conf"
|
||||
LVMLOCAL="etc/lvmlocal.conf"
|
||||
@@ -541,73 +541,6 @@ echo "$SID1" > "$SIDFILE"
|
||||
clear_df_systemid
|
||||
vgremove $vg1
|
||||
|
||||
# vgchange --systemid --majoritypvs
|
||||
SID1=sidfoofile1
|
||||
SID2=sidfoofile2
|
||||
rm -f "$LVMLOCAL"
|
||||
echo "$SID1" > "$SIDFILE"
|
||||
clear_df_systemid
|
||||
aux lvmconf "global/system_id_source = file" \
|
||||
"global/system_id_file = \"$SIDFILE\""
|
||||
# create a vg
|
||||
vgcreate $vg1 "$dev1" "$dev2" "$dev3"
|
||||
vgcreate $vg2 "$dev4" "$dev5"
|
||||
# normal vgs sees the vg
|
||||
# change the local system_id, making the vg foreign
|
||||
echo "$SID2" > "$SIDFILE"
|
||||
clear_df_systemid
|
||||
# normal vgs doesn't see the vg
|
||||
vgs >err
|
||||
not grep $vg1 err
|
||||
not grep $vg2 err
|
||||
# using --foreign we can see the vg
|
||||
vgs --foreign >err
|
||||
grep $vg1 err
|
||||
grep $vg2 err
|
||||
# cannot clear the system_id of the foreign vg
|
||||
not vgchange --yes --systemid "" $vg1
|
||||
not vgchange --yes --systemid "" $vg2
|
||||
# cannot set the system_id of the foreign vg
|
||||
not vgchange --yes --systemid foo $vg1
|
||||
not vgchange --yes --systemid foo $vg2
|
||||
# we are local node SID2, foreign node is SID1
|
||||
# use extra_system_ids to take over the foreign vg, making it local
|
||||
vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1
|
||||
vgs $vg1
|
||||
# make it foreign again
|
||||
vgchange --yes --systemid sidfoofile1 $vg1
|
||||
not vgs $vg1
|
||||
# both vgs are foreign, drop dev1/dev4 so both vgs are missing a device
|
||||
aux hide_dev "$dev1"
|
||||
aux hide_dev "$dev4"
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev4"
|
||||
# neither VG can be changed because both are missing a dev
|
||||
not vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1
|
||||
not vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2
|
||||
# using majoritypvs, vg1 can be changed because 2 of 3 PVs exist
|
||||
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1
|
||||
vgs $vg1
|
||||
# using majoritypvs, vg2 cannot be changed because 1 of 2 PVs exist
|
||||
not vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2
|
||||
not vgs $vg2
|
||||
vgs --foreign $vg2
|
||||
# dev1/dev4 return so we can take over vg2 now
|
||||
# vg1 will complain about stale metadata on dev1
|
||||
aux unhide_dev "$dev1"
|
||||
aux unhide_dev "$dev4"
|
||||
vgs
|
||||
pvs
|
||||
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2
|
||||
vgs $vg2
|
||||
# update metadata on dev1
|
||||
vgck --updatemetadata $vg1
|
||||
vgs $vg1
|
||||
clear_df_systemid
|
||||
vgremove $vg1
|
||||
vgremove $vg2
|
||||
|
||||
|
||||
# vgcfgbackup backs up foreign vg with --foreign
|
||||
SID1=sidfoofile1
|
||||
SID2=sidfoofile2
|
||||
|
@@ -1,197 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2015 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
test_description='Test VG takeover with raid LVs'
|
||||
|
||||
# test does not apply to lvmlockd
|
||||
SKIP_WITH_LVMLOCKD=1
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
print_lvmlocal() {
|
||||
{ echo "local {"; printf "%s\n" "$@"; echo "}"; } >"$LVMLOCAL"
|
||||
}
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3 1024
|
||||
|
||||
SIDFILE="etc/lvm_test.conf"
|
||||
LVMLOCAL="etc/lvmlocal.conf"
|
||||
|
||||
DFDIR="$LVM_SYSTEM_DIR/devices"
|
||||
DF="$DFDIR/system.devices"
|
||||
|
||||
# Avoid system id validation in the devices file
|
||||
# which gets in the way of the test switching the
|
||||
# local system id.
|
||||
clear_df_systemid() {
|
||||
if [[ -f $DF ]]; then
|
||||
sed -e "s|SYSTEMID=.||" "$DF" > tmpdf
|
||||
cp tmpdf $DF
|
||||
fi
|
||||
}
|
||||
|
||||
SID1=sidfoofile1
|
||||
SID2=sidfoofile2
|
||||
echo "$SID1" > "$SIDFILE"
|
||||
clear_df_systemid
|
||||
aux lvmconf "global/system_id_source = file" \
|
||||
"global/system_id_file = \"$SIDFILE\""
|
||||
vgcreate $vg "$dev1" "$dev2" "$dev3"
|
||||
vgs -o+systemid,partial $vg
|
||||
check vg_field $vg systemid "$SID1"
|
||||
|
||||
lvcreate --type raid1 -L 400 -m1 -n $lv1 $vg "$dev1" "$dev2"
|
||||
lvcreate --type raid1 -L 400 -m2 -n $lv2 $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
# give some time for raid init
|
||||
sleep 2
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv2"
|
||||
|
||||
dd if=/dev/urandom of=pattern1 bs=512K count=1
|
||||
|
||||
mount_dir="mnt_takeover"
|
||||
mkdir -p "$mount_dir"
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
dd if=/dev/zero of=$mount_dir/file1 bs=4096 count=1024
|
||||
cp pattern1 $mount_dir/pattern1a
|
||||
cp pattern1 $mount_dir/pattern1b
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
dd if=/dev/zero of=$mount_dir/file1 bs=4096 count=1024
|
||||
cp pattern1 $mount_dir/pattern1a
|
||||
cp pattern1 $mount_dir/pattern1b
|
||||
umount $mount_dir
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
# make the vg foreign
|
||||
vgchange --yes --systemid $SID2 $vg
|
||||
not vgs $vg
|
||||
|
||||
# make one dev missing
|
||||
aux hide_dev "$dev1"
|
||||
|
||||
# take over the vg, like cluster failover would do
|
||||
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID2}\"]" --systemid $SID1 $vg
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
lvchange -ay --activationmode degraded $vg/$lv1
|
||||
lvchange -ay --activationmode degraded $vg/$lv2
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
dd of=/dev/null if=$mount_dir/file1 bs=4096 count=1024
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1b
|
||||
rm $mount_dir/pattern1b
|
||||
rm $mount_dir/file1
|
||||
cp pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
dd of=/dev/null if=$mount_dir/file1 bs=4096 count=1024
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1b
|
||||
rm $mount_dir/pattern1b
|
||||
rm $mount_dir/file1
|
||||
cp pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# fails because the missing dev is used by lvs
|
||||
not vgreduce --removemissing $vg
|
||||
# works because lvs can be used with missing leg
|
||||
vgreduce --removemissing --mirrorsonly --force $vg
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# decline to repair (answer no)
|
||||
lvconvert --repair $vg/$lv1
|
||||
# fails to find another disk to use to repair
|
||||
not lvconvert -y --repair $vg/$lv2
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
aux unhide_dev "$dev1"
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# remove the failed unused leg, leaving 2 legs
|
||||
lvconvert -y -m-1 $vg/$lv2
|
||||
# remove the failed unused leg, leaving 1 leg
|
||||
lvconvert -y -m-1 $vg/$lv1
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
vgextend $vg "$dev1"
|
||||
lvconvert -y -m+1 $vg/$lv1 "$dev1"
|
||||
lvconvert -y -m+1 $vg/$lv2 "$dev1"
|
||||
|
||||
# let raid sync new leg
|
||||
sleep 3
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -f $vg
|
@@ -1,188 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2015 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
test_description='Test VG takeover with raid LVs'
|
||||
|
||||
# test does not apply to lvmlockd
|
||||
SKIP_WITH_LVMLOCKD=1
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
print_lvmlocal() {
|
||||
{ echo "local {"; printf "%s\n" "$@"; echo "}"; } >"$LVMLOCAL"
|
||||
}
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 4 1024
|
||||
|
||||
SIDFILE="etc/lvm_test.conf"
|
||||
LVMLOCAL="etc/lvmlocal.conf"
|
||||
|
||||
DFDIR="$LVM_SYSTEM_DIR/devices"
|
||||
DF="$DFDIR/system.devices"
|
||||
|
||||
# Avoid system id validation in the devices file
|
||||
# which gets in the way of the test switching the
|
||||
# local system id.
|
||||
clear_df_systemid() {
|
||||
if [[ -f $DF ]]; then
|
||||
sed -e "s|SYSTEMID=.||" "$DF" > tmpdf
|
||||
cp tmpdf $DF
|
||||
fi
|
||||
}
|
||||
|
||||
SID1=sidfoofile1
|
||||
SID2=sidfoofile2
|
||||
echo "$SID1" > "$SIDFILE"
|
||||
clear_df_systemid
|
||||
aux lvmconf "global/system_id_source = file" \
|
||||
"global/system_id_file = \"$SIDFILE\""
|
||||
vgcreate $vg "$dev1" "$dev2" "$dev3"
|
||||
vgs -o+systemid,partial $vg
|
||||
check vg_field $vg systemid "$SID1"
|
||||
|
||||
lvcreate --type raid1 -L 400 -m1 -n $lv1 $vg "$dev1" "$dev2"
|
||||
lvcreate --type raid1 -L 400 -m2 -n $lv2 $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
# give some time for raid init
|
||||
sleep 2
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv2"
|
||||
|
||||
dd if=/dev/urandom of=pattern1 bs=512K count=1
|
||||
|
||||
mount_dir="mnt_takeover"
|
||||
mkdir -p "$mount_dir"
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
dd if=/dev/zero of=$mount_dir/file1 bs=4096 count=1024
|
||||
cp pattern1 $mount_dir/pattern1a
|
||||
cp pattern1 $mount_dir/pattern1b
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
dd if=/dev/zero of=$mount_dir/file1 bs=4096 count=1024
|
||||
cp pattern1 $mount_dir/pattern1a
|
||||
cp pattern1 $mount_dir/pattern1b
|
||||
umount $mount_dir
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
# make the vg foreign
|
||||
vgchange --yes --systemid $SID2 $vg
|
||||
not vgs $vg
|
||||
|
||||
# make one dev missing
|
||||
aux hide_dev "$dev1"
|
||||
|
||||
# take over the vg, like cluster failover would do
|
||||
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID2}\"]" --systemid $SID1 $vg
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
lvchange -ay --activationmode degraded $vg/$lv1
|
||||
lvchange -ay --activationmode degraded $vg/$lv2
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
dd of=/dev/null if=$mount_dir/file1 bs=4096 count=1024
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1b
|
||||
rm $mount_dir/pattern1b
|
||||
rm $mount_dir/file1
|
||||
cp pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
dd of=/dev/null if=$mount_dir/file1 bs=4096 count=1024
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1b
|
||||
rm $mount_dir/pattern1b
|
||||
rm $mount_dir/file1
|
||||
cp pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# fails because the missing dev is used by lvs
|
||||
not vgreduce --removemissing $vg
|
||||
# works because lvs can be used with missing leg
|
||||
vgreduce --removemissing --mirrorsonly --force $vg
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# unhide_dev before lvconvert --repair
|
||||
# i.e. the device reappears before the LVs are repaired
|
||||
|
||||
aux unhide_dev "$dev1"
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# this repairs lv1 by using dev3 in place of dev1
|
||||
lvconvert -y --repair $vg/$lv1
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# add a new disk to use for replacing dev1 in lv2
|
||||
vgextend $vg "$dev4"
|
||||
|
||||
lvconvert -y --repair $vg/$lv2
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
# let the new legs sync
|
||||
sleep 3
|
||||
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -f $vg
|
@@ -1,171 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2015 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
test_description='Test VG takeover with raid LVs'
|
||||
|
||||
# test does not apply to lvmlockd
|
||||
SKIP_WITH_LVMLOCKD=1
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
print_lvmlocal() {
|
||||
{ echo "local {"; printf "%s\n" "$@"; echo "}"; } >"$LVMLOCAL"
|
||||
}
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3 1024
|
||||
|
||||
SIDFILE="etc/lvm_test.conf"
|
||||
LVMLOCAL="etc/lvmlocal.conf"
|
||||
|
||||
DFDIR="$LVM_SYSTEM_DIR/devices"
|
||||
DF="$DFDIR/system.devices"
|
||||
|
||||
# Avoid system id validation in the devices file
|
||||
# which gets in the way of the test switching the
|
||||
# local system id.
|
||||
clear_df_systemid() {
|
||||
if [[ -f $DF ]]; then
|
||||
sed -e "s|SYSTEMID=.||" "$DF" > tmpdf
|
||||
cp tmpdf $DF
|
||||
fi
|
||||
}
|
||||
|
||||
SID1=sidfoofile1
|
||||
SID2=sidfoofile2
|
||||
echo "$SID1" > "$SIDFILE"
|
||||
clear_df_systemid
|
||||
aux lvmconf "global/system_id_source = file" \
|
||||
"global/system_id_file = \"$SIDFILE\""
|
||||
vgcreate $vg "$dev1" "$dev2" "$dev3"
|
||||
vgs -o+systemid,partial $vg
|
||||
check vg_field $vg systemid "$SID1"
|
||||
|
||||
lvcreate --type raid1 -L 400 -m1 -n $lv1 $vg "$dev1" "$dev2"
|
||||
lvcreate --type raid1 -L 400 -m2 -n $lv2 $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
# give some time for raid init
|
||||
sleep 2
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
|
||||
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv2"
|
||||
|
||||
dd if=/dev/urandom of=pattern1 bs=512K count=1
|
||||
|
||||
mount_dir="mnt_takeover"
|
||||
mkdir -p "$mount_dir"
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
dd if=/dev/zero of=$mount_dir/file1 bs=4096 count=1024
|
||||
cp pattern1 $mount_dir/pattern1a
|
||||
cp pattern1 $mount_dir/pattern1b
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
dd if=/dev/zero of=$mount_dir/file1 bs=4096 count=1024
|
||||
cp pattern1 $mount_dir/pattern1a
|
||||
cp pattern1 $mount_dir/pattern1b
|
||||
umount $mount_dir
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
# make the vg foreign
|
||||
vgchange --yes --systemid $SID2 $vg
|
||||
not vgs $vg
|
||||
|
||||
# make one dev missing
|
||||
aux hide_dev "$dev1"
|
||||
|
||||
# take over the vg, like cluster failover would do
|
||||
vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID2}\"]" --systemid $SID1 $vg
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
lvchange -ay --activationmode degraded $vg/$lv1
|
||||
lvchange -ay --activationmode degraded $vg/$lv2
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
dd of=/dev/null if=$mount_dir/file1 bs=4096 count=1024
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1b
|
||||
rm $mount_dir/pattern1b
|
||||
rm $mount_dir/file1
|
||||
cp pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
dd of=/dev/null if=$mount_dir/file1 bs=4096 count=1024
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1b
|
||||
rm $mount_dir/pattern1b
|
||||
rm $mount_dir/file1
|
||||
cp pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
# replaces dev1 with dev3
|
||||
lvconvert -y --repair $vg/$lv1
|
||||
|
||||
# no other disk to replace dev1 so remove the leg,
|
||||
# but that's not allowed until the missing disk is removed from the vg
|
||||
not lvconvert -y -m-1 $vg/$lv2
|
||||
vgreduce --removemissing --mirrorsonly --force $vg
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
lvconvert -y -m-1 $vg/$lv2
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
aux unhide_dev "$dev1"
|
||||
|
||||
# put dev1 back into lv2,
|
||||
# requires clearing outdated metadata and putting dev1 back in vg
|
||||
vgck --updatemetadata $vg
|
||||
pvs -o+missing
|
||||
vgextend $vg "$dev1"
|
||||
pvs -o+missing
|
||||
lvconvert -y -m+1 $vg/$lv2 "$dev1"
|
||||
|
||||
pvs -o+missing
|
||||
vgs -o+systemid,partial $vg
|
||||
lvs -a -o+devices $vg
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
mount "$DM_DEV_DIR/$vg/$lv2" $mount_dir
|
||||
diff pattern1 $mount_dir/pattern1a
|
||||
diff pattern1 $mount_dir/pattern1c
|
||||
umount $mount_dir
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -f $vg
|
@@ -416,10 +416,6 @@ arg(logonly_ARG, '\0', "logonly", 0, 0, 0,
|
||||
arg(longhelp_ARG, '\0', "longhelp", 0, 0, 0,
|
||||
"Display long help text.\n")
|
||||
|
||||
arg(majoritypvs_ARG, '\0', "majoritypvs", 0, 0, 0,
|
||||
"Change the VG system ID if the majority of PVs in the VG\n"
|
||||
"are present (one more than half).\n")
|
||||
|
||||
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0,
|
||||
"Sets the maximum recovery rate for a RAID LV. The rate value\n"
|
||||
"is an amount of data per second for each device in the array.\n"
|
||||
|
@@ -1767,7 +1767,7 @@ ID: vgchange_refresh
|
||||
DESC: Reactivate LVs using the latest metadata.
|
||||
|
||||
vgchange --systemid String VG|Tag|Select
|
||||
OO: --select String, --majoritypvs
|
||||
OO: --select String
|
||||
ID: vgchange_systemid
|
||||
DESC: Change the system ID of a VG.
|
||||
|
||||
|
100
tools/pvscan.c
100
tools/pvscan.c
@@ -44,6 +44,8 @@ struct pvscan_aa_params {
|
||||
*/
|
||||
static struct volume_group *saved_vg;
|
||||
|
||||
static int _found_filter_symlinks;
|
||||
|
||||
static int _pvscan_display_pv(struct cmd_context *cmd,
|
||||
struct physical_volume *pv,
|
||||
struct pvscan_params *params)
|
||||
@@ -803,6 +805,49 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The optimization in which only the pvscan arg devname is added to dev-cache
|
||||
* does not work if there's an lvm.conf filter containing symlinks to the dev
|
||||
* like /dev/disk/by-id/lvm-pv-uuid-xyz entries. A full dev_cache_scan will
|
||||
* associate the symlinks with the system dev name passed to pvscan, which lets
|
||||
* filter-regex match the devname with the symlink name in the filter.
|
||||
*/
|
||||
static int _filter_uses_symlinks(struct cmd_context *cmd, int filter_cfg)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
const struct dm_config_value *cv;
|
||||
const char *fname;
|
||||
|
||||
if ((cn = find_config_tree_array(cmd, filter_cfg, NULL))) {
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != DM_CFG_STRING)
|
||||
continue;
|
||||
if (!cv->v.str)
|
||||
continue;
|
||||
|
||||
fname = cv->v.str;
|
||||
|
||||
if (fname[0] != 'a')
|
||||
continue;
|
||||
|
||||
if (strstr(fname, "/dev/disk/"))
|
||||
return 1;
|
||||
if (strstr(fname, "/dev/mapper/"))
|
||||
return 1;
|
||||
|
||||
/* In case /dev/disk/by was omitted */
|
||||
if (strstr(fname, "lvm-pv-uuid"))
|
||||
return 1;
|
||||
if (strstr(fname, "dm-uuid"))
|
||||
return 1;
|
||||
if (strstr(fname, "wwn-"))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pvscan_arg {
|
||||
struct dm_list list;
|
||||
const char *devname;
|
||||
@@ -867,6 +912,31 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args,
|
||||
struct pvscan_arg *arg;
|
||||
struct device_list *devl;
|
||||
|
||||
/*
|
||||
* If no devices file is used, and lvm.conf filter is set to
|
||||
* accept /dev/disk/by-id/lvm-pv-uuid-xyz or another symlink,
|
||||
* but pvscan --cache is passed devname or major:minor, so
|
||||
* pvscan needs to match its arg device to the filter symlink.
|
||||
* setup_dev_in_dev_cache() adds /dev/sda2 to dev-cache which
|
||||
* does not match a symlink to /dev/sda2, so we need a full
|
||||
* dev_cache_scan that will associate all symlinks to sda2,
|
||||
* which allows filter-regex to work. This case could be
|
||||
* optimized if needed by adding dev-cache entries for each
|
||||
* filter "a" entry (filter symlink patterns would still need
|
||||
* a full dev_cache_scan.)
|
||||
* (When no devices file is used and 69-dm-lvm.rules is
|
||||
* used which calls pvscan directly, symlinks may not
|
||||
* have been created by other rules when pvscan runs, so
|
||||
* the full dev_cache_scan may still not find them.)
|
||||
*/
|
||||
if (!cmd->enable_devices_file && !cmd->enable_devices_list &&
|
||||
(_filter_uses_symlinks(cmd, devices_filter_CFG) ||
|
||||
_filter_uses_symlinks(cmd, devices_global_filter_CFG))) {
|
||||
_found_filter_symlinks = 1;
|
||||
log_print_pvscan(cmd, "finding all devices for filter symlinks.");
|
||||
dev_cache_scan(cmd);
|
||||
}
|
||||
|
||||
/* pass NULL filter when getting devs from dev-cache, filtering is done separately */
|
||||
|
||||
/* in common usage, no dev will be found for a devno */
|
||||
@@ -1483,40 +1553,16 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
|
||||
|
||||
cmd->filter_nodata_only = 1;
|
||||
|
||||
/*
|
||||
* Hack to handle regex filter that contains a symlink name for dev arg.
|
||||
* pvscan --cache <dev> is called by our udev rule at a time when the
|
||||
* symlinks for <dev> may not all be created yet (by other udev rules.)
|
||||
* The regex filter in lvm.conf may refer to <dev> using a symlink name,
|
||||
* so we need to know all the symlinks for <dev> in order for the filter
|
||||
* to work correctly. Scanning /dev with dev_cache_scan() would usually
|
||||
* find all the symlink names for <dev>, adding them to dev->aliases,
|
||||
* which would let the filter work, but all symlinks aren't created yet.
|
||||
* But, the DEVLINKS env var, set by udev, contains all the symlink
|
||||
* names for <dev> that have been or *will be* created. So, we add all
|
||||
* these symlink names to dev->aliases, as if we had found them in /dev.
|
||||
* This allows <dev> to be recognized by a regex filter containing a
|
||||
* symlink for <dev>. We have to tell filter-regex to not set the
|
||||
* preferred name for <dev> to a symlink name since the <dev> may not
|
||||
* be usable by that symlink name yet.
|
||||
*/
|
||||
if ((dm_list_size(&pvscan_devs) == 1) &&
|
||||
!cmd->enable_devices_file &&
|
||||
!cmd->enable_devices_list &&
|
||||
regex_filter_contains_symlink(cmd)) {
|
||||
if ((dm_list_size(&pvscan_devs) == 1) && _found_filter_symlinks) {
|
||||
char *env_str;
|
||||
struct dm_list *env_aliases;
|
||||
devl = dm_list_item(dm_list_first(&pvscan_devs), struct device_list);
|
||||
if ((env_str = getenv("DEVLINKS"))) {
|
||||
log_debug("Finding symlink names from DEVLINKS for filter regex.");
|
||||
log_debug("DEVLINKS %s", env_str);
|
||||
env_aliases = str_to_str_list(cmd->mem, env_str, " ", 0);
|
||||
dm_list_splice(&devl->dev->aliases, env_aliases);
|
||||
} else {
|
||||
log_debug("Finding symlink names from /dev for filter regex.");
|
||||
dev_cache_scan(cmd);
|
||||
}
|
||||
cmd->filter_regex_set_preferred_name_disable = 1;
|
||||
/* A symlink from env may not actually exist so don't try to use it. */
|
||||
dev_cache_disable_preferred_names();
|
||||
}
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &pvscan_devs) {
|
||||
|
@@ -883,9 +883,7 @@ int vg_refresh_visible(struct cmd_context *cmd, struct volume_group *vg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lv_is_visible(lvl->lv) &&
|
||||
!(lv_is_cow(lvl->lv) && !lv_is_virtual_origin(origin_from_cow(lvl->lv))) &&
|
||||
!lv_refresh(cmd, lvl->lv)) {
|
||||
if (lv_is_visible(lvl->lv) && !lv_refresh(cmd, lvl->lv)) {
|
||||
r = 0;
|
||||
stack;
|
||||
}
|
||||
@@ -3294,9 +3292,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
/* Skip availability change for non-virt snaps when processing all LVs */
|
||||
/* FIXME: pass process_all to process_single_lv() */
|
||||
if (process_all &&
|
||||
(arg_is_set(cmd, activate_ARG) ||
|
||||
arg_is_set(cmd, refresh_ARG)) &&
|
||||
if (process_all && arg_is_set(cmd, activate_ARG) &&
|
||||
lv_is_cow(lvl->lv) && !lv_is_virtual_origin(origin_from_cow(lvl->lv)))
|
||||
continue;
|
||||
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include "tools.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/label/hints.h"
|
||||
#include "lib/filters/filter.h"
|
||||
|
||||
struct vgchange_params {
|
||||
int lock_start_count;
|
||||
@@ -1384,24 +1383,6 @@ static int _vgchange_systemid_single(struct cmd_context *cmd, const char *vg_nam
|
||||
struct volume_group *vg,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
if (arg_is_set(cmd, majoritypvs_ARG)) {
|
||||
struct pv_list *pvl;
|
||||
int missing_pvs = 0;
|
||||
int found_pvs = 0;
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!pvl->pv->dev)
|
||||
missing_pvs++;
|
||||
else
|
||||
found_pvs++;
|
||||
}
|
||||
if (found_pvs <= missing_pvs) {
|
||||
log_error("Cannot change system ID without the majority of PVs (found %d of %d)",
|
||||
found_pvs, found_pvs+missing_pvs);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_vgchange_system_id(cmd, vg))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
@@ -1434,9 +1415,6 @@ int vgchange_systemid_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, majoritypvs_ARG))
|
||||
cmd->handles_missing_pvs = 1;
|
||||
|
||||
ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, 0, handle, &_vgchange_systemid_single);
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
@@ -28,6 +28,8 @@
|
||||
# Also, keep in mind that recent rules may also require recent
|
||||
# subsystem-specific binaries.
|
||||
|
||||
KERNEL=="device-mapper", NAME="(DM_DIR)/control"
|
||||
|
||||
SUBSYSTEM!="block", GOTO="dm_end"
|
||||
KERNEL!="dm-[0-9]*", GOTO="dm_end"
|
||||
(DM_EXEC_RULE)
|
||||
|
@@ -38,6 +38,7 @@ IMPORT{db}="LVM_MD_PV_ACTIVATED"
|
||||
ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan"
|
||||
ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan"
|
||||
ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan"
|
||||
ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0"
|
||||
GOTO="lvm_end"
|
||||
|
||||
# Loop device:
|
||||
@@ -45,6 +46,7 @@ LABEL="next"
|
||||
KERNEL!="loop[0-9]*", GOTO="next"
|
||||
ACTION=="add", ENV{LVM_LOOP_PV_ACTIVATED}=="1", GOTO="lvm_scan"
|
||||
ACTION=="change", ENV{LVM_LOOP_PV_ACTIVATED}!="1", TEST=="loop/backing_file", ENV{LVM_LOOP_PV_ACTIVATED}="1", GOTO="lvm_scan"
|
||||
ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0"
|
||||
GOTO="lvm_end"
|
||||
|
||||
LABEL="next"
|
||||
@@ -52,6 +54,8 @@ ACTION!="add", GOTO="lvm_end"
|
||||
|
||||
LABEL="lvm_scan"
|
||||
|
||||
ENV{SYSTEMD_READY}="1"
|
||||
|
||||
# pvscan will check if this device completes a VG,
|
||||
# i.e. all PVs in the VG are now present with the
|
||||
# arrival of this PV. If so, it prints to stdout:
|
||||
|
@@ -20,7 +20,7 @@ include $(top_builddir)/make.tmpl
|
||||
DM_RULES=10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
|
||||
LVM_RULES=11-dm-lvm.rules 69-dm-lvm.rules
|
||||
|
||||
DM_DIR=$(shell $(GREP) "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | $(AWK) '{print $$3}')
|
||||
DM_DIR=$(shell $(GREP) "#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | $(AWK) '{print $$3}')
|
||||
|
||||
BINDIR=@bindir@
|
||||
ifeq ("@UDEV_RULE_EXEC_DETECTION@", "yes")
|
||||
|
Reference in New Issue
Block a user