summaryrefslogtreecommitdiff
path: root/lib/cache/lvmcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cache/lvmcache.c')
-rw-r--r--lib/cache/lvmcache.c72
1 files changed, 67 insertions, 5 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index b1d05fb07..f5cd68aa7 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -18,6 +18,7 @@
#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"
@@ -491,6 +492,25 @@ 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.
@@ -596,6 +616,8 @@ 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;
@@ -604,6 +626,7 @@ 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;
@@ -734,6 +757,19 @@ 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;
@@ -752,6 +788,12 @@ 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,
@@ -792,6 +834,13 @@ 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";
@@ -1024,13 +1073,15 @@ 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);
+
log_debug_cache("Finding VG info");
/*
@@ -1043,14 +1094,25 @@ 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:
*
* . del_cache_devs: a list of devs currently in lvmcache that should