1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

filter-mpath: get wwids from sysfs vpd_pg83

to compare with wwids in /etc/multipath/wwids when
excluding multipath components.  The wwid printed
from the sysfs wwid file may not be the wwid used
in multipath wwids.  Save the wwids found for each
device on dev->wwids to avoid repeating reading
and parsing the sysfs files.
This commit is contained in:
David Teigland 2022-06-06 14:04:20 -05:00
parent 2bea95764e
commit 3b0f9cec7e
8 changed files with 455 additions and 44 deletions

View File

@ -41,6 +41,7 @@ SOURCES =\
device/dev-dasd.c \ device/dev-dasd.c \
device/dev-lvm1-pool.c \ device/dev-lvm1-pool.c \
device/online.c \ device/online.c \
device/parse_vpd.c \
display/display.c \ display/display.c \
error/errseg.c \ error/errseg.c \
unknown/unknown.c \ unknown/unknown.c \

View File

@ -80,6 +80,7 @@ static void _dev_init(struct device *dev)
dm_list_init(&dev->aliases); dm_list_init(&dev->aliases);
dm_list_init(&dev->ids); dm_list_init(&dev->ids);
dm_list_init(&dev->wwids);
} }
void dev_destroy_file(struct device *dev) void dev_destroy_file(struct device *dev)
@ -383,6 +384,22 @@ out:
return 1; 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) int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
{ {
FILE *fp; FILE *fp;
@ -1336,6 +1353,7 @@ int dev_cache_exit(void)
dm_hash_iterate(n, _cache.names) { dm_hash_iterate(n, _cache.names) {
dev = (struct device *) dm_hash_get_data(_cache.names, n); dev = (struct device *) dm_hash_get_data(_cache.names, n);
free_dids(&dev->ids); free_dids(&dev->ids);
free_wwids(&dev->wwids);
} }
} }

View File

@ -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); 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_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 get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd); int setup_devices_file(struct cmd_context *cmd);

View File

