pmount & safe removal of USB device

When you plug an USB device on your computer, under Windows it automatically becomes available. Under Arch, not so much. It makes sense, I didn't install/configure anything to do so, so why would it?

So I started wondering about auto-mounting of USB devices, although I must admit that I'm not a fan of such automated tasks, just like I hate (and always disabled) any & all form of autorun that Windows provides. (And on a side note, it's also a potentially major security risk. I think I read recently that Microsoft concluded that by simply turning that damn autorun off, people would see a huge drop (around 50% or something) of virus/malware infections.)

Anyways, I don't really mind having to mount things. Right now I need to call mount whenever I put a CD/DVD in the drive, why should it be any different for an USB device? But the thing is, with a CD I only need to call mount and umount to do the work, no need for sudo Which begs the question, why should it be any different for an USB device?

Enters pmount

pmount is a great little that will allow users to p(u)mount removable devices, USB and the likes, without the need to call sudo -- Exactly what I was looking for. While giving it a try, I did however noticed a couple of things.

First of all, it's a simple thing but where a CD or DVD only ever offers one filesystem to be mounted, an USB device can have just as many partitions as an internal drive, which can be a lot. And I wasn't too happy about having to mount each & every one of those whenever I would need to.

One solution to this problem could be to have pmount automatically called through an udev rule or something, so all partitions would be automounted when the device is plugged in. Of course, we'd be back to the security risk mentioned earlier...

It's a little thing, but it's there. The other thing I noticed was, on the other hand, more of a problem to me. It seems that the only thing pumount does is unmount without the need for sudo. It's exactly what it says it does, so no surprises there.

But if for a CD it makes sense, we're talking about something else here. Because here, it is the actual device I want to remove/unplug from the computer, and simply unmounting any mounted filesystem seemed a little... not enough.

How does one safely remove an USB device, in Linux?

Question I asked myself, and then turned to the Internet. Apparently, a lot of people are fine with, and only do unmount the filesystem before unplugging their device.

Simply call umount and you can turn it off/unplug it.

A common answer I found here & there, when looking for a way to safely remove an USB device on Linux. People would sometimes add a note about how they've been doing it for years without problems.

Great, but somewhat unsatisfying. I mean, after all on Windows - to come back to what I'm used to - I do need to click on the "Remove device" option before I unplug anything, and that even when the drive has no partition on it. And therefore, nothing is/can be mounted, so clearly Windows does more than just mounting whatever needs to be unmounted.

In fact, sometimes the device actually let you know it is ready to be unplugged: a LED goes off, or you hear it spinning down, something. Things that obviously do not happen after a simple call to umount

Unmounting is good, but not enough

Unmounting any mounted filesystem is good, required even, but it's only the first step. I found a great post by Yan Li where he described all the four steps that needs to be done before a device can be safely removed (okay, three, as the last one is optional) :

From the hardware aspect, the drive should only be removed when the following requirements are met:

  1. there's no pending I/O request and software cache flushed
  2. it's hardware cache flushed
  3. it's driver spins down (means "not spinning")
  4. (optional) the USB port is put into "suspend" mode

Unmounting the filesystem will obviously take care of the first step, but that's all it does. To go further, one then needs to unbind the device from the driver - which, according to Alan Stern, will have the Linux kernel automatically "send a SYNCHRONIZE CACHE command followed by START-STOP (if the device supports it)" - after which one can then tell the USB core driver to put that device into suspend mode.

Li also provides a little script that accomplishes all those steps. I tried it a little, and it seems to work as advertised. When used with a device that beeps when it can be unplugged, I got the magic beep. I also noticed that the device was gone from /dev/ afterwards (and before unplugging it), a natural result of unbinding the driver.

So this seems to be not just a better solution than a simple call to (p)umount, but the right way to (fully) do things. To quote Li again,

I know electronic devices are fragile, rigid and obtuse if you don't use them as the way they are designed. For a well-designed and robust piece of hardware, theoretically you can disconnect the device safely when the first two steps are done. The firmware on the device would notice the USB cable was unplugged and shut down the disk drive properly. If not, the drive would be stopped sharply as if you pulled it's power when it's running and this damages the hardware gradually. As an outsider of the manufacturer, we hardly know whether it's well-designed or not so the only safe principle is to follow it's manual, means we should not disconnect the device until at least all three steps are done.

