diff --git a/lib/label/label.c b/lib/label/label.c index d506b81e3..5c77a6923 100644 --- a/lib/label/label.c +++ b/lib/label/label.c @@ -1021,6 +1021,35 @@ int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev return ret; } +/* + * Clear state that label_scan_vg_online() created so it will not + * confuse the standard label_scan() that the caller falls back to. + * the results of filtering (call filter->wipe) + * the results of matching device_id (reset dev and du) + * the results of scanning in lvmcache + */ +static void _clear_scan_state(struct cmd_context *cmd, struct dm_list *devs) +{ + struct device_list *devl; + struct device *dev; + struct dev_use *du; + + dm_list_iterate_items(devl, devs) { + dev = devl->dev; + + cmd->filter->wipe(cmd, cmd->filter, dev, NULL); + dev->flags &= ~DEV_MATCHED_USE_ID; + dev->id = NULL; + + if ((du = get_du_for_dev(cmd, dev))) + du->dev = NULL; + + lvmcache_del_dev(dev); + + memset(dev->pvid, 0, ID_LEN); + } +} + /* * Use files under /run/lvm/, created by pvscan --cache autoactivation, * to optimize device setup/scanning. autoactivation happens during @@ -1033,6 +1062,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, { struct dm_list pvs_online; struct dm_list devs; + struct dm_list devs_drop; struct pv_online *po; struct device_list *devl, *devl2; int relax_deviceid_filter = 0; @@ -1041,6 +1071,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, dm_list_init(&pvs_online); dm_list_init(&devs); + dm_list_init(&devs_drop); log_debug_devs("Finding online devices to scan"); @@ -1116,6 +1147,15 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, * factor code common to pvscan_cache_args */ + /* + * Match devs with the devices file because special/optimized + * device setup was used which does not check the devices file. + * If a match fails here do not exclude it, that will be done below by + * passes_filter() which runs filter-deviceid. The + * relax_deviceid_filter case needs to be able to work around + * unmatching devs. + */ + if (cmd->enable_devices_file) { dm_list_iterate_items(devl, &devs) device_ids_match_dev(cmd, devl->dev); @@ -1127,6 +1167,8 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, if (cmd->enable_devices_file && device_ids_use_devname(cmd)) { relax_deviceid_filter = 1; cmd->filter_deviceid_skip = 1; + /* PVIDs read from devs matched to devices file below instead. */ + log_debug("Skipping device_id filtering due to devname ids."); } cmd->filter_nodata_only = 1; @@ -1136,6 +1178,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, log_print("%s excluded by filters: %s.", dev_name(devl->dev), dev_filtered_reason(devl->dev)); dm_list_del(&devl->list); + dm_list_add(&devs_drop, &devl->list); } } @@ -1160,11 +1203,13 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, label_scan_setup_bcache(); dm_list_iterate_items_safe(devl, devl2, &devs) { + struct dev_use *du; int has_pvid; if (!label_read_pvid(devl->dev, &has_pvid)) { log_print("%s cannot read label.", dev_name(devl->dev)); dm_list_del(&devl->list); + dm_list_add(&devs_drop, &devl->list); continue; } @@ -1172,6 +1217,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, /* Not an lvm device */ log_print("%s not an lvm device.", dev_name(devl->dev)); dm_list_del(&devl->list); + dm_list_add(&devs_drop, &devl->list); continue; } @@ -1180,11 +1226,16 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, * so in place of that check if the pvid is in the devices file. */ if (relax_deviceid_filter) { - if (!get_du_for_pvid(cmd, devl->dev->pvid)) { + if (!(du = get_du_for_pvid(cmd, devl->dev->pvid))) { log_print("%s excluded by devices file (checking PVID).", dev_name(devl->dev)); dm_list_del(&devl->list); + dm_list_add(&devs_drop, &devl->list); continue; + } else { + /* Special case matching for devname entries based on pvid. */ + log_debug("Match device_id %s %s to %s: matching PVID", + idtype_to_str(du->idtype), du->idname, dev_name(devl->dev)); } } @@ -1193,6 +1244,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, log_print("%s excluded by filters: %s.", dev_name(devl->dev), dev_filtered_reason(devl->dev)); dm_list_del(&devl->list); + dm_list_add(&devs_drop, &devl->list); } } @@ -1202,6 +1254,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, free_po_list(&pvs_online); if (dm_list_empty(&devs)) { + _clear_scan_state(cmd, &devs_drop); *found_none = 1; return 1; } @@ -1227,6 +1280,8 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, if (metadata_pv_count > dm_list_size(&devs)) { log_debug("Incomplete PV list from online files %d metadata %d.", dm_list_size(&devs), metadata_pv_count); + _clear_scan_state(cmd, &devs_drop); + _clear_scan_state(cmd, &devs); *found_incomplete = 1; return 1; } @@ -1235,6 +1290,8 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname, *found_all = 1; return 1; bad: + _clear_scan_state(cmd, &devs_drop); + _clear_scan_state(cmd, &devs); free_po_list(&pvs_online); return 0; } @@ -1527,7 +1584,7 @@ int label_read_pvid(struct device *dev, int *has_pvid) lh = (struct label_header *)(buf + 512); if (memcmp(lh->id, LABEL_ID, sizeof(lh->id))) { - /* Not an lvm deice */ + /* Not an lvm device */ label_scan_invalidate(dev); return 1; } @@ -1537,7 +1594,7 @@ int label_read_pvid(struct device *dev, int *has_pvid) * rest of the label_header intact. */ if (memcmp(lh->type, LVM2_LABEL, sizeof(lh->type))) { - /* Not an lvm deice */ + /* Not an lvm device */ label_scan_invalidate(dev); return 1; } diff --git a/tools/vgchange.c b/tools/vgchange.c index 5eebc9ae9..fc076c1d5 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -802,7 +802,7 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd, */ if (!label_scan_vg_online(cmd, vgname, &found_none, &found_all, &found_incomplete)) { log_print("PVs online error%s%s, using all devices.", vgname ? " for VG " : "", vgname ?: ""); - return 1; + goto bad; } /* @@ -815,9 +815,11 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd, } /* - * The expected and optimal usage, because the udev rule calls - * vgchange -aay --autoactivation event vgname when all PVs - * for vgname are found online. Only online pvs are used. + * The expected and optimal usage, which is the purpose of + * this function. We expect online files to be found for + * all PVs because the udev rule calls + * vgchange -aay --autoactivation event + * only after all PVs for vgname are found online. */ if (found_all) { *flags |= PROCESS_SKIP_SCAN; @@ -825,16 +827,6 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd, return 1; } - /* - * The online scanning optimiziation didn't work, so undo the vg - * locking optimization before falling back to normal processing. - */ - if (vg_locked) { - unlock_vg(cmd, NULL, vgname); - *flags &= ~READ_WITHOUT_LOCK; - cmd->can_use_one_scan = 0; - } - /* * Not expected usage, no online pvs for the vgname were found. The * caller will fall back to process_each doing a full label_scan to @@ -842,7 +834,7 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd, */ if (found_none) { log_print("PVs online not found for VG %s, using all devices.", vgname); - return 1; + goto bad; } /* @@ -852,7 +844,7 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd, */ if (found_incomplete) { log_print("PVs online incomplete for VG %s, using all devicess.", vgname); - return 1; + goto bad; } /* @@ -860,7 +852,19 @@ static int _vgchange_autoactivation_setup(struct cmd_context *cmd, * process_each. (No optimization used.) */ log_print("PVs online unknown for VG %s, using all devices.", vgname); + + bad: + /* + * The online scanning optimization didn't work, so undo the vg + * locking optimization before falling back to normal processing. + */ + if (vg_locked) { + unlock_vg(cmd, NULL, vgname); + *flags &= ~READ_WITHOUT_LOCK; + cmd->can_use_one_scan = 0; + } return 1; + } int vgchange(struct cmd_context *cmd, int argc, char **argv)