Forum

Full Version: Change external HDD mount behavior
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Whenever an external HDD is removed uncleanly, kodi plots a warning about it. However, xbian keeps the filesystem mounted (although now empty) to /media/<nameofdrive>. When the drive is now reconnected, it gets mounted to /media/<nameofdrive>1, by this mocking up all library links until either all drives are manually unmounted via shell or xbian is rebooted.

Is there a possibility to unmount disconnected partitions automatically?
Yes, the magic word is udev Tongue

Use this udev rule (I'm using this rule on all my linux boxes, just tested with RPi2, works as expected)

Code:
# /etc/udev/rules.d/50-my-media-automount.rules

# start at sda (to ignore the system hard drive)
KERNEL!="sd[a-z]*", GOTO="my_media_automount_end"
ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="my_media_automount_end"

# import some useful filesystem info as variables
IMPORT{program}="/sbin/blkid -o udev -p %N"

# get the label if present, otherwise assign one based on device/partition
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"

# create the dir in /media and symlink it to /mnt
ACTION=="add", RUN+="/bin/mkdir -p '/media/%E{dir_name}'"

# global mount options
ACTION=="add", ENV{mount_options}="relatime"
# filesystem-specific mount options (777/666 dir/file perms for ntfs/vfat)
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},gid=100,dmask=000,fmask=111,utf8"
ACTION=="add", ENV{ID_FS_TYPE}=="btrfs", ENV{mount_options}="$env{mount_options},compress=lzo"
ACTION=="add", ENV{ID_FS_TYPE}=="ext4", ENV{mount_options}="$env{mount_options},acl,user_xattr"

# automount ntfs filesystems using ntfs-3g driver
ACTION=="add", ENV{ID_FS_TYPE}=="ntfs", RUN+="/bin/mount -t ntfs-3g -o %E{mount_options} /dev/%k '/media/%E{dir_name}'"
# automount all other filesystems
ACTION=="add", ENV{ID_FS_TYPE}!="ntfs", RUN+="/bin/mount -t auto -o %E{mount_options} /dev/%k '/media/%E{dir_name}'"

# start a script in background if desired
#ACTION=="add", RUN+="/sbin/start-stop-daemon --start --background --exec /usr/local/sbin/plugman -- '%E{dir_name}'"

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

# exit
LABEL="my_media_automount_end"

Store this to /etc/udev/rules.d/50-my-media-automount.rules and try again
Thanks a lot, the part about clean up seems to be exactly what I am looking for.

However, I would prefer just adding this code snippet to the rules already existing, but can't find anything under /etc/udev. Do you know where the OS gets its instructions regarding the disk handling from when there are no specific rules defined? I just want to make sure I am not overriding anything important.
ExclamationExclamationExclamation Do never modify existing rules, because they may be overwritten during updates ExclamationExclamationExclamation
(25th Mar, 2016 07:35 AM)Nachteule Wrote: [ -> ]ExclamationExclamationExclamation Do never modify existing rules, because they may be overwritten during updates ExclamationExclamationExclamation

You are right of course, let me rephrase that: If I just put the lines about cleaning up into that new udev rule, would it still work? And just to know what are the defaults, I would still like to know where they are defined.
Quote:If I just put the lines about cleaning up into that new udev rule, would it still work?

If mount procedure mounts device to the same folder: YES, of not: NO. But, testing it out is faster than asking here at the forum Tongue

Quote:I would still like to know where they are defined

The 'default' rules are in package udev and are located in /lib/udev/rules.d
I'm sorry, it took me a while until I could look into this again.

I had another closer look at the rules /lib/udev/rules.d and discovered the file
usbmount.rules:
Code:
# set spindown                                                                                                                      
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="/usr/share/usbmount/usbmount spindown"                  
                                                                                                                                    
# Rules for USBmount -*- conf -*-                                                                                                    
KERNEL=="sd*", DRIVERS=="sbp2",         ACTION=="add",  RUN+="/usr/share/usbmount/usbmount add"                                      
KERNEL=="sd*", SUBSYSTEMS=="block",     ACTION=="add",  RUN+="/usr/share/usbmount/usbmount add"                                      
KERNEL=="ub*", SUBSYSTEMS=="block",     ACTION=="add",  RUN+="/usr/share/usbmount/usbmount add"                                      
KERNEL=="md*", SUBSYSTEMS=="block",     ACTION=="add",  RUN+="/usr/share/usbmount/usbmount add"                                      
KERNEL=="sd*",                          ACTION=="remove",       RUN+="/usr/share/usbmount/usbmount remove"                          
KERNEL=="ub*",                          ACTION=="remove",       RUN+="/usr/share/usbmount/usbmount remove"

Examining mentioned script /usr/share/usbmount/usbmount, especially the "remove" section I found

