From nobody Sun Feb 8 09:12:21 2026 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 58E0832C326 for ; Wed, 14 Jan 2026 17:51:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768413082; cv=none; b=GOs0bLjfdodrNHnWBGk6SagDn41JyEQngrMcmtABwMf12XOXC2cHlkaMfAWFeqRB8/2m7+4i1XfKKnOHePPTGE8gxeZ6C0HRQLh1WpZdKP5BYn4GvlvxGs5b07YpbLRiTOzhlAaqZy3MnWT9GrmSYj/0Q8DCbzgjn7lhwGikoCg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768413082; c=relaxed/simple; bh=0VlneB30FVhi6ckREc4C/e8nnUhhXw+xlKjHB2aXC68=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=bDUUW88F4WSD4sbyEVRS+x7YHgC2EdLIpGNohyVWLr8y89MP+P6mul7LI2WT0rotx6xukUB3HD4K6iakyu8ijHYqBE/mor4q2HkjQYtWMy1eFFsGhLL8ZWPRry/hULx5gQKmqINLM52zAhLv8Ji5nnJ82OjVNfeNHZ2Cs85IC1Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ipylypiv.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nxkOf63O; arc=none smtp.client-ip=209.85.210.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ipylypiv.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nxkOf63O" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-81f53295ac2so109994b3a.0 for ; Wed, 14 Jan 2026 09:51:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768413081; x=1769017881; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=uHdJBd8jMxMRZo0RZLZ+zHyApr0XgodixoY/B3frsaI=; b=nxkOf63ONQUdmFOk+tGK6QWRE0JX74fNcqRRhhgPil9gI3Xyhi1wyAnszHd7wOf3gT 4RFd8WxfMYuQr6i2MuRzn1YE6JrjndH3FXAAfRWjQ2l861u3giLEJvyB3+dKwHPlt3L3 J1jKMb3CnIRvJb8vdI+yuNM75rSAKaZeBRc2TSSBPCeYJnF30V07Rdx2rw06ZeXvf+K8 puK6UlYbXbo25oV7ildb5o+hCc/3LKint3yqLoksyMROwGlZkGdD7/DNAVv9DCQvCfDk HHz6w2irIiT3EIYm0Erd26k8IdSufduUURwCIga0zfd6/UUq+Ou1CsUKz8BabCBeNvtv Awfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768413081; x=1769017881; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=uHdJBd8jMxMRZo0RZLZ+zHyApr0XgodixoY/B3frsaI=; b=X1bzGUnb/y5P0MJZWvz38KecXv+ZG2+2omE/rnTObB3zftDaKTC9JO8bSkIrLbnWyj aOyB0pVszphxwXg72suivNp55MC1rcgFL1Yjj0VfTM3QwzHiOPTtL+hoMXzWPw3mOf7d YVZjwvk6iGd5HNuVQ6sSUqv42ds5A8UZJjS7ZZW0iwiusGVaDfGaDwzqyspOeAbax//r 6nkAMWODEHWxUlPKFR87PKqTrGdlhW+Lgv2bdR2nqRVfpOnsBaW3drUN/+IwxrO5iX0N VmxkXLkaie1Yp87M85Jja4x/HI6U5Sb3BqzdrS6gy5Cjfl2nuB5cgA2tsoNgUJ5P4jnM STLg== X-Forwarded-Encrypted: i=1; AJvYcCVfxcszAS334oKAeA8ImD53UnsrAnwqZ3Qmj7RAYdMUGoUWksphx5QLy/wmQoYuQneY2Di0+cRvaevjfwM=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+1ume5mhYEMmBSID199TuA9hvzTzVBn3qjcEr/K7Cg5azZF+7 axylmxG4mj9x8QJhtZr4Oq84miERFipwvgjpwkJ4FD9GUqCK+K5j4QtvvuqxN1uZdg3AShRELjN GZervz3yYp19WDQ== X-Received: from pfay10.prod.google.com ([2002:a05:6a00:180a:b0:81f:7aad:edfa]) (user=ipylypiv job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:6ca4:b0:81e:f43a:3535 with SMTP id d2e1a72fcca58-81f82012706mr2706210b3a.66.1768413080718; Wed, 14 Jan 2026 09:51:20 -0800 (PST) Date: Wed, 14 Jan 2026 09:51:15 -0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260114175115.384741-1-ipylypiv@google.com> Subject: [PATCH] scsi: core: Add 'serial' sysfs attribute for SCSI/SATA From: Igor Pylypiv To: "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org, Igor Pylypiv Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- drivers/scsi/scsi_lib.c | 53 ++++++++++++++++++++++++++++++++++++++ drivers/scsi/scsi_sysfs.c | 14 ++++++++++ include/scsi/scsi_device.h | 1 + 3 files changed, 68 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 93031326ac3e..dc09785c050c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -3451,6 +3452,58 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *= id, size_t id_len) } EXPORT_SYMBOL(scsi_vpd_lun_id); =20 +/** + * 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) +{ + int len; + const unsigned char *d; + const struct scsi_vpd *vpd_pg80; + + rcu_read_lock(); + vpd_pg80 =3D rcu_dereference(sdev->vpd_pg80); + if (!vpd_pg80) { + rcu_read_unlock(); + return -ENXIO; + } + + len =3D vpd_pg80->len - 4; + d =3D 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) { + rcu_read_unlock(); + return -EINVAL; + } + + memcpy(sn, d, len); + sn[len] =3D '\0'; + + rcu_read_unlock(); + + 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_att= ribute *attr, } static DEVICE_ATTR(wwid, S_IRUGO, sdev_show_wwid, NULL); =20 +static ssize_t +sdev_show_serial(struct device *dev, struct device_attribute *attr, char *= buf) +{ + struct scsi_device *sdev =3D to_scsi_device(dev); + ssize_t ret; + + ret =3D 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)] =3D #name static const char *const sdev_bflags_name[] =3D { @@ -1257,6 +1270,7 @@ static struct attribute *scsi_sdev_attrs[] =3D { &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 *); =20 #ifdef CONFIG_PM --=20 2.52.0.457.g6b5491de43-goog