After chasing the problem of rotational sysfs property of USB flash drives, I started to check another sysfs attributes of USB storage devices, and I noted two missing attributes: vpd_pg80 and vpd_pg83.
As explained here, VPD pages contain data related to the device. In special, page 80 is Unit Serial Number (sn) and page 83 is Device Information (di), which are present in any SCSI device that complies with SPC-2 or later.
Check an example of my sn and di of my SSD using sg_vpd from sg3_utils package:
|
|
This information is exported as attributes of storage devices in sysfs, like my HDD and SSD devices below:
|
|
This is true for the majority of storage devices, but not for USB flash drives. Most USB storage devices don’t have these attributes in sysfs, even when sg_vpd clearly shows them, like below:
|
|
I’ve tested a bunch of different USB flash devices and USB to SATA adapters in my previous post, and neither of them had vpd_pg80 and vpd_pg83 in sysfs, although all SanDisk Cruzer Blade devices tested expose these VPD pages (thanks to my friend Alexandre Vicenzi who also had a Cruzer Blades to test).
In order to understand the problem, I decided to look at the kernel code. By using grep, I found a couple of interesting files:
|
|
At first glance, scsi_sysfs.c seems the best place to start. This file describes the sysfs attributes of SCSI devices, like vpd_pg80 and how the values of this properly is presented. So far, no information from where it is assigned.
File scsi.c had some answers. Looking at function scsi_attach_vpd, we can clearly see where the SCSI layer checks for Device Information and Serial Number.
But, let’s look at the first function that scsi_attach_vpd calls:
|
|
By looking at this function we can presume that try_vpd_pages flag is not set and skip_vpd_pages is. We can discard checking scsi_level because Cruzer Blade is SPC-4 compliant:
|
|
By looking at the comment of scsi_device_supports_vpd, some USB devices crash after checking their VPD pages, in this case, it makes sense to not enable VPD for all devices. Although, our SanDisk Cruzer Blade device clearly supports VPD and does not crash.
scsi_device_supports_vpd is called in two places: scsi_add_lun and scsi_rescan_device. These callers are common path of device setup, so fixing skip_vpd_pages should be enough.
Let’s grep again in the kernel source code to check where skip_vpd_pages is being set:
|
|
Interesting to see that USB layer setting this flag. Let’s check drivers/usb/stoarge/scsiglue.c file:
|
|
By the code above, which belongs to slave_configure function, USB layer disables VPD for all USB storage devices. Makes sense, since some devices are reported to crash when checking for VPD, as stated before.
But, shouldn’t we add support for SanDisk Cruzer Blade at least? There is a per device mapping with specific flags in SCSI layer that should help to fix this situation, specially regarding try_vpd_pages. To add support for SanDisk Cruzer Blade* devices, I submited this patch to the kernel mailing list and it’s now merged:
|
|
The patch adds specific flags that will be checked in SCSI layer and will be applied once the SanDisk Cruzer Blade* device is found. This change alone does not fix the problem as the flag skip_vpd_pages is still enabled. So I submited a second patch, to only set skip_vpd_pages when try_vpd_pages is not set allowing the SCSI layer to process all VPD pages when try_vpd_pages is set.
|
|
With these two patches applied SanDisk Cruzer Blade USB flash device is able to properly show the VPD pages in sysfs:
|
|
That’s all for today. Stay tuned for more posts about Kernel and whatnot, see ya!