1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-28 04:23:49 +03:00

Compare commits

..

1 Commits

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

72
lib/cache/lvmcache.c vendored
View File

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

View File

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

View File

@@ -182,11 +182,6 @@ 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_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 */
/*
@@ -194,9 +189,7 @@ struct cmd_context {
*/
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 */
/*
* Configuration.
@@ -228,7 +221,6 @@ struct cmd_context {
char system_dir[PATH_MAX];
char dev_dir[PATH_MAX];
char proc_dir[PATH_MAX];
char devices_file_path[PATH_MAX];
/*
* Reporting.

View File

@@ -288,14 +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_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"

View File

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

View File

@@ -16,7 +16,6 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/device/device_id.h"
#include "lib/datastruct/btree.h"
#include "lib/config/config.h"
#include "lib/commands/toolcontext.h"
@@ -69,13 +68,11 @@ static void _dev_init(struct device *dev)
dev->bcache_fd = -1;
dev->bcache_di = -1;
dev->read_ahead = -1;
dev->part = -1;
dev->ext.enabled = 0;
dev->ext.src = DEV_EXT_NONE;
dm_list_init(&dev->aliases);
dm_list_init(&dev->ids);
}
void dev_destroy_file(struct device *dev)
@@ -355,7 +352,7 @@ static int _add_alias(struct device *dev, const char *path)
return 1;
}
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
static int _get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
{
FILE *fp;
size_t len;
@@ -396,7 +393,7 @@ static int _get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int mi
return 0;
}
return get_sysfs_value(path, buf, buf_size, 0);
return _get_sysfs_value(path, buf, buf_size, 0);
}
static struct dm_list *_get_or_add_list_by_index_key(struct dm_hash_table *idx, const char *key)
@@ -477,7 +474,7 @@ static struct device *_get_device_for_sysfs_dev_name_using_devno(const char *dev
return NULL;
}
if (!get_sysfs_value(path, buf, sizeof(buf), 1))
if (!_get_sysfs_value(path, buf, sizeof(buf), 1))
return_NULL;
if (sscanf(buf, "%d:%d", &major, &minor) != 2) {
@@ -975,7 +972,7 @@ static int _dev_cache_iterate_sysfs_for_index(const char *path)
return r;
}
static int dev_cache_index_devs(void)
int dev_cache_index_devs(void)
{
static int sysfs_has_dev_block = -1;
char path[PATH_MAX];
@@ -1324,19 +1321,12 @@ int dev_cache_check_for_open_devices(void)
int dev_cache_exit(void)
{
struct device *dev;
struct dm_hash_node *n;
int num_open = 0;
if (_cache.names)
if ((num_open = _check_for_open_devices(1)) > 0)
log_error(INTERNAL_ERROR "%d device(s) were left open and have been closed.", num_open);
dm_hash_iterate(n, _cache.names) {
dev = (struct device *) dm_hash_get_data(_cache.names, n);
free_dids(&dev->ids);
}
if (_cache.mem)
dm_pool_destroy(_cache.mem);
@@ -1659,204 +1649,3 @@ bool dev_cache_has_md_with_end_superblock(struct dev_types *dt)
return false;
}
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 (!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 (!setup_devices_file(cmd))
return_0;
if (!cmd->enable_devices_file)
goto scan;
if (!devices_file_exists(cmd)) {
log_print("Devices file not found, ignoring.");
cmd->enable_devices_file = 0;
goto scan;
}
if (!lock_devices_file(cmd, LOCK_SH)) {
log_error("Failed to lock the devices file to read.");
return 0;
}
if (!device_ids_read(cmd)) {
log_error("Failed to read the devices file.");
return 0;
}
unlock_devices_file(cmd);
scan:
if (stat(devname, &buf) < 0) {
log_error("Cannot access device %s.", devname);
return 0;
}
if (!S_ISBLK(buf.st_mode)) {
log_error("Invaild device type %s.", devname);
return 0;
}
if (!_insert_dev(devname, buf.st_rdev))
return_0;
if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname)))
return_0;
/* Match this device to an entry in devices_file so it will not
be rejected by filter-deviceid. */
if (cmd->enable_devices_file)
device_ids_match_dev(cmd, dev);
return 1;
}

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LVM_DEVICE_ID_H
#define _LVM_DEVICE_ID_H
void free_uid(struct use_id *uid);
void free_uids(struct dm_list *list);
void free_did(struct dev_id *did);
void free_dids(struct dm_list *list);
const char *idtype_to_str(uint16_t idtype);
uint16_t idtype_from_str(const char *str);
const char *dev_idtype(struct device *dev);
const char *dev_id(struct device *dev);
int device_ids_read(struct cmd_context *cmd);
int device_ids_write(struct cmd_context *cmd);
int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid,
const char *idtype_arg, const char *id_arg);
void device_id_pvremove(struct cmd_context *cmd, struct device *dev);
void device_ids_match(struct cmd_context *cmd);
int device_ids_match_dev(struct cmd_context *cmd, struct device *dev);
void device_ids_validate(struct cmd_context *cmd, int force_update);
int device_ids_version_unchanged(struct cmd_context *cmd);
void device_ids_read_pvids(struct cmd_context *cmd);
void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_list);
const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype);
struct use_id *get_uid_for_dev(struct cmd_context *cmd, struct device *dev);
struct use_id *get_uid_for_pvid(struct cmd_context *cmd, const char *pvid);
int devices_file_exists(struct cmd_context *cmd);
int devices_file_touch(struct cmd_context *cmd);
int lock_devices_file(struct cmd_context *cmd, int mode);
int lock_devices_file_try(struct cmd_context *cmd, int mode, int *held);
void unlock_devices_file(struct cmd_context *cmd);
void device_ids_init(struct cmd_context *cmd);
void device_ids_exit(struct cmd_context *cmd);
#endif

View File

@@ -1,60 +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)
{
if (!cmd->enable_devices_file)
return 1;
if (cmd->filter_deviceid_skip)
return 1;
if (dev->flags & DEV_MATCHED_USE_ID)
return 1;
log_debug_devs("%s: Skipping (deviceid)", dev_name(dev));
return 0;
}
static void _destroy_deviceid_filter(struct dev_filter *f)
{
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying deviceid filter while in use %u times.", f->use_count);
free(f);
}
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd)
{
struct dev_filter *f;
if (!(f = zalloc(sizeof(struct dev_filter)))) {
log_error("deviceid filter allocation failed");
return NULL;
}
f->passes_filter = _passes_deviceid_filter;
f->destroy = _destroy_deviceid_filter;
f->use_count = 0;
f->name = "deviceid";
log_debug_devs("deviceid filter initialised.");
return f;
}

View File

@@ -15,7 +15,6 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/commands/toolcontext.h"
struct rfilter {
struct dm_pool *mem;
@@ -154,11 +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_file && !cmd->filter_regex_with_devices_file) {
/* TODO: print a notice if the filter is set to something and we ignore it here. */
return 1;
}
dm_list_iterate_items(sl, &dev->aliases) {
m = dm_regex_match(rf->engine, sl->str);

View File

@@ -30,7 +30,6 @@ struct dev_filter *partitioned_filter_create(struct dev_types *dt);
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *f);
struct dev_filter *sysfs_filter_create(void);
struct dev_filter *signature_filter_create(struct dev_types *dt);
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd);
struct dev_filter *internal_filter_create(void);
int internal_filter_allow(struct dm_pool *mem, struct device *dev);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3507,42 +3507,6 @@ static int _pvduplicate_disp(struct dm_report *rh, struct dm_pool *mem,
return _binary_disp(rh, mem, field, duplicate, GET_FIRST_RESERVED_NAME(pv_duplicate_y), private);
}
static int _pvdeviceid_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct physical_volume *pv = (const struct physical_volume *) data;
char *repstr;
if (!pv->device_id)
return _field_set_value(field, "", NULL);
if (!(repstr = pv_deviceid_dup(mem, pv))) {
log_error("Failed to allocate buffer.");
return 0;
}
return _field_set_value(field, repstr, NULL);
}
static int _pvdeviceidtype_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct physical_volume *pv = (const struct physical_volume *) data;
char *repstr;
if (!pv->device_id_type)
return _field_set_value(field, "", NULL);
if (!(repstr = pv_deviceidtype_dup(mem, pv))) {
log_error("Failed to allocate buffer.");
return 0;
}
return _field_set_value(field, repstr, NULL);
}
static int _vgpermissions_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)

View File

