mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-03 01:44:19 +03:00
Compare commits
1 Commits
dev-dct-de
...
dev-dct-wr
Author | SHA1 | Date | |
---|---|---|---|
|
b6e67d688e |
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
|
@@ -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
76
lib/cache/lvmcache.c
vendored
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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.
|
||||
|
@@ -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")
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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
@@ -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
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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),
|
||||
|
@@ -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
|
||||
|
@@ -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)."
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
198
test/shell/writecache-thin.sh
Normal file
198
test/shell/writecache-thin.sh
Normal 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
|
@@ -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 \
|
||||
|
36
tools/args.h
36
tools/args.h
@@ -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")
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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)))
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
31
tools/pvck.c
31
tools/pvck.c
@@ -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];
|
||||
|
||||
|
@@ -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))) {
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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"
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user