* [RESEND PATCH v2] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA
@ 2026-02-05 18:00 Igor Pylypiv
2026-02-09 17:31 ` Bart Van Assche
0 siblings, 1 reply; 4+ messages in thread
From: Igor Pylypiv @ 2026-02-05 18:00 UTC (permalink / raw)
To: James E.J. Bottomley, Martin K. Petersen
Cc: Bart Van Assche, linux-scsi, linux-ide, linux-kernel,
Igor Pylypiv
Add a 'serial' sysfs attribute for SCSI and SATA devices. This attribute
exposes the Unit Serial Number, which is derived from the Device
Identification Vital Product Data (VPD) page 0x80.
Whitespace is stripped from the retrieved serial number to handle
the different alignment (right-aligned for SCSI, potentially
left-aligned for SATA). As noted in SAT-5 10.5.3, "Although SPC-5 defines
the PRODUCT SERIAL NUMBER field as right-aligned, ACS-5 does not require
its SERIAL NUMBER field to be right-aligned. Therefore, right-alignment
of the PRODUCT SERIAL NUMBER field for the translation is not assured."
This attribute is used by tools such as lsblk to display the serial
number of block devices.
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
v1->v2 changes:
- Reordered declarations in scsi_vpd_lun_serial() from longest to shortest.
- Replaced rcu_read_lock()/rcu_read_unlock() with guard(rcu)().
drivers/scsi/scsi_lib.c | 47 ++++++++++++++++++++++++++++++++++++++
drivers/scsi/scsi_sysfs.c | 14 ++++++++++++
include/scsi/scsi_device.h | 1 +
3 files changed, 62 insertions(+)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c7d6b76c86d2..16eed661d657 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -13,6 +13,7 @@
#include <linux/bitops.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
+#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/init.h>
@@ -3451,6 +3452,52 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
}
EXPORT_SYMBOL(scsi_vpd_lun_id);
+/**
+ * scsi_vpd_lun_serial - return a unique device serial number
+ * @sdev: SCSI device
+ * @sn: buffer for the serial number
+ * @sn_size: size of the buffer
+ *
+ * Copies the device serial number into @sn based on the information in
+ * the VPD page 0x80 of the device. The string will be null terminated
+ * and have leading and trailing whitespace stripped.
+ *
+ * Returns the length of the serial number or error on failure.
+ */
+int scsi_vpd_lun_serial(struct scsi_device *sdev, char *sn, size_t sn_size)
+{
+ const struct scsi_vpd *vpd_pg80;
+ const unsigned char *d;
+ int len;
+
+ guard(rcu)();
+ vpd_pg80 = rcu_dereference(sdev->vpd_pg80);
+ if (!vpd_pg80)
+ return -ENXIO;
+
+ len = vpd_pg80->len - 4;
+ d = vpd_pg80->data + 4;
+
+ /* Skip leading spaces */
+ while (len > 0 && isspace(*d)) {
+ len--;
+ d++;
+ }
+
+ /* Skip trailing spaces */
+ while (len > 0 && isspace(d[len - 1]))
+ len--;
+
+ if (sn_size < len + 1)
+ return -EINVAL;
+
+ memcpy(sn, d, len);
+ sn[len] = '\0';
+
+ return len;
+}
+EXPORT_SYMBOL(scsi_vpd_lun_serial);
+
/**
* scsi_vpd_tpg_id - return a target port group identifier
* @sdev: SCSI device
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 99eb0a30df61..d80a546f54c2 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1013,6 +1013,19 @@ sdev_show_wwid(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(wwid, S_IRUGO, sdev_show_wwid, NULL);
+static ssize_t
+sdev_show_serial(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ ssize_t ret;
+
+ ret = scsi_vpd_lun_serial(sdev, buf, PAGE_SIZE);
+ if (ret < 0)
+ return ret;
+ return sysfs_emit(buf, "%s\n", buf);
+}
+static DEVICE_ATTR(serial, S_IRUGO, sdev_show_serial, NULL);
+
#define BLIST_FLAG_NAME(name) \
[const_ilog2((__force __u64)BLIST_##name)] = #name
static const char *const sdev_bflags_name[] = {
@@ -1257,6 +1270,7 @@ static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_device_busy.attr,
&dev_attr_vendor.attr,
&dev_attr_model.attr,
+ &dev_attr_serial.attr,
&dev_attr_rev.attr,
&dev_attr_rescan.attr,
&dev_attr_delete.attr,
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index d32f5841f4f8..9c2a7bbe5891 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -571,6 +571,7 @@ void scsi_put_internal_cmd(struct scsi_cmnd *scmd);
extern void sdev_disable_disk_events(struct scsi_device *sdev);
extern void sdev_enable_disk_events(struct scsi_device *sdev);
extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t);
+extern int scsi_vpd_lun_serial(struct scsi_device *, char *, size_t);
extern int scsi_vpd_tpg_id(struct scsi_device *, int *);
#ifdef CONFIG_PM
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [RESEND PATCH v2] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA
2026-02-05 18:00 [RESEND PATCH v2] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA Igor Pylypiv
@ 2026-02-09 17:31 ` Bart Van Assche
2026-02-09 19:31 ` Igor Pylypiv
0 siblings, 1 reply; 4+ messages in thread
From: Bart Van Assche @ 2026-02-09 17:31 UTC (permalink / raw)
To: Igor Pylypiv, James E.J. Bottomley, Martin K. Petersen
Cc: linux-scsi, linux-ide, linux-kernel
On 2/5/26 10:00 AM, Igor Pylypiv wrote:
> + return sysfs_emit(buf, "%s\n", buf);
Since many snprintf() variants do not allow to specify the output buffer
as input argument, the above seems risky to me. Has it been considered
to replace the above statement with the following?
return sysfs_emit_at(buf, strlen(buf), "\n");
Thanks,
Bart.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RESEND PATCH v2] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA
2026-02-09 17:31 ` Bart Van Assche
@ 2026-02-09 19:31 ` Igor Pylypiv
2026-02-09 20:27 ` Bart Van Assche
0 siblings, 1 reply; 4+ messages in thread
From: Igor Pylypiv @ 2026-02-09 19:31 UTC (permalink / raw)
To: Bart Van Assche
Cc: James E.J. Bottomley, Martin K. Petersen, linux-scsi, linux-ide,
linux-kernel
On Mon, Feb 09, 2026 at 09:31:39AM -0800, Bart Van Assche wrote:
> On 2/5/26 10:00 AM, Igor Pylypiv wrote:
> > + return sysfs_emit(buf, "%s\n", buf);
>
> Since many snprintf() variants do not allow to specify the output buffer as
> input argument, the above seems risky to me. Has it been considered to
> replace the above statement with the following?
>
> return sysfs_emit_at(buf, strlen(buf), "\n");
Thank you for pointing this out, Bart! I've now realized that you
pointed out this in V1 as well but I misunderstood your comment.
sysfs_emit_at() returns number of characters written starting at &buf[at]
so it would return 1 for the added newline. We can add the number of
characters written by scsi_vpd_lun_serial() to return the correct number
of characters:
return ret + sysfs_emit_at(buf, ret, "\n");
This looks a bit too complicated/ugly to me. Instead, I will put a newline
manually and return the correct number of characters. PAGE_SIZE is passed
to scsi_vpd_lun_serial() so we don't sysfs_emit_at() to check it again.
buf[ret] = '\n';
return ret + 1;
Let me know if this sounds good to you.
Thank you!
Igor
>
> Thanks,
>
> Bart.
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RESEND PATCH v2] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA
2026-02-09 19:31 ` Igor Pylypiv
@ 2026-02-09 20:27 ` Bart Van Assche
0 siblings, 0 replies; 4+ messages in thread
From: Bart Van Assche @ 2026-02-09 20:27 UTC (permalink / raw)
To: Igor Pylypiv
Cc: James E.J. Bottomley, Martin K. Petersen, linux-scsi, linux-ide,
linux-kernel
On 2/9/26 11:31 AM, Igor Pylypiv wrote:
> Instead, I will put a newline
> manually and return the correct number of characters. PAGE_SIZE is passed
> to scsi_vpd_lun_serial() so we don't sysfs_emit_at() to check it again.
>
> buf[ret] = '\n';
> return ret + 1;
This sounds good to me.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-02-09 20:27 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-05 18:00 [RESEND PATCH v2] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA Igor Pylypiv
2026-02-09 17:31 ` Bart Van Assche
2026-02-09 19:31 ` Igor Pylypiv
2026-02-09 20:27 ` Bart Van Assche
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox