Mounting exfat with udev rules automatically

exfatfuseudev

I'm trying to mount various SD cards automatically with udev rules. I started with these rules, solved a problem with the help of this question, and now I have the following situation:

ext4 and vfat formatted devices work perfectly, but when I plug in an exfat or an NTFS formatted disk I get the following line in mount:

/dev/sda1 on /media/GoPro type fuseblk (rw,nosuid,nodev,noatime,user_id=0,group_id=0,default_permissions,allow_other,blksize=4096)

And the directory listing looks like this:

$ ls -l /media/
ls: cannot access '/media/GoPro': Transport endpoint is not connected
total 0
d????????? ? ? ? ?            ? GoPro

I can't do anything under that mountpoint, not even as root:

$ sudo ls -l /media/GoPro
ls: cannot access '/media/GoPro': Transport endpoint is not connected

The only problems I can find from other people with the error message Transport endpoint is not connected seem to happen after a disk wasn't unmounted properly. But I have the problem while the disk is mounted.

My current udev rules look like this:

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"
ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="media_by_label_auto_mount_end"

# Do not mount devices already mounted somewhere else to avoid entries for all your local partitions in /media
ACTION=="add", PROGRAM=="/bin/grep -q ' /dev/%k ' /proc/self/mountinfo", GOTO="media_by_label_auto_mount_end"

# Global mount options
ACTION=="add", ENV{mount_options}="noatime"
# Filesystem-specific mount options
ACTION=="add", PROGRAM=="/sbin/blkid -o value -s TYPE %E{device}", RESULT=="vfat|ntfs", ENV{mount_options}="%E{mount_options},utf8,uid=1000,gid=100,umask=002"
ACTION=="add", PROGRAM=="/sbin/blkid -o value -s TYPE %E{device}", RESULT=="exfat", ENV{mount_options}="%E{mount_options},utf8,allow_other,umask=002,uid=1000,gid=1000"

# Get label if present, otherwise assign one
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"

# Mount the device
ACTION=="add", ENV{dir_name}!="", RUN+="/bin/mkdir -p '/media/%E{dir_name}'", RUN+="/bin/mount -o %E{mount_options} /dev/%k '/media/%E{dir_name}'"

# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l '/media/%E{dir_name}'"
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/rmdir '/media/%E{dir_name}'"

# Exit
LABEL="media_by_label_auto_mount_end"

I tried using user_id and group_id instead of uid and gid but to no avail.

Mounting the device manually works fine:

$ sudo mount -o noatime,utf8,allow_other,umask=002,uid=1000,gid=1000 /dev/sdb1 /media/GoPro/
FUSE exfat 1.2.5
$ ls -l /media/
total 132
drwxrwxr-x 1 pi   pi   131072 Jan  1  1970 GoPro

Best Answer

TL;DR: udev and fuse are not really compatible


After noticing that this problem not only occurs with exfat but also with NTFS formatted devices I started looking specifically for problems with udev and fuse.

Some comments about the combination I found:

I think that the fuse process is being killed. You cannot start long-lived processes from a udev rule, this should be handled by systemd.

(from Debian-devel)

Warning: To mount removable drives, do not call mount from udev rules. In case of FUSE filesystems, you will get Transport endpoint not connected errors. Instead, you could use udisks that handles automount correctly or to make mount work inside udev rules, copy /usr/lib/systemd/system/systemd-udevd.service to /etc/systemd/system/systemd-udevd.service and replace MountFlags=slave to MountFlags=shared.[3] Keep in mind though that udev is not intended to invoke long-running processes.

(from ArchWiki)

And there are more.

I ended up using the scripts and configuration files from this answer. It works perfectly with all filesystem types. I wish I had found this earlier, it would have spared me a couple of days of debugging, trial and error.

Related Question