1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-30 17:44:21 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
f59cb6632b pvscan: use alternate device names from DEVLINKS to check filter
The filter may contains a symlink for the device, and that symlink
may not yet be created when our udev rule runs pvscan --cache using
the kernel dev name.  The kernel dev name does not match the symlink
name in the filter, so pvscan will ignore the device.  udev sets
the DEVLINKS env variable to a list of link names for the device
that will be created, so check the filter with that set of names.
2023-01-19 17:37:31 -06:00
30 changed files with 185 additions and 1090 deletions

View File

@@ -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

View File

@@ -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
=====================================

View File

@@ -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,

View File

@@ -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;

View File

@@ -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.

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -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,

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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)) {

View File

@@ -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;
}
/*

View File

@@ -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).

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)

View File

@@ -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:

View File

@@ -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")