↑↑ Home ↑ UNIX  

Advanced device mounting

Allowing users to mount image files -- Spinning down removable hard drives -- Auto-mounting USB sticks

A collection of howtos for non-standard device mounting tasks.

Allowing users to mount image files

Files containing file system images can be mounted using the loopback device. The uses of loopback mounting include looking at the contents of CD images you have downloaded and checking mkisofs has put your data in the right directories of an ISO image.

Mount commands and fstab lines for a loop device require the image file to be specified. This seems to rule out giving users a blank cheque to mount any image they choose. But it is legal to give a non-existent file in the /tmp directory, so that a user can create a symlink with the required name to the image. This is a solution if this feature is not heavily used (otherwise there will be contention for the image symlink).

The necessary line in /etc/fstab looks like this:

/tmp/image    /mnt/image    auto    user,loop,noauto,nodev,noexec    0 0

Spinning down removable hard drives

I use removable hard drives in external enclosures for backups. It is recommendable to spin them down before removing them; some file systems (XFS) also have to be cleanly unmounted. To spin down a drive, one writes an ASCII '1' to /sys/block/sdX/device/delete. But both this and unmounting auto-mounted drives can only be done as root, which is a nuisance in my use case.

For this reason I wrote this small program, which unmounts all partitions of a disk and spins it down. This can be done by any user if it is installed as SUID root. The program accepts any file on the drive (or its device) as an argument and checks /etc/fstab to prevent unmounting drives which were not auto-mounted. There may still be security implications I have not thought of. Also, disks which have been manually mounted by root can be unmounted. Use of the program can and probably should be restricted by not making it world-executable and choosing an appropriate group ID.

Auto-mounting USB sticks

As operating system design rushes to become part of the show business, fundamental system tasks such as mounting removable disks are increasingly integrated into window managers. As a consequence, users who do not favour one of the common Bulkware Desktops™ are left without automounting of USB sticks.

This can be remedied with udev rules like the following, which are best put in a file of their own, such as /etc/udev/rules.d/98-local.rules:

KERNEL=="sd[a-z][0-9]*", SUBSYSTEM=="block", ACTION=="add",    RUN+="/usr/local/bin/remmount"
KERNEL=="sd[a-z][0-9]*", SUBSYSTEM=="block", ACTION=="remove", RUN+="/usr/local/bin/remmount"

remmount is this script, which creates mount points under /media as needed before mounting the device and removes them when the device is removed.

On some installations, I have had to restrict the udev rules to sda[c-z][0-9]*, excluding the fixed disks, to prevent them from being mounted under /media. Alternatively, one can skip the above lines by filesystem label or UUID by enclosing them in lines like the following:

KERNEL=="sd[a-z][0-9]", ENV{ID_FS_LABEL}=="sys0", GOTO="skip"
KERNEL=="sd[a-z][0-9]", ENV{ID_FS_UUID}=="a6ae14b9-e610-40a1-b324-626c3f86bb73", GOTO="skip"
...
LABEL="skip"

As a side note, the remmount script demonstrates how to escape being killed by udev before finishing the job. Modern versions of udev based on systemd kill all tasks started with a RUN directive after seconds (how long precisely varies). This is done with control groups, a kernel feature for grouping processes (more information). remmount removes itself from the control group that indicates it was started by udev by assigning itself to the top-level control group in the systemd tree:

echo $$ > /sys/fs/cgroup/systemd/tasks

As of version 212, late March 2014, systemd also isolates processes launched by udev by putting them into a different mount namespace, which prevents new mounts from propagating back to the main namespace where other programs live. (See this blog post on tools to deal with namespaces and this article series for some background on namespaces.) To prevent this, one has to customise /usr/lib/systemd/system/systemd-udevd.service by copying it to /etc/systemd/system/systemd-udevd.service and removing the following line:

MountFlags=slave

Systemd >= 219 hackaround

As of version 219, systemd-udevd executes RUN+= scripts while keeping new devices in a state that makes mount fail silently, without any error result value or other diagnostic. Whether this is an intentional attempt to enforce Lord Poettering's pet peeve about mounting devices in udev rules or collateral damage of some other feature creep is impossible to know, as the RedHat team developing systemd rivals the North Korean leadership in transparency, as it rivals Microsoft in standards compliance.

As a consequence, a hack is required to trigger mounts from udev rules. This takes the form of a small server mountsrv.sh triggered by files in /tmp/mountsrv written by remmount if that directory exists. The corresponding systemd service file should be installed in /etc/systemd/system/ and assumes that the server script is installed in /usr/local/sbin.

Warning: You may have noticed that the shell script contains a hard-coded delay before attempting the mount. This is a workaround to the fact that the mount fails when tried immediately, again without any diagnostics. systemd-udevd does not seem to provide any notification when the device is ready to be mounted, so the race condition is unavoidable for now.