HomeHome ArchiveArchive

apm and usb-storage

When suspending and resuming my laptop all the processes that were accessing an external USB harddisk would freeze.

The problem seems to lie in the combination between USB and SCSI, which do not seem to be stateless, that means that when the laptop goes silent and alive again the whole USB stack gets mixed up. I don’t know whether the problem lies within the kernel’s drivers or within the USB/SCSI protocols themselves - I’ve tried the 2.4.27 and the 2.6.9 kernels without success.

I’ve also tried umount -a but that won’t help since processes, that access the filesystem will still freeze inside the kernel with state “D” with no way to kill them. IMHO a clean solution would be to have the whole stack supporting suspending and resuming well or, if the USB/SCSI protocolls don’t allow this, modify Linux fs semantics to that unmounting a fileystem which is being accessed (filehandles or cwds) will work and will cause any access to the filesystem to simply fail, thus allowing applications that access the filesystem to fail gently i.e. do something about the failure (this is being discussed here)

Finally I’ve implemented a work-around. What I do now is, instead of suspending directly with apm -s to first try to unmount the external harddisk, remove all usb-storage related modules and suspend only after that. Maybe not everything is needed, maybe there’s a better solution, comments are wellcome.

The script below assumes that your external HD is mounted under /mnt/maxtor and that you are using the usb-ohci, so adapt as needed.

Enjoy! Tomas Pospisek

$ cat /usr/local/bin/remove_maxtor
#!/bin/sh
#
# remove the external USB drive
#
# v0.1 2005-01-20   Tomas Pospisek
#
# released into the public domain
#

unmount () {
  if mount|grep "on $1" >/dev/null; then
    if ! umount $1; then
      return 1
    fi
  fi
  return 0
}

rmmodule () {
  if lsmod|grep "^$1\b" >/dev/null; then
    if ! rmmod $1; then
      return 1
    fi
  fi
  return 0;
}

if 
  unmount /mnt/maxtor && 
  rmmodule sd_mod && 
  rmmodule usb-storage && 
  rmmodule scsi_mod && 
  rmmodule usb-ohci && 
  rmmodule printer && 
  unmount /proc/bus/usb && 
  rmmodule usbcore;
then 
  echo "successfully removed maxtor"
  exit 0
fi
echo "failed to remove maxtor"
exit 1

#!/bin/sh
#
# put the laptop to sleep
#
# unfortunately we can't put this into
# /etc/apm/suspend.d/ since apm will
# automatically suspend after a certain
# time if called with "apm -s" even if
# the script has not terminated yet
#
# v0.1 2005-01-20   Tomas Pospisek
#
# released into the public domain
#

while ! /usr/local/bin/remove_maxtor; do
  echo "can't remove maxtor"
  sleep 1
done
apm -s