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:
- there's no pending I/O request and software cache flushed
- it's hardware cache flushed
- it's driver spins down (means "not spinning")
- (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 infs.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.