1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-03 01:44:19 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
b6e67d688e writecache: enable use with thin pool data
. it's of little use since the thin pool cannot be extended
  while it's using writecache.

. lvconvert --splitcache on tdata isn't working, the writecache
  table doesn't get updated with the cleaner setting.

. adding writecache to existing tdata not yet implemented
2020-10-28 13:37:44 -05:00
66 changed files with 723 additions and 5324 deletions

View File

@@ -92,12 +92,6 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
if (!add_to_cmd_arr(&cmd_argv, "-An", &i))
goto err;
if (pdlv->devicesfile) {
if (!add_to_cmd_arr(&cmd_argv, "--devicesfile", &i) ||
!add_to_cmd_arr(&cmd_argv, pdlv->devicesfile, &i))
goto err;
}
/* terminating NULL */
if (!add_to_cmd_arr(&cmd_argv, NULL, &i))
goto err;

View File

@@ -555,15 +555,14 @@ static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls
const char *interval, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
unsigned abort_polling, unsigned uinterval,
const char *devicesfile)
unsigned abort_polling, unsigned uinterval)
{
const char **cmdargv, **cmdenvp;
struct lvmpolld_lv *pdlv;
unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0);
pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type,
interval, uinterval, pdst, devicesfile);
interval, uinterval, pdst);
if (!pdlv) {
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure.");
@@ -622,7 +621,6 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL);
const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL);
const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL);
const char *devicesfile = daemon_request_str(req, LVMPD_PARM_DEVICESFILE, NULL);
unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0);
assert(type < POLL_TYPE_MAX);
@@ -682,7 +680,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
pdlv->init_rq_count++; /* safe. protected by store lock */
} else {
pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname,
lvname, sysdir, type, abort_polling, 2 * uinterval, devicesfile);
lvname, sysdir, type, abort_polling, 2 * uinterval);
if (!pdlv) {
pdst_unlock(pdst);
free(id);

View File

@@ -93,13 +93,11 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
const char *sinterval, unsigned pdtimeout,
struct lvmpolld_store *pdst,
const char *devicesfile)
struct lvmpolld_store *pdst)
{
char *lvmpolld_id = strdup(id), /* copy */
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL;
struct lvmpolld_lv tmp = {
.ls = ls,
@@ -107,7 +105,6 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
.lvmpolld_id = lvmpolld_id,
.lvid = _get_lvid(lvmpolld_id, sysdir),
.lvname = full_lvname,
.devicesfile = devicesfile_dup,
.lvm_system_dir_env = lvm_system_dir_env,
.sinterval = strdup(sinterval), /* copy */
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
@@ -127,7 +124,6 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
return pdlv;
err:
free((void *)devicesfile_dup);
free((void *)full_lvname);
free((void *)lvmpolld_id);
free((void *)lvm_system_dir_env);
@@ -140,7 +136,6 @@ err:
void pdlv_destroy(struct lvmpolld_lv *pdlv)
{
free((void *)pdlv->lvmpolld_id);
free((void *)pdlv->devicesfile);
free((void *)pdlv->lvname);
free((void *)pdlv->sinterval);
free((void *)pdlv->lvm_system_dir_env);

View File

@@ -49,7 +49,6 @@ struct lvmpolld_lv {
const enum poll_type type;
const char *const lvid;
const char *const lvmpolld_id;
const char *const devicesfile;
const char *const lvname; /* full vg/lv name */
const unsigned pdtimeout; /* in seconds */
const char *const sinterval;
@@ -102,8 +101,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
const char *sinterval, unsigned pdtimeout,
struct lvmpolld_store *pdst,
const char *devicesfile);
struct lvmpolld_store *pdst);
/* only call with appropriate struct lvmpolld_store lock held */
void pdlv_destroy(struct lvmpolld_lv *pdlv);

View File

@@ -35,7 +35,6 @@
#define LVMPD_PARM_SYSDIR "sysdir"
#define LVMPD_PARM_VALUE "value" /* either retcode or signal value */
#define LVMPD_PARM_VGNAME "vgname"
#define LVMPD_PARM_DEVICESFILE "devicesfile"
#define LVMPD_RESP_FAILED "failed"
#define LVMPD_RESP_FINISHED "finished"

View File

@@ -29,7 +29,6 @@ SOURCES =\
device/bcache.c \
device/bcache-utils.c \
device/dev-cache.c \
device/device_id.c \
device/dev-ext.c \
device/dev-io.c \
device/dev-md.c \
@@ -53,7 +52,6 @@ SOURCES =\
filters/filter-usable.c \
filters/filter-internal.c \
filters/filter-signature.c \
filters/filter-deviceid.c \
format_text/archive.c \
format_text/archiver.c \
format_text/export.c \

76
lib/cache/lvmcache.c vendored
View File

@@ -18,7 +18,6 @@
#include "lib/cache/lvmcache.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/dev-cache.h"
#include "lib/device/device_id.h"
#include "lib/locking/locking.h"
#include "lib/metadata/metadata.h"
#include "lib/mm/memlock.h"
@@ -508,25 +507,6 @@ static const char *_get_pvsummary_device_hint(char *pvid)
return NULL;
}
static const char *_get_pvsummary_device_id(char *pvid, const char **device_id_type)
{
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vginfo *vginfo;
struct pv_list *pvl;
dm_list_iterate_items(vginfo, &_vginfos) {
dm_list_iterate_items(pvl, &vginfo->pvsummaries) {
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
if (!strcmp(pvid_s, pvid)) {
*device_id_type = pvl->pv->device_id_type;
return pvl->pv->device_id;
}
}
}
return NULL;
}
/*
* Check if any PVs in vg->pvs have the same PVID as any
* entries in _unused_duplicates.
@@ -632,8 +612,6 @@ static void _choose_duplicates(struct cmd_context *cmd,
struct device_list *devl, *devl_safe, *devl_add, *devl_del;
struct lvmcache_info *info;
struct device *dev1, *dev2;
const char *device_id = NULL, *device_id_type = NULL;
const char *idname1 = NULL, *idname2 = NULL;
uint32_t dev1_major, dev1_minor, dev2_major, dev2_minor;
uint64_t dev1_size, dev2_size, pvsummary_size;
int in_subsys1, in_subsys2;
@@ -642,7 +620,6 @@ static void _choose_duplicates(struct cmd_context *cmd,
int has_lv1, has_lv2;
int same_size1, same_size2;
int same_name1 = 0, same_name2 = 0;
int same_id1 = 0, same_id2 = 0;
int prev_unchosen1, prev_unchosen2;
int change;
@@ -773,19 +750,6 @@ next:
same_name2 = !strcmp(device_hint, dev_name(dev2));
}
if ((device_id = _get_pvsummary_device_id(devl->dev->pvid, &device_id_type))) {
uint16_t idtype = idtype_from_str(device_id_type);
if (idtype) {
idname1 = device_id_system_read(cmd, dev1, idtype);
idname2 = device_id_system_read(cmd, dev2, idtype);
}
if (idname1)
same_id1 = !strcmp(idname1, device_id);
if (idname2)
same_id2 = !strcmp(idname2, device_id);
}
has_lv1 = (dev1->flags & DEV_USED_FOR_LV) ? 1 : 0;
has_lv2 = (dev2->flags & DEV_USED_FOR_LV) ? 1 : 0;
@@ -804,12 +768,6 @@ next:
dev_name(dev2), dev2_major, dev2_minor,
device_hint ?: "none");
log_debug_cache("PV %s: device_id %s. %s is %s. %s is %s.",
devl->dev->pvid,
device_id ?: ".",
dev_name(dev1), idname1 ?: ".",
dev_name(dev2), idname2 ?: ".");
log_debug_cache("PV %s: size %llu. %s is %llu. %s is %llu.",
devl->dev->pvid,
(unsigned long long)pvsummary_size,
@@ -850,13 +808,6 @@ next:
} else if (prev_unchosen2 && !prev_unchosen1) {
/* keep 1 (NB when unchosen is set we unprefer) */
reason = "of previous preference";
} else if (same_id1 && !same_id2) {
/* keep 1 */
reason = "device id";
} else if (same_id2 && !same_id1) {
/* change to 2 */
change = 1;
reason = "device id";
} else if (has_lv1 && !has_lv2) {
/* keep 1 */
reason = "device is used by LV";
@@ -1105,14 +1056,12 @@ int lvmcache_label_scan(struct cmd_context *cmd)
{
struct dm_list del_cache_devs;
struct dm_list add_cache_devs;
struct dm_list renamed_devs;
struct lvmcache_info *info;
struct lvmcache_vginfo *vginfo;
struct device_list *devl;
int vginfo_count = 0;
int r = 0;
dm_list_init(&renamed_devs);
int r = 0;
log_debug_cache("Finding VG info");
@@ -1126,24 +1075,13 @@ int lvmcache_label_scan(struct cmd_context *cmd)
* Do the actual scanning. This populates lvmcache
* with infos/vginfos based on reading headers from
* each device, and a vg summary from each mda.
*
* Note that this will *skip* scanning a device if
* an info struct already exists in lvmcache for
* the device.
*/
label_scan(cmd);
/*
* When devnames are used as device ids (which is dispreferred),
* changing/unstable devnames can lead to entries in the devices file
* not being matched to a dev even if the PV is present on the system.
* Or, a devices file entry may have been matched to the wrong device
* (with the previous name) that does not have the PVID specified in
* the entry. This function detects that problem, scans labels on all
* devs on the system to find the missing PVIDs, and corrects the
* devices file. We then need to run label scan on these correct
* devices.
*/
device_ids_find_renamed_devs(cmd, &renamed_devs);
if (!dm_list_empty(&renamed_devs))
label_scan_devs(cmd, cmd->filter, &renamed_devs);
/*
* _choose_duplicates() returns:
*
@@ -2784,10 +2722,6 @@ const char *dev_filtered_reason(struct device *dev)
return "device is too small (pv_min_size)";
if (dev->filtered_flags & DEV_FILTERED_UNUSABLE)
return "device is not in a usable state";
if (dev->filtered_flags & DEV_FILTERED_DEVICES_FILE)
return "device is not in devices file";
if (dev->filtered_flags & DEV_FILTERED_DEVICES_LIST)
return "device is not in devices list";
/* flag has not been added here */
if (dev->filtered_flags)

View File

@@ -32,7 +32,6 @@
#include "lib/cache/lvmcache.h"
#include "lib/format_text/archiver.h"
#include "lib/lvmpolld/lvmpolld-client.h"
#include "lib/device/device_id.h"
#include <locale.h>
#include <sys/stat.h>
@@ -1067,7 +1066,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
return 1;
}
#define MAX_FILTERS 11
#define MAX_FILTERS 10
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
{
@@ -1086,9 +1085,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
* sysfs filter. Only available on 2.6 kernels. Non-critical.
* Listed first because it's very efficient at eliminating
* unavailable devices.
*
* TODO: I suspect that using the lvm_type and device_id
* filters before this one may be more efficient.
*/
if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) {
if ((filters[nr_filt] = sysfs_filter_create()))
@@ -1127,13 +1123,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
}
nr_filt++;
/* filter based on the device_ids saved in the devices file */
if (!(filters[nr_filt] = deviceid_filter_create(cmd))) {
log_error("Failed to create deviceid device filter");
goto bad;
}
nr_filt++;
/* usable device filter. Required. */
if (!(filters[nr_filt] = usable_filter_create(cmd, cmd->dev_types, FILTER_MODE_NO_LVMETAD))) {
log_error("Failed to create usabled device filter");
@@ -1728,8 +1717,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
if (!_init_dev_cache(cmd))
goto_out;
device_ids_init(cmd);
memlock_init(cmd);
if (!_init_formats(cmd))
@@ -1855,7 +1842,6 @@ int refresh_toolcontext(struct cmd_context *cmd)
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
device_ids_exit(cmd);
if (!dev_cache_exit())
stack;
_destroy_dev_types(cmd);
@@ -1935,8 +1921,6 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_dev_cache(cmd))
return_0;
device_ids_init(cmd);
if (!_init_formats(cmd))
return_0;
@@ -1986,7 +1970,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
_destroy_filters(cmd);
if (cmd->mem)
dm_pool_destroy(cmd->mem);
device_ids_exit(cmd);
dev_cache_exit();
_destroy_dev_types(cmd);
_destroy_tags(cmd);

View File

@@ -182,24 +182,14 @@ struct cmd_context {
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
unsigned scan_lvs:1;
unsigned wipe_outdated_pvs:1;
unsigned enable_devices_list:1; /* command is using --devices option */
unsigned enable_devices_file:1; /* command is using devices file */
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_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 search_for_devnames:1; /* scan all devs for missing devices file devname entry */
/*
* Devices and filtering.
*/
struct dev_filter *filter;
struct dm_list hints;
struct dm_list use_device_ids;
const char *md_component_checks;
const char *devicesfile; /* from --devicesfile option */
struct dm_list deviceslist; /* from --devices option, struct dm_str_list */
/*
* Configuration.
@@ -231,7 +221,6 @@ struct cmd_context {
char system_dir[PATH_MAX];
char dev_dir[PATH_MAX];
char proc_dir[PATH_MAX];
char devices_file_path[PATH_MAX];
/*
* Reporting.

View File

@@ -288,29 +288,6 @@ cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, C
"preferred_names = [ \"^/dev/mpath/\", \"^/dev/mapper/mpath\", \"^/dev/[hs]d\" ]\n"
"#\n")
cfg(devices_use_devicesfile_CFG, "use_devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_DEVICES_FILE, vsn(2, 3, 10), NULL, 0, NULL,
"Enable or disable the use of a devices file.\n"
"When enabled, lvm will only use devices that\n"
"are lised in the devices file.\n")
cfg(devices_devicesfile_CFG, "devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DEVICES_FILE, vsn(2, 3, 10), NULL, 0, NULL,
"The name of the devices file that lists devices LVM should use.\n")
cfg(devices_search_for_devnames_CFG, "search_for_devnames", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SEARCH_FOR_DEVNAMES, vsn(2, 3, 10), NULL, 0, NULL,
"Look outside of the devices file for missing devname entries.\n"
"A devname entry may have a different device name after reboot,\n"
"or when reattached, in which case the device may be present on\n"
"the system but appear to be missing to lvm commands. When this\n"
"setting is enabled, lvm commands will automatically scan other\n"
"devices outside of the devices file to try to locate a missing\n"
"devices file entry on a new device (based on the PVID.) If this\n"
"setting is disabled, a user can run lvmdevices --addpvid to locate\n"
"a renamed device and update the devices file. This setting does\n"
"not apply to devices with stable device id types. Note that a\n"
"devices file entry that has been detached from the system will\n"
"lead to every command doing a search, so detached devices should\n"
"be removed from the devices file promptly.\n")
cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(1, 0, 0), NULL, 0, NULL,
"Limit the block devices that are used by LVM commands.\n"
"This is a list of regular expressions used to accept or reject block\n"
@@ -1005,7 +982,8 @@ cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECT
"a volume group's metadata, instead of always granting the read-only\n"
"requests immediately, delay them to allow the read-write requests to\n"
"be serviced. Without this setting, write access may be stalled by a\n"
"high volume of read-only requests. This option only affects file locks.\n")
"high volume of read-only requests. This option only affects\n"
"locking_type 1 viz. local file-based locking.\n")
cfg(global_library_dir_CFG, "library_dir", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Search this directory first for shared libraries.\n")

View File

@@ -321,9 +321,4 @@
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
#define DEFAULT_USE_DEVICES_FILE 1
#define DEFAULT_DEVICES_FILE "system.devices"
#define DEFAULT_SEARCH_FOR_DEVNAMES 1
#endif /* _LVM_DEFAULTS_H */

View File

@@ -16,7 +16,6 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/device/device_id.h"
#include "lib/datastruct/btree.h"
#include "lib/config/config.h"
#include "lib/commands/toolcontext.h"
@@ -69,13 +68,11 @@ static void _dev_init(struct device *dev)
dev->bcache_fd = -1;
dev->bcache_di = -1;
dev->read_ahead = -1;
dev->part = -1;
dev->ext.enabled = 0;
dev->ext.src = DEV_EXT_NONE;
dm_list_init(&dev->aliases);
dm_list_init(&dev->ids);
}
void dev_destroy_file(struct device *dev)
@@ -355,7 +352,7 @@ static int _add_alias(struct device *dev, const char *path)
return 1;
}
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
static int _get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
{
FILE *fp;
size_t len;
@@ -396,7 +393,7 @@ static int _get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int mi
return 0;
}
return get_sysfs_value(path, buf, buf_size, 0);
return _get_sysfs_value(path, buf, buf_size, 0);
}
static struct dm_list *_get_or_add_list_by_index_key(struct dm_hash_table *idx, const char *key)
@@ -477,7 +474,7 @@ static struct device *_get_device_for_sysfs_dev_name_using_devno(const char *dev
return NULL;
}
if (!get_sysfs_value(path, buf, sizeof(buf), 1))
if (!_get_sysfs_value(path, buf, sizeof(buf), 1))
return_NULL;
if (sscanf(buf, "%d:%d", &major, &minor) != 2) {
@@ -975,7 +972,7 @@ static int _dev_cache_iterate_sysfs_for_index(const char *path)
return r;
}
static int dev_cache_index_devs(void)
int dev_cache_index_devs(void)
{
static int sysfs_has_dev_block = -1;
char path[PATH_MAX];
@@ -1324,19 +1321,12 @@ int dev_cache_check_for_open_devices(void)
int dev_cache_exit(void)
{
struct device *dev;
struct dm_hash_node *n;
int num_open = 0;
if (_cache.names)
if ((num_open = _check_for_open_devices(1)) > 0)
log_error(INTERNAL_ERROR "%d device(s) were left open and have been closed.", num_open);
dm_hash_iterate(n, _cache.names) {
dev = (struct device *) dm_hash_get_data(_cache.names, n);
free_dids(&dev->ids);
}
if (_cache.mem)
dm_pool_destroy(_cache.mem);
@@ -1659,239 +1649,3 @@ bool dev_cache_has_md_with_end_superblock(struct dev_types *dt)
return false;
}
static int _setup_devices_list(struct cmd_context *cmd)
{
struct dm_str_list *strl;
struct use_id *uid;
/*
* For each --devices arg, add a uid to cmd->use_device_ids.
* The uid has devname is the devices arg value.
*/
dm_list_iterate_items(strl, &cmd->deviceslist) {
if (!(uid = zalloc(sizeof(struct use_id))))
return_0;
if (!(uid->devname = strdup(strl->str)))
return_0;
dm_list_add(&cmd->use_device_ids, &uid->list);
}
return 1;
}
int setup_devices_file(struct cmd_context *cmd)
{
const char *filename = NULL;
if (cmd->devicesfile) {
/* --devicesfile <filename> or "" has been set which overrides
lvm.conf settings use_devicesfile and devicesfile. */
if (!strlen(cmd->devicesfile))
cmd->enable_devices_file = 0;
else {
cmd->enable_devices_file = 1;
filename = cmd->devicesfile;
}
} else {
if (!find_config_tree_bool(cmd, devices_use_devicesfile_CFG, NULL))
cmd->enable_devices_file = 0;
else {
cmd->enable_devices_file = 1;
filename = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
if (!validate_name(filename)) {
log_error("Invalid devices file name from config setting \"%s\".", filename);
return 0;
}
}
}
if (!cmd->enable_devices_file)
return 1;
if (dm_snprintf(cmd->devices_file_path, sizeof(cmd->devices_file_path),
"%s/devices/%s", cmd->system_dir, filename) < 0) {
log_error("Failed to copy devices file path");
return 0;
}
return 1;
}
/*
* Add all system devices to dev-cache, and attempt to
* match all devices_file entries to dev-cache entries.
*/
int setup_devices(struct cmd_context *cmd)
{
int file_exists;
int lock_mode = 0;
if (cmd->enable_devices_list) {
if (!_setup_devices_list(cmd))
return_0;
goto scan;
}
if (!setup_devices_file(cmd))
return_0;
if (!cmd->enable_devices_file)
goto scan;
file_exists = devices_file_exists(cmd);
/*
* Removing the devices file is another way of disabling the use of
* a devices file, unless the command creates the devices file.
*/
if (!file_exists && !cmd->create_edit_devices_file) {
log_print("Devices file not found, ignoring.");
cmd->enable_devices_file = 0;
goto scan;
}
if (!file_exists) {
/* pvcreate/vgcreate/vgimportdevices/lvmdevices-add
create a new devices file here if it doesn't exist.
They have the create_edit_devices_file flag set.
First they create/lock-ex the devices file lockfile.
Other commands will not use a devices file if none exists. */
lock_mode = LOCK_EX;
if (!lock_devices_file(cmd, lock_mode)) {
log_error("Failed to lock the devices file to create.");
return 0;
}
if (!devices_file_touch(cmd)) {
log_error("Failed to create the devices file.");
return 0;
}
} else {
/* Commands that intend to edit the devices file have
edit_devices_file or create_edit_devices_file set (create if
they can also create a new devices file) and lock it ex
here prior to reading. Other commands that intend to just
read the devices file lock sh. */
lock_mode = (cmd->create_edit_devices_file || cmd->edit_devices_file) ? LOCK_EX : LOCK_SH;
if (!lock_devices_file(cmd, lock_mode)) {
log_error("Failed to lock the devices file.");
return 0;
}
}
/*
* Read the list of device ids that lvm can use.
* Adds a struct dev_id to cmd->use_device_ids for each one.
*/
if (!device_ids_read(cmd)) {
log_error("Failed to read the devices file.");
return 0;
}
/*
* When the command is editing the devices file, it acquires
* the ex lock above, will later call device_ids_write(), and
* then unlock the lock after writing the file.
* When the command is just reading the devices file, it's
* locked sh above just before reading the file, and unlocked
* here after reading.
*/
if (lock_mode && (lock_mode == LOCK_SH))
unlock_devices_file(cmd);
scan:
/*
* Add a 'struct device' to dev-cache for each device available on the system.
* This will not open or read any devices, but may look at sysfs properties.
* This list of devs comes from looking /dev entries, or from asking libudev.
* TODO: or from /proc/partitions?
*
* TODO: dev_cache_scan() optimization: start by looking only at
* devnames listed in the devices_file, and if the device_ids for
* those all match we won't need any others.
* Exceptions: the command wants a new device for pvcreate, or
* device_ids don't match the devnames.
*/
dev_cache_scan();
/*
* Match entries from cmd->use_device_ids with device structs in dev-cache.
*/
device_ids_match(cmd);
return 1;
}
/*
* The alternative to setup_devices() when the command is interested
* in using only one PV.
*
* Add one system device to dev-cache, and attempt to
* match its dev-cache entry to a devices_file entry.
*/
int setup_device(struct cmd_context *cmd, const char *devname)
{
struct stat buf;
struct device *dev;
if (cmd->enable_devices_list) {
if (!_setup_devices_list(cmd))
return_0;
goto scan;
}
if (!setup_devices_file(cmd))
return_0;
if (!cmd->enable_devices_file)
goto scan;
if (!devices_file_exists(cmd)) {
log_print("Devices file not found, ignoring.");
cmd->enable_devices_file = 0;
goto scan;
}
if (!lock_devices_file(cmd, LOCK_SH)) {
log_error("Failed to lock the devices file to read.");
return 0;
}
if (!device_ids_read(cmd)) {
log_error("Failed to read the devices file.");
return 0;
}
unlock_devices_file(cmd);
scan:
if (stat(devname, &buf) < 0) {
log_error("Cannot access device %s.", devname);
return 0;
}
if (!S_ISBLK(buf.st_mode)) {
log_error("Invaild device type %s.", devname);
return 0;
}
if (!_insert_dev(devname, buf.st_rdev))
return_0;
if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname)))
return_0;
/* Match this device to an entry in devices_file so it will not
be rejected by filter-deviceid. */
if (cmd->enable_devices_file)
device_ids_match_dev(cmd, dev);
return 1;
}

