mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
toollib: process_each_pv should match by device
When processing PVs specified on the command line, the arg name was being matched against pv_dev_name, which will not always work: - The PV specified on the command line could be an alias, e.g. /dev/disk/by-id/... - The PV specified on the command line could be any random path to the device, e.g. /dev/../dev/sdb To fix this, first resolve the named PV args to struct device's, then iterate through the devices for processing.
This commit is contained in:
parent
6a77b6f43c
commit
1e4a4d48ae
@ -2074,6 +2074,31 @@ static int _get_arg_pvnames(struct cmd_context *cmd,
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
static int _get_arg_devices(struct cmd_context *cmd,
|
||||
struct dm_list *arg_pvnames,
|
||||
struct dm_list *arg_devices)
|
||||
{
|
||||
struct dm_str_list *sl;
|
||||
struct device_list *devl;
|
||||
int ret_max = ECMD_PROCESSED;
|
||||
|
||||
dm_list_iterate_items(sl, arg_pvnames) {
|
||||
if (!(devl = dm_pool_alloc(cmd->mem, sizeof(*devl)))) {
|
||||
log_error("device_list alloc failed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(devl->dev = dev_cache_get(sl->str, cmd->filter))) {
|
||||
log_error("Failed to find physical volume \"%s\".", sl->str);
|
||||
ret_max = ECMD_FAILED;
|
||||
} else {
|
||||
dm_list_add(arg_devices, &devl->list);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
static int _get_all_devices(struct cmd_context *cmd, struct dm_list *all_devices)
|
||||
{
|
||||
struct dev_iter *iter;
|
||||
@ -2118,6 +2143,18 @@ static int _device_list_remove(struct dm_list *all_devices, struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_list_match(struct dm_list *devices, struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
dm_list_iterate_items(devl, devices) {
|
||||
if (devl->dev == dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _process_device_list(struct cmd_context *cmd, struct dm_list *all_devices,
|
||||
void *handle, process_single_pv_fn_t process_single_pv)
|
||||
{
|
||||
@ -2155,7 +2192,7 @@ static int _process_device_list(struct cmd_context *cmd, struct dm_list *all_dev
|
||||
static int _process_pvs_in_vg(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct dm_list *all_devices,
|
||||
struct dm_list *arg_pvnames,
|
||||
struct dm_list *arg_devices,
|
||||
struct dm_list *arg_tags,
|
||||
int process_all,
|
||||
int skip,
|
||||
@ -2179,11 +2216,12 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
|
||||
|
||||
process_pv = process_all;
|
||||
|
||||
/* Remove each pvname as it is processed. */
|
||||
if (!process_pv && !dm_list_empty(arg_pvnames) &&
|
||||
str_list_match_item(arg_pvnames, pv_name)) {
|
||||
/* Remove each arg_devices entry as it is processed. */
|
||||
|
||||
if (!process_pv && !dm_list_empty(arg_devices) &&
|
||||
_device_list_match(arg_devices, pv->dev)) {
|
||||
process_pv = 1;
|
||||
str_list_del(arg_pvnames, pv_name);
|
||||
_device_list_remove(arg_devices, pv->dev);
|
||||
}
|
||||
|
||||
if (!process_pv && !dm_list_empty(arg_tags) &&
|
||||
@ -2222,10 +2260,9 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
/*
|
||||
* When processing only specific PV names, we can quit
|
||||
* once they've all been found.
|
||||
* When processing only specific PVs, we can quit once they've all been found.
|
||||
*/
|
||||
if (!process_all && dm_list_empty(arg_tags) && dm_list_empty(arg_pvnames))
|
||||
if (!process_all && dm_list_empty(arg_tags) && dm_list_empty(arg_devices))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2234,19 +2271,19 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
|
||||
|
||||
/*
|
||||
* Iterate through all PVs in each listed VG. Process a PV if
|
||||
* the name or tag matches arg_pvnames or arg_tags. If both
|
||||
* arg_pvnames and arg_tags are empty, then process all PVs.
|
||||
* its dev or tag matches arg_devices or arg_tags. If both
|
||||
* arg_devices and arg_tags are empty, then process all PVs.
|
||||
* No PV should be processed more than once.
|
||||
*
|
||||
* Each PV is removed from arg_pvnames and all_devices when it is
|
||||
* processed. Any names remaining in arg_pvnames were not found, and
|
||||
* Each PV is removed from arg_devices and all_devices when it is
|
||||
* processed. Any names remaining in arg_devices were not found, and
|
||||
* should produce an error. Any devices remaining in all_devices were
|
||||
* not found and should be processed by process_all_devices().
|
||||
*/
|
||||
static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
|
||||
struct dm_list *all_vgnameids,
|
||||
struct dm_list *all_devices,
|
||||
struct dm_list *arg_pvnames,
|
||||
struct dm_list *arg_devices,
|
||||
struct dm_list *arg_tags,
|
||||
int process_all,
|
||||
void *handle,
|
||||
@ -2254,7 +2291,6 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct vgnameid_list *vgnl;
|
||||
struct dm_str_list *sl;
|
||||
const char *vg_name;
|
||||
const char *vg_uuid;
|
||||
int ret_max = ECMD_PROCESSED;
|
||||
@ -2282,7 +2318,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
|
||||
* vg->pvs entries from devices list.
|
||||
*/
|
||||
|
||||
ret = _process_pvs_in_vg(cmd, vg, all_devices, arg_pvnames, arg_tags,
|
||||
ret = _process_pvs_in_vg(cmd, vg, all_devices, arg_devices, arg_tags,
|
||||
process_all, skip, handle, process_single_pv);
|
||||
if (ret != ECMD_PROCESSED)
|
||||
stack;
|
||||
@ -2295,16 +2331,10 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
|
||||
unlock_and_release_vg(cmd, vg, vg->name);
|
||||
|
||||
/* Quit early when possible. */
|
||||
if (!process_all && dm_list_empty(arg_tags) && dm_list_empty(arg_pvnames))
|
||||
if (!process_all && dm_list_empty(arg_tags) && dm_list_empty(arg_devices))
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
/* Return an error if a pvname arg was not found. */
|
||||
dm_list_iterate_items(sl, arg_pvnames) {
|
||||
log_error("Failed to find physical volume \"%s\".", sl->str);
|
||||
ret_max = ECMD_FAILED;
|
||||
}
|
||||
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
@ -2317,8 +2347,10 @@ int process_each_pv(struct cmd_context *cmd,
|
||||
{
|
||||
struct dm_list arg_tags; /* str_list */
|
||||
struct dm_list arg_pvnames; /* str_list */
|
||||
struct dm_list arg_devices; /* device_list */
|
||||
struct dm_list all_vgnameids; /* vgnameid_list */
|
||||
struct dm_list all_devices; /* device_list */
|
||||
struct device_list *devl;
|
||||
int process_all_pvs;
|
||||
int process_all_devices;
|
||||
int ret_max = ECMD_PROCESSED;
|
||||
@ -2326,6 +2358,7 @@ int process_each_pv(struct cmd_context *cmd,
|
||||
|
||||
dm_list_init(&arg_tags);
|
||||
dm_list_init(&arg_pvnames);
|
||||
dm_list_init(&arg_devices);
|
||||
dm_list_init(&all_vgnameids);
|
||||
dm_list_init(&all_devices);
|
||||
|
||||
@ -2333,9 +2366,14 @@ int process_each_pv(struct cmd_context *cmd,
|
||||
* Create two lists from argv:
|
||||
* arg_pvnames: pvs explicitly named in argv
|
||||
* arg_tags: tags explicitly named in argv
|
||||
*
|
||||
* Then convert arg_pvnames, which are free-form, user-specified,
|
||||
* names/paths into arg_devices which can be used to match below.
|
||||
*/
|
||||
if ((ret = _get_arg_pvnames(cmd, argc, argv, &arg_pvnames, &arg_tags)) != ECMD_PROCESSED)
|
||||
if ((ret = _get_arg_pvnames(cmd, argc, argv, &arg_pvnames, &arg_tags)) != ECMD_PROCESSED) {
|
||||
stack;
|
||||
return ret;
|
||||
}
|
||||
|
||||
process_all_pvs = dm_list_empty(&arg_pvnames) && dm_list_empty(&arg_tags);
|
||||
|
||||
@ -2343,6 +2381,11 @@ int process_each_pv(struct cmd_context *cmd,
|
||||
(cmd->command->flags & ENABLE_ALL_DEVS) &&
|
||||
arg_count(cmd, all_ARG);
|
||||
|
||||
if ((ret = _get_arg_devices(cmd, &arg_pvnames, &arg_devices) != ECMD_PROCESSED)) {
|
||||
/* get_arg_devices reports the error for any PV names not found. */
|
||||
ret_max = ECMD_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the caller wants to process all devices (not just PVs), then all PVs
|
||||
* from all VGs are processed first, removing them from all_devices. Then
|
||||
@ -2359,13 +2402,18 @@ int process_each_pv(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
ret = _process_pvs_in_vgs(cmd, flags, &all_vgnameids, &all_devices,
|
||||
&arg_pvnames, &arg_tags, process_all_pvs,
|
||||
&arg_devices, &arg_tags, process_all_pvs,
|
||||
handle, process_single_pv);
|
||||
if (ret != ECMD_PROCESSED)
|
||||
stack;
|
||||
if (ret > ret_max)
|
||||
ret_max = ret;
|
||||
|
||||
dm_list_iterate_items(devl, &arg_devices) {
|
||||
log_error("Failed to find physical volume \"%s\".", dev_name(devl->dev));
|
||||
ret_max = ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!process_all_devices)
|
||||
goto out;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user