summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/config/config_settings.h3
-rw-r--r--lib/config/defaults.h2
-rw-r--r--lib/device/device.h4
-rw-r--r--lib/device/device_id.c103
-rw-r--r--lib/device/device_id.h2
5 files changed, 112 insertions, 2 deletions
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index b172c7c5f..699b40bd0 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -224,6 +224,9 @@ cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADV
"Directory in which to create volume group device nodes.\n"
"Commands also accept this as a prefix on volume group names.\n")
+cfg(devices_device_id_sysfs_dir_CFG, "device_id_sysfs_dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_UNSUPPORTED, CFG_TYPE_STRING, DEFAULT_DEVICE_ID_SYSFS_DIR, vsn(2, 3, 17), NULL, 0, NULL,
+ "Location of sysfs for finding device ids (for testing.)\n")
+
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
"Directories containing device nodes to use with LVM.\n")
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 3308b1ea6..571054dc4 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -332,4 +332,6 @@
#define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online"
#define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup"
+#define DEFAULT_DEVICE_ID_SYSFS_DIR "/sys/" /* trailing / to match dm_sysfs_dir() */
+
#endif /* _LVM_DEFAULTS_H */
diff --git a/lib/device/device.h b/lib/device/device.h
index 89173a840..ca46490ce 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -67,7 +67,11 @@ struct dev_ext {
#define DEV_ID_TYPE_CRYPT_UUID 6
#define DEV_ID_TYPE_LVMLV_UUID 7
#define DEV_ID_TYPE_DEVNAME 8
+#define DEV_ID_TYPE_WWID_NAA 9
+#define DEV_ID_TYPE_WWID_EUI 10
+#define DEV_ID_TYPE_WWID_T10 11
+/* Max length of WWID_NAA, WWID_EUI, WWID_T10 */
#define DEV_WWID_SIZE 128
/*
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 5481bb6b0..6383f69fb 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -188,13 +188,17 @@ static int _read_sys_block(struct cmd_context *cmd, struct device *dev,
int binary, int *retlen)
{
char path[PATH_MAX];
+ const char *sysfs_dir;
dev_t devt = dev->dev;
dev_t prim = 0;
int ret;
+ if (!(sysfs_dir = find_config_tree_str(cmd, devices_device_id_sysfs_dir_CFG, NULL)))
+ sysfs_dir = dm_sysfs_dir();
+
retry:
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/%s",
- dm_sysfs_dir(), (int)MAJOR(devt), (int)MINOR(devt), suffix) < 0) {
+ sysfs_dir, (int)MAJOR(devt), (int)MINOR(devt), suffix) < 0) {
log_error("Failed to create sysfs path for %s", dev_name(dev));
return 0;
}
@@ -338,6 +342,26 @@ static int _wwid_type_num(char *id)
return -1;
}
+int wwid_type_to_idtype(int wwid_type)
+{
+ switch (wwid_type) {
+ case 3: return DEV_ID_TYPE_WWID_NAA;
+ case 2: return DEV_ID_TYPE_WWID_EUI;
+ case 1: return DEV_ID_TYPE_WWID_T10;
+ default: return -1;
+ }
+}
+
+int idtype_to_wwid_type(int idtype)
+{
+ switch (idtype) {
+ case DEV_ID_TYPE_WWID_NAA: return 3;
+ case DEV_ID_TYPE_WWID_EUI: return 2;
+ case DEV_ID_TYPE_WWID_T10: return 1;
+ default: return -1;
+ }
+}
+
void free_wwids(struct dm_list *ids)
{
struct dev_wwid *dw, *safe;
@@ -436,6 +460,7 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
{
char sysbuf[PATH_MAX] = { 0 };
const char *idname = NULL;
+ struct dev_wwid *dw;
int i;
if (idtype == DEV_ID_TYPE_SYS_WWID) {
@@ -485,6 +510,18 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
return idname;
}
+ else if (idtype == DEV_ID_TYPE_WWID_NAA ||
+ idtype == DEV_ID_TYPE_WWID_EUI ||
+ idtype == DEV_ID_TYPE_WWID_T10) {
+ if (!(dev->flags & DEV_ADDED_VPD_WWIDS))
+ dev_read_vpd_wwids(cmd, dev);
+ dm_list_iterate_items(dw, &dev->wwids) {
+ if (idtype_to_wwid_type(idtype) == dw->type)
+ return strdup(dw->id);
+ }
+ return NULL;
+ }
+
/* wwids are already munged if needed */
if (idtype != DEV_ID_TYPE_SYS_WWID) {
for (i = 0; i < strlen(sysbuf); i++) {
@@ -591,6 +628,12 @@ const char *idtype_to_str(uint16_t idtype)
return "md_uuid";
if (idtype == DEV_ID_TYPE_LOOP_FILE)
return "loop_file";
+ if (idtype == DEV_ID_TYPE_WWID_NAA)
+ return "wwid_naa";
+ if (idtype == DEV_ID_TYPE_WWID_EUI)
+ return "wwid_eui";
+ if (idtype == DEV_ID_TYPE_WWID_T10)
+ return "wwid_t10";
return "unknown";
}
@@ -612,6 +655,12 @@ uint16_t idtype_from_str(const char *str)
return DEV_ID_TYPE_MD_UUID;
if (!strcmp(str, "loop_file"))
return DEV_ID_TYPE_LOOP_FILE;
+ if (!strcmp(str, "wwid_naa"))
+ return DEV_ID_TYPE_WWID_NAA;
+ if (!strcmp(str, "wwid_eui"))
+ return DEV_ID_TYPE_WWID_EUI;
+ if (!strcmp(str, "wwid_t10"))
+ return DEV_ID_TYPE_WWID_T10;
return 0;
}
@@ -1202,13 +1251,26 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
/*
* No device-specific, existing, or user-specified idtypes,
- * so use first available of sys_wwid / sys_serial / devname.
+ * so use first available of sys_wwid, wwid_naa, wwid_eui,
+ * wwid_t10, sys_serial, devname.
*/
idtype = DEV_ID_TYPE_SYS_WWID;
if ((idname = device_id_system_read(cmd, dev, idtype)))
goto id_done;
+ idtype = DEV_ID_TYPE_WWID_NAA;
+ if ((idname = device_id_system_read(cmd, dev, idtype)))
+ goto id_done;
+
+ idtype = DEV_ID_TYPE_WWID_EUI;
+ if ((idname = device_id_system_read(cmd, dev, idtype)))
+ goto id_done;
+
+ idtype = DEV_ID_TYPE_WWID_T10;
+ if ((idname = device_id_system_read(cmd, dev, idtype)))
+ goto id_done;
+
idtype = DEV_ID_TYPE_SYS_SERIAL;
if ((idname = device_id_system_read(cmd, dev, idtype)))
goto id_done;
@@ -1731,6 +1793,43 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
idtype_to_str(du->idtype), du->idname ?: ".", dev_name(dev), idname ?: ".");
*/
+ /*
+ * Make the du match this device if the dev has a vpd_pg83 wwid
+ * that matches du->idname, even if the sysfs wwid for dev did
+ * not match the du->idname. This could happen if sysfs changes
+ * which wwid it reports (there are often multiple), or if lvm in
+ * the future selects a sys_wwid value from vpd_pg83 data rather
+ * than from the sysfs wwid.
+ *
+ * TODO: update the df entry IDTYPE somewhere?
+ */
+ if (du->idtype == DEV_ID_TYPE_SYS_WWID) {
+ struct dev_wwid *dw;
+
+ if (!(dev->flags & DEV_ADDED_VPD_WWIDS))
+ dev_read_vpd_wwids(cmd, dev);
+
+ dm_list_iterate_items(dw, &dev->wwids) {
+ if (!strcmp(dw->id, du->idname)) {
+ if (!(id = zalloc(sizeof(struct dev_id))))
+ return_0;
+ /* wwid types are 1,2,3 and idtypes are DEV_ID_TYPE_ */
+ id->idtype = wwid_type_to_idtype(dw->type);
+ id->idname = strdup(dw->id);
+ id->dev = dev;
+ dm_list_add(&dev->ids, &id->list);
+ du->dev = dev;
+ dev->id = id;
+ dev->flags |= DEV_MATCHED_USE_ID;
+ log_print("Match device_id %s %s to vpd_pg83 %s %s",
+ idtype_to_str(du->idtype), du->idname,
+ idtype_to_str(id->idtype), dev_name(dev));
+ du->idtype = id->idtype;
+ return 1;
+ }
+ }
+ }
+
return 0;
}
diff --git a/lib/device/device_id.h b/lib/device/device_id.h
index 46ab33784..6962925df 100644
--- a/lib/device/device_id.h
+++ b/lib/device/device_id.h
@@ -63,6 +63,8 @@ int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out);
+int wwid_type_to_idtype(int wwid_type);
+int idtype_to_wwid_type(int idtype);
void free_wwids(struct dm_list *ids);
struct dev_wwid *dev_add_wwid(char *id, int id_type, struct dm_list *ids);
int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev);