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:
parent
36a923926c
commit
bdab36cf3f
@ -228,5 +228,6 @@ int dev_mpath_init(const char *config_wwids_file);
|
||||
void dev_mpath_exit(void);
|
||||
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 parse_vpd_serial(const unsigned char *in, char *out, int outsize);
|
||||
|
||||
#endif
|
||||
|
@ -454,6 +454,67 @@ int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev,
|
||||
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)
|
||||
{
|
||||
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';
|
||||
}
|
||||
|
||||
else if (idtype == DEV_ID_TYPE_SYS_SERIAL)
|
||||
read_sys_block(cmd, dev, "device/serial", sysbuf, sizeof(sysbuf));
|
||||
else if (idtype == DEV_ID_TYPE_SYS_SERIAL) {
|
||||
_dev_read_sys_serial(cmd, dev, sysbuf, sizeof(sysbuf));
|
||||
}
|
||||
|
||||
else if (idtype == DEV_ID_TYPE_MPATH_UUID) {
|
||||
read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
|
||||
|
@ -211,3 +211,43 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user