@@ -0,0 +1,198 @@
#!/usr/bin/env bash
# Copyright (C) 2018 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SKIP_WITH_LVMPOLLD=1
. lib/inittest
mkfs_mount_unmount()
{
lvt=$1
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lvt"
mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir"
cp pattern1 "$mount_dir/pattern1"
umount "$mount_dir"
}
setup_thin_lvs()
{
pool=$1
for i in $(seq 1 4); do
lvcreate --type thin -V1G -n th$i --thinpool $pool $vg
mkfs_mount_unmount th${i}
lvchange -an $vg/th${i}
done
}
diff_thin_lvs()
{
for i in $(seq 1 4); do
diff pattern1 "${mount_dir}_${i}/pattern1"
diff pattern2 "${mount_dir}_${i}/pattern2"
done
}
mount_thin_lvs()
{
for i in $(seq 1 4); do
lvchange -ay $vg/th$i
mount "$DM_DEV_DIR/$vg/th$i" "${mount_dir}_${i}"
done
}
unmount_thin_lvs()
{
for i in $(seq 1 4); do
umount "${mount_dir}_${i}"
lvchange -an $vg/th${i}
done
}
write_thin_lvs()
{
for i in $(seq 1 4); do
cp pattern2 "${mount_dir}_${i}/pattern2"
done
}
aux have_writecache 1 0 0 || skip
which mkfs.xfs || skip
mount_dir="mnt"
mount_dir_1="mnt1"
mount_dir_2="mnt2"
mount_dir_3="mnt3"
mount_dir_4="mnt4"
mkdir -p "$mount_dir"
for i in $(seq 1 4); do
mkdir -p "${mount_dir}_${i}"
done
# generate random data
dd if=/dev/urandom of=pattern1 bs=512K count=1
dd if=/dev/urandom of=pattern2 bs=512 count=15
aux prepare_devs 6 40
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6"
#
# writecache as thin pool data
# splitcache while inactive
#
# lv1 holds thin pool data and uses writecache
# lv2 holds cachevol for writecache
# lv3 holds thin pool metadata
lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev2"
lvcreate -n $lv2 -l 2 -an $vg "$dev3"
lvcreate -n $lv3 -l 2 -an $vg "$dev4"
lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
lvconvert -y --type thin-pool --poolmetadata $lv3 --poolmetadataspare n $vg/$lv1
setup_thin_lvs $lv1
mount_thin_lvs
write_thin_lvs
unmount_thin_lvs
lvchange -an $vg/$lv1
lvconvert --splitcache --cachesettings cleaner=0 $vg/${lv1}_tdata
lvs -o segtype $vg/$lv2 | grep linear
mount_thin_lvs
diff_thin_lvs
unmount_thin_lvs
lvremove -y $vg/$lv1
lvremove -y $vg/$lv2
#
# writecache as thin pool data
# splitcache while active
#
# lv1 holds thin pool data and uses writecache
# lv2 holds cachevol for writecache
# lv3 holds thin pool metadata
lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev2"
lvcreate -n $lv2 -l 2 -an $vg "$dev3"
lvcreate -n $lv3 -l 2 -an $vg "$dev4"
lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
lvconvert -y --type thin-pool --poolmetadata $lv3 --poolmetadataspare n $vg/$lv1
setup_thin_lvs $lv1
mount_thin_lvs
write_thin_lvs
# FIXME: splitcache setting cleaner on tdata writecache doesn't work,
# bypassing that with cleaner=0 here.
lvconvert --splitcache --cachesettings cleaner=0 $vg/${lv1}_tdata
lvs -o segtype $vg/$lv2 | grep linear
diff_thin_lvs
unmount_thin_lvs
mount_thin_lvs
diff_thin_lvs
unmount_thin_lvs
lvremove -y $vg/$lv1
lvremove -y $vg/$lv2
#
# add writecache to raid, then use writecache for thin pool data
#
# lv1 holds thin pool data and uses writecache
# lv2 holds cachevol for writecache
# lv3 holds thin pool metadata
lvcreate --type raid1 -m1 -n $lv1 -l 16 -an $vg "$dev1" "$dev2" "$dev5" "$dev6"
lvcreate -n $lv2 -l 2 -an $vg "$dev3"
lvcreate -n $lv3 -l 2 -an $vg "$dev4"
lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1
lvconvert -y --type thin-pool --poolmetadata $lv3 --poolmetadataspare n $vg/$lv1
setup_thin_lvs $lv1
mount_thin_lvs
write_thin_lvs
lvconvert --splitcache --cachesettings cleaner=0 $vg/${lv1}_tdata
lvs -o segtype $vg/$lv2 | grep linear
diff_thin_lvs
unmount_thin_lvs
mount_thin_lvs
diff_thin_lvs
unmount_thin_lvs
lvremove -y $vg/$lv1
lvremove -y $vg/$lv2
#
# remove writecache from thin pool data when cachevol is missing
#
#
# FIXME: add writecache to existing thin pool data
#
#
# FIXME: thin pool data cannot be extended when it uses writecache
#
vgremove -ff $vg

View File

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

View File

@@ -44,15 +44,6 @@ arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0,
"Adds a tag to a PV, VG or LV. This option can be repeated to add\n"
"multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
arg(adddev_ARG, '\0', "adddev", pv_VAL, 0, 0,
"Add a device to the devices file.\n")
arg(deldev_ARG, '\0', "deldev", pv_VAL, 0, 0,
"Remove a device from the devices file.\n")
arg(addpvid_ARG, '\0', "addpvid", string_VAL, 0, 0,
"Find a device with the PVID and add the device to the devices file.\n")
arg(delpvid_ARG, '\0', "delpvid", string_VAL, 0, 0,
"Remove a device with the PVID from the devices file.\n")
arg(aligned_ARG, '\0', "aligned", 0, 0, 0,
"Use with --separator to align the output columns\n")
@@ -141,9 +132,6 @@ arg(cachedevice_ARG, '\0', "cachedevice", pv_VAL, ARG_GROUPABLE, 0,
arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
"The size of cache to use.\n")
arg(check_ARG, '\0', "check", 0, 0, 0,
"Check the content of the devices file.\n")
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0,
"The command profile to use for command configuration.\n"
"See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
@@ -217,15 +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(devicesfile_ARG, '\0', "devicesfile", string_VAL, 0, 0,
"The file listing device IDs that LVM should use.")
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"
@@ -301,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"
@@ -799,9 +775,6 @@ arg(uncache_ARG, '\0', "uncache", 0, 0, 0,
"Separates a cache pool from a cache LV, and deletes the unused cache pool LV.\n"
"Before the separation, the cache is flushed. Also see --splitcache.\n")
arg(update_ARG, '\0', "update", 0, 0, 0,
"Update the content of the devices file.\n")
arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0,
"Specifies the cache policy for a cache LV.\n"
"See \\fBlvmcache\\fP(7) for more information.\n")

View File

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

View File

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

View File