View File

@@ -34,6 +34,7 @@ struct dev_filter {
const char *name;
};
int dev_cache_index_devs(void);
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid);
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid);
@@ -74,10 +75,4 @@ void dev_cache_failed_path(struct device *dev, const char *path);
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
int setup_devices_file(struct cmd_context *cmd);
int setup_devices(struct cmd_context *cmd);
int setup_device(struct cmd_context *cmd, const char *devname);
#endif

View File

@@ -380,45 +380,6 @@ static int _loop_is_with_partscan(struct device *dev)
return partscan;
}
int dev_get_partition_number(struct device *dev, int *num)
{
char path[PATH_MAX];
char buf[8] = { 0 };
dev_t devt = dev->dev;
struct stat sb;
if (dev->part != -1) {
*num = dev->part;
return 1;
}
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
dm_sysfs_dir(), (int)MAJOR(devt), (int)MINOR(devt)) < 0) {
log_error("Failed to create sysfs path for %s", dev_name(dev));
return 0;
}
if (stat(path, &sb)) {
dev->part = 0;
*num = 0;
return 1;
}
if (!get_sysfs_value(path, buf, sizeof(buf), 0)) {
log_error("Failed to read sysfs path for %s", dev_name(dev));
return 0;
}
if (!buf[0]) {
log_error("Failed to read sysfs partition value for %s", dev_name(dev));
return 0;
}
dev->part = atoi(buf);
*num = dev->part;
return 1;
}
/* See linux/genhd.h and fs/partitions/msdos */
#define PART_MAGIC 0xAA55
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)

View File

@@ -83,7 +83,6 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev);
int major_max_partitions(struct dev_types *dt, int major);
int dev_is_partitioned(struct dev_types *dt, struct device *dev);
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result);
int dev_get_partition_number(struct device *dev, int *num);
/* Various device properties */
unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev);

View File

@@ -38,7 +38,6 @@
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_device_ids */
/*
* Support for external device info.
@@ -57,42 +56,12 @@ struct dev_ext {
void *handle;
};
#define DEV_ID_TYPE_SYS_WWID 0x0001
#define DEV_ID_TYPE_SYS_SERIAL 0x0002
#define DEV_ID_TYPE_MPATH_UUID 0x0003
#define DEV_ID_TYPE_MD_UUID 0x0004
#define DEV_ID_TYPE_LOOP_FILE 0x0005
#define DEV_ID_TYPE_DEVNAME 0x0006
/* A device ID of a certain type for a device. */
struct dev_id {
struct dm_list list;
struct device *dev;
uint16_t idtype;
char *idname;
};
/* A device listed in devices file that lvm should use. */
struct use_id {
struct dm_list list;
struct device *dev;
int part;
uint16_t idtype;
char *idname;
char *devname;
char *pvid;
};
/*
* All devices in LVM will be represented by one of these.
* pointer comparisons are valid.
*/
struct device {
struct dm_list aliases; /* struct dm_str_list */
struct dm_list ids; /* struct dev_id */
struct dev_id *id; /* points to the ids entry being used for this dev */
dev_t dev;
/* private */
@@ -103,7 +72,6 @@ struct device {
int read_ahead;
int bcache_fd;
int bcache_di;
int part; /* partition number */
uint32_t flags;
uint32_t filtered_flags;
unsigned size_seqno;

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* 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 Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser 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
*/
#ifndef _LVM_DEVICE_ID_H
#define _LVM_DEVICE_ID_H
void free_uid(struct use_id *uid);
void free_uids(struct dm_list *list);
void free_did(struct dev_id *did);
void free_dids(struct dm_list *list);
const char *idtype_to_str(uint16_t idtype);
uint16_t idtype_from_str(const char *str);
const char *dev_idtype(struct device *dev);
const char *dev_id(struct device *dev);
int device_ids_read(struct cmd_context *cmd);
int device_ids_write(struct cmd_context *cmd);
int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid,
const char *idtype_arg, const char *id_arg);
void device_id_pvremove(struct cmd_context *cmd, struct device *dev);
void device_ids_match(struct cmd_context *cmd);
int device_ids_match_dev(struct cmd_context *cmd, struct device *dev);
void device_ids_validate(struct cmd_context *cmd, int force_update);
int device_ids_version_unchanged(struct cmd_context *cmd);
void device_ids_read_pvids(struct cmd_context *cmd);
void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_list);
const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype);
struct use_id *get_uid_for_dev(struct cmd_context *cmd, struct device *dev);
struct use_id *get_uid_for_pvid(struct cmd_context *cmd, const char *pvid);
int devices_file_exists(struct cmd_context *cmd);
int devices_file_touch(struct cmd_context *cmd);
int lock_devices_file(struct cmd_context *cmd, int mode);
int lock_devices_file_try(struct cmd_context *cmd, int mode, int *held);
void unlock_devices_file(struct cmd_context *cmd);
void device_ids_init(struct cmd_context *cmd);
void device_ids_exit(struct cmd_context *cmd);
#endif

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* 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 Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser 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
*/
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/commands/toolcontext.h"
static int _passes_deviceid_filter(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
dev->filtered_flags &= ~DEV_FILTERED_DEVICES_FILE;
dev->filtered_flags &= ~DEV_FILTERED_DEVICES_LIST;
if (!cmd->enable_devices_file && !cmd->enable_devices_list)
return 1;
if (cmd->filter_deviceid_skip)
return 1;
if (dev->flags & DEV_MATCHED_USE_ID)
return 1;
if (cmd->enable_devices_file)
dev->filtered_flags |= DEV_FILTERED_DEVICES_FILE;
else if (cmd->enable_devices_list)
dev->filtered_flags |= DEV_FILTERED_DEVICES_LIST;
log_debug_devs("%s: Skipping (deviceid)", dev_name(dev));
return 0;
}
static void _destroy_deviceid_filter(struct dev_filter *f)
{
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying deviceid filter while in use %u times.", f->use_count);
free(f);
}
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd)
{
struct dev_filter *f;
if (!(f = zalloc(sizeof(struct dev_filter)))) {
log_error("deviceid filter allocation failed");
return NULL;
}
f->passes_filter = _passes_deviceid_filter;
f->destroy = _destroy_deviceid_filter;
f->use_count = 0;
f->name = "deviceid";
log_debug_devs("deviceid filter initialised.");
return f;
}

View File

@@ -15,7 +15,6 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/commands/toolcontext.h"
struct rfilter {
struct dm_pool *mem;
@@ -154,14 +153,6 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
dev->filtered_flags &= ~DEV_FILTERED_REGEX;
if (cmd->enable_devices_list)
return 1;
if (cmd->enable_devices_file && !cmd->filter_regex_with_devices_file) {
/* TODO: print a notice if the filter is set to something and we ignore it here. */
return 1;
}
dm_list_iterate_items(sl, &dev->aliases) {
m = dm_regex_match(rf->engine, sl->str);

View File

@@ -30,7 +30,6 @@ struct dev_filter *partitioned_filter_create(struct dev_types *dt);
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *f);
struct dev_filter *sysfs_filter_create(void);
struct dev_filter *signature_filter_create(struct dev_types *dt);
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd);
struct dev_filter *internal_filter_create(void);
int internal_filter_allow(struct dm_pool *mem, struct device *dev);
@@ -64,7 +63,5 @@ struct dev_filter *usable_filter_create(struct cmd_context *cmd, struct dev_type
#define DEV_FILTERED_DEVTYPE 0x00000100
#define DEV_FILTERED_MINSIZE 0x00000200
#define DEV_FILTERED_UNUSABLE 0x00000400
#define DEV_FILTERED_DEVICES_FILE 0x00000800
#define DEV_FILTERED_DEVICES_LIST 0x00001000
#endif /* _LVM_FILTER_H */

View File

@@ -23,7 +23,6 @@
#include "lib/metadata/segtype.h"
#include "lib/format_text/text_export.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device_id.h"
#include "libdaemon/client/config-util.h"
#include <stdarg.h>
@@ -556,11 +555,6 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
dm_escape_double_quotes(buffer, pv_dev_name(pv)));
outnl(f);
if (dev_idtype(pv->dev) && dev_id(pv->dev)) {
outf(f, "device_id_type = \"%s\"", dev_idtype(pv->dev));
outf(f, "device_id = \"%s\"", dev_id(pv->dev));
}
if (!_print_flag_config(f, pv->status, PV_FLAGS))
return_0;

View File

