get scsi_device from scsi_generic

本秂侑毒 提交于 2019-12-25 00:35:59

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!