@ -200,11 +200,12 @@ static void _read_wwid_exclusions(void)
log_debug("multipath config ignored %d wwids", rem_count); 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; FILE *fp;
char line[MAX_WWID_LINE]; char line[MAX_WWID_LINE];
char *wwid, *p; char *wwid, *p;
char typestr[2] = { 0 };
int count = 0; int count = 0;
if (config_wwids_file[0] != '/') { if (config_wwids_file[0] != '/') {
@ -226,8 +227,17 @@ static void _read_wwid_file(const char *config_wwids_file)
if (line[0] == '/') if (line[0] == '/')
wwid++; 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, '/'))) if ((p = strchr(wwid, '/')))
*p = '\0'; *p = '\0';
@ -240,6 +250,7 @@ static void _read_wwid_file(const char *config_wwids_file)
stack; stack;
log_debug("multipath wwids read %d from %s", count, config_wwids_file); log_debug("multipath wwids read %d from %s", count, config_wwids_file);
*entries = count;
} }
int dev_mpath_init(const char *config_wwids_file) 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_pool *mem;
struct dm_hash_table *minor_tab; struct dm_hash_table *minor_tab;
struct dm_hash_table *wwid_tab; struct dm_hash_table *wwid_tab;
int entries = 0;
dm_list_init(&_ignored); dm_list_init(&_ignored);
dm_list_init(&_ignored_exceptions); dm_list_init(&_ignored_exceptions);
@ -283,10 +295,16 @@ int dev_mpath_init(const char *config_wwids_file)
_wwid_hash_tab = wwid_tab; _wwid_hash_tab = wwid_tab;
if (config_wwids_file) { if (config_wwids_file) {
_read_wwid_file(config_wwids_file); _read_wwid_file(config_wwids_file, &entries);
_read_wwid_exclusions(); _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; return 1;
} }
@ -434,10 +452,10 @@ static int _dev_is_mpath_component_udev(struct device *dev)
/* mpath_devno is major:minor of the dm multipath device currently using the component dev. */ /* mpath_devno is major:minor of the dm multipath device currently using the component dev. */
static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev, dev_t *mpath_devno) static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev,
int primary_result, dev_t primary_dev, dev_t *mpath_devno)
{ {
struct dev_types *dt = cmd->dev_types; struct dev_types *dt = cmd->dev_types;
const char *part_name;
const char *name; /* e.g. "sda" for "/dev/sda" */ const char *name; /* e.g. "sda" for "/dev/sda" */
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */ char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */ char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
@ -451,25 +469,15 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
int dm_dev_major; int dm_dev_major;
int dm_dev_minor; int dm_dev_minor;
struct stat info; struct stat info;
dev_t primary_dev;
int is_mpath_component = 0; int is_mpath_component = 0;
/* multipathing is only known to exist for SCSI or NVME devices */ switch (primary_result) {
if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
return 0;
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
case 2: /* The dev is partition. */ 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 */ /* 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)))) if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0; return_0;
log_debug_devs("%s: Device is a partition, using primary "
"device %s for mpath component detection",
part_name, name);
break; break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */ case 1: /* The dev is already a primary dev. Just continue with the dev. */
@ -593,47 +601,189 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
return is_mpath_component; 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 idtmp[DEV_WWID_SIZE];
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;
/* 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;
/* 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; char *wwid;
long look;
if (!_wwid_hash_tab) if (!_wwid_hash_tab)
return 0; return 0;
if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf))) /*
return 0; * Check the primary device, not the partition.
*/
if (!sysbuf[0]) if (primary_result == 2) {
return 0; 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;
}
}
/* /*
* sysfs prints wwid as <typestr>.<value> * This function may be called multiple times for the same device, in
* multipath wwid uses '3'<value> * particular if partitioned for each partition.
* does "<typestr>." always correspond to "3"?
*/ */
if (!(wwid = strchr(sysbuf, '.'))) if (!dm_list_empty(&dev->wwids))
return 0; goto lookup;
/* skip the type and dot, just as '3' was skipped from wwids entry */ /*
wwid++; * 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
look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid)); * value printed from the sysfs wwid file.
*/
_read_sys_vpd_wwids(cmd, dev, &dev->wwids);
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); * This will read the sysfs wwid file, nvme devices in particular have
return 1; * 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; return 0;
} }
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *holder_devno) int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *holder_devno)
{ {
if (_dev_is_mpath_component_sysfs(cmd, dev, holder_devno) == 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, holder_devno) == 1)
goto found; goto found;
if (_dev_in_wwid_file(cmd, dev)) if (_dev_in_wwid_file(cmd, dev, primary_result, primary_dev))
goto found; goto found;
if (external_device_info_source() == DEV_EXT_UDEV) { if (external_device_info_source() == DEV_EXT_UDEV) {
@ -641,6 +791,12 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *h
goto found; 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; return 0;
found: found:
return 1; return 1;

View File

@ -59,6 +59,14 @@ struct dev_ext {
void *handle; 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_WWID 0x0001
#define DEV_ID_TYPE_SYS_SERIAL 0x0002 #define DEV_ID_TYPE_SYS_SERIAL 0x0002
#define DEV_ID_TYPE_MPATH_UUID 0x0003 #define DEV_ID_TYPE_MPATH_UUID 0x0003
@ -105,6 +113,7 @@ struct dev_use {
*/ */
struct device { struct device {
struct dm_list aliases; /* struct dm_str_list */ 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 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 */ struct dev_id *id; /* points to the the ids entry being used for this dev */
dev_t dev; dev_t dev;
@ -206,5 +215,9 @@ void dev_destroy_file(struct device *dev);
int dev_mpath_init(const char *config_wwids_file); int dev_mpath_init(const char *config_wwids_file);
void dev_mpath_exit(void); 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 #endif

View File

@ -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]; char path[PATH_MAX];
dev_t devt = dev->dev; 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; 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 (ret) {
if (prim)
log_debug("Using primary device_id for partition %s.", dev_name(dev));
sysbuf[sysbufsize - 1] = '\0'; sysbuf[sysbufsize - 1] = '\0';
return 1; return 1;
} }
@ -220,6 +228,19 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
return 0; 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) static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix)
{ {
if (!strncmp(sysbuf, prefix, strlen(prefix))) if (!strncmp(sysbuf, prefix, strlen(prefix)))

View File

@ -58,6 +58,8 @@ void devices_file_exit(struct cmd_context *cmd);
void unlink_searched_devnames(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(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); int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out);

199
lib/device/parse_vpd.c Normal file
View File

@ -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;
}