Code:
elif [ "$ACTION" = remove];then                                                                                
                                                                                                                                                                                                            
    # A block or partition device has been removed.                              
    # Test if it is mounted.                                                                              
    findmnt -S "$DEVNAME"  -n -o fstype,target -r | sort -k2r \                            
    | while read fstype mountpoint; do                                                
            # If the mountpoint and filesystem type are maintained by              
            # this script, unmount the filesystem.                                                        
            if in_list "$fstype" "fuseblk $FILESYSTEMS"; then                            
                # Run hook scripts; ignore errors.    
                export UM_DEVICE="$DEVNAME"                                                                          
                export UM_MOUNTPOINT="$mountpoint"        
                export UM_FILESYSTEM="$fstype"                                                                          
                log info "executing command: run-parts /etc/usbmount/pre-umount.d"        
                run-parts /etc/usbmount/pre-umount.d || :  

                log info "executing command: umount $mountpoint"
                timeout=0
                mountpoint -q "$mountpoint" && while ! umount "$mountpoint" > /dev/null 2>&1; do sleep $timeout; timeout=$(($timeout+1)); [ $timeout -gt 10 ] && break; done || true
                ! mountpoint -q "$mountpoint" || umount -l "$mountpoint" || :   "$mountpoint")  
                if [ -e "/var/run/usbmount/$bs" ]; then  
                        rmdir "$mountpoint"                                                                
                        rm "/var/run/usbmount/$bs"                                                        
        fi  

                # Run hook scripts; ignore errors.                                                
                export UM_DEVICE="$DEVNAME"
                export UM_MOUNTPOINT="$mountpoint"                                                                    
                export UM_FILESYSTEM="$fstype"                                                                    
                log info "executing command: run-parts /etc/usbmount/umount.d"                      
                run-parts /etc/usbmount/umount.d || :                                          
         fi                                                                                
    done

Shouldn't this already have done the trick? Or does it not affect my hard drives? Where should I be able to find the corresponding log files?
Install/enable a system logger (syslog[-ng], rsyslog) and look into /var/log/syslog (I'm using rsyslog)
I don't know what run-parts /etc/usbmount/umount.d does.
Maybe there is missing the option '-l' when umounting drive
I'm sorry for reliving this old topic, but after a long break, I looked into this once more and I might have discovered the reason for the inconsistent behavior in the first place:

Apparently, xbian's implementation of usbmount handles all the mounting and unmounting rather well, EXCEPT when there are whitespaces in the device label! (Yeah, I know, whitespaces in Unix, big no no...)

Thats because findmnt would return the target value of a device named "device name" as "device\x20name". the read command then takes this as "devicex20name" and saves it as variable mountpoint. Using the -r option here leaves the \, but won't help either eventually, because the moutpoint and umount commands only work with device\ name or "device name".

I have tested this with an USB stick whose mount point was deleted properly when the label contained no white spaces but remained as an empty folder when it did.

I suppose, the mast straightforward solution would be piping the device name through some text stream tool to reformat the hex into the corresponding shell escape sequence.

Maybe there is a newer version of usbmount available? Or is this one customized anyway?
(12th Sep, 2016 11:35 PM)daharn Wrote: [ -> ]I have tested this with an USB stick whose mount point was deleted properly when the label contained no white spaces but remained as an empty folder when it did.

I suppose, the mast straightforward solution would be piping the device name through some text stream tool to reformat the hex into the corresponding shell escape sequence.

Maybe there is a newer version of usbmount available? Or is this one customized anyway?

There is no newer version and it is not configurable

A simple solution could be changing line 273 of file /usr/local/sbin/usbmount to

Code:
findmnt -S "$DEVNAME"  -n -o fstype,target -r | sed 's/\\x20/ /g' | sort -k2r \

This changes \x20 to ' '

Tested it here and it works
(13th Sep, 2016 03:25 AM)Nachteule Wrote: [ -> ]A simple solution could be changing line 273 of file /usr/local/sbin/usbmount to

Code:
findmnt -S "$DEVNAME"  -n -o fstype,target -r | sed 's/\\x20/ /g' | sort -k2r \

Yes, something like that was my idea too, thanks for pointing me right to the script in question.

However, changing an sbin probably isn't the "cleanest" way of doing this. Wouldn't survive an update, would it? Should I file an issue/request?
(13th Sep, 2016 09:47 AM)daharn Wrote: [ -> ]However, changing an sbin probably isn't the "cleanest" way of doing this. Wouldn't survive an update, would it? Should I file an issue/request?

For testing it's ok. But you're right, it wouldn't survive update of package. I'll keep it on mind and will change it in sources later Smile
(13th Sep, 2016 07:43 PM)Nachteule Wrote: [ -> ]
(13th Sep, 2016 09:47 AM)daharn Wrote: [ -> ]However, changing an sbin probably isn't the "cleanest" way of doing this. Wouldn't survive an update, would it? Should I file an issue/request?

For testing it's ok. But you're right, it wouldn't survive update of package. I'll keep it on mind and will change it in sources later Smile

Done
Reference URL's