diff --git a/tools/toollib.c b/tools/toollib.c index 41e6f88a2..1b3883e7f 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -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;