USB Storage on Debian

This is an account of my experiences getting my USB pen drives to work on my Debian system. It cost me quite a lot of work, so I though I might as well share my experiences. The solution doesn't look so complicated, but boy did it take me long to find this out. There really needs to be a package that does all this, but I'll have to leave that up to somebody with more time on his hands.

What I'm using:

  • Debian unstable (current version as of 21-07-2004)
  • udev package (0.030-1)
  • hotplug package (0.0.20040329-12)
  • sg3-utils package (1.05-2)
  • disktype package (7-1)
  • procmail package (for the "lockfile" utility -- thanks to Paul Telford for noticing this dependency)
  • Kernel 2.6.7-mm7 (custom-built, not a Debian kernel)
  • usb-mount (0.9)

All of this is on i686 hardware, but that shouldn't really matter. The major differences between your situation and mine is probably in the kernel. I'm using a custom-built non-modular kernel, so if you need to load modules on-demand, this page will not help you with that. This page *will* help you to get the basics working though.

The Instructions

  1. If you have a modular kernel (like the standard debian kernels), make sure you have the right kernel modules loaded: usb_storage, sg, sd_mod, scsi_mod.
  2. Install usb-mount and get it to work. The usb-mount package contains instructions on how to do this. My two cents:
    • Set MOUNT_OPTIONS="-o noatime" in the usb-mount config file (/usr/local/etc/usb-mount.conf. The noatime option prevents unnecessary writes to the device to update access times. This is required because the flash memory that is used in usb pens can handle only a relatively limited number of write cycles before it wears out. IMPORTANT: until recently this page recommended options "sync" and "dirsync" as well. However, only recent kernels actually honor this, and it will slow down your transfer speeds to a crawl. In addition, it will write the filesystem metadata after every file write, which will greatly increase the wear on flash-based USB drives. If you still have these options set, REMOVE THEM. (The problem is then that you can't just unplug the USB drive anymore. I haven't found a solution for that except to explicitly "sync" before unplugging. Probably waiting for 35 seconds works too, as the kernel always writes everything to disk within 35 seconds. If anybody has a better solution, let me know!)
    • Set UMOUNT_OPTIONS="-f". The kernel will not gladly unmount a device if it's already been unplugged, except if you pass the -f flag. You might even want to use -lf if -f doesn't work.
    • Most pen drives are formatted with a FAT filesystem that can be mounted as type vfat as well as msdos. If "msdos" is listed earlier than "vfat" in /etc/filesystems, linux will detect the drives as having filesystem "msdos", which doesn't support long filenames. To fix this, edit /etc/filesystems and move the line containing "vfat" above the one containing "msdos".

    Installing usb-mount should get you into the following situation: if you insert a usb-storage device and run usb-mount, it automatically gets mounted at a new directory called (mount point)/device-0, and if you remove the device and then run usb-mount, the directory (mount point)/device-0 will disappear. You need to get this working before you continue with the next steps.

  3. Create a file /etc/hotplug/usb/pen.usermap, containing the following line:
    pen 0 0 0 0 0 0 0 0 0 0 0

    This directs the hotplug code to
    execute the script /etc/hotplug/usb/pen each time a usb device is inserted. I'm pretty sure this could be narrowed down some more so that it is only called for usb-storage devices, but for now this will have to do.

  4. Create a file /etc/hotplug/usb/pen, containing the following text:
    #! /bin/bash
    USBMOUNT=/usr/local/bin/usb-mount
    # Unfortunately udev only creates the device nodes AFTER this script is run.
    # We sleep for 2 seconds in the background and then run usb-mount. This will
    # mount the device.
    (sleep 2 && $USBMOUNT) &
    # Install usb-mount as the script that is run when the device is removed.
    # This will automatically unmount the filesystem.
    ln -s $USBMOUNT $REMOVER
    

    In this script, you must set USBMOUNT to the location of your installed usb-mount. Make the script executable, i.e. run:

    chmod u+x /etc/hotplub/usb/pen
  5. This should set you up with a working system. Inserting the usb-storage device should mount the device automatically (albeit with a delay of up to 10 seconds), and subsequently removing the device should unmount it.

    NOTE: The hotplug version that
    I'm using contains a bug that makes that the unmount script is not called. The cause of this bug is that it tries to calculate the name of the "removal script" from the kernel-supplied device name, which no longer exists when the device is already removed. If your device does not get removed after you unplug it, edit the file /etc/hotplug/usb.agent and check if it contains the lines:

    if [ "$DEVPATH" != "" ]; then
      # probably, 2.6.x
      REMOVER=/var/run/usb/$(readlink -f $SYSFS/$DEVPATH | sed -e 's;/;%;g')
    elif [ "$DEVICE" != "" ]; then
      # 2.4.x?
      REMOVER=/var/run/usb/$(echo $DEVICE | sed -e 's;/;%;g')
    else
      # should not happen?
      REMOVER=/var/run/usb/$(echo "$INTERFACE/$PRODUCT/$TYPE" | sed -e 's;/;%;g')
    fi
    

    Try commenting out the first three lines (by putting a # at the beginning of the line), and changing the fourth line to read "if" instead of "elif". That fixed it for me. This bug is supposed to be fixed in a more recent version of Debian's hotplug scripts, but I haven't seen the fix yet. I'll update this page when the fix comes
    through.