And since most of my USB devices happen to be drives where I hold precious data, I'd rather do things right, just in case.

pmount, the return

I then knew what I has been looking for, had the steps to safely remove an USB device, so I decided to try and modify pmount a little bit. The reason behind this was not only to have only one tool to do the job, but also that Li's script, while it works fine, requires root privileges, therefore sudo. Since pmount already allows to deal with things without such a requirement, I figured it might be a good idea.

So I added a new option -D that will do the following:

  • in pmount : it will mount all the partitions of the specified device.
  • in pumount : it will unmount all the partitions of the specified device, and then make it safe to be removed.

In pmount, what it means is that when you call e.g. pmount /dev/sdd1 and here happen to be two more partitions on that device, they will both also be mounted. You could as well have used either one of those, or even /dev/sdd and would have gotten the exact same result. This is just to allow mounting of all partitions of a drive without the need to do each one manually (or use some sort of automounting).

In pumount, it's the same but in reverse. Similarly you can use either /dev/sdd or any of the partitions (e.g. /dev/sdd2) or, in typical pumount fashion, use a mount point, e.g. /media/sdd2 It will always (try to) unmount all the mounted partitions of the device.

Then, unless there was an error, it will also do those four steps to prepare the device for safe removal. That is:

  • Calls sync() to flush buffers
  • Unbinds the driver (which, as discussed earlier, takes care of sending the SYNCHRONIZE CACHE and START-STOP messages to the device)
  • Suspend the device

This is all done according to the discussion and script by Yan Li. And in pure pmount fashion, you don't need to use sudo to get this done, unlike with the previously mentioned script.

/etc/pmount.conf for some configuration

I also did something else, and introduced the use of a configuration file, in /etc/pmount.conf

Because while I could p(u)mount my USB drives easily now, and safely unplug them as well, there was one more thing I would have liked: I wanted to mount them outside of /media/ Also, I intend to use LUKS-encrypted partitions, and I figured it would be nice if those drives were mounted automatically without the need for me to enter a passphrase (*).

(*) After all, It's already how it works for internal drives. Once I enterred the passphrase for the root file system, other partitions are LUKS decrypted using key-files (found in /root/).

pmount offers a command-line option to specify a file to use for passphrase, instead of prompting the user. So I decided to introduce a configuration file where a few options could be defined, options that would take precedence over default & command-line arguments.

This file (/etc/pmount.conf) has a structure somewhat similar to an INI file: sections defined using a name in between square brackets ([ ]), then one or more options defined simply in format name=value

The name of the sections must be a way to identify the partition. It could be /dev/sdd1 although it would make more sense, I imagine, to use an entry either in /dev/disk/by-label/ or in /dev/disk/by-uuid/ When mounting said partition, pmount will take care of resolving the device name, meaning that it doesn't have to be mounted using the same name/symlink (E.g. you could use the UUID in the configuration file, and the label when calling pmount to mount it...).

Supported options in the file are:

  • fs to define the file system (overwrites option -t)
  • charset to define the I/O character set (overwrites option -c)
  • passphrase to define the file to read passphrase from (overwrites options -p/--passphrase)
  • mntpt to define the mount point. Overwrites the usual way (e.g. specified label), can be anywhere (not restricted to /media/)
  • options to defines the mounting options. That is, this allows you to overwrite the defaut options, as defined in fs.c No checks are done here, so make sure not to include non-existing options, as well as not to include any options auto-added by pmount (that is, things based on command-line options, such as atime/noatime, exec/noexec, etc)

Values should not be quoted, and comments are supported using either ; or #

In the end, with a simple call to pmount I can now have my LUKS encrypted partitions mounted automatically; and when I'm done one call to pumount will have them all unmounted, and the device be prepared for safe removal. I think I now have everything I was looking for. If you're interested, it's all below.

Download

The modified source code is available on this BitBucket repository.

For Arch Linux users, you can also find a PKGBUILD in the AUR, which uses the official source code and a patch to get there, simply because I figured it would allow people to check the changes more easily.

It's all released under GPL, and of course bug reports, suggestions or any other form of constructive criticism is very much welcome.

Top of Page