]> sourceware.org Git - lvm2.git/commitdiff
device_id: look for serial number in other locations
authorDavid Teigland <teigland@redhat.com>
Mon, 24 Oct 2022 21:23:36 +0000 (16:23 -0500)
committerDavid Teigland <teigland@redhat.com>
Mon, 7 Nov 2022 14:56:02 +0000 (08:56 -0600)
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)

lib/device/device.h
lib/device/device_id.c
lib/device/parse_vpd.c

index ca46490ceab680b9542860571d5952162b0c35c0..519754e41e2cdf521fe2408f2415cdbf0e7e17d1 100644 (file)
@@ -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
index bd9b3c4bf4e44fce02a0da870e26eb90b251401b..15b34a158d78746b1bf81417c13d65cabb3d6db2 100644 (file)
@@ -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));
index 99e8c0ec2fb9f10e4f33531bbe60f2c20d267cfa..23b0c6efa465ed3e0c4d69bad34ff8fb7e5f3801 100644 (file)
@@ -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;
+}
+
This page took 0.037078 seconds and 5 git commands to generate.