summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile.in1
-rw-r--r--lib/device/dev-cache.c18
-rw-r--r--lib/device/dev-cache.h1
-rw-r--r--lib/device/dev-mpath.c232
-rw-r--r--lib/device/device.h13
-rw-r--r--lib/device/device_id.c31
-rw-r--r--lib/device/device_id.h2
-rw-r--r--lib/device/parse_vpd.c199
8 files changed, 454 insertions, 43 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 8b3eac60a..3077825d2 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -40,6 +40,7 @@ SOURCES =\
device/dev-luks.c \
device/dev-dasd.c \
device/dev-lvm1-pool.c \
+ device/parse_vpd.c \
display/display.c \
error/errseg.c \
unknown/unknown.c \
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 0eb2568b5..65e1cb138 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -80,6 +80,7 @@ static void _dev_init(struct device *dev)
dm_list_init(&dev->aliases);
dm_list_init(&dev->ids);
+ dm_list_init(&dev->wwids);
}
void dev_destroy_file(struct device *dev)
@@ -383,6 +384,22 @@ out:
return 1;
}
+int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen)
+{
+ int ret;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ ret = read(fd, buf, buf_size);
+ close(fd);
+ if (ret <= 0)
+ return 0;
+ *retlen = ret;
+ return 1;
+}
+
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
{
FILE *fp;
@@ -1336,6 +1353,7 @@ int dev_cache_exit(void)
dm_hash_iterate(n, _cache.names) {
dev = (struct device *) dm_hash_get_data(_cache.names, n);
free_dids(&dev->ids);
+ free_wwids(&dev->wwids);
}
}
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 321a56d7b..c49e6265d 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -74,6 +74,7 @@ void dev_cache_failed_path(struct device *dev, const char *path);
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
+int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen);
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd);
diff --git a/lib/device/dev-mpath.c b/lib/device/dev-mpath.c
index 7abbfb289..3795c992d 100644
--- a/lib/device/dev-mpath.c
+++ b/lib/device/dev-mpath.c
@@ -200,11 +200,12 @@ static void _read_wwid_exclusions(void)
log_debug("multipath config ignored %d wwids", rem_count);
}
-static void _read_wwid_file(const char *config_wwids_file)
+static void _read_wwid_file(const char *config_wwids_file, int *entries)
{
FILE *fp;
char line[MAX_WWID_LINE];
char *wwid, *p;
+ char typestr[2] = { 0 };
int count = 0;
if (config_wwids_file[0] != '/') {
@@ -226,8 +227,17 @@ static void _read_wwid_file(const char *config_wwids_file)
if (line[0] == '/')
wwid++;
- /* skip the initial '3' */
- wwid++;
+
+ /*
+ * the initial character is the id type,
+ * 1 is t10, 2 is eui, 3 is naa, 8 is scsi name.
+ * wwids are stored in the hash table without the type charater.
+ * It seems that sometimes multipath does not include
+ * the type charater (seen with t10 scsi_debug devs).
+ */
+ typestr[0] = *wwid;
+ if (typestr[0] == '1' || typestr[0] == '2' || typestr[0] == '3')
+ wwid++;
if ((p = strchr(wwid, '/')))
*p = '\0';
@@ -240,6 +250,7 @@ static void _read_wwid_file(const char *config_wwids_file)
stack;
log_debug("multipath wwids read %d from %s", count, config_wwids_file);
+ *entries = count;
}
int dev_mpath_init(const char *config_wwids_file)
@@ -247,6 +258,7 @@ int dev_mpath_init(const char *config_wwids_file)
struct dm_pool *mem;
struct dm_hash_table *minor_tab;
struct dm_hash_table *wwid_tab;
+ int entries = 0;
dm_list_init(&_ignored);
dm_list_init(&_ignored_exceptions);
@@ -283,10 +295,16 @@ int dev_mpath_init(const char *config_wwids_file)
_wwid_hash_tab = wwid_tab;
if (config_wwids_file) {
- _read_wwid_file(config_wwids_file);
+ _read_wwid_file(config_wwids_file, &entries);
_read_wwid_exclusions();
}
+ if (!entries) {
+ /* reading dev wwids is skipped with null wwid_hash_tab */
+ dm_hash_destroy(_wwid_hash_tab);
+ _wwid_hash_tab = NULL;
+ }
+
return 1;
}
@@ -432,10 +450,10 @@ static int _dev_is_mpath_component_udev(struct device *dev)
}
#endif
-static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev)
+static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev,
+ int primary_result, dev_t primary_dev)
{
struct dev_types *dt = cmd->dev_types;
- const char *part_name;
const char *name; /* e.g. "sda" for "/dev/sda" */
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
@@ -449,25 +467,15 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
int dm_dev_major;
int dm_dev_minor;
struct stat info;
- dev_t primary_dev;
int is_mpath_component = 0;
- /* multipathing is only known to exist for SCSI or NVME devices */
- if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
- return 0;
-
- switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
+ switch (primary_result) {
case 2: /* The dev is partition. */
- part_name = dev_name(dev); /* name of original dev for log_debug msg */
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
-
- log_debug_devs("%s: Device is a partition, using primary "
- "device %s for mpath component detection",
- part_name, name);
break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */
@@ -589,47 +597,189 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
return is_mpath_component;
}
-static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev)
+static int _read_sys_wwid(struct cmd_context *cmd, struct device *dev,
+ char *idbuf, int idbufsize)
{
- char sysbuf[PATH_MAX] = { 0 };
- char *wwid;
- long look;
+ char idtmp[DEV_WWID_SIZE];
- if (!_wwid_hash_tab)
+ if (!read_sys_block(cmd, dev, "device/wwid", idbuf, idbufsize)) {
+ /* the wwid file is not under device for nvme devs */
+ if (!read_sys_block(cmd, dev, "wwid", idbuf, idbufsize))
+ return 0;
+ }
+ if (!idbuf[0])
return 0;
- if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
+ /* in t10 id, replace series of spaces with one _ like multipath */
+ if (!strncmp(idbuf, "t10.", 4) && strchr(idbuf, ' ')) {
+ if (idbufsize < DEV_WWID_SIZE)
+ return 0;
+ memcpy(idtmp, idbuf, DEV_WWID_SIZE);
+ memset(idbuf, 0, idbufsize);
+ format_t10_id((const unsigned char *)idtmp, DEV_WWID_SIZE, (unsigned char *)idbuf, idbufsize);
+ }
+ return 1;
+}
+
+#define VPD_SIZE 4096
+
+static int _read_sys_vpd_wwids(struct cmd_context *cmd, struct device *dev,
+ struct dm_list *ids)
+{
+ unsigned char vpd_data[VPD_SIZE] = { 0 };
+ int vpd_datalen = 0;
+
+ if (!read_sys_block_binary(cmd, dev, "device/vpd_pg83", (char *)vpd_data, VPD_SIZE, &vpd_datalen))
+ return 0;
+ if (!vpd_datalen)
return 0;
- if (!sysbuf[0])
+ /* adds dev_wwid entry to dev->wwids for each id in vpd data */
+ parse_vpd_ids(vpd_data, vpd_datalen, ids);
+ return 1;
+}
+
+void free_wwids(struct dm_list *ids)
+{
+ struct dev_wwid *dw, *safe;
+
+ dm_list_iterate_items_safe(dw, safe, ids) {
+ dm_list_del(&dw->list);
+ free(dw);
+ }
+}
+
+static int _wwid_type_num(char *id)
+{
+ if (!strncmp(id, "naa.", 4))
+ return 3;
+ else if (!strncmp(id, "eui.", 4))
+ return 2;
+ else if (!strncmp(id, "t10.", 4))
+ return 1;
+ else
+ return -1;
+}
+
+/*
+ * TODO: if each of the different wwid types (naa/eui/t10) were
+ * represented by different DEV_ID_TYPE_FOO values, and used
+ * as device_id types, then we could drop struct dev_wwid and
+ * drop dev->wwids, and just use dev->ids for each of the
+ * different wwids found in vpd_pg83. This would also require
+ * the ability to handle both the original method of replacing
+ * every space in the id string with _ and the new/multipath
+ * format_t10_id replacing series of spaces with one _.
+ */
+struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids)
+{
+ struct dev_wwid *dw;
+ int len;
+
+ if (!id_type) {
+ id_type = _wwid_type_num(id);
+ if (id_type == -1)
+ log_debug("unknown wwid type %s", id);
+ }
+
+ if (!(dw = zalloc(sizeof(struct dev_wwid))))
+ return NULL;
+ len = strlen(id);
+ if (len >= DEV_WWID_SIZE)
+ len = DEV_WWID_SIZE - 1;
+ memcpy(dw->id, id, len);
+ dw->type = id_type;
+ dm_list_add(ids, &dw->list);
+ return dw;
+}
+
+/*
+ * we save ids with format: naa.<value>, eui.<value>, t10.<value>.
+ * multipath wwids file uses format: 3<value>, 2<value>, 1<value>.
+ * The values are saved in wwid_hash_tab without the type prefix.
+ */
+
+static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev,
+ int primary_result, dev_t primary_dev)
+{
+ char idbuf[DEV_WWID_SIZE] = { 0 };
+ struct dev_wwid *dw;
+ char *wwid;
+
+ if (!_wwid_hash_tab)
return 0;
/*
- * sysfs prints wwid as <typestr>.<value>
- * multipath wwid uses '3'<value>
- * does "<typestr>." always correspond to "3"?
+ * Check the primary device, not the partition.
*/
- if (!(wwid = strchr(sysbuf, '.')))
- return 0;
+ if (primary_result == 2) {
+ if (!(dev = dev_cache_get_by_devt(cmd, primary_dev))) {
+ log_debug("dev_is_mpath_component %s no primary dev", dev_name(dev));
+ return 0;
+ }
+ }
- /* skip the type and dot, just as '3' was skipped from wwids entry */
- wwid++;
-
- look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid));
+ /*
+ * This function may be called multiple times for the same device, in
+ * particular if partitioned for each partition.
+ */
+ if (!dm_list_empty(&dev->wwids))
+ goto lookup;
- if (look) {
- log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid);
- return 1;
+ /*
+ * Get all the ids for the device from vpd_pg83 and check if any of
+ * those are in /etc/multipath/wwids. These ids should include the
+ * value printed from the sysfs wwid file.
+ */
+ _read_sys_vpd_wwids(cmd, dev, &dev->wwids);
+ if (!dm_list_empty(&dev->wwids))
+ goto lookup;
+
+ /*
+ * This will read the sysfs wwid file, nvme devices in particular have
+ * a wwid file but not a vpd_pg83 file.
+ */
+ if (_read_sys_wwid(cmd, dev, idbuf, sizeof(idbuf)))
+ add_wwid(idbuf, 0, &dev->wwids);
+
+ lookup:
+ dm_list_iterate_items(dw, &dev->wwids) {
+ if (dw->type == 1 || dw->type == 2 || dw->type == 3)
+ wwid = &dw->id[4];
+ else
+ wwid = dw->id;
+
+ if (dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid))) {
+ log_debug_devs("dev_is_mpath_component %s %s in wwids file", dev_name(dev), dw->id);
+ return 1;
+ }
}
+
return 0;
}
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev)
{
- if (_dev_is_mpath_component_sysfs(cmd, dev) == 1)
+ struct dev_types *dt = cmd->dev_types;
+ int primary_result;
+ dev_t primary_dev;
+
+ /*
+ * multipath only uses SCSI or NVME devices
+ */
+ if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dt, dev))
+ return 0;
+
+ /*
+ * primary_result 2: dev is a partition, primary_dev is the whole device
+ * primary_result 1: dev is a whole device
+ */
+ primary_result = dev_get_primary_dev(dt, dev, &primary_dev);
+
+ if (_dev_is_mpath_component_sysfs(cmd, dev, primary_result, primary_dev) == 1)
goto found;
- if (_dev_in_wwid_file(cmd, dev))
+ if (_dev_in_wwid_file(cmd, dev, primary_result, primary_dev))
goto found;
if (external_device_info_source() == DEV_EXT_UDEV) {
@@ -637,6 +787,12 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev)
goto found;
}
+ /*
+ * TODO: save the result of this function in dev->flags and use those
+ * flags on repeated calls to avoid repeating the work multiple times
+ * for the same device when there are partitions on the device.
+ */
+
return 0;
found:
return 1;
diff --git a/lib/device/device.h b/lib/device/device.h
index 572994bb9..1c85f37a9 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -59,6 +59,14 @@ struct dev_ext {
void *handle;
};
+#define DEV_WWID_SIZE 128
+
+struct dev_wwid {
+ struct dm_list list;
+ int type;
+ char id[DEV_WWID_SIZE];
+};
+
#define DEV_ID_TYPE_SYS_WWID 0x0001
#define DEV_ID_TYPE_SYS_SERIAL 0x0002
#define DEV_ID_TYPE_MPATH_UUID 0x0003
@@ -105,6 +113,7 @@ struct dev_use {
*/
struct device {
struct dm_list aliases; /* struct dm_str_list */
+ struct dm_list wwids; /* struct dev_wwid, used for multipath component detection */
struct dm_list ids; /* struct dev_id, different entries for different idtypes */
struct dev_id *id; /* points to the the ids entry being used for this dev */
dev_t dev;
@@ -206,5 +215,9 @@ void dev_destroy_file(struct device *dev);
int dev_mpath_init(const char *config_wwids_file);
void dev_mpath_exit(void);
+struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids);
+void free_wwids(struct dm_list *ids);
+int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids);
+int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes);
#endif
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index 20901ab90..4d8fa5c9c 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -182,7 +182,9 @@ void free_dids(struct dm_list *ids)
}
}
-int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize)
+static int _read_sys_block(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize,
+ int binary, int *retlen)
{
char path[PATH_MAX];
dev_t devt = dev->dev;
@@ -196,11 +198,17 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
return 0;
}
- get_sysfs_value(path, sysbuf, sysbufsize, 0);
+ if (binary) {
+ ret = get_sysfs_binary(path, sysbuf, sysbufsize, retlen);
+ if (ret && !*retlen)
+ ret = 0;
+ } else {
+ ret = get_sysfs_value(path, sysbuf, sysbufsize, 0);
+ if (ret && !sysbuf[0])
+ ret = 0;
+ }
- if (sysbuf[0]) {
- if (prim)
- log_debug("Using primary device_id for partition %s.", dev_name(dev));
+ if (ret) {
sysbuf[sysbufsize - 1] = '\0';
return 1;
}
@@ -220,6 +228,19 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
return 0;
}
+int read_sys_block(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize)
+{
+ return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 0, NULL);
+}
+
+int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize,
+ int *retlen)
+{
+ return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 1, retlen);
+}
+
static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix)
{
if (!strncmp(sysbuf, prefix, strlen(prefix)))
diff --git a/lib/device/device_id.h b/lib/device/device_id.h
index 2cd2fd7c6..e049e2333 100644
--- a/lib/device/device_id.h
+++ b/lib/device/device_id.h
@@ -55,6 +55,8 @@ void devices_file_exit(struct cmd_context *cmd);
void unlink_searched_devnames(struct cmd_context *cmd);
int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize);
+int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
+ const char *suffix, char *sysbuf, int sysbufsize, int *retlen);
int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out);
diff --git a/lib/device/parse_vpd.c b/lib/device/parse_vpd.c
new file mode 100644
index 000000000..4bafa7b9e
--- /dev/null
+++ b/lib/device/parse_vpd.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "base/memory/zalloc.h"
+#include "lib/misc/lib.h"
+#include "lib/device/device.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <limits.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <assert.h>
+
+/*
+ * Replace series of spaces with a single _.
+ */
+int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes)
+{
+ int in_space = 0;
+ int retlen = 0;
+ int j = 0;
+ int i;
+
+ for (i = 0; i < in_bytes; i++) {
+ if (!in[i])
+ break;
+ if (j >= (out_bytes - 2))
+ break;
+ /* skip leading spaces */
+ if (!retlen && (in[i] == ' '))
+ continue;
+ /* replace one or more spaces with _ */
+ if (in[i] == ' ') {
+ in_space = 1;
+ continue;
+ }
+ /* spaces are finished so insert _ */
+ if (in_space) {
+ out[j++] = '_';
+ in_space = 0;
+ retlen++;
+ }
+ out[j++] = in[i];
+ retlen++;
+ }
+ return retlen;
+}
+
+static int _to_hex(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes)
+{
+ int off = 0;
+ int num;
+ int i;
+
+ for (i = 0; i < in_bytes; i++) {
+ num = sprintf((char *)out + off, "%02x", in[i]);
+ if (num < 0)
+ break;
+ off += num;
+ if (off + 2 >= out_bytes)
+ break;
+ }
+ return off;
+}
+
+#define ID_BUFSIZE 1024
+
+/*
+ * based on linux kernel function
+ */
+int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids)
+{
+ char id[ID_BUFSIZE];
+ unsigned char tmp_str[ID_BUFSIZE];
+ const unsigned char *d, *cur_id_str;
+ size_t id_len = ID_BUFSIZE;
+ int id_size = -1;
+ uint8_t cur_id_size = 0;
+
+ memset(id, 0, ID_BUFSIZE);
+ for (d = vpd_data + 4;
+ d < vpd_data + vpd_datalen;
+ d += d[3] + 4) {
+ memset(tmp_str, 0, sizeof(tmp_str));
+
+ switch (d[1] & 0xf) {
+ case 0x1:
+ /* T10 Vendor ID */
+ cur_id_size = d[3];
+ if (cur_id_size + 4 > id_len)
+ cur_id_size = id_len - 4;
+ cur_id_str = d + 4;
+ format_t10_id(cur_id_str, cur_id_size, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "t10.%s", tmp_str);
+ if (id_size < 0)
+ break;
+ if (id_size >= ID_BUFSIZE)
+ id_size = ID_BUFSIZE - 1;
+ add_wwid(id, 1, ids);
+ break;
+ case 0x2:
+ /* EUI-64 */
+ cur_id_size = d[3];
+ cur_id_str = d + 4;
+ switch (cur_id_size) {
+ case 8:
+ _to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
+ break;
+ case 12:
+ _to_hex(cur_id_str, 12, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
+ break;
+ case 16:
+ _to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
+ break;
+ default:
+ break;
+ }
+ if (id_size < 0)
+ break;
+ if (id_size >= ID_BUFSIZE)
+ id_size = ID_BUFSIZE - 1;
+ add_wwid(id, 2, ids);
+ break;
+ case 0x3:
+ /* NAA */
+ cur_id_size = d[3];
+ cur_id_str = d + 4;
+ switch (cur_id_size) {
+ case 8:
+ _to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str);
+ break;
+ case 16:
+ _to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str));
+ id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str);
+ break;
+ default:
+ break;
+ }
+ if (id_size < 0)
+ break;
+ if (id_size >= ID_BUFSIZE)
+ id_size = ID_BUFSIZE - 1;
+ add_wwid(id, 3, ids);
+ break;
+ case 0x8:
+ /* SCSI name string */
+ cur_id_size = d[3];
+ cur_id_str = d + 4;
+ if (cur_id_size >= id_len)
+ cur_id_size = id_len - 1;
+ memcpy(id, cur_id_str, cur_id_size);
+ id_size = cur_id_size;
+
+ /*
+ * Not in the kernel version, copying multipath code,
+ * which checks if this string begins with naa or eui
+ * and if so does tolower() on the chars.
+ */
+ if (!strncmp(id, "naa.", 4) || !strncmp(id, "eui.", 4)) {
+ int i;
+ for (i = 0; i < id_size; i++)
+ id[i] = tolower(id[i]);
+ }
+ add_wwid(id, 8, ids);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return id_size;
+}