The rest of auto-mounting can also be implemented with udev rules and one or two helper scripts that make use of udisksctl from udisks2. This way the udisks-osmc and udisks-glue-osmc packages (both obsolete) can be dropped and replaced with udisks2.
Holler if you want me to proceed. Sadly, Iâve just burnt my RPi4 which I was using for testing, and I either need to figure out how to fix it or find another box I can (ab)use for testingâŚ
Yes, Iâd like to move forward. UDisks 2 could work.
We could also look at udevil. LibreELEC use udevil but they run as everything as root â which means they donât have the permissions issues we have. I donât want to do this.
There are some pitfalls with UDisks1. For example sometimes it does not populate filesystem promptly enough and the mount will fail. Although this is rare and reports on this seem to have calmed down for a few years.
I have some notes from what I wanted in an improved auto-mounter. Keep in mind that I wrote these notes in 2019 and hadnât had a chance to work out how to implement it yet. If UDisks2 can do this, then it would be great.
Some of the ideas I had:
Detecting disk events
Mount disk if not in fstab
Mount if disk is not in a blacklist.d path (allow some mounts to be ignored)
Inform Kodi that the drive has been mounted (Kodi supports UDisks2 subscription via DBus polling so not much should be needed if you take this path)
If the device is not mounted on /, configure a spindown
Mounting rules
Each filesystem has mounting rules under a directory like /usr/osmc/automounter/fs/X.conf, where X.conf is the name of filesystem, i.e. ext4.conf. Each config file provides configuration of:
Mount-as-root: true/false. Useful for some drives with permissions issues
Hide-directories: allow some directories to be hidden like .DS_STORE etc
Filesystem options: allows custom fs options
Mount command: the command to actually mount the filesystem
Customisation
Support this being overwritten on a line by line basis by sourcing a downstream /etc/osmc/prefs.d/automounter/fs/X.conf
Add postmount.d, postrm.d rules in a similar fashion which have a standard set of rules such as net use (to Samba share); adjust read-ahead and net remove in rm.d (checking for presence of Samba server). Supplemental postmount.d and postrm.d rules which run commands after the above and are also in /etc/osmc/prefs.d/fs/post{mount|rm}.d. You could even use your postmounts.d to handle LUKS for you. Perhaps we could also support postmounts.d/UUID-*.conf or postmounts.d/LABEL.conf as well as general 000-do-foo-task.conf.
Add blacklist-drives.d in prefs directory to allow blacklisting of mounting based on label or UUID
Add diskidle.d which lets you override disk idling based on name of mountpoint (label) or UUID.
Do you reckon we could adapt UDisks2 to handle this?
But, instead of having per-FS and per-drive individual config files, I would suggest using INI-style config files with sections for each FS/drive. This way we can offload parsing and overrides to the configparser module. The files can be, like you said, in:
Any options in the [DEFAULT] section would apply to every device. The remaining section names would consist of comma-separated key/value pairs that are matched against device properties provided by udev.
The list of device properties can be obtained with udevadm info /dev/blah.
Here is an example of what it could look like (Iâve stripped ID_ prefix from the property names):
[DEFAULT]
# options common to ALL devices go here
# mount and unmount filesystems
[FS_USAGE=filesystem]
mount = true
post_mount = /usr/osmc/bin/samba-helper add $DEVPATH
unmount = true
post_unmount = /usr/osmc/bin/samba-helper remove $DEVPATH
# use different options for optical media
[FS_USAGE=filesystem,CDROM]
mount_opts = uid=1000,gid=1000,mode=0444,dmode=0555
# set spin-down time for optical media
[DEVTYPE=disk,CDROM]
add = /sbin/hdparm -S 1024 $DEVPATH
# set read-ahead for non-optical media
[DEVTYPE=disk,!CDROM]
add = /bin/sh -c "echo 1024 > /sys/dev/block/$MAJOR:$MINOR/queue/read_ahead_kb"
# don't mount this drive
[FS_UUID=996D-BDEB]
mount = false
If all goes well, I should have something working by tomorrow.
This (from experience) can be racy and has caused us problems in the past. Checking as soon as a udev event comes in doesnât guarantee that youâll have all of the properties populated yet. It seems to be some race condition in the kernel.
Yep. But thatâs what udisks-glue, udevil and other packages do under the hood (except they do it through DBus), so we shouldnât have more problems than they do.
Except it never does. I got it working⌠mostly⌠using a few udev rules and about a page worth of python. But, it turns out itâs no longer possible to mount devices from within udev events.
So, I am going to rewrite it as a systemd service using udisks2dbus API instead. The basic idea will stay the same. I am thinking of making it into a standalone Debian package, as I want to use it for other things as well (outside of OSMC).
@sam_nazarko since this will be itâs own package, I am thinking the config files should go into /usr/share/automount/*.conf and /etc/automount/*.conf. The package will provide a vary basic config and all OSMC-specific stuff can be provided by the diskmount-osmc package.
Donât worry about packaging yet. Thatâs easy to do. Youâll probably get stuck on things like deprecating the old packages which is something we can easily build up and test to make sure that udisks2 and scripts are working in a truly isolated environment.
The hard part will be making it all work, not the packaging per se.
@sam_nazarko I got it working. Ran into a few corner cases, so took a bit longer than expected.
I ended up creating a separate package called automount, which you can find here:
It is not directly tied to OSMC, and all the glue to make it work for OSMC can be provided by the existing diskmount-osmc package. Here are the steps to test it:
Disable the existing udisks and udisks-glue daemons:
sudo systemctl mask --now udisks udisks-glue
OPTIONAL: Reboot the box and make sure auto-mounting is now disabled.
Download and install the automount package (it will pull in udisks2 as a dependency):
By default udisks2 mounts drives in /media/<user>/. To make it mount in /media/, create /usr/lib/udev/rules.d/99-osmc-diskmount.conf with the following contents:
Enable polkit rules for udisks2 by adding (or replacing) the following to /lib/polkit-1/localauthority/90-mandatory.d/osmc-diskmount.pkla:
[Mounting, checking, etc. of internal drives]
Identity=unix-user:osmc
Action=org.freedesktop.udisks2.filesystem-mount-system;org.freedesktop.udisks2.encrypted-unlock-system;org.freedesktop.udisks2.filesystem-fstab;org.freedesktop.udisks2.filesystem-mount-other-seat
ResultAny=yes
ResultActive=yes
Create /etc/automount/50-osmc-diskmount.conf with the following contents:
# 50-osmc-diskmount.conf
[ID_FS_USAGE=filesystem]
auto-mount = yes
mount-as = osmc:osmc
on-mount = /usr/osmc/bin/samba-helper add ${DEVNAME} ${ID_TYPE} ${MOUNT_POINT}
on-unmount = /usr/osmc/bin/samba-helper remove ${DEVNAME} ${ID_TYPE} ${MOUNT_POINT}
# set spin-down time for optical media
[DEVTYPE=disk ID_TYPE=cd]
on-add = /sbin/hdparm -S 240 ${DEVNAME}
# set read-ahead for non-optical media
[DEVTYPE=disk ID_TYPE=disk]
on-add = /bin/sh -c "echo 1024 > /sys/dev/block/${MAJOR}:${MINOR}/queue/read_ahead_kb"
Create /usr/osmc/bin/samba-helper with the following contents:
#!/bin/bash
action="$1" dev_name="$2" dev_type="$3" mount_point="$4"
if [[ "$action" == "add" ]]; then
[[ "$dev_type" == "disk" ]] && chmod a+rwx "$mount_point" 2>/dev/null
if [[ -x /usr/bin/net ]] && /bin/systemctl is-enabled samba > /dev/null 2>&1; then
share=$(basename "$mount_point")
id -u "${share,,}" > /dev/null 2>&1 && share+="-auto"
for n in $(seq 0 5 120); do
/usr/bin/net usershare add "$share" "$mount_point" "Auto-mount Volume" "$(hostname -s)\\osmc:f" && break
sleep 5
done
fi
elif [[ "$action" == "remove" ]]; then
if [[ -x /usr/bin/net ]] && /bin/systemctl is-enabled samba > /dev/null 2>&1; then
share=$(basename "$mount_point")
id -u "${share,,}" > /dev/null 2>&1 && share+="-auto"
/usr/bin/net usershare delete "$share"
fi
[[ "$dev_type" == "cd" ]] && /usr/bin/eject "$dev_name" 2>/dev/null || true
fi
And make it executable:
sudo chmod +x /usr/osmc/bin/samba-helper
Reboot the box (preferred) or run the following commands instead:
sudo udevadm control --reload
sudo systemctl reload automount.service
Yep, Iâve looked at that too, but unfortunately they donât have hooks.
I do in the automount file. The other two modules are not meant to be launched directly, so I didnât use it there. It prevents people from being able to launch them directly.
Iâll fork your automount repo. Iâd like to create a Debian package for it / convert it to OSMC diskmount package and add some postinst rules to make sure the service (udisks2) and automount are running as that doesnât seem to be provisioned in the Debian rules from a quick glance.