trapexit / mergerfs

a featureful union filesystem
http://spawn.link
Other
4.3k stars 174 forks source link

Globbing in fstab together with mountall (running mounts in parallel) causing directories not found #1035

Open lsylsy2 opened 2 years ago

lsylsy2 commented 2 years ago

Describe the bug

I'm using fstab configuration like this in a snapraid+mergerfs build. /media/disk*/parity2 /media/parity2 fuse.mergerfs allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs,func.getattr=newest 0 0 there are directories under each disk called parity0, parity1, etc. which indicates different levels of parity and used to store data with different importance. However, when the system is booting, mount.fuse is ran together with the disks, so when mergerfs tries to find "/media/disk*/parity2", it will see nothing (because /media/disk0 is empty waiting to be mount, and so on), so fails. after the system is booted up, umount /media/parity2 then mount /media/parity2 fixes the problem. not using globbing fixes the problem, but it's ugly. /media/disk1/parity0:/media/disk2/parity0:/media/disk3/parity0:/media/disk4/parity0:/media/disk5/parity0:/media/disk6/parity0:/media/disk7/parity0:/media/disk8/parity0

To Reproduce

# ls /media/disk*
/media/disk1:
lost+found  parity0  parity1  parity1.content  parity2  parity2.content
/media/disk2:
lost+found  parity0  parity1  parity1.content  parity2  parity2.content
/media/disk3:
lost+found  parity0  parity1.content  parity1.parity  parity2.content  parity2.parity
/media/disk4:
lost+found  parity0  parity1  parity1.content  parity2  parity2.content
/media/disk5:
lost+found  parity0  parity1  parity1.content  parity2.content  parity2.parity
/media/disk6:
lost+found  parity0  parity1  parity1.content  parity2  parity2.content
/media/disk7:
lost+found  parity0  parity1  parity1.content  parity2  parity2.content
/media/disk8:
lost+found  parity0  parity1  parity1.content  parity2  parity2.content
# cat /etc/fstab
# some entries
/dev/disk/by-uuid/1 /media/disk1/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/2 /media/disk2/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/3 /media/disk3/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/4 /media/disk4/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/5 /media/disk5/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/6 /media/disk6/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/7 /media/disk7/ ext4 noatime,defaults 0 0
/dev/disk/by-uuid/8 /media/disk8/ ext4 noatime,defaults 0 0

# this will succeed
/media/disk1/parity0:/media/disk2/parity0:/media/disk3/parity0:/media/disk4/parity0:/media/disk5/parity0:/media/disk6/parity0:/media/disk7/parity0:/media/disk8/parity0 /media/parity0 fuse.mergerfs allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs,func.getattr=newest 0 0
# these will fail
/media/disk*/parity1 /media/parity1 fuse.mergerfs allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs,func.getattr=newest 0 0
/media/disk*/parity2 /media/parity2 fuse.mergerfs allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs,func.getattr=newest 0 0

Expected behavior

use some options to wait for dependencies to be mounted, while still keep the beauty of globbing.

System information:

Additional context

Add any other context about the problem here.

trapexit commented 2 years ago

What do you suggest mergerfs do? This is hardly unique to it. The same would happen with any dependency not yet mounted. systemd has the ability to manage dependencies and that is the standard way to handle such things.

lsylsy2 commented 2 years ago

I've searched some issues and sof sites, it looks like systemd doesn't support globbing, so no meaning to solve at that stage (If I write configuration with no globbing, I can just live with the ugly mergerfs configuration.) How will mergerfs do in this scenario (parallel mounting in fstab) if I'm using /mnt/disk*, just like in README.md ? That should be a common usage of globbing. From my understanding, systemd handle things before these parameters, and globbing happens in mergerfs code. Add a parameter like "waitmount=/media/disk*"? Or mergerfs is just writing paths into its memory, and don't care if that directory is a null mounting point at one time, but mounted with a disk next time?

trapexit commented 2 years ago

Add a parameter like "waitmount=/media/disk*"?

So to have it wait for all found paths to be mounted to before moving forward? Is it only checking against root to compare the device/filesystem or just the parent path? Cause mounts can be at any level and mounts in mounts. There would have to be a timeout otherwise it could block forever on mount failure. And then does it mount anyway or fail?

I've already started to accommodate for some of this in mergerfs v3 where there is a much more expressive config system but doing all that in the current release isn't so easy. It'd be much simpler for you just to code up what the conditions are for mounting and add it as a systemd service like many people do with mergerfs already... just doing it after your conditions are met.

trapexit commented 2 years ago

You can pretty easily create this dependency in systemd. I had been meaning to put this up. Perhaps you can use this? You can do whatever you want in the prep script.

https://github.com/trapexit/mergerfs/wiki/systemd

davidkna commented 2 years ago

@trapexit Wouldn't a mount unit work better than an exec unit here? You can also forward some parameters to systemd via fstab (x-systemd.requires-mounts-for=, x-systemd.requires=, x-systemd.after=).

trapexit commented 2 years ago

I don't see how. The "problem" is that the op doesn't want to have to enumerate all dependencies. So you need to come up with a way to discover those dependencies which a mount unit would not offer. You can't articulate "for each directory (that I know to be a target for a filesystem mount that I've defined elsewhere) wait some amount of time till all the mounts shows up (because I have it in fstab and have the drive connected and don't expect it to fail much) and then start mergerfs."

Alternatively you could write a script to generate those dependencies and update fstab or create a mount unit with them but in either case you've got to script something. This isn't something that can be managed otherwise with traditional means.

trapexit commented 2 years ago

The point of the glob feature in mergerfs is to make mounting large numbers of filesystems easier. You have to have a directory present for a mount to happen so this works without concern with a race condition because by the time userland really starts the mounts are up and mergerfs simply doesn't care whether or not a branch is different from the root filesystem or not. It just reacts when requested.

If you want that same convenience for branch locations inside a filesystem... meaning it literally doesn't exist at the time mergerfs starts... then that's a whole other ball of wax. mergerfs could try to be smart but it still will have to depend on what is known. Like... /mnt/disk/foo could strip /foo and then run the glob, find the /mnt/disk that exist, and then append /foo back on. But that means something different from what /mnt/disk*/foo means as a glob. That might be sufficient for many usecases but such behavior would need to be created. It's not an existing thing.

dpantel commented 4 months ago

I'm posting here, because this appears to be the only issue open on the topic.

I think the "bug" has been addressed in #1300. However, adding all of the x-systemd.requires-mounts-for= options in the fstab defeats the purpose of globbing the mergerfs mount. Either way, you have to spell out all the paths.