2

Apologies if this is a duplicate, however.

I have 2 usb mass storage devices, and I need to be able to work out which physical device maps to a block device.

They are not both always present, so I can't just rely on a fixed block device path.

I've tried to determine the device path from lsusb, but that just provides the device info.

Bus 001 Device 016: ID 0781:5406 SanDisk Corp. Cruzer Micro 1/2/4GB Flash Drive
Bus 001 Device 015: ID 4971:ce23 SimpleTech

sudo fdisk -l is not able to read any partition as its a truecrypt encrypted volume.

Is there some way to detect which physical device is mapped to a block device ?

I'm not able to mount the filesystem until I know which is which.

have I approached this problem in the wrong way ?

Any suggestions ?

1

Are the physical devices both the same size? Are they the exact same brand as well?

If they are different sizes, fdisk -l should show you the size of the entire disk in the header along with the block device name, which should help you.

You can also check the output of dmesg. When a USB device is connected, dmesg will display the process it undergoes to bring it online, as well as showing you the block device it assigned. Here's a sample output:

Aug 14 16:35:02 xen kernel: [2526561.710931] usb 5-5: new high speed USB device using ehci_hcd and address 4
Aug 14 16:35:02 xen kernel: [2526561.859909] usb 5-5: configuration #1 chosen from 1 choice
Aug 14 16:35:02 xen kernel: [2526562.138808] usbcore: registered new interface driver libusual
Aug 14 16:35:02 xen kernel: [2526562.162072] Initializing USB Mass Storage driver...
Aug 14 16:35:02 xen kernel: [2526562.163248] scsi4 : SCSI emulation for USB Mass Storage devices
Aug 14 16:35:02 xen kernel: [2526562.163452] usbcore: registered new interface driver usb-storage
Aug 14 16:35:02 xen kernel: [2526562.163455] USB Mass Storage support registered.
Aug 14 16:35:07 xen kernel: [2526567.161157] scsi 4:0:0:0: Direct-Access     WDC WD50 00AAKS-00A7B0         PQ: 0 ANSI: 2 CCS
Aug 14 16:35:07 xen kernel: [2526567.171712] sd 4:0:0:0: [sdb] 976773168 512-byte hardware sectors (500108 MB)
Aug 14 16:35:07 xen kernel: [2526567.172736] sd 4:0:0:0: [sdb] Write Protect is off
Aug 14 16:35:07 xen kernel: [2526567.173733] sd 4:0:0:0: [sdb] 976773168 512-byte hardware sectors (500108 MB)
Aug 14 16:35:07 xen kernel: [2526567.174606] sd 4:0:0:0: [sdb] Write Protect is off
Aug 14 16:35:13 xen kernel: [2526567.174616]  sdb: sdb1
Aug 14 16:35:13 xen kernel: [2526572.854493] sd 4:0:0:0: [sdb] Attached SCSI disk
Aug 14 16:35:13 xen kernel: [2526572.854544] sd 4:0:0:0: Attached scsi generic sg2 type 0

As you can see, the kernel assigned /dev/sdb to the USB device. Hope this helps!

  • I think i'll write a small wrapper script around dmesg to provide the most recent mapping for the USB devices. Thankyou for your help – Bovril Aug 23 '10 at 15:13
1

I was wondering what to do in the case where there are multiple devices with the same vendor:product IDs.

I tried running udevadm info -a /dev/sde, which "walks up the chain of parent devices" (whatever that means?). By matching "ATTRS{devnum}" and "ATTRS{busnum}" with the Bus X Device Y output of lsusb, I could see that not only did the udevadm listing produce the bus and device numbers for the USB hard drive as a "parent" of the block device /dev/sde, but also the bus and device numbers of the hub it was connected to as well as the host controller! That could be useful if you want to identify a device by the port it's connected to.

I was a bit confused about why it seems so hard to get the USB device corresponding to a given block device, and I guess this clears that up a bit: the devices are not the same, there is a kind of filial relationship between the two.

Udevadm gives the paths of each parent, so you have some idea how to locate the correct parent by trimming the child path:

$ udevadm info --path=$(udevadm info -q path /dev/sde | cut -d / -f 1-7)
P: /devices/pci0000:00/0000:00:1d.7/usb2/2-2/2-2.4
N: bus/usb/002/024
E: BUSNUM=002
E: DEVNAME=/dev/bus/usb/002/024
E: DEVNUM=024
E: DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-2/2-2.4
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=External_HDD
....

We can pass the DEVNAME to lsusb:

$ lsusb -D $(udevadm info --path=$(udevadm info -q path /dev/sde
    | cut -d / -f 1-7) | grep DEVNAME | cut -d = -f 2)
Device: ID 1058:0705 Western Digital Technologies, Inc. My Passport Elite (WDML)
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
...

So we can use this to tell that, for example, /dev/sde is connected as a USB 2.0 device (from the bcdUSB line above).

I'm not sure if this answers your question, but it gives a way to identify USB devices from block devices. Also it is not quite complete because I think you'll have to give a different argument to 'cut' if you don't have a hub in-between the controller and the device. Probably I should be counting from the end of the device path, rather than the beginning, but I couldn't find a way to pass a numeric argument to dirname.

Update: Here is a solution that uses zsh to trim components from the end of the device path, let me know if it works for you:

$ cat usb-device-from-block-device
#!/bin/zsh                         
udevadm info --path ${${$(udevadm info -q path $1)}%/*/*/*/*/*/*} | grep DEVNAME | cut -d = -f 2

# Example:
$ usb-device-from-block-device /dev/sdc
/dev/bus/usb/001/017
$ lsusb -D $(usb-device-from-block-device /dev/sdc)
...
0

