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);
|
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
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user