@@ -17,7 +17,6 @@
#include "lvm2cmdline.h"
#include "lib/label/label.h"
#include "lib/device/device_id.h"
#include "lvm-version.h"
#include "lib/locking/lvmlockd.h"
@@ -2428,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.
@@ -2444,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))
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;
@@ -2489,19 +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;
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;
}
}
/*
* This is set to zero by process_each which wants to print errors
* itself rather than having them printed in vg_read.

View File

@@ -1,339 +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);
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)) {
/* FIXME: print which filters */
log_warn("WARNING: %s is currently excluded by filters.", dev_name(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)) {
/* FIXME: print which filters */
log_error("PVID %s found on %s which is excluded by filters",
pvid, dev_name(dev));
goto_bad;
}
if (!device_id_add(cmd, dev, dev->pvid, NULL, NULL))
goto_bad;
if (!device_ids_write(cmd))
goto_bad;
goto out;
}
if (arg_is_set(cmd, deldev_ARG)) {
const char *devname;
if (!(devname = arg_str_value(cmd, deldev_ARG, NULL)))
goto_bad;
/* we don't need to filter_deviceid_skip since we're
removing a dev from devices_file, that dev should
be in the devices_file and pass the filter */
if (!(dev = dev_cache_get(cmd, devname, cmd->filter))) {
log_error("No device found for %s.", devname);
goto bad;
}
/* dev_cache_scan uses sysfs to check if an LV is using each dev
and sets this flag is so. */
if (dev->flags & DEV_USED_FOR_LV) {
if (!arg_count(cmd, yes_ARG) &&
yes_no_prompt("Device %s is used by an active LV, continue to remove? ", devname) == 'n') {
log_error("Device not removed.");
goto bad;
}
}
if (!(uid = get_uid_for_dev(cmd, dev))) {
log_error("Device not found in devices_file.");
goto bad;
}
dm_list_del(&uid->list);
free_uid(uid);
device_ids_write(cmd);
goto out;
}
if (arg_is_set(cmd, delpvid_ARG)) {
struct id id;
char pvid[ID_LEN+1] = { 0 };
const char *pvid_arg;
pvid_arg = arg_str_value(cmd, delpvid_ARG, NULL);
if (!id_read_format_try(&id, pvid_arg)) {
log_error("Invalid PVID.");
goto bad;
}
memcpy(pvid, &id.uuid, ID_LEN);
if (!(uid = get_uid_for_pvid(cmd, pvid))) {
log_error("PVID not found in devices_file.");
goto_bad;
}
if (uid->devname && (uid->devname[0] != '.')) {
if ((dev = dev_cache_get(cmd, uid->devname, NULL)) &&
(dev->flags & DEV_USED_FOR_LV)) {
if (!arg_count(cmd, yes_ARG) &&
yes_no_prompt("Device %s is used by an active LV, continue to remove? ", uid->devname) == 'n') {
log_error("Device not removed.");
goto bad;
}
}
}
dm_list_del(&uid->list);
free_uid(uid);
device_ids_write(cmd);
goto out;
}
/* If no options, print use_device_ids list */
dm_list_iterate_items(uid, &cmd->use_device_ids) {
char part_buf[64] = { 0 };
if (uid->part)
snprintf(part_buf, 63, " PART=%d", uid->part);
log_print("Device %s IDTYPE=%s IDNAME=%s DEVNAME=%s PVID=%s%s",
uid->dev ? dev_name(uid->dev) : ".",
uid->idtype ? idtype_to_str(uid->idtype) : ".",
uid->idname ? uid->idname : ".",
uid->devname ? uid->devname : ".",
uid->pvid ? (char *)uid->pvid : ".",
part_buf);
}
out:
return ECMD_PROCESSED;
bad:
return ECMD_FAILED;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,6 @@
#include "tools.h"
#include "lib/format_text/format-text.h"
#include "lib/label/hints.h"
#include "lib/device/device_id.h"
#include <sys/stat.h>
#include <signal.h>
@@ -5302,18 +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;
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);
/*
@@ -5326,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?
@@ -5536,8 +5529,6 @@ do_command:
dm_list_iterate_items(devl, &rescan_devs)
cmd->filter->wipe(cmd, cmd->filter, devl->dev, NULL);
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");
@@ -5551,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.");
@@ -5647,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);
@@ -5688,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));
@@ -5736,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);
}
@@ -5754,15 +5733,10 @@ do_command:
lvmcache_del_dev_from_duplicates(pd->dev);
device_id_pvremove(cmd, pd->dev);
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped.",
pd->name);
}
/* TODO: when vgcreate uses only existing PVs this doesn't change and can be skipped */
device_ids_write(cmd);
/*
* Don't keep devs open excl in bcache because the excl will prevent
* using that dev elsewhere.

View File

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

View File

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

View File

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

View File

@@ -15,39 +15,62 @@
#include "tools.h"
#include "lib/cache/lvmcache.h"
#include "lib/filters/filter.h"
#include "lib/device/device_id.h"
struct vgimportclone_params {
struct dm_list new_devs;
unsigned done;
unsigned total;
int import_vg;
int found_args;
struct dm_list arg_import;
const char *base_vgname;
const char *old_vgname;
const char *new_vgname;
unsigned import_devices:1;
unsigned import_vg:1;
};
static struct device_list *_get_device_list(struct dm_list *list, struct device *dev)
{
struct device_list *devl;
struct vgimportclone_device {
struct dm_list list;
struct device *dev;
unsigned found_in_vg : 1;
};
dm_list_iterate_items(devl, list) {
if (devl->dev == dev)
return devl;
static int _vgimportclone_pv_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv, struct processing_handle *handle)
{
struct vgimportclone_params *vp = (struct vgimportclone_params *) handle->custom_handle;
struct vgimportclone_device *vd;
if (vg && is_orphan_vg(vg->name)) {
log_error("Cannot import clone of orphan PV %s.", dev_name(pv->dev));
return ECMD_FAILED;
}
return NULL;
if (!(vd = dm_pool_zalloc(cmd->mem, sizeof(*vd)))) {
log_error("alloc failed.");
return ECMD_FAILED;
}
vd->dev = pv->dev;
dm_list_add(&vp->arg_import, &vd->list);
log_debug("vgimportclone dev %s VG %s found to import",
dev_name(vd->dev), vg ? vg->name : "<none>");
vp->found_args++;
return ECMD_PROCESSED;
}
static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
struct vgimportclone_params *vp)
static int _vgimportclone_vg_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, struct processing_handle *handle)
{
char uuid[64] __attribute__((aligned(8)));
struct vgimportclone_params *vp = (struct vgimportclone_params *) handle->custom_handle;
struct vgimportclone_device *vd;
struct pv_list *pvl, *new_pvl;
struct lv_list *lvl;
struct device_list *devl;
struct dm_list tmp_devs;
int devs_used_for_lv = 0;
dm_list_init(&tmp_devs);
int found;
if (vg_is_exported(vg) && !vp->import_vg) {
log_error("VG %s is exported, use the --import option.", vg->name);
@@ -65,10 +88,6 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
* that's being imported, so check DEV_USED_FOR_LV.
*/
dm_list_iterate_items(pvl, &vg->pvs) {
if (is_missing_pv(pvl->pv) || !pvl->pv->dev) {
log_error("VG is missing a device.");
goto bad;
}
if (pvl->pv->dev->flags & DEV_USED_FOR_LV) {
log_error("Device %s has active LVs, deactivate first.", dev_name(pvl->pv->dev));
devs_used_for_lv++;
@@ -79,14 +98,21 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
goto_bad;
/*
* The new_devs list must match the PVs in VG.
* The arg_import list must match the PVs in VG.
*/
dm_list_iterate_items(pvl, &vg->pvs) {
if ((devl = _get_device_list(&vp->new_devs, pvl->pv->dev))) {
dm_list_del(&devl->list);
dm_list_add(&tmp_devs, &devl->list);
} else {
found = 0;
dm_list_iterate_items(vd, &vp->arg_import) {
if (pvl->pv->dev != vd->dev)
continue;
vd->found_in_vg = 1;
found = 1;
break;
}
if (!found) {
if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
goto_bad;
@@ -98,21 +124,21 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
}
}
dm_list_iterate_items(devl, &vp->new_devs) {
/* device arg is not in the VG. */
log_error("Device %s was not found in VG %s.", dev_name(devl->dev), vg->name);
log_error("The devices to import must match the devices in the VG.");
goto bad;
dm_list_iterate_items(vd, &vp->arg_import) {
if (!vd->found_in_vg) {
/* device arg is not in the VG. */
log_error("Device %s was not found in VG %s.", dev_name(vd->dev), vg->name);
log_error("The devices to import must match the devices in the VG.");
goto bad;
}
}
dm_list_splice(&vp->new_devs, &tmp_devs);
/*
* Write changes.
*/
if (!archive(vg))
goto_bad;
return_ECMD_FAILED;
if (vp->import_vg)
vg->status &= ~EXPORTED_VG;
@@ -149,8 +175,6 @@ static int _update_vg(struct cmd_context *cmd, struct volume_group *vg,
if (!id_create(&new_pvl->pv->id))
goto_bad;
memcpy(&pvl->pv->dev->pvid, &new_pvl->pv->id.uuid, ID_LEN);
dm_list_add(&vg->pv_write_list, &new_pvl->list);
}
@@ -159,256 +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;
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);
dm_list_init(&vp.new_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));
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.)
*/
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)) {
@@ -431,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) {
@@ -447,61 +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.
*/
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;
}
/* 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, NULL);
if (!vg) {
log_error("Failed to read VG %s from devices being imported.", 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.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.new_vgname);
goto out;
}
release_vg(vg);
unlock_vg(cmd, NULL, vp.new_vgname);
/*
* Should we be using device_ids_validate to check/fix other
* devs in the devices file?
* Trying to lock the duplicated VG would conflict with the original,
* and it's not needed because the new VG will be imported as a local VG.
*/
if (vp.import_devices) {
if (!device_ids_write(cmd)) {
log_error("Failed to write devices file.");
goto out;
}
}
ret = ECMD_PROCESSED;
cmd->lockd_vg_disable = 1;
clear_hint_file(cmd);
ret = process_each_vg(cmd, 0, NULL, vp.old_vgname, NULL, READ_FOR_UPDATE, 0, handle, _vgimportclone_vg_single);
unlock_vg(cmd, NULL, vp.new_vgname);
out:
unlock_devices_file(cmd);
internal_filter_clear();
init_internal_filtering(0);
destroy_processing_handle(cmd, handle);
return ret;
}

View File

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