From: David Teigland Date: Tue, 26 Feb 2019 22:35:16 +0000 (-0600) Subject: pvscan: reorganize code X-Git-Tag: v2_03_03~69 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=417724efe260723889ca4013dd7fff80bb5375c3;p=lvm2.git pvscan: reorganize code to simplify and prepare for subsequent change. Should be no change in behavior. --- diff --git a/tools/pvscan.c b/tools/pvscan.c index d69d919b7..f0944cdfa 100644 --- a/tools/pvscan.c +++ b/tools/pvscan.c @@ -860,7 +860,8 @@ static int _pvscan_aa(struct cmd_context *cmd, struct pvscan_aa_params *pp, int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) { struct pvscan_aa_params pp = { 0 }; - struct dm_list single_devs; + struct dm_list add_devs; + struct dm_list rem_devs; struct dm_list vgnames; struct dm_list *complete_vgnames = NULL; struct device *dev; @@ -870,6 +871,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) int32_t major = -1; int32_t minor = -1; int devno_args = 0; + int all_devs; struct arg_value_group_list *current_group; dev_t devno; int do_activate = arg_is_set(cmd, activate_ARG); @@ -877,7 +879,8 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) int add_single_count = 0; int ret = ECMD_PROCESSED; - dm_list_init(&single_devs); + dm_list_init(&add_devs); + dm_list_init(&rem_devs); dm_list_init(&vgnames); if (do_activate) @@ -891,89 +894,36 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) return EINVALID_CMD_LINE; } - _online_dir_setup(); - _online_file_setup(); - + if (argc || devno_args) { + log_verbose("pvscan devices on command line."); + cmd->pvscan_cache_single = 1; + all_devs = 0; + } else { + all_devs = 1; + } + if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_READ, NULL)) { log_error("Unable to obtain global lock."); return ECMD_FAILED; } - /* - * Scan all devices when no args are given. - */ - if (!argc && !devno_args) { - /* - * pvscan --cache removes existing hints and recreates new ones. - * We begin by clearing hints at the start of the command. - * The pvscan_recreate_hints flag is used to enable the - * special case hint recreation in label_scan. - */ - cmd->pvscan_recreate_hints = 1; - pvscan_recreate_hints_begin(cmd); - - _lock_online(LOCK_EX, 0); - log_verbose("pvscan all devices for requested refresh."); - _online_files_remove(_pvs_online_dir); - _online_files_remove(_vgs_online_dir); - _online_pvscan_all_devs(cmd, complete_vgnames, NULL); - _unlock_online(); + _online_dir_setup(); + _online_file_setup(); - cmd->pvscan_recreate_hints = 0; - cmd->use_hints = 0; - goto activate; - } + /* Creates a list of dev names from /dev, sysfs, etc; does not read any. */ + dev_cache_scan(); /* - * Initialization case: - * lock_online ex - * if empty - * pvscan all - * create pvid files - * identify complete vgs - * unlock_online - * activate complete vgs - * - * Non-initialization case: - * lock_online ex - * if not empty - * unlock_unlock - * pvscan devs - * create pvid files - * identify complete vgs - * activate complete vgs - * - * In the non-init case, a VG with two PVs, where both PVs appear at once, - * two parallel pvscans for each PV create the pvid files for each PV in - * parallel, then both pvscans see the vg has completed, and both pvscans - * activate the VG in parallel. The first pvscan to create the vgname - * file in vgs_online will do the activation, any others will skip it. + * For each device command arg (from either position or --major/--minor), + * decide if that device is being added to the system (a dev node exists + * for it in /dev), or being removed from the system (no dev node exists + * for it in /dev). Create entries in add_devs/rem_devs for each arg + * accordingly. */ - _lock_online(LOCK_EX, 0); - - if (_online_pvid_files_missing()) { - log_verbose("pvscan all devices to initialize available PVs."); - _online_files_remove(_pvs_online_dir); - _online_files_remove(_vgs_online_dir); - cmd->pvscan_cache_single = 1; - _online_pvscan_all_devs(cmd, complete_vgnames, NULL); - _unlock_online(); - goto activate; - } else { - log_verbose("pvscan only specific devices."); - _unlock_online(); - } + while (argc) { + argc--; - if (argc || devno_args) { - log_verbose("pvscan devices on command line."); - cmd->pvscan_cache_single = 1; - } - - /* Creates a list of dev names from /dev, sysfs, etc; does not read any. */ - dev_cache_scan(); - - while (argc--) { pv_name = *argv++; if (pv_name[0] == '/') { if (!(dev = dev_cache_get(cmd, pv_name, cmd->filter))) { @@ -994,7 +944,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) return_0; devl->dev = dev; - dm_list_add(&single_devs, &devl->list); + dm_list_add(&add_devs, &devl->list); } } else { if (sscanf(pv_name, "%d:%d", &major, &minor) != 2) { @@ -1005,7 +955,13 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) if (!(dev = dev_cache_get_by_devt(cmd, devno, cmd->filter))) { log_debug("pvscan arg %d:%d not found.", major, minor); - _online_pvid_file_remove_devno(major, minor); + if (!(dev = dm_pool_zalloc(cmd->mem, sizeof(struct device)))) + return_0; + if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) + return_0; + dev->dev = devno; + devl->dev = dev; + dm_list_add(&rem_devs, &devl->list); } else { /* * Scan device. This dev could still be removed @@ -1016,41 +972,11 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) return_0; devl->dev = dev; - dm_list_add(&single_devs, &devl->list); + dm_list_add(&add_devs, &devl->list); } } - - if (sigint_caught()) { - ret = ECMD_FAILED; - goto_out; - } } - if (!dm_list_empty(&single_devs)) { - label_scan_devs(cmd, cmd->filter, &single_devs); - - dm_list_iterate_items(devl, &single_devs) { - dev = devl->dev; - - if (dev->flags & DEV_FILTER_OUT_SCAN) - continue; - - add_single_count++; - - /* - * Devices that exist and pass the lvmetad filter - * are online. - */ - if (!_online_pvscan_one(cmd, dev, NULL, complete_vgnames, 0, &pvid_without_metadata)) - add_errors++; - } - } - - if (!devno_args) - goto activate; - - dm_list_init(&single_devs); - /* Process any grouped --major --minor args */ dm_list_iterate_items(current_group, &cmd->arg_value_groups) { major = grouped_arg_int_value(current_group->arg_values, major_ARG, major); @@ -1063,26 +989,114 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) if (!(dev = dev_cache_get_by_devt(cmd, devno, cmd->filter))) { log_debug("pvscan arg %d:%d not found.", major, minor); - _online_pvid_file_remove_devno(major, minor); + if (!(dev = dm_pool_zalloc(cmd->mem, sizeof(struct device)))) + return_0; + if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) + return_0; + dev->dev = devno; + devl->dev = dev; + dm_list_add(&rem_devs, &devl->list); } else { log_debug("pvscan arg %d:%d found.", major, minor); if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl)))) return_0; devl->dev = dev; - dm_list_add(&single_devs, &devl->list); + dm_list_add(&add_devs, &devl->list); } + } - if (sigint_caught()) { - ret = ECMD_FAILED; - goto_out; - } + /* + * No device args means rescan/regenerate/[reactivate] everything. + * Scan all devices when no args are given; clear all pvid + * files on recreate pvid files for existing devices. + * When -aay is set, any complete vg is activated + * (even if it's already active.) + */ + + if (all_devs) { + /* + * pvscan --cache removes existing hints and recreates new ones. + * We begin by clearing hints at the start of the command. + * The pvscan_recreate_hints flag is used to enable the + * special case hint recreation in label_scan. + */ + cmd->pvscan_recreate_hints = 1; + pvscan_recreate_hints_begin(cmd); + + _lock_online(LOCK_EX, 0); + log_verbose("pvscan all devices for requested refresh."); + _online_files_remove(_pvs_online_dir); + _online_files_remove(_vgs_online_dir); + _online_pvscan_all_devs(cmd, complete_vgnames, NULL); + _unlock_online(); + + cmd->pvscan_recreate_hints = 0; + cmd->use_hints = 0; + goto activate; } - if (!dm_list_empty(&single_devs)) { - label_scan_devs(cmd, cmd->filter, &single_devs); + /* + * Initialization case: + * lock_online ex + * if empty + * pvscan all + * create pvid files + * identify complete vgs + * unlock_online + * activate complete vgs + * + * Non-initialization case: + * lock_online ex + * if not empty + * unlock_unlock + * pvscan devs + * create pvid files + * identify complete vgs + * activate complete vgs + * + * In the non-init case, a VG with two PVs, where both PVs appear at once, + * two parallel pvscans for each PV create the pvid files for each PV in + * parallel, then both pvscans see the vg has completed, and both pvscans + * activate the VG in parallel. The first pvscan to create the vgname + * file in vgs_online will do the activation, any others will skip it. + */ + + _lock_online(LOCK_EX, 0); + + if (_online_pvid_files_missing()) { + log_verbose("pvscan all devices to initialize available PVs."); + _online_files_remove(_pvs_online_dir); + _online_files_remove(_vgs_online_dir); + _online_pvscan_all_devs(cmd, complete_vgnames, NULL); + _unlock_online(); + goto activate; + } + + _unlock_online(); + log_verbose("pvscan only specific devices add %d rem %d.", + dm_list_size(&add_devs), dm_list_size(&rem_devs)); + + /* + * Unlink online files for devices that no longer have a device node. + * When unlinking a pvid file for dev, we don't need to scan the dev + * (we can't since it's gone), but we know which pvid file it is + * because the major:minor are saved in the pvid files which we can + * read to find the correct one. + */ + dm_list_iterate_items(devl, &rem_devs) + _online_pvid_file_remove_devno((int)MAJOR(devl->dev->dev), (int)MINOR(devl->dev->dev)); + + /* + * Create online files for devices that exist and pass the filter. + * When creating a pvid file for a dev, we have to scan it first + * to know that it's ours and what its pvid is (and which vg it + * belongs to if we want to do autoactivation.) + */ + if (!dm_list_empty(&add_devs)) { + label_scan_devs(cmd, cmd->filter, &add_devs); - dm_list_iterate_items(devl, &single_devs) { + dm_list_iterate_items(devl, &add_devs) { dev = devl->dev; if (dev->flags & DEV_FILTER_OUT_SCAN) @@ -1090,16 +1104,27 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv) add_single_count++; - /* - * Devices that exist and pass the lvmetad filter - * are online. - */ - if (!_online_pvscan_one(cmd, devl->dev, NULL, complete_vgnames, 0, &pvid_without_metadata)) + if (!_online_pvscan_one(cmd, dev, NULL, complete_vgnames, 0, &pvid_without_metadata)) add_errors++; } } -activate: + /* + * After scanning only specific devs to add a device, there is a + * special case that requires us to then scan all devs. That is when + * the dev scanned has no VG metadata, and it's the final device to + * complete the VG. In this case we want to autoactivate the VG, but + * the scanned device does not know what VG it's in or whether that VG + * is now complete. In this case we need to scan all devs and pick out + * the complete VG holding this device so we can then autoactivate that + * VG. + */ + if (!dm_list_empty(&add_devs) && complete_vgnames && dm_list_empty(complete_vgnames) && + pvid_without_metadata && do_activate) { + log_verbose("pvscan all devices for PV without metadata: %s.", pvid_without_metadata); + _online_pvscan_all_devs(cmd, complete_vgnames, &add_devs); + } + /* * When a new PV appears, the system runs pvscan --cache dev. * This also means that existing hints are invalid, and @@ -1110,20 +1135,7 @@ activate: if (add_single_count) invalidate_hints(cmd); - /* - * Special case: pvscan --cache -aay dev - * where dev has no VG metadata, and it's the final device to - * complete the VG. In this case we want to autoactivate the - * VG, but the scanned device does not know what VG it's in or - * whether that VG is now complete. In this case we need to - * scan all devs and pick out the complete VG holding this - * device so we can then autoactivate that VG. - */ - if (!dm_list_empty(&single_devs) && complete_vgnames && dm_list_empty(complete_vgnames) && - pvid_without_metadata && do_activate) { - log_verbose("pvscan all devices for PV without metadata: %s.", pvid_without_metadata); - _online_pvscan_all_devs(cmd, complete_vgnames, &single_devs); - } +activate: /* * Step 2: when the PV was recorded online, we check if all the @@ -1133,7 +1145,6 @@ activate: if (do_activate) ret = _pvscan_aa(cmd, &pp, complete_vgnames); -out: if (add_errors || pp.activate_errors) ret = ECMD_FAILED;