Once you connect a device you can visit /dev/disk and go from there knowing that the symlinks there get created dynamically:

[user@host disk]$ pwd
/dev/disk
[user@host disk]$ ll -R
.:
total 0
drwxr-xr-x 2 root root  80 Jul 30 09:54 by-id
drwxr-xr-x 2 root root  80 Jul 30 09:54 by-label
drwxr-xr-x 2 root root 160 Jul 30 09:54 by-path
drwxr-xr-x 2 root root  80 Jul 30 09:54 by-uuid

./by-id:
total 0
lrwxrwxrwx 1 root root  9 Jul 30 09:54 usb-WD_10EAVS_External_57442D574341553436313337373137 -> ../../sdb
lrwxrwxrwx 1 root root 10 Jul 30 09:54 usb-WD_10EAVS_External_57442D574341553436313337373137-part1 -> ../../sdb1

./by-label:
total 0
lrwxrwxrwx 1 root root 10 Jul 30 09:54 backup -> ../../sdb1
lrwxrwxrwx 1 root root 10 Mar  3 18:51 boot -> ../../sda1

./by-path:
total 0
lrwxrwxrwx 1 root root  9 Jul 30 09:54 pci-0000:00:1d.7-usb-0:6:1.0-scsi-0:0:0:0 -> ../../sdb
lrwxrwxrwx 1 root root 10 Jul 30 09:54 pci-0000:00:1d.7-usb-0:6:1.0-scsi-0:0:0:0-part1 -> ../../sdb1
lrwxrwxrwx 1 root root  9 Mar  3 18:51 pci-0000:00:1f.1-ide-0:0 -> ../../hda
lrwxrwxrwx 1 root root  9 Mar  3 18:51 pci-0000:02:0e.0-scsi-0:2:0:0 -> ../../sda
lrwxrwxrwx 1 root root 10 Mar  3 18:51 pci-0000:02:0e.0-scsi-0:2:0:0-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 Mar  3 18:51 pci-0000:02:0e.0-scsi-0:2:0:0-part2 -> ../../sda2

./by-uuid:
total 0
lrwxrwxrwx 1 root root 10 Mar  3 18:51 72734cea-d59d-443b-8fdd-3e7a0e2c7731 -> ../../sda1
lrwxrwxrwx 1 root root 10 Jul 30 09:54 efcb8d1e-3f46-4021-bc55-22a85846429b -> ../../sdb1
[user@host disk]$ 

Hope this helps.

0

You can query sysfs to report the vendor and model of the drive:

$ cat /sys/block/sdd/device/{vendor,model}
DSE     
MicroDrive 1GB  

$ cat /sys/block/sdc/device/{vendor,model}
JetFlash
Transcend 4GB   

If you want to go further than that, you could add udev rules (assuming your linux distro has udev) to map your different drives to different device names, or to provide a different symlink based on the drive model

EG, here has some examples.

I could do something like this to create a /dev/transcend symlink, with partition numbers appended where appropriate, to whatever real device is actually created when I insert my Transcend stick:

KERNEL=="sd*", SUBSYSTEMS=="scsi", ATTRS{model}==\ 
 "Transcend 4GB", SYMLINK+="transcend%n"

Of course, if I put in multiple devices of the same model, there would be a collision, but with a bit of work you can get around that

0

I haven't seen a UUID-centric answer, so here's one:

If you have a filesystem on that device, that filesystem has a UUID. You can use this UUID to mount the filesystem reliably, no matter what device major/minor block device the flash drive comes in as on the system

You can easily display which device goes to which UUID/filesystem with lsblk -f. The following is an example from my system, which shows a nice descriptive tree off of my single NVMe drive. The flash drives in this question would probably present a much simpler output.

[dhay@GLaDOS ~]$ lsblk -f
NAME              FSTYPE      LABEL       UUID                                   MOUNTPOINT
nvme0n1                                                                          
├─nvme0n1p1       vfat        ESP         F2F6-9BC7                              /boot/efi
├─nvme0n1p2                                                                      
├─nvme0n1p3       crypto_LUKS             abde2123-0ee9-46b5-8d05-2b0b91b21054   
│ └─syspvluks     LVM2_member             ZsBxHH-tvRz-xE3k-e2dJ-I0O0-Gv4e-Ckap71 
│   ├─system-root xfs         root        a3acf72b-3309-408e-b6a4-0c3f28b86a53   /
│   └─system-swap swap        swap        5006f803-af24-4179-a5fa-7c5720b383d2   [SWAP]
├─nvme0n1p4       ntfs        WINRETOOLS  A0B0BED5B0BEB0E0                       
├─nvme0n1p5       ntfs        Image       D6E6BF67E6BF4711                       
├─nvme0n1p6       ntfs        DELLSUPPORT 00CED73ECED72AA4                       
└─nvme0n1p7       xfs         boot        b3e3a722-e37a-4c15-8d6c-4085c00b778a   /boot

With that UUID in hand, you can identify filesystems with it regardless of what they're on. This is also great for migrating a filesystem from one device to another without having to update any configuration. The following is an exmaple of my /etc/fstab file, which is using a combination of device labels, UUIDs, and LVM persistent names rather than direct kernel names for block devices:

/dev/mapper/system-root /                       xfs     defaults,discard       0 0
UUID=F2F6-9BC7          /boot/efi               vfat    umask=0077,shortname=winnt 0 2
/dev/mapper/system-swap swap                    swap    defaults        0 0
LABEL=boot              /boot                   xfs     defaults,discard     0 0

Likewise, I can use a UUID as a device argument in this mount command to mount my root filesystem to a directory :

[dhay@GLaDOS ~]$ mount UUID=a3acf72b-3309-408e-b6a4-0c3f28b86a53 /mnt/root

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.