NetBSD desktop pt.5: automounting with Berkeley am-utils


#1

Introduction

This time we cover automounting removable media (FAT32-formatted flash drives and ISO9660 on optical drive) on NetBSD.
While NetBSD -HEAD branch implements Solaris’ autofs, like practically any other *nix OS nowadays, this feature didn’t make its way into 8.0, so our hopes for an automounting suite shall rest with we good old Berkeley am-utils (amd), also known as 4.4BSD Automounter, which is found in NetBSD base system.

amd is a lightweight,portable and easy to set up solution, which unlike autofs, runs in userspace (autofs is part of *nix kernel and relies on its VFS). So why did everybody ditch it in favor of autofs? its being a software-level suite makes it slower and prone to segfaults at high I/O loads; moreover amd can’t directly mount FSs on target dir, rather, it has to mount it inside a dedicated root-owned folder (/amd in the example below) which is symlinked to the wanted ‘pseudo’ mountpoint parent folder (in our case /media), where an amd ‘map’ is mounted.
That said, I definitely prefer amd over autofs, as autofs is extremely complex, very server-oriented, and hard to make work as expected[1]

preliminary tasks

# create mountpoints
% mkdir /{amd,media}
# create maps'definitions dir
% mkdir /etc/amd

/etc/amd.conf

# this is am-utils configuration file, \
# refer to amd.conf(5)
[ global ]
karch             = amd64
auto_dir          = /amd
unmount_on_exit   = no
restart_mounts    = yes
browsable_dirs    = yes
print_pid         = no
print_version     = no
dismount_interval = 5
cache_duration    = 5
localhost_address = 127.0.0.1
log_file          = /var/log/amd.log
log_options       = all
search_path       = /etc/amd
map_type          = file
map_options       = cache:=all

[ /home/${USER}/media ] [2]
map_name =          media

/etc/amd/media

# this is our 'map' for removable media
# a maps consists of a series of rules \
# to mount and unmount filesystems[3][4]

  /defaults    type:=program;fs:=${autodir}/${key};\
               unmount:="/sbin/umount umount" 


  cd           mount:="/sbin/mount mount -t cd9660 \
                       /dev/cd0a ${fs}"
  usb1         mount:="/sbin/mount mount -t msdos \
                       /dev/sd0e ${fs}"
  usb2         mount:="/sbin/mount mount -t msdos \
                       /dev/sd1e ${fs}"
requests  stale     mount     mount     unmount
deferred  fhandles  ok        failed    failed
3         0         4         0         1   

enable amd

% echo amd="YES" >> /etc/rc.conf
% service amd start

If everything went right it will just print:
NetBSD-8 amd[3274]/info: using configuration file /etc/amd.conf

otherwise check out /var/log/amd.log

managing amd

amd will mount any filesystem matching a definition for a mounted map under the map’s mountpoint. This means in my case, 2 FAT32 usb drives inserted at the same time and a cd-rom inserted in the optical drive, will appear mounted under /home/sehnsucht/media as ‘usb1’,‘usb2’ and ‘cd’ respectively. According to what we said above those mountpoints are actually only symlinks to the real mountpoints found under auto_dir='.' (/amd in our case). Filesystems are not actually mounted until user reads the map’s mountpoint (from CLI, with ls() or with a FM), which is pretty convenient. So after opening ~/media, I can see my drives mounted:

% df -h | grep amd
/dev/sd1e           15G       404M        14G   2% /amd/usb2
/dev/sd0e           58G        52M        58G   0% /amd/usb1
/dev/cd0a          418M       418M         0B 100% /amd/cd

am-utils include a nice automounter query tool, amq(8), which proves quite useful in managing amd

  • list filesystems currently automounted by amd
% amq -m | grep amd

mount -t msdos /dev/sd1e /amd/usb2  /amd/usb2              program  1   localhost is up 
mount -t msdos /dev/sd0e /amd/usb1  /amd/usb1              program  1   localhost is up 
mount -t cd9660 /dev/cd0a /amd/cd   /amd/cd                program  1   localhost is up 
  • show statistics on amd daemon
% amq -s
requests  stale     mount     mount     unmount
deferred  fhandles  ok        failed    failed
3         0         4         0         2 
  • kill misbehaving amd
% kill -9 $(amq -p)

Here’s a screenshot of my pcmanfm, showing the ‘media’ map mounted and the filesystems as symlinks inside it

2018-12-07-020330_472x296_scrot

My FreeDOS CD-ROM:

2018-12-07-033950_557x388_scrot

notes

[1]
On systems which provide a device state change daemon (udev on Linux and devd on FreeBSD), much simpler solutions, based on those, are available and imho result more suited to desktop usage: I’m speaking of udevil and @vermaden’s sysutils/automount respectively

[2] remember to actually replace $USER with your username

[3] am-utils was heavily inspired to SunOS automounter, as such it often uses old Solaris mount() syntax and terms. For example fs:= option is defined by Solaris /etc/dfs/fstypes(4) (linking respective Illumos man), so FAT is referred as pcfs instead of msdos, iso9660 as cdfs instead of cd9660. Instead of complicating configuration for BSD users in this way, I decided to just define fs:= as program (NetBSD’s mount(8) in this case) and simply let NetBSD mount() take care of everything

[4]* /defaults string applies to all filesystems described by the same map. Following are 3 filesystem mount rules definitions: usb1-2 automount 2 FAT removable flash drives, cd automounts CD-ROM*

Further reading


#2

Wow very nicely written… Thanks a ton :heart_eyes: