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

device_id: look for serial number in other locations

Only /sys/dev/block/major:minor/device/serial was read to find
a disk serial number, but a serial number seems to be reported
more often in other locations, so check these also:
/sys/dev/block/major:minor/device/vpd_pg80
/sys/class/block/vda/serial (for virtio disks only)
This commit is contained in:
David Teigland 2022-10-24 16:23:36 -05:00
parent 36a923926c
commit bdab36cf3f
3 changed files with 105 additions and 2 deletions

View File

@ -228,5 +228,6 @@ int dev_mpath_init(const char *config_wwids_file);
void dev_mpath_exit(void); void dev_mpath_exit(void);
int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, 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); int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes);
int parse_vpd_serial(const unsigned char *in, char *out, int outsize);
#endif #endif

View File

@ -454,6 +454,67 @@ int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev,
return 1; return 1;
} }
static int _dev_read_sys_serial(struct cmd_context *cmd, struct device *dev,
char *buf, int bufsize)
{
unsigned char vpd_data[VPD_SIZE] = { 0 };
const char *devname;
int vpd_datalen = 0;
/*
* Look in
* /sys/dev/block/major:minor/device/serial
* /sys/dev/block/major:minor/device/vpd_pg80
* /sys/class/block/vda/serial
* (Only virtio disks /dev/vdx are known to use /sys/class/block/vdx/serial.)
*/
read_sys_block(cmd, dev, "device/serial", buf, bufsize);
if (buf[0])
return 1;
if (read_sys_block_binary(cmd, dev, "device/vpd_pg80", (char *)vpd_data, VPD_SIZE, &vpd_datalen) && vpd_datalen) {
parse_vpd_serial(vpd_data, buf, bufsize);
if (buf[0])
return 1;
}
devname = dev_name(dev);
if (!strncmp(devname, "/dev/vd", 7)) {
char path[PATH_MAX];
char vdx[8] = { 0 };
const char *sysfs_dir;
const char *base;
int i, j = 0, ret;
/* /dev/vda to vda */
base = basename(devname);
/* vda1 to vda */
for (i = 0; i < strlen(base); i++) {
if (isdigit(base[i]))
break;
vdx[j] = base[i];
j++;
}
sysfs_dir = cmd->device_id_sysfs_dir ?: dm_sysfs_dir();
if (dm_snprintf(path, sizeof(path), "%s/class/block/%s/serial", sysfs_dir, vdx) < 0)
return 0;
ret = get_sysfs_value(path, buf, bufsize, 0);
if (ret && !buf[0])
ret = 0;
if (ret) {
buf[bufsize - 1] = '\0';
return 1;
}
}
return 0;
}
const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype) const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype)
{ {
char sysbuf[PATH_MAX] = { 0 }; char sysbuf[PATH_MAX] = { 0 };
@ -471,8 +532,9 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
sysbuf[0] = '\0'; sysbuf[0] = '\0';
} }
else if (idtype == DEV_ID_TYPE_SYS_SERIAL) else if (idtype == DEV_ID_TYPE_SYS_SERIAL) {
read_sys_block(cmd, dev, "device/serial", sysbuf, sizeof(sysbuf)); _dev_read_sys_serial(cmd, dev, sysbuf, sizeof(sysbuf));
}
else if (idtype == DEV_ID_TYPE_MPATH_UUID) { else if (idtype == DEV_ID_TYPE_MPATH_UUID) {
read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)); read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));

View File

@ -211,3 +211,43 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
return id_size; return id_size;
} }
int parse_vpd_serial(const unsigned char *in, char *out, int outsize)
{
uint8_t len_buf[2] __attribute__((aligned(8))) = { 0 };;
size_t len;
/* parsing code from multipath tools */
/* ignore in[0] and in[1] */
/* len is in[2] and in[3] */
/* serial begins at in[4] */
len_buf[0] = in[2];
len_buf[1] = in[3];
len = len_buf[0] << 8 | len_buf[1];
if (outsize == 0)
return 0;
if (len > DEV_WWID_SIZE)
len = DEV_WWID_SIZE;
/*
* Strip leading and trailing whitespace
*/
while (len > 0 && in[len + 3] == ' ')
--len;
while (len > 0 && in[4] == ' ') {
++in;
--len;
}
if (len >= outsize)
len = outsize - 1;
if (len > 0) {
memcpy(out, in + 4, len);
out[len] = '\0';
}
return len;
}