问题
I'm enumerating scsi_generic devices with udev to retrieve the /dev/sg*
filename so I can send an Inquiry to each device.
Can I also get the /dev/sd*
filename (the scsi_device) while I'm right there?
If not, how do I get the scsi_device given a scsi_generic path?
This is my udev code:
IntPtr udev = IntPtr.Zero;
IntPtr enumerate = IntPtr.Zero;
try
{
udev = Libudev.udev_new();
if (udev == IntPtr.Zero)
throw new UdevException("Failed to create udev");
enumerate = Libudev.udev_enumerate_new(udev);
if (enumerate == IntPtr.Zero)
throw new UdevException("Failed to enumerate udev");
Libudev.udev_enumerate_add_match_subsystem(enumerate, "scsi_generic");
Libudev.udev_enumerate_scan_devices(enumerate);
for (IntPtr listEntry = Libudev.udev_enumerate_get_list_entry(enumerate);
listEntry != IntPtr.Zero;
listEntry = Libudev.udev_list_entry_get_next(listEntry))
{
// Get the filename of the /sys entry for the device
string deviceSysPath = Libudev.udev_list_entry_get_name(listEntry);
IntPtr device = Libudev.udev_device_new_from_syspath(udev, deviceSysPath);
if (device == IntPtr.Zero)
continue;
// Get the /dev path of the device (/dev/sg*)
string deviceDevPath = Libudev.udev_device_get_devnode(device);
// Send Inquiry
// <snip>
Libudev.udev_device_unref(device);
}
}
catch (DllNotFoundException ex)
{
throw new DllNotFoundException("libudev is either not installed, or ldconfig has mapped it in an unexpected way. See source README file for information.", ex);
}
finally
{
if (enumerate != IntPtr.Zero)
Libudev.udev_enumerate_unref(enumerate);
if (udev != IntPtr.Zero)
Libudev.udev_unref(udev);
}
回答1:
You can retrieve the device serial number with the INQUIRY command and then use the serial number to find the associated block device in /dev/disk/by-id/
:
$ sudo sg_inq --page=sn /dev/sg0
VPD INQUIRY: Unit serial number page
Unit serial number: 110427E3834563H46N0N
$ basename $(readlink /dev/disk/by-id/scsi-SATA_*110427E3834563H46N0N)
sda
回答2:
I solved it by performing two enumerations. First by enumerating over scsi_generic
devices, then by block
devices.
I create a hash table (Dictionary< string, string >
) to map the generic device's sysname to its devnode.
While enumerating scsi_generic
devices I get the parent (udev_device_get_parent
), then get the sysname (udev_device_get_sysname
) and add it to the map. For SCSI disks, you get something like "9:0:0:0".
While enumerating block
devices I do the same: Get the parent and the sysname. If the hash table contains the same key, I have found the generic device that matches the block device.
来源:https://stackoverflow.com/questions/24436808/get-scsi-device-from-scsi-generic