6

I have a bunch of usb ports and hubs. When you attach usb thumb drives, Linux assigns them to virtual block devices on a first-come first-serve basis. It creates sdd, sde, sdf, and so on, regardless of which port I plug the drives into. We copy files onto these drives and when there is an error, it is impossible for me to tell which drive the error occured on.

What I'd like to do is configure udev so that it maps physical hardware devices/ports to specific virtual devices. That is, port 1 => sdd, port 2 => sde, port 3 => sdf, etc. This would allow me to tell which thumbdrive the error occured on.

I've found a few resources (e.g. http://reactivated.net/writing_udev_rules.html), from which, I can tell that this can be done. However I have no experience with such low level configurations. They are confusing to me.

Is there another reference that might make things clearer? Or perhaps some software which does it for me? Or a library that makes it easier?

Nick
  • 81
  • 1
  • 2

4 Answers4

6

/dev/disk/by-path will contain consistent names that will map to specific USB ports (at least they do on my box).

Also check out /dev/disk/by-id and /dev/disk/by-uuid for ways to access specific devices regardless of which path is used to access them.

Heath
  • 1,240
  • 9
  • 4
0

Are these drives being automounted? What tool are you using for auto-mounting? Are you recreating the filesystem each time they are mounted, or are the partitions/filesystem pretty stable?

If you uniquely label the filesystems usually you can mount the filesystem by the label instead of the device name.

When you create a filesystem a UUID is assigned to the filesystem. You could put a label of some sort on the USB device that corresponds to the UUID.

Zoredache
  • 128,755
  • 40
  • 271
  • 413
  • the same data is being copied to every usb drive. thus they will all have the same label, the same everything. that said, the drives are already formatted when inserted (though we usually reformat them, just in case). – Nick Aug 13 '10 at 18:27
0

The most typical use case would be to match by filesystem uuid, but it you're writing whole-disk-identical devices, that won't do. Instead, you can match by model and serial number. An example (untested) udev rule for this is:

KERNEL=="sd*", ATTR{removable}=="1", ATTR{vendor}=="Yoyodine", ENV{ID_SERIAL}=="123-456-789", NAME=="disk/by-serial/scsi-$attr{vendor}-$env{ID_SERIAL}"

To see what ATTR values exist for a given device now known as /dev/sdz, run udevinfo -n /dev/sdz -a. To see what ENV values exist, run udevinfo -n /dev/sdz --query=env.

If you want to match by port rather than by serial number, look up parent devices in the document you cite. I suspect something like KERNELS=="usb42" would work, but I haven't tried.

  • To help you (OP) understand and walk through setting it up, see articles like this: http://www.cyberciti.biz/tips/linux-assign-static-names-to-scsi-devices.html Google for 'udev static devices' to find more. –  Sep 06 '10 at 15:14
0

I am using this hack with two Python scripts for a similar purpose:

ophis@tlatoani:~$ more /usr/bin/drive.py
# !/usr/bin/env python

import os, sys

if len(sys.argv) == 2:

  label = sys.argv[1]

  os.system("drivelabels.py >/tmp/drv.txt")

  drvmap = map(lambda x:map(lambda y:y.strip(), x.split("\t")), file("/tmp/drv.txt").readlines())

  for d in drvmap:

    if d[0] == label:

      print d[1]

      sys.exit()

print "/srv"

ophis@tlatoani:~$ more /usr/bin/drivelabels.py

#!/usr/bin/env python

import os

os.system("ls -lh /dev/disk/by-label >/tmp/bylabels.txt ; df -ha >/tmp/drivemap.txt")

bylabel_text=map(lambda x:x.split(" "), file("/tmp/bylabels.txt").readlines())

l, ll = {}, {}

for byl_t in bylabel_text:

  label, dev = byl_t[len(byl_t)-3], byl_t[len(byl_t)-1]

  dev = dev[-dev.rfind("/"):].strip()

  if dev != "": l[ label ] = dev

drivemap_txt=map(lambda x:x.split(" "), file("/tmp/drivemap.txt").readlines())

for k in l.keys():

  for d in drivemap_txt:

    if d[0].strip() == "/dev/%s" % l[k]: ll[ k ] = d[-1].strip()

for assign in ll.keys(): print "%s\t%s" % (assign, ll[assign])

So this allows me to access drives via the label:

target=`drive.py STICKY`
cp -v *.tex $target

Hope that anybody will find this helpful!

j0k
  • 401
  • 9
  • 16