@@ -188,7 +188,7 @@ static int _read_pv(struct cmd_context *cmd,
struct physical_volume *pv;
struct pv_list *pvl;
const struct dm_config_value *cv;
const char *str;
const char *device_hint;
uint64_t size, ba_start;
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
@@ -233,21 +233,11 @@ static int _read_pv(struct cmd_context *cmd,
return 0;
}
if (dm_config_get_str(pvn, "device", &str)) {
if (!(pv->device_hint = dm_pool_strdup(mem, str)))
if (dm_config_get_str(pvn, "device", &device_hint)) {
if (!(pv->device_hint = dm_pool_strdup(mem, device_hint)))
log_error("Failed to allocate memory for device hint in read_pv.");
}
if (dm_config_get_str(pvn, "device_id", &str)) {
if (!(pv->device_id = dm_pool_strdup(mem, str)))
log_error("Failed to allocate memory for device_id in read_pv.");
}
if (dm_config_get_str(pvn, "device_id_type", &str)) {
if (!(pv->device_id_type = dm_pool_strdup(mem, str)))
log_error("Failed to allocate memory for device_id_type in read_pv.");
}
if (!_read_uint64(pvn, "pe_start", &pv->pe_start)) {
log_error("Couldn't read extent start value (pe_start) "
"for physical volume.");
@@ -316,7 +306,7 @@ static int _read_pvsummary(struct cmd_context *cmd,
{
struct physical_volume *pv;
struct pv_list *pvl;
const char *str;
const char *device_hint;
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv))))
@@ -336,19 +326,9 @@ static int _read_pvsummary(struct cmd_context *cmd,
!_read_uint64(pvn, "dev_size", &pv->size))
log_warn("Couldn't read dev size for physical volume.");
if (dm_config_get_str(pvn, "device", &str)) {
if (!(pv->device_hint = dm_pool_strdup(mem, str)))
log_error("Failed to allocate memory for device hint in read_pv_sum.");
}
if (dm_config_get_str(pvn, "device_id", &str)) {
if (!(pv->device_id = dm_pool_strdup(mem, str)))
log_error("Failed to allocate memory for device_id in read_pv_sum.");
}
if (dm_config_get_str(pvn, "device_id_type", &str)) {
if (!(pv->device_id_type = dm_pool_strdup(mem, str)))
log_error("Failed to allocate memory for device_id_type in read_pv_sum.");
if (dm_config_get_str(pvn, "device", &device_hint)) {
if (!(pv->device_hint = dm_pool_strdup(mem, device_hint)))
log_error("Failed to allocate memory for device hint in read_pv.");
}
dm_list_add(&vgsummary->pvsummaries, &pvl->list);

View File

@@ -145,7 +145,6 @@
#include "lib/activate/activate.h"
#include "lib/label/hints.h"
#include "lib/device/dev-type.h"
#include "lib/device/device_id.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -167,10 +166,8 @@ static const char *_newhints_file = DEFAULT_RUN_DIR "/newhints";
* than they were built with. Increase the minor number
* when adding features that older lvm versions can just
* ignore while continuing to use the other content.
*
* MAJOR 2: add devices_file
*/
#define HINTS_VERSION_MAJOR 2
#define HINTS_VERSION_MAJOR 1
#define HINTS_VERSION_MINOR 1
#define HINT_LINE_LEN (PATH_MAX + NAME_LEN + ID_LEN + 64)
@@ -715,9 +712,8 @@ static int _read_hint_file(struct cmd_context *cmd, struct dm_list *hints, int *
break;
}
if (hv_major != HINTS_VERSION_MAJOR) {
log_debug("ignore hints with version %d.%d current %d.%d",
hv_major, hv_minor, HINTS_VERSION_MAJOR, HINTS_VERSION_MINOR);
if (hv_major > HINTS_VERSION_MAJOR) {
log_debug("ignore hints with newer major version %d.%d", hv_major, hv_minor);
*needs_refresh = 1;
break;
}
@@ -762,25 +758,6 @@ static int _read_hint_file(struct cmd_context *cmd, struct dm_list *hints, int *
continue;
}
keylen = strlen("devices_file:");
if (!strncmp(_hint_line, "devices_file:", keylen)) {
const char *df_hint = _hint_line + keylen;
const char *df_config = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
/* when a devices file is not used, hints should have devices_file:. */
if (!cmd->enable_devices_file || !df_hint || !df_config) {
if (df_hint[0] != '.') {
log_debug("ignore hints with different devices_file: not enabled vs %s", df_hint);
*needs_refresh = 1;
break;
}
} else if (strcmp(df_hint, df_config)) {
log_debug("ignore hints with different devices_file: %s vs %s", df_hint, df_config);
*needs_refresh = 1;
break;
}
continue;
}
keylen = strlen("devs_hash:");
if (!strncmp(_hint_line, "devs_hash:", keylen)) {
if (sscanf(_hint_line + keylen, "%u %u", &read_hash, &read_count) != 2) {
@@ -850,12 +827,8 @@ static int _read_hint_file(struct cmd_context *cmd, struct dm_list *hints, int *
if (!(iter = dev_iter_create(NULL, 0)))
return 0;
while ((dev = dev_iter_get(cmd, iter))) {
if (cmd->enable_devices_file && !get_uid_for_dev(cmd, dev))
continue;
if (!_dev_in_hint_hash(cmd, dev))
continue;
(void) dm_strncpy(devpath, dev_name(dev), sizeof(devpath));
calc_hash = calc_crc(calc_hash, (const uint8_t *)devpath, strlen(devpath));
calc_count++;
@@ -914,7 +887,6 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
struct device *dev;
const char *vgname;
char *filter_str = NULL;
const char *config_devices_file = NULL;
uint32_t hash = INITIAL_CRC;
uint32_t count = 0;
time_t t;
@@ -975,19 +947,6 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
fprintf(fp, "scan_lvs:%d\n", cmd->scan_lvs);
/*
* Only associate hints with the default/system devices file.
* If no default/system devices file is used, "." is set.
* If we are using a devices file other than the config setting
* (from --devicesfile), then we should not be using hints and
* shouldn't get here.
*/
config_devices_file = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
if (cmd->enable_devices_file && !cmd->devicesfile && config_devices_file)
fprintf(fp, "devices_file:%s\n", config_devices_file);
else
fprintf(fp, "devices_file:.\n");
/*
* iterate through all devs and write a line for each
* dev flagged DEV_SCAN_FOUND_LABEL
@@ -1005,14 +964,6 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
* 2. add PVs to the hint file
*/
while ((dev = dev_iter_get(cmd, iter))) {
if (cmd->enable_devices_file && !get_uid_for_dev(cmd, dev)) {
if (dev->flags & DEV_SCAN_FOUND_LABEL) {
/* should never happen */
log_error("skip hint hash no uid but found label %s", dev_name(dev));
}
continue;
}
if (!_dev_in_hint_hash(cmd, dev)) {
if (dev->flags & DEV_SCAN_FOUND_LABEL) {
/* should never happen */

View File

@@ -25,7 +25,6 @@
#include "lib/label/hints.h"
#include "lib/metadata/metadata.h"
#include "lib/format_text/layout.h"
#include "lib/device/device_id.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -806,6 +805,16 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
}
}
/*
* This will search the system's /dev for new path names and
* could help us reopen the device if it finds a new preferred
* path name for this dev's major:minor. It does that by
* inserting a new preferred path name on dev->aliases. open
* uses the first name from that list.
*/
log_debug_devs("Scanning refreshing device paths.");
dev_cache_scan();
/* Put devs that failed to open back on the original list to retry. */
dm_list_splice(devs, &reopen_devs);
goto scan_more;
@@ -927,12 +936,6 @@ static void _prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_d
#endif
}
/*
* Currently the only caller is pvck which probably doesn't need
* deferred filters checked after the read... it wants to know if
* anything has the pvid, even a dev that might be filtered.
*/
int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev_out)
{
char buf[LABEL_SIZE] __attribute__((aligned(8)));
@@ -945,20 +948,7 @@ int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev
dm_list_init(&devs);
/*
* Creates a list of available devices, does not open or read any,
* and does not filter them.
*/
if (!setup_devices(cmd)) {
log_error("Failed to set up devices.");
return 0;
}
/*
* Iterating over all available devices with cmd->filter filters
* devices; those returned from dev_iter_get are the devs that
* pass filters, and are those we can use.
*/
dev_cache_scan();
if (!(iter = dev_iter_create(cmd->filter, 0))) {
log_error("Scanning failed to get devices.");
@@ -1048,17 +1038,12 @@ int label_scan(struct cmd_context *cmd)
}
/*
* Creates a list of available devices, does not open or read any,
* and does not filter them. The list of all available devices
* is kept in "dev-cache", and comes from /dev entries or libudev.
* The list of devs found here needs to be filtered to get the
* list of devs we can use. The dev_iter calls using cmd->filter
* are what filters the devs.
* dev_cache_scan() creates a list of devices on the system
* (saved in in dev-cache) which we can iterate through to
* search for LVM devs. The dev cache list either comes from
* looking at dev nodes under /dev, or from udev.
*/
if (!setup_devices(cmd)) {
log_error("Failed to set up devices.");
return 0;
}
dev_cache_scan();
/*
* If we know that there will be md components with an end
@@ -1165,12 +1150,6 @@ int label_scan(struct cmd_context *cmd)
*/
_scan_list(cmd, cmd->filter, &scan_devs, 0, NULL);
/*
* Check if the devices_file content is up to date and
* if not update it.
*/
device_ids_validate(cmd, 0);
/*
* Metadata could be larger than total size of bcache, and bcache
* cannot currently be resized during the command. If this is the

View File

@@ -112,6 +112,7 @@ void label_scan_invalidate(struct device *dev);
void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
void label_scan_drop(struct cmd_context *cmd);
void label_scan_destroy(struct cmd_context *cmd);
void label_scan_confirm(struct device *dev);
int label_scan_setup_bcache(void);
int label_scan_open(struct device *dev);
int label_scan_open_excl(struct device *dev);

View File

@@ -247,13 +247,6 @@ static int _process_poll_init(const struct cmd_context *cmd, const char *poll_ty
goto out_req;
}
if (parms->devicesfile[0] &&
!(daemon_request_extend(req, LVMPD_PARM_DEVICESFILE " = %s",
parms->devicesfile, NULL))) {
log_error("Failed to create %s request." , poll_type);
goto out_req;
}
rep = daemon_send(_lvmpolld, req);
if (rep.error) {

View File

@@ -60,7 +60,6 @@ struct daemon_parms {
const char *progress_title;
uint64_t lv_type;
struct poll_functions *poll_fns;
char devicesfile[128];
};
int poll_daemon(struct cmd_context *cmd, unsigned background,

View File

@@ -895,52 +895,12 @@ int lv_get_raid_integrity_settings(struct logical_volume *lv, struct integrity_s
return 0;
}
int lv_raid_integrity_total_mismatches(struct cmd_context *cmd,
const struct logical_volume *lv,
uint64_t *mismatches)
{
struct logical_volume *lv_image;
struct lv_segment *seg, *seg_image;
uint32_t s;
uint64_t mismatches_image;
uint64_t total = 0;
int errors = 0;
if (!lv_is_raid(lv))
return 0;
seg = first_seg(lv);
for (s = 0; s < seg->area_count; s++) {
lv_image = seg_lv(seg, s);
seg_image = first_seg(lv_image);
if (!seg_is_integrity(seg_image))
continue;
mismatches_image = 0;
if (!lv_integrity_mismatches(cmd, lv_image, &mismatches_image))
errors++;
total += mismatches_image;
}
*mismatches = total;
if (errors)
return 0;
return 1;
}
int lv_integrity_mismatches(struct cmd_context *cmd,
const struct logical_volume *lv,
uint64_t *mismatches)
{
struct lv_with_info_and_seg_status status;
if (lv_is_raid(lv) && lv_raid_has_integrity((struct logical_volume *)lv))
return lv_raid_integrity_total_mismatches(cmd, lv, mismatches);
if (!lv_is_integrity(lv))
return_0;

View File

@@ -1433,6 +1433,5 @@ int lv_extend_integrity_in_raid(struct logical_volume *lv, struct dm_list *pvh);
int lv_get_raid_integrity_settings(struct logical_volume *lv, struct integrity_settings **isettings);
int integrity_mode_set(const char *mode, struct integrity_settings *settings);
int lv_integrity_mismatches(struct cmd_context *cmd, const struct logical_volume *lv, uint64_t *mismatches);
int lv_raid_integrity_total_mismatches(struct cmd_context *cmd, const struct logical_volume *lv, uint64_t *mismatches);
#endif

View File

@@ -52,20 +52,6 @@ char *pv_tags_dup(const struct physical_volume *pv)
return tags_format_and_copy(pv->vg->vgmem, &pv->tags);
}
char *pv_deviceid_dup(struct dm_pool *mem, const struct physical_volume *pv)
{
if (!pv->device_id)
return NULL;
return dm_pool_strdup(mem, pv->device_id);
}
char *pv_deviceidtype_dup(struct dm_pool *mem, const struct physical_volume *pv)
{
if (!pv->device_id_type)
return NULL;
return dm_pool_strdup(mem, pv->device_id_type);
}
const struct format_type *pv_format_type(const struct physical_volume *pv)
{
return pv_field(pv, fmt);

View File

@@ -27,8 +27,6 @@ struct physical_volume {
struct id old_id; /* Set during pvchange -u. */
struct device *dev;
const char *device_hint; /* primary name last time metadata was written */
const char *device_id;
const char *device_id_type;
const struct format_type *fmt;
struct format_instance *fid;
@@ -79,8 +77,6 @@ char *pv_attr_dup(struct dm_pool *mem, const struct physical_volume *pv);
const char *pv_dev_name(const struct physical_volume *pv);
char *pv_uuid_dup(struct dm_pool *mem, const struct physical_volume *pv);
char *pv_tags_dup(const struct physical_volume *pv);
char *pv_deviceid_dup(struct dm_pool *mem, const struct physical_volume *pv);
char *pv_deviceidtype_dup(struct dm_pool *mem, const struct physical_volume *pv);
uint64_t pv_size(const struct physical_volume *pv);
uint64_t pv_size_field(const struct physical_volume *pv);
uint64_t pv_dev_size(const struct physical_volume *pv);

View File

@@ -206,8 +206,6 @@ FIELD(PVS, pv, SIZ, "BA Start", ba_start, 0, size64, pv_ba_start, "Offset to the
FIELD(PVS, pv, SIZ, "BA Size", ba_size, 0, size64, pv_ba_size, "Size of PV Bootloader Area in current units.", 0)
FIELD(PVS, pv, BIN, "PInUse", id, 0, pvinuse, pv_in_use, "Set if PV is used.", 0)
FIELD(PVS, pv, BIN, "Duplicate", id, 0, pvduplicate, pv_duplicate, "Set if PV is an unchosen duplicate.", 0)
FIELD(PVS, pv, STR, "DeviceID", id, 0, pvdeviceid, pv_device_id, "Device ID such as the WWID.", 0)
FIELD(PVS, pv, STR, "DeviceIDType", id, 0, pvdeviceidtype, pv_device_id_type, "Type of device ID such as WWID.", 0)
/*
* End of PVS type fields
*/

View File

@@ -238,10 +238,6 @@ GET_PV_NUM_PROPERTY_FN(pv_ba_start, SECTOR_SIZE * pv->ba_start)
#define _pv_ba_start_set prop_not_implemented_set
GET_PV_NUM_PROPERTY_FN(pv_ba_size, SECTOR_SIZE * pv->ba_size)
#define _pv_ba_size_set prop_not_implemented_set
GET_PV_STR_PROPERTY_FN(pv_device_id, pv->device_id)
#define _pv_device_id_set prop_not_implemented_set
GET_PV_STR_PROPERTY_FN(pv_device_id_type, pv->device_id_type)
#define _pv_device_id_type_set prop_not_implemented_set
#define _pv_allocatable_set prop_not_implemented_set
#define _pv_allocatable_get prop_not_implemented_get

View File

@@ -3338,10 +3338,6 @@ static int _integritymismatches_disp(struct dm_report *rh __attribute__((unused)
if (lv_is_integrity(lv) && lv_integrity_mismatches(lv->vg->cmd, lv, &mismatches))
return dm_report_field_uint64(rh, field, &mismatches);
if (lv_is_raid(lv) && lv_raid_has_integrity(lv) &&
lv_raid_integrity_total_mismatches(lv->vg->cmd, lv, &mismatches))
return dm_report_field_uint64(rh, field, &mismatches);
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
@@ -3511,42 +3507,6 @@ static int _pvduplicate_disp(struct dm_report *rh, struct dm_pool *mem,
return _binary_disp(rh, mem, field, duplicate, GET_FIRST_RESERVED_NAME(pv_duplicate_y), private);
}
static int _pvdeviceid_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct physical_volume *pv = (const struct physical_volume *) data;
char *repstr;
if (!pv->device_id)
return _field_set_value(field, "", NULL);
if (!(repstr = pv_deviceid_dup(mem, pv))) {
log_error("Failed to allocate buffer.");
return 0;
}
return _field_set_value(field, repstr, NULL);
}
static int _pvdeviceidtype_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct physical_volume *pv = (const struct physical_volume *) data;
char *repstr;
if (!pv->device_id_type)
return _field_set_value(field, "", NULL);
if (!(repstr = pv_deviceidtype_dup(mem, pv))) {
log_error("Failed to allocate buffer.");
return 0;
}
return _field_set_value(field, repstr, NULL);
}
static int _vgpermissions_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)

View File

@@ -255,7 +255,7 @@ static int _target_present(struct cmd_context *cmd,
return 0;
}
if (min >= 3) {
if (min >= 2) {
_writecache_cleaner_supported = 1;
_writecache_max_age_supported = 1;
}

View File

@@ -2,7 +2,9 @@
.SH NAME
lvmvdo \(em LVM Virtual Data Optimizer support
.SH DESCRIPTION
VDO (which includes kvdo and vdo) is software that provides inline
block-level deduplication, compression, and thin provisioning capabilities
for primary storage.
@@ -11,9 +13,9 @@ Deduplication is a technique for reducing the consumption of storage
resources by eliminating multiple copies of duplicate blocks. Compression
takes the individual unique blocks and shrinks them with coding
algorithms; these reduced blocks are then efficiently packed together into
physical blocks. Thin provisioning manages the mapping from logical blocks
presented by VDO to where the data has actually been physically stored,
and also eliminates any blocks of all zeroes.
physical blocks. Thin provisioning manages the mapping from LBAs presented
by VDO to where the data has actually been stored, and also eliminates any
blocks of all zeroes.
With deduplication, instead of writing the same data more than once each
duplicate block is detected and recorded as a reference to the original
@@ -46,23 +48,29 @@ thin provisioning, block sharing, and compression;
the "\fIuds\fP" module provides memory-efficient duplicate
identification. The userspace tools include \fBvdostats\fP(8)
for extracting statistics from those volumes.
.SH VDO TERMS
.SH VDO Terms
.TP
VDODataLV
.br
VDO data LV
.br
large hidden LV with suffix _vdata created in a VG
large hidden LV with suffix _vdata created in a VG.
.br
used by VDO kernel target to store all data and metadata blocks.
used by VDO target to store all data and metadata blocks.
.TP
VDOPoolLV
.br
VDO pool LV
.br
pool for virtual VDOLV(s) with the size of used VDODataLV
maintains virtual for LV(s) stored in attached VDO data LV
and it has same size.
.br
a single VDOLV is currently supported.
contains VDOLV(s) (currently supports only a single VDOLV).
.TP
VDOLV
.br
@@ -70,10 +78,14 @@ VDO LV
.br
created from VDOPoolLV
.br
appears blank after creation.
.SH VDO USAGE
appears blank after creation
.SH VDO Usage
The primary methods for using VDO with lvm2:
.SS 1. Create VDOPoolLV with VDOLV
Create a VDOPoolLV that will hold VDO data together with
virtual size VDOLV, that user can use. When the virtual size
is not specified, then such LV is created with maximum size that
@@ -94,15 +106,18 @@ operation.
.fi
.I Example
.br
.nf
# lvcreate --type vdo -n vdo0 -L 10G -V 100G vg/vdopool0
# mkfs.ext4 -E nodiscard /dev/vg/vdo0
.fi
.SS 2. Create VDOPoolLV from conversion of an existing LV into VDODataLV
Convert an already created/existing LV into a volume that can hold
VDO data and metadata (volume referenced by VDOPoolLV).
VDO data and metadata (a volume reference by VDOPoolLV).
User will be prompted to confirm such conversion as it is \fBIRREVERSIBLY
DESTROYING\fP content of such volume and it is being immediately
DESTROYING\fP content of such volume, as it's being immediately
formatted by \fBvdoformat\fP(8) as VDO pool data volume. User can
specify virtual size of associated VDOLV with this VDOPoolLV.
When the virtual size is not specified, it will be set to the maximum size
@@ -114,10 +129,13 @@ that can keep 100% uncompressible data there.
.fi
.I Example
.br
.nf
# lvconvert --type vdo-pool -n vdo0 -V10G vg/ExistingLV
# lvconvert --type vdo-pool -n vdo0 -V10G vg/existinglv
.fi
.SS 3. Change default settings used for creating VDOPoolLV
VDO allows to set large variety of options. Lots of these settings
can be specified by lvm.conf or profile settings. User can prepare
number of different profiles in #DEFAULT_SYS_DIR#/profile directory
@@ -126,6 +144,7 @@ Check output of \fBlvmconfig --type full\fP for detailed description
of all individual vdo settings.
.I Example
.br
.nf
# cat <<EOF > #DEFAULT_SYS_DIR#/profile/vdo_create.profile
allocation {
@@ -154,8 +173,10 @@ EOF
# lvcreate --vdo -L10G --metadataprofile vdo_create vg/vdopool0
# lvcreate --vdo -L10G --config 'allocation/vdo_cpu_threads=4' vg/vdopool1
.fi
.SS 4. Change compression and deduplication of VDOPoolLV
Disable or enable compression and deduplication for VDOPoolLV
Disable or enable compression and deduplication for VDO pool LV
(the volume that maintains all VDO LV(s) associated with it).
.nf
@@ -163,11 +184,14 @@ Disable or enable compression and deduplication for VDOPoolLV
.fi
.I Example
.br
.nf
# lvchange --compression n vg/vdopool0
# lvchange --deduplication y vg/vdopool1
# lvchange --compression n vg/vdpool0
# lvchange --deduplication y vg/vdpool1
.fi
.SS 5. Checking usage of VDOPoolLV
To quickly check how much data of VDOPoolLV are already consumed
use \fBlvs\fP(8). Field Data% will report how much data occupies
content of virtual data for VDOLV and how much space is already
@@ -177,6 +201,7 @@ For a detailed description use \fBvdostats\fP(8) command.
Note: \fBvdostats\fP(8) currently understands only /dev/mapper device names.
.I Example
.br
.nf
# lvcreate --type vdo -L10G -V20G -n vdo0 vg/vdopool0
# mkfs.ext4 -E nodiscard /dev/vg/vdo0
@@ -194,16 +219,12 @@ Note: \fBvdostats\fP(8) currently understands only /dev/mapper device names.
data blocks used : 79
...
.fi
.SS 6. Extending VDOPoolLV size
Adding more space to hold VDO data and metadata can be made via
extension of VDODataLV with commands
\fBlvresize\fP(8), \fBlvextend\fP(8).
Extension needs to add at least one new VDO slab which can be
configured with \fBallocation/vdo_slab_size_mb\fP setting.
User can also enable automatic size extension of monitored VDOPoolLV
with \fBactivation/vdo_pool_autoextend_percent\fP and
\fBactivation/vdo_pool_autoextend_threshold\fP settings.
Note: Size of VDOPoolLV cannot be reduced.
@@ -214,12 +235,15 @@ Note: Size of cached VDOPoolLV cannot be changed.
.fi
.I Example
.br
.nf
# lvextend -L+50G vg/vdopool0
# lvresize -L300G vg/vdopool1
.fi
.SS 7. Extending or reducing VDOLV size
Virtual VDO LV can be extended or reduced as standard LV with commands
VDO LV can be extended or reduced as standard LV with commands
\fBlvresize\fP(8), \fBlvextend\fP(8), \fBlvreduce\fP(8).
Note: Reduction needs to process TRIM for reduced disk area
@@ -232,61 +256,79 @@ a long time.
.fi
.I Example
.br
.nf
# lvextend -L+50G vg/vdo0
# lvreduce -L-50G vg/vdo1
# lvresize -L200G vg/vdo2
.fi
.SS 8. Component activation of VDODataLV
VDODataLV can be activated separately as component LV for examination
purposes. It activates data LV in read-only mode and cannot be modified.
If the VDODataLV is active as component, any upper LV using this volume CANNOT
be activated. User has to deactivate VDODataLV first to continue to use VDOPoolLV.
.I Example
.br
.nf
# lvchange -ay vg/vpool0_vdata
# lvchange -an vg/vpool0_vdata
.fi
.SH VDO TOPICS
.SH VDO Topics
.SS 1. Stacking VDO
User can convert/stack VDOPooLV with these currently supported
volume types: linear, stripe, raid and cache with cachepool
.SS 2. VDOPoolLV on top of raid
Using raid type LV for VDODataLV.
User can convert/stack VDO with existing volumes.
.SS 2. VDO on top of raid
Using Raid type LV for VDO Data LV.
.I Example
.br
.nf
# lvcreate --type raid1 -L 5G -n vdopool vg
# lvconvert --type vdo-pool -V 10G vg/vdopool
# lvcreate --type raid1 -L 5G -n vpool vg
# lvconvert --type vdo-pool -V 10G vg/vpool
.fi
.SS 3. Caching VDODataLV, VDOPoolLV
VDODataLV (accepts also VDOPoolLV) caching provides mechanism
to accelerate read and write of already compressed and deduplicated
data blocks together with VDO metadata.
Cached VDO data LV cannot be currently resized and also the threshold
based automatic resize will not work.
VDO Pool LV (accepts also VDOPoolLV) caching provides mechanism
to accelerate read and write of already compressed and deduplicated
blocks together with vdo metadata.
Cached VDO Data LV cannot be currently resized (also automatic
resize will not work).
.I Example
.br
.nf
# lvcreate --type vdo -L 5G -V 10G -n vdo1 vg/vdopool
# lvcreate --type cache-pool -L 1G -n cachepool vg
# lvconvert --cache --cachepool vg/cachepool vg/vdopool
# lvconvert --uncache vg/vdopool
# lvcreate --type vdo -L 5G -V 10G -n vdo1 vg/vpool
# lvcreate --type cache-pool -L 1G -n cpool vg
# lvconvert --cache --cachepool vg/cpool vg/vpool
# lvconvert --uncache vg/vpool
.fi
.SS 4. Caching VDOLV
VDO LV cache allow users to 'cache' device for better perfomance before
it hits processing of VDO Pool LV layer.
.I Example
.br
.nf
# lvcreate -L 5G -V 10G -n vdo1 vg/vdopool
# lvcreate --type cache-pool -L 1G -n cachepool vg
# lvconvert --cache --cachepool vg/cachepool vg/vdo1
# lvcreate -L 5G -V 10G -n vdo1 vg/vpool
# lvcreate --type cache-pool -L 1G -n cpool vg
# lvconvert --cache --cachepool vg/cpool vg/vdo1
# lvconvert --uncache vg/vdo1
.fi
.SS 5. Usage of Discard/TRIM with VDOLV
User can discard data in VDO LV and reduce used blocks in VDOPoolLV.
However present performance of discard operation is still not optimal
and takes considerable amount of time and CPU.
@@ -300,53 +342,10 @@ provisioning in other regions of VDO LV.
For the same reason, user should avoid using mkfs with discard for
freshly created VDO LV to save a lot of time this operation would
take otherwise as device after create empty.
.SS 6. Memory usage
VDO target requires 370 MiB of RAM plus an additional 268 MiB
per each 1 TiB of physical storage managed by the volume.
UDS requires a minimum of 250 MiB of RAM,
which is also the default amount that deduplication uses.
.br
The memory required for the UDS index is determined by the index type
and the required size of the deduplication window and
is controled by \fBallocation/vdo_use_sparse_index\fP setting.
With enabled UDS sparse indexing it relies on the temporal locality of data
and attempts to retain only the most relevant index entries in memory and
can maintain a deduplication window that is ten times larger
than with dense while using the same amount of memory.
Although the sparse index provides the greatest coverage,
the dense index provides more deduplication advice.
For most workloads, given the same amount of memory,
the difference in deduplication rates between dense
and sparse indexes is negligible.
Dense index with 1 GiB of RAM maintains 1 TiB deduplication window,
while sparse index with 1 GiB of RAM maintains 10 TiB deduplication window.
In general 1 GiB is sufficient for 4 TiB or physical space with
dense index and 40 TiB with sparse index.
.SS 7. Storage space requirements
User can configure a VDOPoolLV to use up to 256 TiB of physical storage.
Only a certain part of the physical storage is usable to store data.
This section provides the calculations to determine the usable size
of a VDO-managed volume.
VDO target requires storage for two types of VDO metadata and for the UDS index:
.TP
\(bu
The first type of VDO metadata uses approximately 1 MiB for each 4 GiB
of physical storage plus an additional 1 MiB per slab.
.TP
\(bu
The second type of VDO metadata consumes approximately 1.25 MiB
for each 1 GiB of logical storage, rounded up to the nearest slab.
.TP
\(bu
The amount of storage required for the UDS index depends on the type of index
and the amount of RAM allocated to the index. For each 1 GiB of RAM,
a dense UDS index uses 17 GiB of storage and a sparse UDS index will use
170 GiB of storage.
\&
.SH SEE ALSO
.BR lvm (8),

View File

@@ -1,7 +1,6 @@
vgsplit moves one or more PVs from a source VG (the first VG arg) to a
destination VG (the second VG arg). The PV(s) to move are named after the
source and destination VGs, or an LV is named, in which case the PVs
underlying the LV are moved.
vgsplit moves one or more PVs from a source VG to a destination VG. The
PVs can be specified explicitly or implicitly by naming an LV, in which
case on PVs underlying the LV are moved.
If the destination VG does not exist, a new VG is created (command options
can be used to specify properties of the new VG, also see

View File

@@ -109,7 +109,6 @@ help:
@echo " LVM_TEST_CACHE_REPAIR_CMD Command for cache_repair [$(LVM_TEST_CACHE_REPAIR_CMD)]."
@echo " LVM_TEST_CACHE_RESTORE_CMD Command for cache_restore [$(LVM_TEST_CACHE_RESTORE_CMD)]."
@echo " LVM_TEST_UNLIMITED Set to get unlimited test log (>32MB)"
@echo " LVM_TEST_DEVICE_LIST File path listing real devs that tests can use."
@echo " LVM_VALGRIND Enable valgrind testing, execs $$"VALGRIND.
@echo " LVM_VALGRIND_DMEVENTD Enable valgrind testing of dmeventd (1)."
@echo " LVM_VALGRIND_LVMPOLLD Enable valgrind testing of lvmpolld (1)."

View File

@@ -657,24 +657,6 @@ prepare_ramdisk() {
touch RAMDISK
}
prepare_real_devs() {
aux lvmconf 'devices/scan = "/dev"'
touch REAL_DEVICES
if test -n "$LVM_TEST_DEVICE_LIST"; then
local count=0
while read path; do
REAL_DEVICES[$count]=$path
count=$(( count + 1 ))
aux extend_filter "a|$path|"
dd if=/dev/zero of="$path" bs=32k count=1
wipefs -a "$path" 2>/dev/null || true
done < $LVM_TEST_DEVICE_LIST
fi
printf "%s\\n" "${REAL_DEVICES[@]}" > REAL_DEVICES
}
# A drop-in replacement for prepare_loop() that uses scsi_debug to create
# a ramdisk-based SCSI device upon which all LVM devices will be created
# - scripts must take care not to use a DEV_SIZE that will enduce OOM-killer
@@ -927,6 +909,7 @@ prepare_devs() {
echo "ok"
}
common_dev_() {
local tgtype=$1
local dev=$2

View File

@@ -252,11 +252,6 @@ skip() {
exit 200
}
get_real_devs() {
REAL_DEVICES=( $(<REAL_DEVICES) )
export REAL_DEVICES
}
get_devs() {
local IFS=$IFS_NL
DEVICES=( $(<DEVICES) )
@@ -270,21 +265,10 @@ prepare_test_vars() {
lv=LV
for i in {1..16}; do
eval "dev$i=\"$DM_DEV_DIR/mapper/${PREFIX}pv$i\""
eval "lv$i=\"LV$i\""
eval "vg$i=\"${PREFIX}vg$i\""
done
if test -n "$LVM_TEST_DEVICE_LIST"; then
local count=0
while read path; do
count=$(( count + 1 ))
eval "dev$count=\"$path\""
done < $LVM_TEST_DEVICE_LIST
else
for i in {1..16}; do
eval "dev$i=\"$DM_DEV_DIR/mapper/${PREFIX}pv$i\""
done
fi
}
if test -z "${abs_top_builddir+varset}" && test -z "${installed_testsuite+varset}"; then

View File

@@ -1,522 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2020 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='devices file'
. lib/inittest
aux prepare_devs 7
RUNDIR="/run"
test -d "$RUNDIR" || RUNDIR="/var/run"
PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online"
VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online"
PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup"
_clear_online_files() {
# wait till udev is finished
aux udev_wait
rm -f "$PVS_ONLINE_DIR"/*
rm -f "$VGS_ONLINE_DIR"/*
rm -f "$PVS_LOOKUP_DIR"/*
}
DFDIR="$LVM_SYSTEM_DIR/devices"
mkdir $DFDIR
#
# Test with use_devicesfile=0 (no devices file is being applied by default)
#
aux lvmconf 'devices/use_devicesfile = 0'
# create one VG in a non-system devices file
vgcreate --devicesfile test.devices $vg1 $dev1
vgextend --devicesfile test.devices $vg1 $dev2
# create two VGs outside the special devices file
vgcreate $vg2 $dev3 $dev4
vgcreate $vg3 $dev5 $dev6
PVID1=`pvs $dev1 --noheading -o uuid | tr -d - | awk '{print $1}'`
PVID2=`pvs $dev2 --noheading -o uuid | tr -d - | awk '{print $1}'`
PVID3=`pvs $dev3 --noheading -o uuid | tr -d - | awk '{print $1}'`
PVID4=`pvs $dev4 --noheading -o uuid | tr -d - | awk '{print $1}'`
PVID5=`pvs $dev5 --noheading -o uuid | tr -d - | awk '{print $1}'`
PVID6=`pvs $dev6 --noheading -o uuid | tr -d - | awk '{print $1}'`
lvcreate -l4 -an -i2 -n $lv1 $vg1
lvcreate -l4 -an -i2 -n $lv2 $vg2
lvcreate -l4 -an -i2 -n $lv3 $vg3
# verify devices file is working
vgs --devicesfile test.devices $vg1
not vgs --devicesfile test.devices $vg2
not vgs --devicesfile test.devices $vg2
# devicesfile and devices cannot be used together
not vgs --devicesfile test.devices --devices $dev1,$dev1 $vg1
# verify correct vgs are seen / not seen when devices are specified
vgs --devices $dev1,$dev2 $vg1
vgs --devices $dev3,$dev4 $vg2
vgs --devices $dev5,$dev6 $vg3
not vgs --devices $dev1,$dev2 $vg2
not vgs --devices $dev1,$dev2 $vg3
not vgs --devices $dev1,$dev2 $vg2
not vgs --devices $dev5,$dev6 $vg2
not vgs --devices $dev1,$dev2 $vg3
not vgs --devices $dev3,$dev4 $vg3
vgs --devices $dev1,$dev2 |tee out
grep $vg1 out
not grep $vg2 out
not grep $vg3 out
vgs --devices $dev3,$dev4 |tee out
not grep $vg1 out
grep $vg2 out
not grep $vg3 out
# verify correct pvs are seen / not seen when devices are specified
pvs --devices $dev1,$dev2 $dev1 $dev2
pvs --devices $dev3,$dev4 $dev3 $dev4
pvs --devices $dev5,$dev6 $dev5 $dev6
not pvs --devices $dev1,$dev2 $dev3 $dev4
not pvs --devices $dev1,$dev2 $dev5 $dev6
not pvs --devices $dev3,$dev4 $dev1 $dev2 $dev5 $dev6
pvs --devices $dev1,$dev2 |tee out
grep $dev1 out
grep $dev2 out
not grep $dev3 out
not grep $dev4 out
not grep $dev5 out
not grep $dev6 out
pvs --devices $dev3,$dev4 |tee out
not grep $dev1 out
not grep $dev2 out
grep $dev3 out
grep $dev4 out
not grep $dev5 out
not grep $dev6 out
# verify correct lvs are activated / not activated when devices are specified
vgchange --devices $dev1,$dev2 -ay
check lv_field $vg1/$lv1 lv_active "active"
check lv_field $vg2/$lv2 lv_active ""
check lv_field $vg3/$lv3 lv_active ""
vgchange --devices $dev1,$dev2 -an
check lv_field $vg1/$lv1 lv_active ""
vgchange --devices $dev3,$dev4 -ay
check lv_field $vg1/$lv1 lv_active ""
check lv_field $vg2/$lv2 lv_active "active"
check lv_field $vg3/$lv3 lv_active ""
vgchange --devices $dev3,$dev4 -an
check lv_field $vg2/$lv2 lv_active ""
# verify devices covering multiple vgs
vgs --devices $dev1,$dev2,$dev3,$dev4 $vg1 $vg2 |tee out
grep $vg1 out
grep $vg2 out
not grep $vg3 out
vgs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 $vg1 $vg2 $vg3 |tee out
grep $vg1 out
grep $vg2 out
grep $vg3 out
# verify vgs seen when incomplete devices are specified
vgs --devices $dev1 $vg1
vgs --devices $dev3 $vg2
vgs --devices $dev5 $vg3
# incomplete vg because of --devices is the same as vg incomplete because
# of missing device
not lvcreate --devices $dev1 -l1 $vg1
not lvchange --devices $dev1 -ay $vg1/$lv1
not lvextend --devices $dev1 -l+1 $vg1/$lv1
not vgremove --devices $dev1 $vg1
not lvcreate --devices $dev3 -l1 $vg2
not lvchange --devices $dev3 -ay $vg2/$lv2
not lvextend --devices $dev3 -l+1 $vg2/$lv2
not vgremove --devices $dev3 $vg2
# verify various commands with --devices for vg in a devicesfile
not lvcreate --devices $dev1,$dev2 -l1 -n $lv2 -an $vg1 $dev7
lvcreate --devices $dev1,$dev2 -l1 -n $lv2 -an $vg1
lvs --devices $dev1,$dev2 $vg1/$lv2
lvextend --devices $dev1,$dev2 -l2 $vg1/$lv2
lvchange --devices $dev1,$dev2 -ay $vg1/$lv2
lvchange --devices $dev1,$dev2 -an $vg1/$lv2
lvremove --devices $dev1,$dev2 $vg1/$lv2
vgchange --devices $dev1,$dev2 -ay $vg1
vgchange --devices $dev1,$dev2 -an $vg1
not vgextend --devices $dev1,$dev2 $vg1 $dev7
vgextend --devices $dev1,$dev2,$dev7 $vg1 $dev7
vgreduce --devices $dev1,$dev2,$dev7 $vg1 $dev7
vgexport --devices $dev1,$dev2 $vg1
vgimport --devices $dev1,$dev2 $vg1
not pvremove --devices $dev1,$dev2 $dev7
not pvcreate --devices $dev1,$dev2 $dev7
not vgcreate --devices $dev1,$dev2 $vg7 $dev7
pvremove --devices $dev7 $dev7
pvcreate --devices $dev7 $dev7
vgcreate --devices $dev7 $vg7 $dev7
vgremove --devices $dev7 $vg7
pvremove --devices $dev7 $dev7
# verify various commands with --devices for vg not in a devicesfile
not lvcreate --devices $dev3,$dev4 -l1 -n $lv4 -an $vg2 $dev7
lvcreate --devices $dev3,$dev4 -l1 -n $lv4 -an $vg2
lvs --devices $dev3,$dev4 $vg2/$lv4
lvextend --devices $dev3,$dev4 -l2 $vg2/$lv4
lvchange --devices $dev3,$dev4 -ay $vg2/$lv4
lvchange --devices $dev3,$dev4 -an $vg2/$lv4
lvremove --devices $dev3,$dev4 $vg2/$lv4
vgchange --devices $dev3,$dev4 -ay $vg2
vgchange --devices $dev3,$dev4 -an $vg2
not vgextend --devices $dev3,$dev4 $vg2 $dev7
vgextend --devices $dev3,$dev4,$dev7 $vg2 $dev7
vgreduce --devices $dev3,$dev4,$dev7 $vg2 $dev7
vgexport --devices $dev3,$dev4 $vg2
vgimport --devices $dev3,$dev4 $vg2
not pvremove --devices $dev3,$dev4 $dev7
not pvcreate --devices $dev3,$dev4 $dev7
not vgcreate --devices $dev3,$dev4 $vg7 $dev7
pvremove --devices $dev7 $dev7
pvcreate --devices $dev7 $dev7
vgcreate --devices $dev7 $vg7 $dev7
vgremove --devices $dev7 $vg7
pvremove --devices $dev7 $dev7
# verify pvscan with devices file and devices list
# arg not in devices file
_clear_online_files
pvscan --devicesfile test.devices --cache -aay $dev3
not ls "$RUNDIR/lvm/pvs_online/$PVID3"
pvscan --devicesfile test.devices --cache -aay $dev4
not ls "$RUNDIR/lvm/pvs_online/$PVID4"
check lv_field $vg1/$lv1 lv_active ""
check lv_field $vg2/$lv2 lv_active ""
# arg in devices file
_clear_online_files
pvscan --devicesfile test.devices --cache $dev1
pvscan --devicesfile test.devices --cache $dev2
ls "$RUNDIR/lvm/pvs_online/$PVID1"
ls "$RUNDIR/lvm/pvs_online/$PVID2"
# autoactivate with devices file
_clear_online_files
pvscan --devicesfile test.devices --cache -aay $dev1
pvscan --devicesfile test.devices --cache -aay $dev2
check lv_field $vg1/$lv1 lv_active "active"
vgchange -an $vg1
# autoactivate with no devices file
_clear_online_files
pvscan --cache -aay $dev3
pvscan --cache -aay $dev4
check lv_field $vg2/$lv2 lv_active "active"
vgchange -an $vg2
# arg not in devices list
_clear_online_files
pvscan --devices $dev1,$dev2 --cache $dev3
not ls "$RUNDIR/lvm/pvs_online/$PVID3"
pvscan --devices $dev4 --cache $dev3
not ls "$RUNDIR/lvm/pvs_online/$PVID3"
pvscan --devices $dev5 --cache $dev3
not ls "$RUNDIR/lvm/pvs_online/$PVID3"
# arg in devices list
_clear_online_files
pvscan --devices $dev3 --cache -aay $dev3
pvscan --devices $dev4 --cache -aay $dev4
check lv_field $vg2/$lv2 lv_active "active"
vgchange -an $vg2
# verify --devicesfile and --devices are not affected by a filter
# hide_dev excludes using existing filter
aux hide_dev $dev2
aux hide_dev $dev4
pvs --devicesfile test.devices $dev1
pvs --devicesfile test.devices $dev2
not pvs --devicesfile test.devices $dev3
not pvs --devicesfile test.devices $dev4
pvs --devices $dev1 $dev1
pvs --devices $dev2 $dev2
pvs --devices $dev3 $dev3
pvs --devices $dev4 $dev4
pvs --devices $dev5 $dev5
pvs --devices $dev1,$dev2,$dev3,$dev4,$dev5 $dev1 $dev2 $dev3 $dev4 $dev5 | tee out
grep $dev1 out
grep $dev2 out
grep $dev3 out
grep $dev4 out
grep $dev5 out
vgchange --devices $dev1,$dev2 -ay $vg1
check lv_field $vg1/$lv1 lv_active "active"
lvchange --devices $dev1,$dev2 -an $vg1/$lv1
vgchange --devices $dev3,$dev4 -ay $vg2
check lv_field $vg2/$lv2 lv_active "active"
lvchange --devices $dev3,$dev4 -an $vg2/$lv2
aux unhide_dev $dev2
aux unhide_dev $dev4
vgchange --devicesfile "" -an
vgremove --devicesfile "" -y $vg1
vgremove --devicesfile "" -y $vg2
vgremove --devicesfile "" -y $vg3
#
# Test with use_devicesfile=1 (system devices file is in use by default)
#
aux lvmconf 'devices/use_devicesfile = 1'
DF="$DFDIR/system.devices"
touch $DF
# create one VG in a non-system devices file
vgcreate --devicesfile test.devices $vg1 $dev1 $dev2
# create one VG in the default system devices file
vgcreate $vg2 $dev3 $dev4
# create one VG in neither devices file
vgcreate --devicesfile "" $vg3 $dev5 $dev6
lvcreate --devicesfile test.devices -l4 -an -i2 -n $lv1 $vg1
lvcreate -l4 -an -i2 -n $lv2 $vg2
lvcreate --devicesfile "" -l4 -an -i2 -n $lv3 $vg3
# system.devices only sees vg2
vgs |tee out
not grep $vg1 out
grep $vg2 out
not grep $vg3 out
not vgs $vg1
vgs $vg2
not vgs $vg3
pvs |tee out
not grep $dev1 out
not grep $dev2 out
grep $dev3 out
grep $dev4 out
not grep $dev5 out
not grep $dev6 out
# test.devices only sees vg1
vgs --devicesfile test.devices |tee out
grep $vg1 out
not grep $vg2 out
not grep $vg3 out
pvs --devicesfile test.devices |tee out
grep $dev1 out
grep $dev2 out
not grep $dev3 out
not grep $dev4 out
not grep $dev5 out
not grep $dev6 out
# no devices file sees all
vgs --devicesfile "" |tee out
grep $vg1 out
grep $vg2 out
grep $vg3 out
vgs --devicesfile "" $vg1
vgs --devicesfile "" $vg2
vgs --devicesfile "" $vg3
pvs --devicesfile "" |tee out
grep $dev1 out
grep $dev2 out
grep $dev3 out
grep $dev4 out
grep $dev5 out
grep $dev6 out
vgchange -ay
lvs --devicesfile test.devices -o active $vg1/$lv1 |tee out
not grep active out
lvs -o active $vg2/$lv2 |tee out
grep active out
lvs --devicesfile "" -o active $vg3/$lv3 |tee out
not grep active out
vgchange -an
lvs -o active $vg2/$lv2 |tee out
not grep active out
vgchange --devicesfile test.devices -ay
lvs --devicesfile test.devices -o active $vg1/$lv1 |tee out
grep active out
lvs -o active $vg2/$lv2 |tee out
not grep active out
lvs --devicesfile "" -o active $vg3/$lv3 |tee out
not grep active out
vgchange --devicesfile test.devices -an
lvs --devicesfile test.devices -o active $vg1/$lv1 |tee out
not grep active out
# --devices overrides all three cases:
# always gives access to the specified devices
# always denies access to unspecified devices
vgs --devices $dev1,$dev2 $vg1
vgs --devices $dev3,$dev4 $vg2
vgs --devices $dev5,$dev6 $vg3
pvs --devices $dev1 $dev1
pvs --devices $dev3 $dev3
pvs --devices $dev5 $dev5
not pvs --devices $dev1 $dev1 $dev2 |tee out
grep $dev1 out
not grep $dev2 out
not pvs --devices $dev3 $dev3 $dev4 |tee out
grep $dev3 out
not grep $dev4 out
not pvs --devices $dev5 $dev1 $dev2 $dev3 $dev4 $dev5 |tee out
grep $dev5 out
not grep $dev1 out
not grep $dev2 out
not grep $dev3 out
not grep $dev4 out
not grep $dev6 out
pvs --devices $dev1,$dev2,$dev3,$dev4,$dev5 $dev5 |tee out
grep $dev5 out
not grep $dev1 out
not grep $dev2 out
not grep $dev3 out
not grep $dev4 out
not grep $dev6 out
pvs --devices $dev1,$dev2,$dev3,$dev4,$dev5 $dev1 $dev2 $dev3 $dev4 $dev5 |tee out
grep $dev1 out
grep $dev2 out
grep $dev3 out
grep $dev4 out
grep $dev5 out
vgchange --devices $dev1,$dev2 -ay
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
grep $lv1 out
not grep $lv2 out
not grep $lv3 out
vgchange --devices $dev1,$dev2 -an
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | tee out
not grep active out
vgchange --devices $dev3,$dev4 -ay
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
not grep $lv1 out
grep $lv2 out
not grep $lv3 out
vgchange --devices $dev3,$dev4 -an
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active |tee out
not grep active out
vgchange --devices $dev5,$dev6 -ay
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
not grep $lv1 out
not grep $lv2 out
grep $lv3 out
vgchange --devices $dev5,$dev6 -an
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active |tee out
not grep active out
lvcreate --devices $dev1,$dev2 -l1 -an -n $lv4 $vg1
lvremove --devices $dev1,$dev2 $vg1/$lv4
lvcreate --devices $dev3,$dev4 -l1 -an -n $lv4 $vg2
lvremove --devices $dev3,$dev4 $vg2/$lv4
lvcreate --devices $dev5,$dev6 -l1 -an -n $lv4 $vg3
lvremove --devices $dev5,$dev6 $vg3/$lv4
not vgchange --devices $dev1,$dev2 -ay $vg2
not vgchange --devices $dev1,$dev2 -ay $vg3
not vgchange --devices $dev3,$dev4 -ay $vg1
not vgchange --devices $dev3,$dev4 -ay $vg3
not vgchange --devices $dev5,$dev6 -ay $vg1
not vgchange --devices $dev5,$dev6 -ay $vg2
not lvcreate --devices $dev1,$dev2 -an -l1 $vg2
not lvcreate --devices $dev1,$dev2 -an -l1 $vg3
not lvcreate --devices $dev3,$dev4 -an -l1 $vg1
not lvcreate --devices $dev3,$dev4 -an -l1 $vg3
not lvcreate --devices $dev5,$dev6 -an -l1 $vg1
not lvcreate --devices $dev5,$dev6 -an -l1 $vg2
# autoactivate devs in default devices file
_clear_online_files
pvscan --cache -aay $dev3
pvscan --cache -aay $dev4
check lv_field $vg2/$lv2 lv_active "active"
vgchange -an $vg2
pvscan --cache -aay $dev1
not ls "$RUNDIR/lvm/pvs_online/$PVID1"
pvscan --cache -aay $dev2
not ls "$RUNDIR/lvm/pvs_online/$PVID2"
pvscan --cache -aay $dev5
not ls "$RUNDIR/lvm/pvs_online/$PVID5"
_clear_online_files
pvscan --devices $dev3 --cache -aay $dev3
pvscan --devices $dev3,$dev4 --cache -aay $dev4
lvs --devices $dev3,$dev4 -o active $vg2/$lv2 | grep active
vgchange --devices $dev3,$dev4 -an $vg2
not vgchange -ay $vg1
vgchange --devicesfile test.devices -ay $vg1
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
grep $lv1 out
not grep $lv2 out
not grep $lv3 out
vgchange -ay $vg2
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
grep $lv1 out
grep $lv2 out
not grep $lv3 out
not vgchange -ay $vg3
vgchange --devicesfile "" -ay $vg3
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
grep $lv1 out
grep $lv2 out
grep $lv3 out
vgchange -an
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
grep $lv1 out
not grep $lv2 out
grep $lv3 out
vgchange -ay
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active | grep active |tee out
grep $lv1 out
grep $lv2 out
grep $lv3 out
vgchange --devicesfile "" -an
lvs --devices $dev1,$dev2,$dev3,$dev4,$dev5,$dev6 -o name,active |tee out
not grep active out
not vgremove $vg1
not vgremove $vg3
vgremove -y $vg2
vgremove --devicesfile test.devices -y $vg1
vgremove --devicesfile "" -y $vg3

View File

@@ -1,545 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2020 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='devices file with real devs'
. lib/inittest
#
# To use this test, add two or more devices with real device ids,
# e.g. wwids, to a file, e.g.
# $ cat /tmp/devs
# /dev/sdb
# /dev/sdc
# /dev/sdd
#
# Specify this file as LVM_TEST_DEVICE_LIST=/tmp/devs
# when running the test.
#
# This test will wipe these devices.
#
test -e "$LVM_TEST_DEVICE_LIST" || skip
num_devs=$(cat $LVM_TEST_DEVICE_LIST | wc -l)
aux prepare_real_devs
aux lvmconf 'devices/dir = "/dev"'
aux lvmconf 'devices/use_devicesfile = 1'
DFDIR="$LVM_SYSTEM_DIR/devices"
DF="$DFDIR/system.devices"
mkdir $DFDIR
not ls $DF
get_real_devs
wipe_all() {
for dev in "${REAL_DEVICES[@]}"; do
wipefs -a $dev
done
}
wipe_all
# check each dev is added correctly to df
for dev in "${REAL_DEVICES[@]}"; do
pvcreate $dev
ls $DF
pvs -o+uuid $dev
maj=$(get pv_field "$dev" major)
min=$(get pv_field "$dev" minor)
pvid=`pvs $dev --noheading -o uuid | tr -d - | awk '{print $1}'`
sys_wwid_file="/sys/dev/block/$maj:$min/device/wwid"
sys_serial_file="/sys/dev/block/$maj:$min/device/serial"
sys_dm_uuid_file="/sys/dev/block/$maj:$min/dm/uuid"
sys_md_uuid_file="/sys/dev/block/$maj:$min/md/uuid"
sys_loop_file="/sys/dev/block/$maj:$min/loop/backing_file"
if test -e $sys_wwid_file; then
sys_file=$sys_wwid_file
idtype="sys_wwid"
elif test -e $sys_serial_file; then
sys_file=$sys_serial_file
idtype="sys_serial"
elif test -e $sys_dm_uuid_file; then
sys_file=$sys_dm_uuid_file
idtype="mpath_uuid"
elif test -e $sys_md_uuid_file; then
sys_file=$sys_md_uuid_file
idtype="md_uuid"
elif test -e $sys_loop_file; then
sys_file=$sys_loop_file
idtype="loop_file"
else
echo "no id type for device"
skip
fi
idname=$(< $sys_file)
rm -f idline
grep IDNAME=$idname $DF | tee idline
grep IDTYPE=$idtype idline
grep DEVNAME=$dev idline
grep PVID=$pvid idline
done
cp $DF df2
# vgcreate from existing pvs, already in df
vgcreate $vg ${REAL_DEVICES[@]}
vgremove $vg
rm $DF
# vgcreate from existing pvs, adding to df
vgcreate $vg ${REAL_DEVICES[@]}
grep IDNAME $DF > df.ids
grep IDNAME df2 > df2.ids
diff df.ids df2.ids
# check device id metadata fields
for dev in "${REAL_DEVICES[@]}"; do
grep $dev $DF
deviceid=`pvs $dev --noheading -o deviceid | awk '{print $1}'`
deviceidtype=`pvs $dev --noheading -o deviceidtype | awk '{print $1}'`
grep $dev $DF | grep $deviceid
grep $dev $DF | grep $deviceidtype
lvcreate -l1 $vg $dev
done
vgchange -an $vg
vgremove -y $vg
# check pvremove leaves devs in df but without pvid
for dev in "${REAL_DEVICES[@]}"; do
maj=$(get pv_field "$dev" major)
min=$(get pv_field "$dev" minor)
pvid=`pvs $dev --noheading -o uuid | tr -d - | awk '{print $1}'`
pvremove $dev
grep $dev $DF
not grep $pvid $DF
done
# Many of remaining tests require two devices
test $num_devs -gt 1 || skip
# check vgextend adds new dev to df, vgreduce leaves dev in df
rm $DF
vgcreate $vg $dev1
vgextend $vg $dev2
grep $dev1 $DF
grep $dev2 $DF
id1=`pvs $dev1 --noheading -o deviceid | awk '{print $1}'`
id2=`pvs $dev2 --noheading -o deviceid | awk '{print $1}'`
grep $id1 $DF
grep $id2 $DF
vgreduce $vg $dev2
grep $dev2 $DF
vgremove $vg
# check devs are not visible to lvm until added to df
rm $DF
# df needs to exist otherwise devicesfile feature turned off
touch $DF
not pvs $dev1
not pvs $dev2
pvs -a |tee all
not grep $dev1 all
not grep $dev2 all
not grep $dev1 $DF
not grep $dev2 $DF
pvcreate $dev1
pvs $dev1
not pvs $dev2
pvs -a |tee all
grep $dev1 all
not grep $dev2 all
grep $dev1 $DF
not grep $dev2 $DF
pvcreate $dev2
pvs $dev1
pvs $dev2
pvs -a |tee all
grep $dev1 all
grep $dev2 all
grep $dev1 $DF
grep $dev2 $DF
vgcreate $vg $dev1
pvs $dev1
pvs $dev2
pvs -a |tee all
grep $dev1 all
grep $dev2 all
grep $dev1 $DF
grep $dev2 $DF
vgextend $vg $dev2
pvs $dev1
pvs $dev2
pvs -a |tee all
grep $dev1 all
grep $dev2 all
grep $dev1 $DF
grep $dev2 $DF
# check vgimportdevices VG
rm $DF
wipe_all
vgcreate $vg ${REAL_DEVICES[@]}
rm $DF
touch $DF
for dev in "${REAL_DEVICES[@]}"; do
not pvs $dev
done
vgimportdevices $vg
for dev in "${REAL_DEVICES[@]}"; do
pvs $dev
done
# check vgimportdevices -a
rm $DF
wipe_all
vgcreate $vg1 $dev1
vgcreate $vg2 $dev2
rm $DF
vgimportdevices -a
vgs $vg1
vgs $vg2
pvs $dev1
pvs $dev2
# check vgimportclone --importdevices
rm $DF
wipe_all
vgcreate $vg1 $dev1
vgimportdevices $vg1
dd if=$dev1 of=$dev2 bs=1M count=1
pvs $dev1
not pvs $dev2
grep $dev1 $DF
not grep $dev2 $DF
not vgimportclone $dev2
not grep $dev2 $DF
vgimportclone --basevgname $vg2 --importdevices $dev2
pvid1=`pvs $dev1 --noheading -o uuid | tr -d - | awk '{print $1}'`
pvid2=`pvs $dev2 --noheading -o uuid | tr -d - | awk '{print $1}'`
test "$pvid1" != "$pvid2" || die "same uuid"
id1=`pvs $dev1 --noheading -o deviceid | tr -d - | awk '{print $1}'`
id2=`pvs $dev2 --noheading -o deviceid | tr -d - | awk '{print $1}'`
test "$id1" != "$id2" || die "same device id"
grep $dev1 $DF
grep $dev2 $DF
grep $pvid1 $DF
grep $pvid2 $DF
grep $id1 $DF
grep $id2 $DF
vgs $vg1
vgs $vg2
#
# check lvmdevices
#
wipe_all
rm $DF
# set up pvs and save pvids/deviceids
count=0
for dev in "${REAL_DEVICES[@]}"; do
pvcreate $dev
vgcreate ${vg}_${count} $dev
pvid=`pvs $dev --noheading -o uuid | tr -d - | awk '{print $1}'`
did=`pvs $dev --noheading -o deviceid | awk '{print $1}'`
echo dev $dev pvid $pvid did $did
PVIDS[$count]=$pvid
DEVICEIDS[$count]=$did
count=$(( count + 1 ))
done
rm $DF
not lvmdevices
touch $DF
lvmdevices
# check lvmdevices --adddev
count=0
for dev in "${REAL_DEVICES[@]}"; do
pvid=${PVIDS[$count]}
did=${DEVICEIDS[$count]}
not pvs $dev
lvmdevices --adddev $dev
lvmdevices |tee out
grep $dev out |tee idline
grep $pvid idline
grep $did idline
grep $dev $DF
pvs $dev
count=$(( count + 1 ))
done
# check lvmdevices --deldev
count=0
for dev in "${REAL_DEVICES[@]}"; do
pvid=${PVIDS[$count]}
did=${DEVICEIDS[$count]}
pvs $dev
lvmdevices --deldev $dev
lvmdevices |tee out
not grep $dev out
not grep $pvid out
not grep $did out
not grep $dev $DF
not pvs $dev
count=$(( count + 1 ))
done
# check lvmdevices --addpvid
count=0
for dev in "${REAL_DEVICES[@]}"; do
pvid=${PVIDS[$count]}
did=${DEVICEIDS[$count]}
not pvs $dev
lvmdevices --addpvid $pvid
lvmdevices |tee out
grep $dev out |tee idline
grep $pvid idline
grep $did idline
grep $dev $DF
pvs $dev
count=$(( count + 1 ))
done
# check lvmdevices --delpvid
count=0
for dev in "${REAL_DEVICES[@]}"; do
pvid=${PVIDS[$count]}
did=${DEVICEIDS[$count]}
pvs $dev
lvmdevices --delpvid $pvid
lvmdevices |tee out
not grep $dev out
not grep $pvid out
not grep $did out
not grep $dev $DF
not pvs $dev
count=$(( count + 1 ))
done
# wrong pvid in df
rm $DF
pvid1=${PVIDS[0]}
pvid2=${PVIDS[1]}
did1=${DEVICEIDS[0]}
did2=${DEVICEIDS[1]}
lvmdevices --adddev $dev1
lvmdevices --adddev $dev2
# test bad pvid
cp $DF $DF.orig
rm $DF
sed "s/$pvid1/badpvid/" "$DF.orig" |tee $DF
not grep $pvid1 $DF
grep $did1 $DF
lvmdevices --check 2>&1|tee out
grep $dev1 out
grep badpvid out
grep $pvid1 out
not grep $dev2 out
lvmdevices |tee out
grep $dev1 out |tee out1
grep badpvid out1
not grep $pvid1 out1
grep $dev2 out
lvmdevices --update
lvmdevices 2>&1|tee out
grep $dev1 out
grep $dev2 out
not grep badpvid
grep $pvid1 out
grep $did1 out
grep $pvid1 $DF
grep $did1 $DF
# wrong deviceid in df
# the devicesfile logic and behavior is based on the idname being
# the primary identifier that we trust over everything else, i.e.
# we'll never assume that the deviceid is wrong and some other
# field is correct, and "fix" the deviceid. We always assume the
# deviceid correct and other values are wrong (since pvid and devname
# have known, common ways of becoming wrong, but the deviceid doesn't
# really have any known way of becoming wrong apart from random
# file corruption.)
# So, if the deviceid *is* corrupted, as we do here, then standard
# commands won't correct it. We need to use delpvid/addpvid explicitly
# to say that we are targetting the given pvid.
rm $DF
sed "s/$did1/baddid/" "$DF.orig" |tee $DF
lvmdevices --check 2>&1|tee out
grep $dev1 out
grep baddid out
not grep $dev2 out
lvmdevices 2>&1|tee out
grep $pvid1 out
grep $pvid2 out
grep baddid out
grep $did2 out
grep $dev2 out
lvmdevices --delpvid $pvid1
lvmdevices --addpvid $pvid1
lvmdevices |tee out
grep $dev1 out
grep $dev2 out
not grep baddid
grep $pvid1 out
grep $did1 out
grep $pvid1 $DF
grep $did1 $DF
# wrong devname in df, this is expected to become incorrect regularly
# given inconsistent dev names after reboot
rm $DF
d1=$(basename $dev1)
d3=$(basename $dev3)
sed "s/$d1/$d3/" "$DF.orig" |tee $DF
lvmdevices --check |tee out
grep $dev1 out
lvmdevices --update
lvmdevices |tee out
grep $dev1 out |tee out1
grep $pvid1 out1
grep $did1 out1
grep $dev2 out |tee out2
grep $pvid2 out2
grep $did2 out2
# swap devnames for two existing entries
rm $DF
d1=$(basename $dev1)
d2=$(basename $dev2)
sed "s/$d1/tmp/" "$DF.orig" |tee ${DF}_1
sed "s/$d2/$d1/" "${DF}_1" |tee ${DF}_2
sed "s/tmp/$d2/" "${DF}_2" |tee $DF
rm ${DF}_1 ${DF}_2
lvmdevices --check |tee out
grep $dev1 out
grep $dev2 out
lvmdevices --update
lvmdevices |tee out
grep $dev1 out |tee out1
grep $pvid1 out1
grep $did1 out1
grep $dev2 out |tee out2
grep $pvid2 out2
grep $did2 out2
# ordinary command is not confused by wrong devname and fixes
# the wrong devname in df
rm $DF
d1=$(basename $dev1)
d3=$(basename $dev3)
sed "s/$d1/$d3/" "$DF.orig" |tee $DF
lvmdevices --check |tee out
grep $dev1 out
pvs -o+uuid,deviceid | grep $vg |tee out
grep $dev1 out |tee out1
grep $dev2 out |tee out2
grep $did1 out1
grep $did2 out2
not grep $dev3 out
# same dev info reported after df is fixed
pvs -o+uuid,deviceid | grep $vg |tee out3
diff out out3
pvid=`pvs $dev1 --noheading -o uuid | tr -d - | awk '{print $1}'`
test "$pvid" == "$pvid1" || die "wrong uuid"
pvid=`pvs $dev2 --noheading -o uuid | tr -d - | awk '{print $1}'`
test "$pvid" == "$pvid2" || die "wrong uuid"
lvmdevices |tee out
grep $dev1 out |tee out1
grep $pvid1 out1
grep $did1 out1
grep $dev2 out |tee out2
grep $pvid2 out2
grep $did2 out2
# pvscan --cache doesn't fix wrong devname but still works correctly with
# the correct device
wipe_all
rm $DF

View File

@@ -1,212 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2018 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
SKIP_WITH_LVMPOLLD=1
. lib/inittest
aux have_integrity 1 5 0 || skip
which mkfs.xfs || skip
which xfs_growfs || skip
mnt="mnt"
mkdir -p $mnt
aux prepare_devs 3 40
# Use awk instead of anoyingly long log out from printf
#printf "%0.sA" {1..16384} >> fileA
awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA
awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB
awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC
_prepare_vg() {
# zero devs so we are sure to find the correct file data
# on the underlying devs when corrupting it
dd if=/dev/zero of="$dev1" bs=1M oflag=direct || true
dd if=/dev/zero of="$dev2" bs=1M oflag=direct || true
dd if=/dev/zero of="$dev3" bs=1M oflag=direct || true
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvs
}
_test1() {
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
# we don't want fileA to be located too early in the fs,
# otherwise activating the LV will trigger the corruption
# to be found and corrected, leaving nothing for syncaction
# to find and correct.
dd if=/dev/urandom of=$mnt/rand16M bs=1M count=16
cp fileA $mnt
cp fileB $mnt
cp fileC $mnt
umount $mnt
lvchange -an $vg/$lv1
xxd "$dev1" > dev1.txt
# corrupt fileB
sed -e 's/4242 4242 4242 4242 4242 4242 4242 4242/4242 4242 4242 4242 4242 4242 4242 4243/' dev1.txt > dev1.bad
rm -f dev1.txt
xxd -r dev1.bad > "$dev1"
rm -f dev1.bad
lvchange -ay $vg/$lv1
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
grep 0 mismatch
lvchange --syncaction check $vg/$lv1
_wait_recalc $vg/$lv1
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
not grep 0 mismatch
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
cmp -b $mnt/fileA fileA
cmp -b $mnt/fileB fileB
cmp -b $mnt/fileC fileC
umount $mnt
}
_test2() {
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
# we don't want fileA to be located too early in the fs,
# otherwise activating the LV will trigger the corruption
# to be found and corrected, leaving nothing for syncaction
# to find and correct.
dd if=/dev/urandom of=$mnt/rand16M bs=1M count=16
cp fileA $mnt
cp fileB $mnt
cp fileC $mnt
umount $mnt
lvchange -an $vg/$lv1
# corrupt fileB and fileC on dev1
xxd "$dev1" > dev1.txt
sed -e 's/4242 4242 4242 4242 4242 4242 4242 4242/4242 4242 4242 4242 4242 4242 4242 4243/' dev1.txt > dev1.bad
sed -e 's/4343 4343 4343 4343 4343 4343 4343 4343/4444 4444 4444 4444 4444 4444 4444 4444/' dev1.txt > dev1.bad
rm -f dev1.txt
xxd -r dev1.bad > "$dev1"
rm -f dev1.bad
# corrupt fileA on dev2
xxd "$dev2" > dev2.txt
sed -e 's/4141 4141 4141 4141 4141 4141 4141 4141/4141 4141 4141 4141 4141 4141 4145 4141/' dev2.txt > dev2.bad
rm -f dev2.txt
xxd -r dev2.bad > "$dev2"
rm -f dev2.bad
lvchange -ay $vg/$lv1
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
grep 0 mismatch
lvs -o integritymismatches $vg/${lv1}_rimage_1 |tee mismatch
grep 0 mismatch
lvchange --syncaction check $vg/$lv1
_wait_recalc $vg/$lv1
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
not grep 0 mismatch
lvs -o integritymismatches $vg/${lv1}_rimage_1 |tee mismatch
not grep 0 mismatch
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
cmp -b $mnt/fileA fileA
cmp -b $mnt/fileB fileB
cmp -b $mnt/fileC fileC
umount $mnt
}
_sync_percent() {
local checklv=$1
get lv_field "$checklv" sync_percent | cut -d. -f1
}
_wait_recalc() {
local checklv=$1
for i in $(seq 1 10) ; do
sync=$(_sync_percent "$checklv")
echo "sync_percent is $sync"
if test "$sync" = "100"; then
return
fi
sleep 1
done
# TODO: There is some strange bug, first leg of RAID with integrity
# enabled never gets in sync. I saw this in BB, but not when executing
# the commands manually
if test -z "$sync"; then
echo "TEST\ WARNING: Resync of dm-integrity device '$checklv' failed"
dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}"
exit
fi
echo "timeout waiting for recalc"
return 1
}
_prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 6 $vg "$dev1" "$dev2"
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
_test1
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 6 $vg "$dev1" "$dev2"
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
_test2
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid5 --raidintegrity y -n $lv1 -l 6 $vg "$dev1" "$dev2" "$dev3"
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
_test1
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg

View File

@@ -46,14 +46,12 @@ _prepare_vg() {
pvs
}
_test_fs_with_read_repair() {
_test_fs_with_error() {
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
cp randA $mnt
cp randB $mnt
cp randC $mnt
# add original data
cp fileA $mnt
cp fileB $mnt
cp fileC $mnt
@@ -61,21 +59,137 @@ _test_fs_with_read_repair() {
umount $mnt
lvchange -an $vg/$lv1
for dev in "$@"; do
xxd "$dev" > dev.txt
# corrupt fileB
sed -e 's/4242 4242 4242 4242 4242 4242 4242 4242/4242 4242 4242 4242 4242 4242 4242 4243/' dev.txt > dev.bad
rm -f dev.txt
xxd -r dev.bad > "$dev"
rm -f dev.bad
done
# corrupt the original data on the underying dev
# flip one bit in fileB, changing a 0x42 to 0x43
# the bit is changed in the last 4096 byte block
# of the file, so when reading back the file we
# will get the first three 4096 byte blocks, for
# a total of 12288 bytes before getting an error
# on the last 4096 byte block.
xxd "$dev1" > dev1.txt
tac dev1.txt > dev1.rev
rm -f dev1.txt
sed -e '0,/4242 4242 4242 4242 4242 4242 4242 4242/ s/4242 4242 4242 4242 4242 4242 4242 4242/4242 4242 4242 4242 4242 4242 4242 4243/' dev1.rev > dev1.rev.bad
rm -f dev1.rev
tac dev1.rev.bad > dev1.bad
rm -f dev1.rev.bad
xxd -r dev1.bad > "$dev1"
rm -f dev1.bad
lvchange -ay $vg/$lv1
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
# read complete fileA which was not corrupted
dd if=$mnt/fileA of=tmp bs=1k
ls -l tmp
stat -c %s tmp
cmp -b fileA tmp
rm tmp
# read partial fileB which was corrupted
not dd if=$mnt/fileB of=tmp bs=1k
ls -l tmp
stat -c %s tmp | grep 12288
not cmp -b fileB tmp
rm tmp
umount $mnt
}
_test_fs_with_read_repair() {
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
# add original data
cp fileA $mnt
cp fileB $mnt
cp fileC $mnt
umount $mnt
lvchange -an $vg/$lv1
# FIXME: this is only finding/corrupting the bit with raid1
# other raid levels may require looking at a different dev.
# (Attempt this xxd/tac/sed/xxd on each dev in the LV?)
xxd "$dev1" > dev1.txt
tac dev1.txt > dev1.rev
rm -f dev1.txt
sed -e '0,/4242 4242 4242 4242 4242 4242 4242 4242/ s/4242 4242 4242 4242 4242 4242 4242 4242/4242 4242 4242 4242 4242 4242 4242 4243/' dev1.rev > dev1.rev.bad
rm -f dev1.rev
tac dev1.rev.bad > dev1.bad
rm -f dev1.rev.bad
xxd -r dev1.bad > "$dev1"
rm -f dev1.bad
lvchange -ay $vg/$lv1
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
# read complete fileA which was not corrupted
dd if=$mnt/fileA of=tmp bs=1k
ls -l tmp
stat -c %s tmp | grep 16384
cmp -b fileA tmp
rm tmp
# read complete fileB, corruption is corrected by raid
dd if=$mnt/fileB of=tmp bs=1k
ls -l tmp
stat -c %s tmp | grep 16384
cmp -b fileB tmp
rm tmp
umount $mnt
}
_test_fs_with_syncaction_check() {
mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
# add original data
cp fileA $mnt
cp fileB $mnt
cp fileC $mnt
umount $mnt
lvchange -an $vg/$lv1
# FIXME: this is only finding/corrupting the bit with raid1
# other raid levels may require looking at a different dev.
# (Attempt this xxd/tac/sed/xxd on each dev in the LV?)
xxd "$dev1" > dev1.txt
tac dev1.txt > dev1.rev
rm -f dev1.txt
sed -e '0,/4242 4242 4242 4242 4242 4242 4242 4242/ s/4242 4242 4242 4242 4242 4242 4242 4242/4242 4242 4242 4242 4242 4242 4242 4243/' dev1.rev > dev1.rev.bad
rm -f dev1.rev
tac dev1.rev.bad > dev1.bad
rm -f dev1.rev.bad
xxd -r dev1.bad > "$dev1"
rm -f dev1.bad
lvchange -ay $vg/$lv1
lvchange --syncaction check $vg/$lv1
mount "$DM_DEV_DIR/$vg/$lv1" $mnt
cmp -b $mnt/fileA fileA
cmp -b $mnt/fileB fileB
cmp -b $mnt/fileC fileC
# read complete fileA which was not corrupted
dd if=$mnt/fileA of=tmp bs=1k
ls -l tmp
stat -c %s tmp | grep 16384
cmp -b fileA tmp
rm tmp
# read complete fileB
dd if=$mnt/fileB of=tmp bs=1k
ls -l tmp
stat -c %s tmp | grep 16384
cmp -b fileB tmp
rm tmp
umount $mnt
}
@@ -168,105 +282,170 @@ _wait_recalc() {
# it is detected by integrity and corrected by raid.
_prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2"
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1"
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
not grep 0 mismatch
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3"
lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1" "$dev2"
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
not grep 0 mismatch
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid4 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3"
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1" "$dev2" "$dev3"
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3"
lvcreate --type raid4 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1" "$dev2" "$dev3"
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/${lv1}_rimage_4
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/${lv1}_rimage_3
lvs -o integritymismatches $vg/${lv1}_rimage_4
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4"
lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1" "$dev3"
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/${lv1}_rimage_3
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
# Test corrupting data on an image and verifying that
# it is detected and corrected using syncaction check
_prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_test_fs_with_syncaction_check
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
check lv_field $vg/${lv1}_rimage_0 integritymismatches "1"
check lv_field $vg/${lv1}_rimage_1 integritymismatches "0"
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid4 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_test_fs_with_syncaction_check
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
check lv_field $vg/${lv1}_rimage_0 integritymismatches "2"
check lv_field $vg/${lv1}_rimage_1 integritymismatches "0"
check lv_field $vg/${lv1}_rimage_2 integritymismatches "0"
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_test_fs_with_syncaction_check
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/${lv1}_rimage_4
_test_fs_with_syncaction_check
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/${lv1}_rimage_3
lvs -o integritymismatches $vg/${lv1}_rimage_4
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_test_fs_with_syncaction_check
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/${lv1}_rimage_3
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
@@ -278,7 +457,6 @@ _prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity n $vg/$lv1
_add_more_data_to_mnt
@@ -293,8 +471,6 @@ _prepare_vg
lvcreate --type raid4 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity n $vg/$lv1
_add_more_data_to_mnt
@@ -309,8 +485,6 @@ _prepare_vg
lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity n $vg/$lv1
_add_more_data_to_mnt
@@ -325,10 +499,6 @@ _prepare_vg
lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/${lv1}_rimage_4
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity n $vg/$lv1
_add_more_data_to_mnt
@@ -343,7 +513,6 @@ _prepare_vg
lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity n $vg/$lv1
_add_more_data_to_mnt
@@ -358,7 +527,6 @@ vgremove -ff $vg
_prepare_vg
lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity y $vg/$lv1
_wait_recalc $vg/${lv1}_rimage_0
@@ -373,7 +541,6 @@ vgremove -ff $vg
_prepare_vg
lvcreate --type raid4 -n $lv1 -l 8 $vg
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity y $vg/$lv1
_wait_recalc $vg/${lv1}_rimage_0
@@ -388,7 +555,6 @@ vgremove -ff $vg
_prepare_vg
lvcreate --type raid5 -n $lv1 -l 8 $vg
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity y $vg/$lv1
_wait_recalc $vg/${lv1}_rimage_0
@@ -403,12 +569,6 @@ vgremove -ff $vg
_prepare_vg
lvcreate --type raid6 -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/${lv1}_rimage_4
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity y $vg/$lv1
_wait_recalc $vg/${lv1}_rimage_0
@@ -423,7 +583,6 @@ vgremove -ff $vg
_prepare_vg
lvcreate --type raid10 -n $lv1 -l 8 $vg
_wait_recalc $vg/$lv1
_add_new_data_to_mnt
lvconvert --raidintegrity y $vg/$lv1
_wait_recalc $vg/${lv1}_rimage_0
@@ -442,7 +601,6 @@ _prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
umount $mnt
@@ -466,10 +624,6 @@ _prepare_vg
lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/${lv1}_rimage_4
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
umount $mnt
@@ -495,7 +649,6 @@ _prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
lvextend -l 16 $vg/$lv1
@@ -515,8 +668,6 @@ _prepare_vg
lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
lvextend -l 16 $vg/$lv1
@@ -536,7 +687,6 @@ _prepare_vg
lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
lvextend -l 16 $vg/$lv1
@@ -558,7 +708,6 @@ _prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
lvconvert -y -m+1 $vg/$lv1
@@ -581,7 +730,6 @@ lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
lvconvert -y -m-1 $vg/$lv1
@@ -600,7 +748,6 @@ _prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
lvs -a -o+devices $vg
_add_new_data_to_mnt
not lvconvert -y -m-1 $vg/$lv1
@@ -621,36 +768,23 @@ vgremove -ff $vg
# Repeat many of the tests above using bitmap mode
_prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1 "$dev2"
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1"
lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch
not grep 0 mismatch
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
vgremove -ff $vg
_prepare_vg
lvcreate --type raid6 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_wait_recalc $vg/${lv1}_rimage_2
_wait_recalc $vg/${lv1}_rimage_3
_wait_recalc $vg/${lv1}_rimage_4
_wait_recalc $vg/$lv1
_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
lvcreate --type raid6 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg
_test_fs_with_read_repair
lvs -o integritymismatches $vg/${lv1}_rimage_0
lvs -o integritymismatches $vg/${lv1}_rimage_1
lvs -o integritymismatches $vg/${lv1}_rimage_2
lvs -o integritymismatches $vg/${lv1}_rimage_3
lvs -o integritymismatches $vg/${lv1}_rimage_4
lvs -o integritymismatches $vg/$lv1 |tee mismatch
not grep 0 mismatch
lvchange -an $vg/$lv1
lvconvert --raidintegrity n $vg/$lv1
lvremove $vg/$lv1
@@ -658,7 +792,7 @@ vgremove -ff $vg
# remove from active lv
_prepare_vg
lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2"
lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg
_wait_recalc $vg/${lv1}_rimage_0
_wait_recalc $vg/${lv1}_rimage_1
_add_new_data_to_mnt

View File

@@ -145,7 +145,7 @@ pvcreate --pvmetadatacopies 2 --metadatasize 32M "$dev1"
vgcreate $SHARED -s 64K --metadatasize 32M $vg "$dev1" "$dev2" "$dev3" "$dev4"
for i in $(seq 1 500); do echo "lvcreate -an -n lv$i -l1 $vg"; done | lvm
for i in $(seq 1 500); do lvcreate -an -n lv$i -l1 $vg; done
pvck --dump headers "$dev1" > h1

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2020 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='hello world for user-defined device list'
. lib/inittest
aux prepare_real_devs
echo "$dev1"
pvcreate "$dev1"
pvs "$dev1"
pvremove "$dev1"
vgcreate $vg "$dev1"
lvcreate -l1 $vg
vgchange -an $vg
vgremove -ff $vg
get_real_devs
for d in "${REAL_DEVICES[@]}"; do
echo $d
done

View File

@@ -0,0 +1,198 @@
#!/usr/bin/env bash
# Copyright (C) 2018 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
SKIP_WITH_LVMPOLLD=1
. lib/inittest
mkfs_mount_unmount()
{
lvt=$1
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lvt"
mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir"
cp pattern1 "$mount_dir/pattern1"
umount "$mount_dir"
}
setup_thin_lvs()
{
pool=$1
for i in $(seq 1 4); do
lvcreate --type thin -V1G -n th$i --thinpool $pool $vg
mkfs_mount_unmount th${i}
lvchange -an $vg/th${i}
done
}
diff_thin_lvs()
{
for i in $(seq 1 4); do
diff pattern1 "${mount_dir}_${i}/pattern1"
diff pattern2 "${mount_dir}_${i}/pattern2"
done
}
mount_thin_lvs()
{
for i in $(seq 1 4); do
lvchange -ay $vg/th$i
mount "$DM_DEV_DIR/$vg/th$i" "${mount_dir}_${i}"
done
}
unmount_thin_lvs()
{
for i in $(seq 1 4); do
umount "${mount_dir}_${i}"
lvchange -an $vg/th${i}
done
}
write_thin_lvs()
{
for i in $(seq 1 4); do
cp pattern2 "${mount_dir}_${i}/pattern2"
done
}
aux have_writecache 1 0 0 || skip
which mkfs.xfs || skip
mount_dir="mnt"
mount_dir_1="mnt1"
mount_dir_2="mnt2"
mount_dir_3="mnt3"
mount_dir_4="mnt4"
mkdir -p "$mount_dir"
for i in $(seq 1 4); do
mkdir -p "${mount_dir}_${i}"
done
# generate random data
dd if=/dev/urandom of=pattern1 bs=512K count=1
dd if=/dev/urandom of=pattern2 bs=512 count=15
aux prepare_devs 6 40
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6"
#
# writecache as thin pool data
# splitcache while inactive
#
# lv1 holds thin pool data and uses writecache
# lv2 holds cachevol for writecache
# lv3 holds thin pool metadata
lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev2"
lvcreate -n $lv2 -l 2 -an $vg "$dev3"
lvcreate -n $lv3 -l 2 -an $vg "$dev4"
lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
lvconvert -y --type thin-pool --poolmetadata $lv3 --poolmetadataspare n $vg/$lv1
setup_thin_lvs $lv1
mount_thin_lvs
write_thin_lvs
unmount_thin_lvs
lvchange -an $vg/$lv1
lvconvert --splitcache --cachesettings cleaner=0 $vg/${lv1}_tdata
lvs -o segtype $vg/$lv2 | grep linear
mount_thin_lvs
diff_thin_lvs
unmount_thin_lvs
lvremove -y $vg/$lv1
lvremove -y $vg/$lv2
#
# writecache as thin pool data
# splitcache while active
#
# lv1 holds thin pool data and uses writecache
# lv2 holds cachevol for writecache
# lv3 holds thin pool metadata
lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev2"
lvcreate -n $lv2 -l 2 -an $vg "$dev3"
lvcreate -n $lv3 -l 2 -an $vg "$dev4"
lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
lvconvert -y --type thin-pool --poolmetadata $lv3 --poolmetadataspare n $vg/$lv1
setup_thin_lvs $lv1
mount_thin_lvs
write_thin_lvs
# FIXME: splitcache setting cleaner on tdata writecache doesn't work,
# bypassing that with cleaner=0 here.
lvconvert --splitcache --cachesettings cleaner=0 $vg/${lv1}_tdata
lvs -o segtype $vg/$lv2 | grep linear
diff_thin_lvs
unmount_thin_lvs
mount_thin_lvs
diff_thin_lvs
unmount_thin_lvs
lvremove -y $vg/$lv1
lvremove -y $vg/$lv2
#
# add writecache to raid, then use writecache for thin pool data
#
# lv1 holds thin pool data and uses writecache
# lv2 holds cachevol for writecache
# lv3 holds thin pool metadata
lvcreate --type raid1 -m1 -n $lv1 -l 16 -an $vg "$dev1" "$dev2" "$dev5" "$dev6"
lvcreate -n $lv2 -l 2 -an $vg "$dev3"
lvcreate -n $lv3 -l 2 -an $vg "$dev4"
lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
lvconvert -y --type thin-pool --poolmetadata $lv3 --poolmetadataspare n $vg/$lv1
setup_thin_lvs $lv1
mount_thin_lvs
write_thin_lvs
lvconvert --splitcache --cachesettings cleaner=0 $vg/${lv1}_tdata
lvs -o segtype $vg/$lv2 | grep linear
diff_thin_lvs
unmount_thin_lvs
mount_thin_lvs
diff_thin_lvs
unmount_thin_lvs
lvremove -y $vg/$lv1
lvremove -y $vg/$lv2
#
# remove writecache from thin pool data when cachevol is missing
#
#
# FIXME: add writecache to existing thin pool data
#
#
# FIXME: thin pool data cannot be extended when it uses writecache
#
vgremove -ff $vg

View File

@@ -27,7 +27,6 @@ SOURCES =\
lvdisplay.c \
lvextend.c \
lvmcmdline.c \
lvmdevices.c \
lvmdiskscan.c \
lvpoll.c \
lvreduce.c \
@@ -59,7 +58,6 @@ SOURCES =\
vgextend.c \
vgimport.c \
vgimportclone.c \
vgimportdevices.c \
vgmerge.c \
vgmknodes.c \
vgreduce.c \

View File

@@ -44,15 +44,6 @@ arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0,
"Adds a tag to a PV, VG or LV. This option can be repeated to add\n"
"multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
arg(adddev_ARG, '\0', "adddev", pv_VAL, 0, 0,
"Add a device to the devices file.\n")
arg(deldev_ARG, '\0', "deldev", pv_VAL, 0, 0,
"Remove a device from the devices file.\n")
arg(addpvid_ARG, '\0', "addpvid", string_VAL, 0, 0,
"Find a device with the PVID and add the device to the devices file.\n")
arg(delpvid_ARG, '\0', "delpvid", string_VAL, 0, 0,
"Remove a device with the PVID from the devices file.\n")
arg(aligned_ARG, '\0', "aligned", 0, 0, 0,
"Use with --separator to align the output columns\n")
@@ -141,9 +132,6 @@ arg(cachedevice_ARG, '\0', "cachedevice", pv_VAL, ARG_GROUPABLE, 0,
arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
"The size of cache to use.\n")
arg(check_ARG, '\0', "check", 0, 0, 0,
"Check the content of the devices file.\n")
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0,
"The command profile to use for command configuration.\n"
"See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
@@ -217,24 +205,6 @@ arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0,
"Detaches a metadata profile from a VG or LV.\n"
"See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
arg(deviceid_ARG, '\0', "deviceid", string_VAL, 0, 0,
"A device ID with a format determined by --deviceidtype.")
arg(deviceidtype_ARG, '\0', "deviceidtype", string_VAL, 0, 0,
"A device ID type: sys_wwid, sys_serial, mpath_uuid.")
arg(devices_ARG, '\0', "devices", pv_VAL, ARG_GROUPABLE, 0,
"Devices that the command can use. This option can be repeated\n"
"or accepts a comma separated list of devices. This overrides\n"
"the devices file.\n")
arg(devicesfile_ARG, '\0', "devicesfile", string_VAL, 0, 0,
"A file listing devices that LVM should use.\n"
"The file must exist in /etc/lvm/devices/ and is managed\n"
"with the lvmdevices(8) command.\n"
"This overrides the lvm.conf devices/devicesfile and\n"
"devices/use_devicesfile settings.\n")
arg(discards_ARG, '\0', "discards", discards_VAL, 0, 0,
"Specifies how the device-mapper thin pool layer in the kernel should\n"
"handle discards.\n"
@@ -310,9 +280,6 @@ arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", 0, 0, 0,
"and \\fBdiff\\fP types include unsupported settings in their output by default,\n"
"all the other types ignore unsupported settings.\n")
arg(importdevices_ARG, '\0', "importdevices", 0, 0, 0,
"Add devices to the devices file.\n")
arg(labelsector_ARG, '\0', "labelsector", number_VAL, 0, 0,
"By default the PV is labelled with an LVM2 identifier in its second\n"
"sector (sector 1). This lets you use a different sector near the\n"
@@ -808,9 +775,6 @@ arg(uncache_ARG, '\0', "uncache", 0, 0, 0,
"Separates a cache pool from a cache LV, and deletes the unused cache pool LV.\n"
"Before the separation, the cache is flushed. Also see --splitcache.\n")
arg(update_ARG, '\0', "update", 0, 0, 0,
"Update the content of the devices file.\n")
arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0,
"Specifies the cache policy for a cache LV.\n"
"See \\fBlvmcache\\fP(7) for more information.\n")

View File

@@ -188,7 +188,7 @@
#
OO_ALL: --commandprofile String, --config String, --debug,
--driverloaded Bool, --help, --nolocking, --lockopt String, --longhelp, --profile String, --quiet,
--verbose, --version, --yes, --test, --devicesfile String, --devices PV
--verbose, --version, --yes, --test
#
# options for pvs, lvs, vgs, fullreport
@@ -512,7 +512,7 @@ RULE: all and lv_is_visible
---
lvconvert --type thin-pool LV_linear_striped_raid_cache
lvconvert --type thin-pool LV_linear_striped_raid_cache_writecache
OO: --stripes_long Number, --stripesize SizeKB,
--discards Discards, OO_LVCONVERT_POOL, OO_LVCONVERT
OP: PV ...
@@ -1384,31 +1384,6 @@ ID: lvmconfig_general
---
lvmdevices
ID: lvmdevices_list
lvmdevices --check
ID: lvmdevices_check
lvmdevices --update
ID: lvmdevices_update
lvmdevices --adddev PV
OO: --deviceidtype String, --deviceid String
ID: lvmdevices_edit
lvmdevices --deldev PV
ID: lvmdevices_edit
lvmdevices --addpvid String
OO: --deviceidtype String, --deviceid String
ID: lvmdevices_edit
lvmdevices --delpvid String
ID: lvmdevices_edit
---
lvreduce --size NSizeMB LV
OO: --autobackup Bool, --force, --nofsck, --noudevsync,
--reportformat ReportFmt, --resizefs
@@ -1539,8 +1514,7 @@ OO: --dataalignment SizeKB, --dataalignmentoffset SizeKB, --bootloaderareasize S
--force, --labelsector Number, --metadatatype MetadataType,
--pvmetadatacopies MetadataCopiesPV, --metadatasize SizeMB,
--metadataignore Bool, --norestorefile, --setphysicalvolumesize SizeMB,
--reportformat ReportFmt, --restorefile String, --uuidstr String, --zero Bool,
--deviceidtype String, --deviceid String
--reportformat ReportFmt, --restorefile String, --uuidstr String, --zero Bool
ID: pvcreate_general
RULE: --norestorefile not --restorefile
RULE: --bootloaderareasize not --restorefile
@@ -1790,23 +1764,11 @@ DESC: Import all VGs.
---
vgimportclone PV ...
OO: --basevgname VG, --import, --importdevices
OO: --basevgname VG, --import
ID: vgimportclone_general
---
vgimportdevices VG|Tag|Select ...
OO: --deviceidtype String, --select String, --foreign, --reportformat ReportFmt
ID: vgimportdevices_some
DESC: Add devices from specific VGs to the devices file.
vgimportdevices --all
OO: --deviceidtype String, --foreign, --reportformat ReportFmt
ID: vgimportdevices_all
DESC: Add devices from all accessible VGs to the devices file.
---
vgmerge VG VG
OO: --autobackup Bool, --list
ID: vgmerge_general

View File

@@ -69,10 +69,6 @@ xx(lvmconfig,
"Display and manipulate configuration information",
PERMITTED_READ_ONLY | NO_METADATA_PROCESSING)
xx(lvmdevices,
"Manage the devices file listing devices for LVM to use",
0)
xx(lvmdiskscan,
"List devices that may be used as physical volumes",
PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ALLOW_EXPORTED)
@@ -211,10 +207,6 @@ xx(vgimportclone,
"Import a VG from cloned PVs",
ALLOW_EXPORTED)
xx(vgimportdevices,
"Add devices for a VG to the devices file.",
ALL_VGS_IS_DEFAULT | ALLOW_EXPORTED)
xx(vgmerge,
"Merge volume groups",
0)

View File

@@ -202,7 +202,7 @@ static int _lvchange_activate(struct cmd_context *cmd, struct logical_volume *lv
strcmp(lv->vg->system_id, cmd->system_id) &&
is_change_activating(activate)) {
log_error("Cannot activate LVs in a foreign VG.");
return 0;
return ECMD_FAILED;
}
if (lv_activation_skip(lv, activate, arg_is_set(cmd, ignoreactivationskip_ARG)))

View File

@@ -17,10 +17,8 @@
#include "lvm2cmdline.h"
#include "lib/label/label.h"
#include "lib/device/device_id.h"
#include "lvm-version.h"
#include "lib/locking/lvmlockd.h"
#include "lib/datastruct/str_list.h"
#include "stub.h"
#include "lib/misc/last-path-component.h"
@@ -2390,30 +2388,6 @@ static void _apply_current_output_settings(struct cmd_context *cmd)
init_silent(cmd->current_settings.silent);
}
static int _read_devices_list(struct cmd_context *cmd)
{
struct arg_value_group_list *group;
const char *names;
struct dm_list *names_list;
dm_list_iterate_items(group, &cmd->arg_value_groups) {
if (!grouped_arg_is_set(group->arg_values, devices_ARG))
continue;
if (!(names = (char *)grouped_arg_str_value(group->arg_values, devices_ARG, NULL)))
continue;
if (!strchr(names, ',')) {
if (!str_list_add(cmd->mem, &cmd->deviceslist, names))
return 0;
} else {
if ((names_list = str_to_str_list(cmd->mem, names, ",", 1)))
dm_list_splice(&cmd->deviceslist, names_list);
}
}
return 1;
}
static int _get_current_settings(struct cmd_context *cmd)
{
const char *activation_mode;
@@ -2453,7 +2427,7 @@ static int _get_current_settings(struct cmd_context *cmd)
/*
* enable_hints is set to 1 if any commands are using hints.
* use_hints is set to 0 if this command doesn't use the hints.
* use_hints is set to 1 if this command doesn't use the hints.
* enable_hints=1 and use_hints=0 means that this command won't
* use the hints, but it may invalidate the hints that are used
* by other commands.
@@ -2469,10 +2443,6 @@ static int _get_current_settings(struct cmd_context *cmd)
else
cmd->use_hints = 0;
/* The hints file is associated with the default/system devices file. */
if (arg_is_set(cmd, devicesfile_ARG) || arg_is_set(cmd, devices_ARG))
cmd->use_hints = 0;
if ((hint_mode = find_config_tree_str(cmd, devices_hints_CFG, NULL))) {
if (!strcmp(hint_mode, "none"))
cmd->enable_hints = 0;
@@ -2514,35 +2484,6 @@ static int _get_current_settings(struct cmd_context *cmd)
cmd->record_historical_lvs = find_config_tree_bool(cmd, metadata_record_lvs_history_CFG, NULL) ?
(arg_is_set(cmd, nohistory_ARG) ? 0 : 1) : 0;
cmd->search_for_devnames = find_config_tree_bool(cmd, devices_search_for_devnames_CFG, NULL);
if (arg_is_set(cmd, devicesfile_ARG)) {
const char *devices_file = arg_str_value(cmd, devicesfile_ARG, NULL);
if (devices_file && !strlen(devices_file)) {
cmd->devicesfile = "";
} else if (!devices_file || !validate_name(devices_file)) {
log_error("Invalid devices file name.");
return EINVALID_CMD_LINE;
} else if (!(cmd->devicesfile = dm_pool_strdup(cmd->libmem, devices_file))) {
log_error("Failed to copy devices file name.");
return EINVALID_CMD_LINE;
}
}
dm_list_init(&cmd->deviceslist);
if (arg_is_set(cmd, devices_ARG)) {
if (cmd->devicesfile && strlen(cmd->devicesfile)) {
log_error("A --devices list cannot be used with --devicesfile.");
return EINVALID_CMD_LINE;
}
cmd->enable_devices_list = 1;
if (!_read_devices_list(cmd)) {
log_error("Failed to read --devices args.");
return EINVALID_CMD_LINE;
}
}
/*
* This is set to zero by process_each which wants to print errors
* itself rather than having them printed in vg_read.

View File

@@ -1,356 +0,0 @@
/*
* Copyright (C) 2020 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* 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 Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser 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
*/
#include "tools.h"
#include "lib/cache/lvmcache.h"
#include "lib/filters/filter.h"
#include "lib/device/device_id.h"
int lvmdevices(struct cmd_context *cmd, int argc, char **argv)
{
struct device *dev;
struct use_id *uid;
if (!setup_devices_file(cmd))
return ECMD_FAILED;
if (!cmd->enable_devices_file) {
log_error("Devices file not enabled.");
return ECMD_FAILED;
}
if (arg_is_set(cmd, update_ARG) ||
arg_is_set(cmd, adddev_ARG) || arg_is_set(cmd, deldev_ARG) ||
arg_is_set(cmd, addpvid_ARG) || arg_is_set(cmd, delpvid_ARG)) {
if (!lock_devices_file(cmd, LOCK_EX)) {
log_error("Failed to lock the devices file to create.");
return ECMD_FAILED;
}
if (!devices_file_exists(cmd)) {
if (!devices_file_touch(cmd)) {
log_error("Failed to create the devices file.");
return ECMD_FAILED;
}
}
/*
* The hint file is associated with the default/system devices file,
* so don't clear hints when using a different --devicesfile.
*/
if (!cmd->devicesfile)
clear_hint_file(cmd);
} else {
if (!lock_devices_file(cmd, LOCK_SH)) {
log_error("Failed to lock the devices file.");
return ECMD_FAILED;
}
if (!devices_file_exists(cmd)) {
log_error("Devices file does not exist.");
return ECMD_FAILED;
}
}
if (!device_ids_read(cmd)) {
log_error("Failed to read the devices file.");
return ECMD_FAILED;
}
dev_cache_scan();
device_ids_match(cmd);
if (arg_is_set(cmd, check_ARG)) {
/* For each cmd->use_device_ids:
reads pvid from header, sets dev->pvid and uid->pvid */
label_scan_setup_bcache();
device_ids_read_pvids(cmd);
dm_list_iterate_items(uid, &cmd->use_device_ids) {
dev = uid->dev;
if (!dev) {
log_print("Device not found for %s %s PVID %s previously seen on %s.",
uid->idtype ? idtype_to_str(uid->idtype) : ".",
uid->idname ?: ".",
uid->pvid ?: ".",
uid->devname ?: ".");
continue;
}
if (!uid->devname || strcmp(dev_name(uid->dev), uid->devname)) {
log_print("Device %s has incorrect name in devices file (%s)",
dev_name(dev), uid->devname ?: ".");
}
}
goto out;
}
if (arg_is_set(cmd, update_ARG)) {
/* For each cmd->use_device_ids:
reads pvid from header, sets dev->pvid and uid->pvid */
label_scan_setup_bcache();
device_ids_read_pvids(cmd);
/* Any uid fields found/set/fixed will be written. */
if (!device_ids_write(cmd))
goto_bad;
goto out;
}
if (arg_is_set(cmd, adddev_ARG)) {
const char *devname;
if (!(devname = arg_str_value(cmd, adddev_ARG, NULL)))
goto_bad;
/*
* addev will add a device to devices_file even if that device
* is excluded by filters.
*/
/*
* No filter applied here (only the non-data filters would
* be applied since we haven't read the device yet.
*/
if (!(dev = dev_cache_get(cmd, devname, NULL))) {
log_error("No device found for %s.", devname);
goto_bad;
}
/*
* reads pvid from dev header, sets dev->pvid.
* (it's ok if the device is not a PV and has no PVID)
*/
label_scan_setup_bcache();
label_read_pvid(dev);
/*
* Allow filtered devices to be added to devices_file, but
* check if it's excluded by filters to print a warning.
* Since label_read_pvid has read the first 4K of the device,
* the filters should not for the most part need to do any further
* reading of the device.
*
* (This is the first time filters are being run, so we do
* not need to wipe filters of any previous result that was
* based on filter_deviceid_skip=0.)
*/
cmd->filter_deviceid_skip = 1;
cmd->filter_regex_with_devices_file = 1;
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
log_warn("WARNING: %s is currently excluded by filter %s.",
dev_name(dev), dev_filtered_reason(dev));
}
if (!device_id_add(cmd, dev, dev->pvid,
arg_str_value(cmd, deviceidtype_ARG, NULL),
arg_str_value(cmd, deviceid_ARG, NULL)))
goto_bad;
if (!device_ids_write(cmd))
goto_bad;
goto out;
}
if (arg_is_set(cmd, addpvid_ARG)) {
struct dev_iter *iter;
struct id id;
char pvid[ID_LEN+1] = { 0 };
const char *pvid_arg;
struct device_list *devl, *safe;
struct dm_list devs;
dm_list_init(&devs);
/*
* Iterate through all devs on the system, reading the
* pvid of each to check if it has this pvid.
* Devices that are excluded by no-data filters will not
* be checked for the PVID.
* addpvid will not add a device to devices_file if it's
* excluded by filters.
*/
pvid_arg = arg_str_value(cmd, addpvid_ARG, NULL);
if (!id_read_format_try(&id, pvid_arg)) {
log_error("Invalid PVID.");
goto bad;
}
memcpy(pvid, &id.uuid, ID_LEN);
if ((uid = get_uid_for_pvid(cmd, pvid))) {
log_error("PVID already exists in devices_file for %s.", dev_name(uid->dev));
goto bad;
}
/*
* Create a list of all devices on the system, without applying
* any filters, since we do not want filters to read any of the
* devices yet.
*/
if (!(iter = dev_iter_create(NULL, 0)))
goto_bad;
while ((dev = dev_iter_get(cmd, iter))) {
if (!(devl = zalloc(sizeof(*devl))))
continue;
devl->dev = dev;
dm_list_add(&devs, &devl->list);
}
dev_iter_destroy(iter);
/*
* Apply the filters that do not require reading the devices
* The regex filter will be used and filter-deviceid not used.
*/
log_debug("Filtering devices without data");
cmd->filter_nodata_only = 1;
cmd->filter_deviceid_skip = 1;
cmd->filter_regex_with_devices_file = 1;
dm_list_iterate_items_safe(devl, safe, &devs) {
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL))
dm_list_del(&devl->list);
}
label_scan_setup_bcache();
dev = NULL;
dm_list_iterate_items(devl, &devs) {
if (!label_read_pvid(devl->dev))
continue;
if (!strcmp(devl->dev->pvid, pvid)) {
dev = devl->dev;
break;
}
}
if (!dev) {
log_error("PVID %s not found on any devices.", pvid);
goto bad;
}
/*
* Now that the device has been read, apply the filters again
* which will now include filters that read data from the device.
* N.B. we've already skipped devs that were excluded by the
* no-data filters, so if the PVID exists on one of those devices
* no warning is printed.
*/
log_debug("Filtering device with data");
cmd->filter_nodata_only = 0;
cmd->filter_deviceid_skip = 1;
cmd->filter_regex_with_devices_file = 1;
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
log_error("PVID %s found on %s which is excluded by filter %s",
pvid, dev_name(dev), dev_filtered_reason(dev));
goto_bad;
}
if (!device_id_add(cmd, dev, dev->pvid, NULL, NULL))
goto_bad;
if (!device_ids_write(cmd))
goto_bad;
goto out;
}
if (arg_is_set(cmd, deldev_ARG)) {
const char *devname;
if (!(devname = arg_str_value(cmd, deldev_ARG, NULL)))
goto_bad;
/* we don't need to filter_deviceid_skip since we're
removing a dev from devices_file, that dev should
be in the devices_file and pass the filter */
if (!(dev = dev_cache_get(cmd, devname, cmd->filter))) {
log_error("No device found for %s.", devname);
goto bad;
}
/* dev_cache_scan uses sysfs to check if an LV is using each dev
and sets this flag is so. */
if (dev->flags & DEV_USED_FOR_LV) {
if (!arg_count(cmd, yes_ARG) &&
yes_no_prompt("Device %s is used by an active LV, continue to remove? ", devname) == 'n') {
log_error("Device not removed.");
goto bad;
}
}
if (!(uid = get_uid_for_dev(cmd, dev))) {
log_error("Device not found in devices_file.");
goto bad;
}
dm_list_del(&uid->list);
free_uid(uid);
device_ids_write(cmd);
goto out;
}
if (arg_is_set(cmd, delpvid_ARG)) {
struct id id;
char pvid[ID_LEN+1] = { 0 };
const char *pvid_arg;
pvid_arg = arg_str_value(cmd, delpvid_ARG, NULL);
if (!id_read_format_try(&id, pvid_arg)) {
log_error("Invalid PVID.");
goto bad;
}
memcpy(pvid, &id.uuid, ID_LEN);
if (!(uid = get_uid_for_pvid(cmd, pvid))) {
log_error("PVID not found in devices_file.");
goto_bad;
}
if (uid->devname && (uid->devname[0] != '.')) {
if ((dev = dev_cache_get(cmd, uid->devname, NULL)) &&
(dev->flags & DEV_USED_FOR_LV)) {
if (!arg_count(cmd, yes_ARG) &&
yes_no_prompt("Device %s is used by an active LV, continue to remove? ", uid->devname) == 'n') {
log_error("Device not removed.");
goto bad;
}
}
}
dm_list_del(&uid->list);
free_uid(uid);
device_ids_write(cmd);
goto out;
}
/* If no options, print use_device_ids list */
dm_list_iterate_items(uid, &cmd->use_device_ids) {
char part_buf[64] = { 0 };
if (uid->part)
snprintf(part_buf, 63, " PART=%d", uid->part);
log_print("Device %s IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s",
uid->dev ? dev_name(uid->dev) : ".",
uid->idtype ? idtype_to_str(uid->idtype) : ".",
uid->idname ? uid->idname : ".",
uid->devname ? uid->devname : ".",
uid->pvid ? (char *)uid->pvid : ".",
part_buf);
}
out:
return ECMD_PROCESSED;
bad:
return ECMD_FAILED;
}

View File

@@ -670,15 +670,6 @@ static int _daemon_parms_init(struct cmd_context *cmd, struct daemon_parms *parm
parms->progress_display = parms->interval ? 1 : 0;
memset(parms->devicesfile, 0, sizeof(parms->devicesfile));
if (cmd->devicesfile) {
if (strlen(cmd->devicesfile) >= sizeof(parms->devicesfile)) {
log_error("devicefile name too long for lvmpolld");
return 0;
}
strcpy(parms->devicesfile, cmd->devicesfile);
}
return 1;
}

View File

@@ -26,7 +26,6 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
struct pvchange_params *params = (struct pvchange_params *) handle->custom_handle;
const char *pv_name = pv_dev_name(pv);
char uuid[64] __attribute__((aligned(8)));
struct use_id *uid;
unsigned done = 0;
int used;
@@ -148,9 +147,6 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
if (arg_is_set(cmd, uuid_ARG)) {
/* --uuid: Change PV ID randomly */
uid = get_uid_for_pvid(cmd, pv->dev->pvid);
memcpy(&pv->old_id, &pv->id, sizeof(pv->id));
if (!id_create(&pv->id)) {
log_error("Failed to generate new random UUID for %s.",
@@ -188,16 +184,6 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
goto bad;
}
if (uid) {
if (uid->pvid)
free(uid->pvid);
if (!(uid->pvid = strndup((char *)&pv->id, ID_LEN)))
log_error("Failed to set pvid for devices file.");
if (!device_ids_write(cmd))
log_warn("Failed to update devices file.");
unlock_devices_file(cmd);
}
log_print_unless_silent("Physical volume \"%s\" changed", pv_name);
params->done++;
@@ -224,9 +210,6 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv)
goto out;
}
if (arg_is_set(cmd, uuid_ARG))
cmd->edit_devices_file = 1;
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
ret = ECMD_FAILED;

View File

@@ -19,7 +19,6 @@
#include "lib/format_text/layout.h"
#include "lib/mm/xlate.h"
#include "lib/misc/crc.h"
#include "lib/device/device_id.h"
#define ONE_MB_IN_BYTES 1048576
@@ -3034,11 +3033,6 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
if (!setup_device(cmd, pv_name)) {
log_error("Failed to set up device %s.", pv_name);
return ECMD_FAILED;
}
if (!(dev = dev_cache_get(cmd, pv_name, NULL))) {
log_error("Cannot use %s: %s.", pv_name, devname_error_reason(pv_name));
return ECMD_FAILED;
@@ -3048,11 +3042,6 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, dump_ARG)) {
pv_name = argv[0];
if (!setup_device(cmd, pv_name)) {
log_error("Failed to set up device %s.", pv_name);
return ECMD_FAILED;
}
dev = dev_cache_get(cmd, pv_name, NULL);
if (!dev)
@@ -3075,23 +3064,10 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
label_scan_setup_bcache();
if (dev) {
char buf[4096];
/*
* Check nodata filters including device_id filter,
* then clear the result so the full filter can be
* checked after reading the dev.
*/
cmd->filter_nodata_only = 1;
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
log_error("Cannot use %s: %s.", pv_name, dev_filtered_reason(dev));
return ECMD_FAILED;
}
cmd->filter_nodata_only = 0;
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
label_scan_setup_bcache();
/*
* This buf is not used, but bcache data is used for subsequent
@@ -3175,11 +3151,6 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
* but this is here to preserve the historical output.
*/
if (argc == 1)
setup_device(cmd, argv[0]);
else
setup_devices(cmd);
for (i = 0; i < argc; i++) {
pv_name = argv[i];

View File

@@ -142,8 +142,6 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
cmd->create_edit_devices_file = 1;
lvmcache_label_scan(cmd);
if (!(handle = init_processing_handle(cmd, NULL))) {

View File

@@ -1445,10 +1445,7 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
cmd->pvscan_cache_single = 1;
if (!setup_devices(cmd)) {
log_error("Failed to set up devices.");
return_0;
}
dev_cache_scan();
/*
* Get list of args. Do not use filters.

View File

@@ -16,7 +16,6 @@
#include "tools.h"
#include "lib/format_text/format-text.h"
#include "lib/label/hints.h"
#include "lib/device/device_id.h"
#include <sys/stat.h>
#include <signal.h>
@@ -5302,20 +5301,13 @@ int pvcreate_each_device(struct cmd_context *cmd,
* going to rerun the filters and don't want to get the results saved
* by the prior filtering. The filtering in label scan will use full
* md filter.
*
* We allow pvcreate to look outside devices file here to find
* the target device, in case the user has not added the device
* being pvcreated to the devices file.
*/
dm_list_iterate_items(devl, &scan_devs)
cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
cmd->use_full_md_check = 1;
if (cmd->enable_devices_file)
cmd->filter_deviceid_skip = 1;
log_debug("Scanning and filtering device args (%u).", dm_list_size(&scan_devs));
log_debug("Scanning and filtering device args.");
label_scan_devs(cmd, cmd->filter, &scan_devs);
/*
@@ -5328,7 +5320,6 @@ int pvcreate_each_device(struct cmd_context *cmd,
dm_list_add(&pp->arg_fail, &pd->list);
}
}
cmd->filter_deviceid_skip = 0;
/*
* Can the command continue if some specified devices were not found?
@@ -5538,9 +5529,6 @@ do_command:
dm_list_iterate_items(devl, &rescan_devs)
cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
if (cmd->enable_devices_file)
cmd->filter_deviceid_skip = 1;
log_debug("Rescanning and filtering device args with exclusive open");
if (!label_scan_devs_excl(cmd, cmd->filter, &rescan_devs)) {
log_debug("Failed to rescan devs excl");
@@ -5554,7 +5542,6 @@ do_command:
dm_list_add(&pp->arg_fail, &pd->list);
}
}
cmd->filter_deviceid_skip = 0;
if (dm_list_empty(&pp->arg_process) && dm_list_empty(&remove_duplicates)) {
log_debug("No devices to process.");
@@ -5650,11 +5637,6 @@ do_command:
log_debug("Using existing orphan PV %s.", pv_dev_name(vgpvl->pv));
pvl->pv = vgpvl->pv;
dm_list_add(&pp->pvs, &pvl->list);
device_id_add(cmd, pd->dev, (const char *)&pvl->pv->id.uuid,
arg_str_value(cmd, deviceidtype_ARG, NULL),
arg_str_value(cmd, deviceid_ARG, NULL));
} else {
log_error("Failed to find PV %s", pd->name);
dm_list_move(&pp->arg_fail, &pd->list);
@@ -5691,10 +5673,6 @@ do_command:
continue;
}
device_id_add(cmd, pd->dev, (const char *)&pv->id.uuid,
arg_str_value(cmd, deviceidtype_ARG, NULL),
arg_str_value(cmd, deviceid_ARG, NULL));
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
" available sectors.", pv_name, pv_size(pv));
@@ -5739,8 +5717,6 @@ do_command:
continue;
}
device_id_pvremove(cmd, pd->dev);
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped.",
pd->name);
}
@@ -5757,15 +5733,10 @@ do_command:
lvmcache_del_dev_from_duplicates(pd->dev);
device_id_pvremove(cmd, pd->dev);
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped.",
pd->name);
}
/* TODO: when vgcreate uses only existing PVs this doesn't change and can be skipped */
device_ids_write(cmd);
/*
* Don't keep devs open excl in bcache because the excl will prevent
* using that dev elsewhere.

View File

@@ -29,7 +29,6 @@
#include "lib/config/defaults.h"
#include "lib/device/dev-cache.h"
#include "lib/device/device.h"
#include "lib/device/device_id.h"
#include "lib/display/display.h"
#include "errors.h"
#include "lib/metadata/metadata-exported.h"

View File

@@ -82,8 +82,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
cmd->create_edit_devices_file = 1;
lvmcache_label_scan(cmd);
if (lvmcache_vginfo_from_vgname(vp_new.vg_name, NULL)) {
@@ -102,8 +100,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
return_ECMD_FAILED;
}
unlock_devices_file(cmd);
if (!(vg = vg_create(cmd, vp_new.vg_name)))
goto_bad;

View File

@@ -168,8 +168,6 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
clear_hint_file(cmd);
cmd->edit_devices_file = 1;
lvmcache_label_scan(cmd);
if (!(handle = init_processing_handle(cmd, NULL))) {
@@ -184,8 +182,6 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
}
}
unlock_devices_file(cmd);
/*
* It is always ok to add new PVs to a VG - even if there are
* missing PVs. No LVs are affected by this operation, but

View File

@@ -15,39 +15,62 @@
#include "tools.h"
#include "lib/cache/lvmcache.h"
#include "lib/filters/filter.h"
#include "lib/device/device_id.h"
struct vgimportclone_params {
struct dm_list new_devs;
unsigned done;
unsigned total;
int import_vg;
int found_args;
struct dm_list arg_import;
const char *base_vgname;
const char *old_vgname;
const char *new_vgname;
unsigned import_devices:1;
unsigned import_vg:1;
};
static struct device_list *_get_device_list(struct dm_list *list, struct device *dev)
{
struct device_list *devl;
struct vgimportclone_device {
struct dm_list list;
struct device *dev;
unsigned found_in_vg : 1;
};
dm_list_iterate_items(devl, list) {
if (devl->dev == dev)
return devl;
static int _vgimportclone_pv_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv, struct processing_handle *handle)
{
struct vgimportclone_params *vp = (struct vgimportclone_params *) handle->custom_handle;
struct vgimportclone_device *vd;
if (vg && is_orphan_vg(vg->name)) {
log_error("Cannot import clone of orphan PV %s.", dev_name(pv->dev));
return ECMD_FAILED;
}
return NULL;
if (!(vd = dm_pool_zalloc(cmd->mem, sizeof(*vd)))) {
log_error("alloc failed.");
return ECMD_FAILED;
}
vd->dev = pv->dev;
dm_list_add(&vp->arg_import, &vd->list);
log_debug("vgimportclone dev %s VG %s found to import",
dev_name(vd->dev), vg ? vg->name : "<none>");
vp->found_args++;
return ECMD_PROCESSED;
}
static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
struct vgimportclone_params *vp)
static int _vgimportclone_vg_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, struct processing_handle *handle)
{
char uuid[64] __attribute__((aligned(8)));
struct vgimportclone_params *vp = (struct vgimportclone_params *) handle->custom_handle;
struct vgimportclone_device *vd;
struct pv_list *pvl, *new_pvl;
struct lv_list *lvl;
struct device_list *devl;
struct dm_list tmp_devs;
int devs_used_for_lv = 0;
dm_list_init(&tmp_devs);
int found;
if (vg_is_exported(vg) && !vp->import_vg) {
log_error("VG %s is exported, use the --import option.", vg->name);
@@ -65,10 +88,6 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
* that's being imported, so check DEV_USED_FOR_LV.
*/
dm_list_iterate_items(pvl, &vg->pvs) {
if (is_missing_pv(pvl->pv) || !pvl->pv->dev) {
log_error("VG is missing a device.");
goto bad;
}
if (pvl->pv->dev->flags & DEV_USED_FOR_LV) {
log_error("Device %s has active LVs, deactivate first.", dev_name(pvl->pv->dev));
devs_used_for_lv++;
@@ -79,14 +98,21 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
goto_bad;
/*
* The new_devs list must match the PVs in VG.
* The arg_import list must match the PVs in VG.
*/
dm_list_iterate_items(pvl, &vg->pvs) {
if ((devl = _get_device_list(&vp->new_devs, pvl->pv->dev))) {
dm_list_del(&devl->list);
dm_list_add(&tmp_devs, &devl->list);
} else {
found = 0;
dm_list_iterate_items(vd, &vp->arg_import) {
if (pvl->pv->dev != vd->dev)
continue;
vd->found_in_vg = 1;
found = 1;
break;
}
if (!found) {
if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
goto_bad;
@@ -98,21 +124,21 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
}
}
dm_list_iterate_items(devl, &vp->new_devs) {
/* device arg is not in the VG. */
log_error("Device %s was not found in VG %s.", dev_name(devl->dev), vg->name);
log_error("The devices to import must match the devices in the VG.");
goto bad;
dm_list_iterate_items(vd, &vp->arg_import) {
if (!vd->found_in_vg) {
/* device arg is not in the VG. */
log_error("Device %s was not found in VG %s.", dev_name(vd->dev), vg->name);
log_error("The devices to import must match the devices in the VG.");
goto bad;
}
}
dm_list_splice(&vp->new_devs, &tmp_devs);
/*
* Write changes.
*/
if (!archive(vg))
goto_bad;
return_ECMD_FAILED;
if (vp->import_vg)
vg->status &= ~EXPORTED_VG;
@@ -149,8 +175,6 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
if (!id_create(&new_pvl->pv->id))
goto_bad;
memcpy(&pvl->pv->dev->pvid, &new_pvl->pv->id.uuid, ID_LEN);
dm_list_add(&vg->pv_write_list, &new_pvl->list);
}
@@ -159,258 +183,97 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
lvl->lv->lock_args = NULL;
}
/*
* Add the device id before writing the vg so that the device id
* will be included in the metadata. The device file is written
* (with these additions) at the end of the command.
*/
if (vp->import_devices) {
dm_list_iterate_items(devl, &vp->new_devs) {
if (!device_id_add(cmd, devl->dev, devl->dev->pvid, NULL, NULL)) {
log_error("Failed to add device id for %s.", dev_name(devl->dev));
goto bad;
}
}
}
if (!vg_write(vg) || !vg_commit(vg))
goto_bad;
return 1;
return ECMD_PROCESSED;
bad:
return 0;
}
/*
* Create a list of devices that label_scan would scan excluding devs in
* new_devs.
*/
static int _get_other_devs(struct cmd_context *cmd, struct dm_list *new_devs, struct dm_list *other_devs)
{
struct dev_iter *iter;
struct device *dev;
struct device_list *devl;
if (!(iter = dev_iter_create(cmd->filter, 0)))
return_0;
while ((dev = dev_iter_get(cmd, iter))) {
if (_get_device_list(new_devs, dev))
continue;
if (!(devl = malloc(sizeof(*devl))))
return_0;
devl->dev = dev;
dm_list_add(other_devs, &devl->list);
}
dev_iter_destroy(iter);
return 1;
return ECMD_FAILED;
}
int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
{
struct vgimportclone_params vp;
struct dm_list vgnames;
struct vgimportclone_params vp = { 0 };
struct processing_handle *handle = NULL;
struct dm_list vgnameids_on_system; /* vgnameid_list */
struct vgnameid_list *vgnl;
struct device *dev;
struct device_list *devl;
struct dm_list other_devs;
struct volume_group *vg, *error_vg;
struct vgimportclone_device *vd;
struct lvmcache_info *info;
const char *vgname;
char base_vgname[NAME_LEN] = { 0 };
char tmp_vgname[NAME_LEN] = { 0 };
uint32_t lockd_state = 0;
uint32_t error_flags = 0;
unsigned int vgname_count;
int ret = ECMD_FAILED;
int i;
dm_list_init(&vgnames);
dm_list_init(&other_devs);
if (!argc) {
log_error("PV names required.");
return EINVALID_CMD_LINE;
}
dm_list_init(&vgnameids_on_system);
dm_list_init(&vp.arg_import);
set_pv_notify(cmd);
memset(&vp, 0, sizeof(vp));
dm_list_init(&vp.new_devs);
vp.import_devices = arg_is_set(cmd, importdevices_ARG);
vp.import_vg = arg_is_set(cmd, import_ARG);
if (!lock_global(cmd, "ex"))
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
}
handle->custom_handle = &vp;
clear_hint_file(cmd);
cmd->edit_devices_file = 1;
if (!setup_devices(cmd)) {
log_error("Failed to set up devices.");
if (!lock_global(cmd, "ex")) {
destroy_processing_handle(cmd, handle);
return ECMD_FAILED;
}
/*
* When importing devices not in the devices file
* we cannot use the device id filter when looking
* for the devs.
* Find the devices being imported which are named on the command line.
* They may be in the list of unchosen duplicates.
*/
if (vp.import_devices) {
if (!cmd->enable_devices_file) {
log_print("Devices file not enabled, ignoring importdevices.");
vp.import_devices = 0;
} else if (!devices_file_exists(cmd)) {
log_print("Devices file does not exist, ignoring importdevices.");
vp.import_devices = 0;
} else {
cmd->filter_deviceid_skip = 1;
}
log_debug("Finding devices to import.");
cmd->cname->flags |= ENABLE_DUPLICATE_DEVS;
process_each_pv(cmd, argc, argv, NULL, 0, 0, handle, _vgimportclone_pv_single);
if (vp.found_args != argc) {
log_error("Failed to find all devices.");
goto out;
}
/*
* For each device arg, get the dev from dev-cache.
* Only apply nodata filters when getting the devs
* from dev cache. The data filters will be applied
* next when label scan is done on them.
* Find the VG name of the PVs being imported, save as old_vgname.
* N.B. If vd->dev is a duplicate, then it may not match info->dev.
*/
cmd->filter_nodata_only = 1;
for (i = 0; i < argc; i++) {
if (!(dev = dev_cache_get(cmd, argv[i], cmd->filter))) {
/* FIXME: if filtered print which */
log_error("Failed to find device %s.", argv[i]);
goto out;
}
if (!(devl = malloc(sizeof(*devl))))
goto_out;
devl->dev = dev;
dm_list_add(&vp.new_devs, &devl->list);
}
/*
* Clear the result of nodata filtering so all
* filters will be applied in label_scan.
*/
dm_list_iterate_items(devl, &vp.new_devs)
cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
/*
* Scan lvm info from each new dev, and apply the filters
* again, this time applying filters that use data.
*/
log_debug("scan new devs");
label_scan_setup_bcache();
cmd->filter_nodata_only = 0;
label_scan_devs(cmd, cmd->filter, &vp.new_devs);
/*
* Check if any new devs were excluded by filters
* in label scan, where all filters were applied.
* (incl those that need data.)
*/
dm_list_iterate_items(devl, &vp.new_devs) {
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, "persistent")) {
/* FIXME: print which filter */
log_error("Device %s was excluded by filters.", dev_name(devl->dev));
goto out;
}
}
/*
* Look up vg info in lvmcache for each new_devs entry. This info was
* found by label scan. Verify all the new devs are from the same vg.
* The lvmcache at this point only reflects a label scan, not a vg_read
* which would assign PV info's for PVs without metadata. So this
* check is incomplete, and the same vg for devs is verified again
* later.
*/
dm_list_iterate_items(devl, &vp.new_devs) {
struct lvmcache_info *info;
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, devl->dev, 0))) {
log_error("Failed to find PVID for device %s.", dev_name(devl->dev));
dm_list_iterate_items(vd, &vp.arg_import) {
if (!(info = lvmcache_info_from_pvid(vd->dev->pvid, NULL, 0))) {
log_error("Failed to find PVID for device %s in lvmcache.", dev_name(vd->dev));
goto out;
}
if (!(vgname = lvmcache_vgname_from_info(info))) {
/* The PV may not have metadata, this will be resolved in
the process_each_vg/vg_read at the end. */
continue;
log_error("Failed to find VG name for device %s in lvmcache.", dev_name(vd->dev));
goto out;
}
if (!vp.old_vgname) {
if (!(vp.old_vgname = dm_pool_strdup(cmd->mem, vgname)))
goto_out;
} else if (strcmp(vp.old_vgname, vgname)) {
log_error("Devices must be from the same VG.");
goto out;
} else {
if (strcmp(vp.old_vgname, vgname)) {
log_error("Devices must be from the same VG.");
goto out;
}
}
}
if (!vp.old_vgname) {
log_error("No VG found on devices.");
goto out;
}
/*
* Get rid of lvmcache info from the new devs because we are going to
* read the other devs next (which conflict with the new devs because
* of the duplicated info.)
*/
dm_list_iterate_items(devl, &vp.new_devs)
label_scan_invalidate(devl->dev);
lvmcache_destroy(cmd, 1, 0);
/*
* Now processing other devs instead of new devs, so return to using
* the deviceid filter. (wiping filters not needed since these other
* devs have not been filtered yet.)
*/
cmd->filter_deviceid_skip = 0;
/*
* Scan all other devs (devs that would normally be seen excluding new
* devs). This is necessary to check if the new vgname conflicts with
* an existing vgname on other devices. We don't need to actually
* process any existing VGs, we only process the VG on the new devs
* being imported after this.
*
* This only requires a label_scan of the other devs which is enough to
* see what the other vgnames are.
*
* Only apply nodata filters when creating the other_devs list.
* Then apply all filters when label_scan_devs processes the label.
*/
log_debug("get other devices");
cmd->filter_nodata_only = 1;
if (!_get_other_devs(cmd, &vp.new_devs, &other_devs))
goto_out;
log_debug("scan other devices");
cmd->filter_nodata_only = 0;
/*
* Clear the result of nodata filtering so all
* filters will be applied in label_scan.
*/
dm_list_iterate_items(devl, &other_devs)
cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
label_scan_devs(cmd, cmd->filter, &other_devs);
if (!lvmcache_get_vgnameids(cmd, &vgnames, NULL, 0))
goto_out;
/*
* Pick a new VG name, save as new_vgname. The new name begins with
* the basevgname or old_vgname, plus a $i suffix, if necessary, to
* make it unique.
* make it unique. This requires comparing the old_vgname with all the
* VG names on the system.
*/
if (arg_is_set(cmd, basevgname_ARG)) {
@@ -433,8 +296,11 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
vgname_count = 1;
}
if (!lvmcache_get_vgnameids(cmd, &vgnameids_on_system, NULL, 0))
goto_out;
retry_name:
dm_list_iterate_items(vgnl, &vgnames) {
dm_list_iterate_items(vgnl, &vgnameids_on_system) {
if (!strcmp(vgnl->vg_name, tmp_vgname)) {
vgname_count++;
if (dm_snprintf(tmp_vgname, sizeof(tmp_vgname), "%s%u", base_vgname, vgname_count) < 0) {
@@ -449,72 +315,42 @@ retry_name:
goto_out;
log_debug("Using new VG name %s.", vp.new_vgname);
/*
* Get rid of lvmcache info from the other devs because we are going to
* read the new devs again, now to update them.
*/
dm_list_iterate_items(devl, &other_devs)
label_scan_invalidate(devl->dev);
lvmcache_destroy(cmd, 1, 0);
log_debug("import vg on new devices");
/*
* Create a device filter so that we are only working with the devices
* in arg_import. With the original devs hidden (that arg_import were
* cloned from), we can read and write the cloned PVs and VG without
* touching the original PVs/VG.
*/
init_internal_filtering(1);
dm_list_iterate_items(vd, &vp.arg_import)
internal_filter_allow(cmd->mem, vd->dev);
refresh_filters(cmd);
log_debug("Changing VG %s to %s.", vp.old_vgname, vp.new_vgname);
if (!lock_vol(cmd, vp.new_vgname, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for new VG name %s", vp.new_vgname);
goto out;
}
if (!lock_vol(cmd, vp.old_vgname, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for VG name %s", vp.old_vgname);
goto out;
}
/* No filter used since these devs have already been filtered above. */
label_scan_devs_rw(cmd, NULL, &vp.new_devs);
cmd->can_use_one_scan = 1;
cmd->include_exported_vgs = 1;
vg = vg_read(cmd, vp.old_vgname, NULL, READ_WITHOUT_LOCK | READ_FOR_UPDATE, lockd_state, &error_flags, &error_vg);
if (!vg) {
log_error("Failed to read VG %s from devices being imported.", vp.old_vgname);
unlock_vg(cmd, NULL, vp.old_vgname);
unlock_vg(cmd, NULL, vp.new_vgname);
goto out;
}
if (error_flags) {
log_error("Error reading VG %s from devices being imported.", vp.old_vgname);
release_vg(vg);
unlock_vg(cmd, NULL, vp.old_vgname);
unlock_vg(cmd, NULL, vp.new_vgname);
goto out;
}
if (!_update_vg(cmd, vg, &vp)) {
log_error("Failed to update VG on devices being imported.");
release_vg(vg);
unlock_vg(cmd, NULL, vp.old_vgname);
unlock_vg(cmd, NULL, vp.new_vgname);
goto out;
}
release_vg(vg);
unlock_vg(cmd, NULL, vp.old_vgname);
unlock_vg(cmd, NULL, vp.new_vgname);
/*
* Should we be using device_ids_validate to check/fix other
* devs in the devices file?
* Trying to lock the duplicated VG would conflict with the original,
* and it's not needed because the new VG will be imported as a local VG.
*/
if (vp.import_devices) {
if (!device_ids_write(cmd)) {
log_error("Failed to write devices file.");
goto out;
}
}
ret = ECMD_PROCESSED;
cmd->lockd_vg_disable = 1;
clear_hint_file(cmd);
ret = process_each_vg(cmd, 0, NULL, vp.old_vgname, NULL, READ_FOR_UPDATE, 0, handle, _vgimportclone_vg_single);
unlock_vg(cmd, NULL, vp.new_vgname);
out:
unlock_devices_file(cmd);
internal_filter_clear();
init_internal_filtering(0);
destroy_processing_handle(cmd, handle);
return ret;
}

View File

@@ -1,210 +0,0 @@
/*
* Copyright (C) 2020 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* 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 Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser 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
*/
#include "tools.h"
#include "lib/cache/lvmcache.h"
#include "lib/filters/filter.h"
#include "lib/device/device_id.h"
struct vgimportdevices_params {
uint32_t added_devices;
};
static int _vgimportdevices_single(struct cmd_context *cmd,
const char *vg_name,
struct volume_group *vg,
struct processing_handle *handle)
{
struct vgimportdevices_params *vp = (struct vgimportdevices_params *) handle->custom_handle;
struct pv_list *pvl;
struct physical_volume *pv;
int update_vg = 1;
int updated_pvs = 0;
const char *idtypestr;
dm_list_iterate_items(pvl, &vg->pvs) {
if (is_missing_pv(pvl->pv) || !pvl->pv->dev) {
log_error("Not importing devices for VG %s with missing PV %32s.",
vg->name, (const char *)&pvl->pv->id.uuid);
goto bad;
}
}
/*
* We want to allow importing devices of foreign and shared
* VGs, but we do not want to update device_ids in those VGs.
*
* If --foreign is set, then foreign VGs will be passed
* to this function; add devices but don't update vg.
* shared VGs are passed to this function; add devices
* and do not update.
*/
if (vg_is_foreign(vg) || vg_is_shared(vg))
update_vg = 0;
/*
* TODO: let users import devices without updating VG device_ids.
* if --nodeviceidupdate; update_vg = 0;
*/
/*
* User can select the idtype to use when importing.
*/
idtypestr = arg_str_value(cmd, deviceidtype_ARG, NULL);
dm_list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
if (!idtypestr && pv->device_id_type)
idtypestr = pv->device_id_type;
device_id_add(cmd, pv->dev, (const char *)&pvl->pv->id.uuid, idtypestr, NULL);
vp->added_devices++;
/* We could skip update if the device_id has not changed. */
if (!update_vg)
continue;
updated_pvs++;
}
if (updated_pvs) {
if (!vg_write(vg) || !vg_commit(vg))
goto_bad;
backup(vg);
}
return ECMD_PROCESSED;
bad:
return ECMD_FAILED;
}
/*
* This command always scans all devices on the system,
* any pre-existing devices_file does not limit the scope.
*
* This command adds the VG's devices to whichever
* devices_file is set in config or command line.
* If devices_file doesn't exist, it's created.
*
* If devices_file is "" then this file will scan all devices
* and show the devices that it would otherwise have added to
* the devices_file. The VG is not updated with device_ids.
*
* This command updates the VG metadata to add device_ids
* (if the metadata is missing them), unless an option is
* set to skip that, e.g. --nodeviceidupdate?
*
* If the VG found has a foreign system ID then an error
* will be printed. To import devices from a foreign VG:
* vgimportdevices --foreign -a
* vgimportdevices --foreign VG
*
* If there are duplicate VG names it will do nothing.
*
* If there are duplicate PVIDs related to VG it will do nothing,
* the user would need to add the PVs they want with lvmdevices --add.
*
* vgimportdevices -a (no vg arg) will import all accesible VGs.
*/
int vgimportdevices(struct cmd_context *cmd, int argc, char **argv)
{
struct vgimportdevices_params vp = { 0 };
struct processing_handle *handle;
int ret = ECMD_PROCESSED;
if (arg_is_set(cmd, foreign_ARG))
cmd->include_foreign_vgs = 1;
cmd->include_shared_vgs = 1;
/* So that we can warn about this. */
cmd->handles_missing_pvs = 1;
/* Print a notice if a regex filter is being applied?
Possibly offer an option to ignore a regex filter? */
if (!lock_global(cmd, "ex"))
return ECMD_FAILED;
/*
* Prepare devices file preemptively because the error path for this
* case from process_each is not as clean.
*/
if (!setup_devices_file(cmd)) {
log_error("Failed to set up devices file.");
return ECMD_FAILED;
}
if (!devices_file_exists(cmd) && !devices_file_touch(cmd)) {
log_error("Failed to create devices file.");
return ECMD_FAILED;
}
/*
* The hint file is associated with the default/system devices file,
* so don't clear hints when using a different --devicesfile.
*/
if (!cmd->devicesfile)
clear_hint_file(cmd);
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
ret = ECMD_FAILED;
goto out;
}
handle->custom_handle = &vp;
/*
* import is a case where we do not want to be limited by an existing
* devices file because we want to search outside the devices file for
* new devs to add to it, but we do want devices file entries on
* use_device_ids so we can update and write out that list.
*
* Ususally when devices file is enabled, we use filter-deviceid and
* skip filter-regex. In this import case it's reversed, and we skip
* filter-deviceid and use filter-regex.
*/
cmd->filter_deviceid_skip = 1;
cmd->filter_regex_with_devices_file = 1;
cmd->create_edit_devices_file = 1;
/*
* For each VG:
* device_id_add() each PV in the VG
* update device_ids in the VG (potentially)
*/
ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
0, handle, _vgimportdevices_single);
if (ret == ECMD_FAILED)
goto out;
if (!vp.added_devices) {
log_print("No devices to add.");
goto out;
}
if (!device_ids_write(cmd)) {
log_print("Failed to update devices file.");
ret = ECMD_FAILED;
goto out;
}
log_print("Added %u devices to devices file.", vp.added_devices);
out:
destroy_processing_handle(cmd, handle);
return ret;
}