Solved zfs: automount removable media

I'd like to format SD-cards and USB-thumb drives with zfs.

When plugged-in I'd like them to automatically mount read-only, so that I can carelessly pull them out again.

I guess I need a devd rule with zfs import/export and rmdir.

Is there somebody here doing similar? How do you?
 
Probably worthwhile to also explore autofs(5)().

It's a component to automount disks.



The devd daemon is responsible to propage events like "a USB drive has been inserted",
so yes, a devd rule seems a good idea.

Code:
notify 100 {
    match "system" "DEVFS";
    match "subsystem" "CDEV";
    match "type" "CREATE";
    match "cdev" "da[0-9]+$";
    action "/usr/local/sbin/zfs-autoimport.sh $cdev attach";
};

You could also target instead system USB, subsystem DEVICE and type ATTACH.

The challenge for me is to find a way to detect in zfs-autoimport.sh you inserted a drive with a ZFS pool, but perhaps we can just live with exit code as long as the pool has the same name on each disk (but in that case how to insert TWO disks at the same time?)
Code:
zpool import -o readonly=on <pool name>

I would also look what happens when we remove the disk, perhaps some zpool export is needed with a second rule calling /usr/local/sbin/zfs-autoimport.sh $cdev detach?
(if not, the attach parameter won't be helpful)


sh:
#!/bin/sh

#   -------------------------------------------------------------
#   ZFS auto import
#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

set -e

#   -------------------------------------------------------------
#   Parse arguments
#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

if [ $# -lt 3 ]; then
    echo "Usage: $(basename "$0") <device> <action>" >&2
    exit 1
fi

CDEV=$1
ACTION=$2

#   -------------------------------------------------------------
#   Handle the ZFS pool
#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# Here some heuristic to find pool name?
# What about parsing `zpool import -aN`?
POOL=external

LOGTAG=zfs-autoimport

# Device needs a little time to be available
sleep 3

if [ "$ACTION" = "attach" ]; then
    logger -t $LOGTAG "Trying to import ZFS pool for device $CDEV"
    zpool import -o readonly=on $POOL
elif [ "$ACTION" = "detach" ]; then
    logger -t $LOGTAG "Trying to export ZFS pool as device $CDEV has been removed"
    zpool export $POOL
else
fi
 
  • Like
Reactions: mro
The challenge for me is to find a way to detect in zfs-autoimport.sh you inserted a drive with a ZFS pool,
There are various pool names following no convention.
I think I will go for the ATTACH events and then
  1. find potential pools $ zpool import | grep -F pool: | cut -c10-
  2. one after the other $ zpool import <poolname> them and
  3. check if the device attached is the first word in $ zpool status <poolname> | grep -F " ONLINE " | tail -1
  4. if yes we're done, otherwise $ zpool export <poolname> and continue what we do if not zfs
  5. $ beep if successful
Either way I will automatically mount it readonly, so that I can recklessly unplug unless deliberately remounted rw.
 
to auto (un-)mount zfs sd-cards I ended up with

sh:
$ cat /usr/local/etc/devd/mmcsd.conf
# see also https://wiki.freebsd.org/Devd but IMO simpler than automountd
notify 100 {
    match "system"        "GEOM";
    match "subsystem"    "DEV";
    match "type"        "CREATE|DESTROY";
    match "cdev"        "mmcsd.+";
    action "sh /usr/local/etc/devd/mmcsd.sh $type $cdev";
};

plus

sh:
$ cat /usr/local/etc/devd/mmcsd.sh
#!/bin/sh
# see also https://wiki.freebsd.org/Devd but IMO simpler than automountd
echo "$0 $@" | logger -t devd
set -e

case $1 in
"CREATE")
  shift
  sleep 2
  pool="$(zpool import | grep -B 1 -F " $1 " | grep -oE "[^ ]+"| head -1 | xargs)"

  zpool import -o readonly=on "$pool"
  beep
  echo "Mounted readonly. Make writeable: zpool export $pool && zpool import $pool # $1" | logger -t devd
  ;;
"DESTROY")
  shift
  pool="$(zpool status | grep -B 1 -F "$1" | grep -oE "[^ ]+" | head -1 | xargs)"
  [ "$pool" = "" ] && exit 0

  echo "zpool export -f $pool # $1" | logger -t devd
  zpool export -f "$pool"
  rmdir "/media/zfs/$pool"
  ;;
*)
  exit 1
  ;;
esac
 
If you want compatibility with Linux for file transfer, the optimal file system is exFAT. Simple, good for flash, without limitations for size of files and volume.
 
Back
Top