Expand the set of filesystems considered remote on Linux

Some background: fish has some files which should be updated atomically:
specifically the history file and the universal variables file. If two fish
processes modified these in-place at the same time, then that could result
in interleaved writes and corrupted files.

To prevent this, fish uses the write-to-adjacent-file-then-rename to
atomically swap in a new file (history is slightly more complicated than
this, for performance, but this remains true). This avoids corruption.

However if two fish processes attempt this at the same time, then one
process will win the race and the data from the other process will be lost.
To prevent this, fish attempts to take an (advisory) lock on the target
file before beginning this process. This prevents data loss because only
one fish instance can replace the target file at once. (fish checks to
ensure it's locked the right file).

However some filesystems, particularly remote file systems, may have locks
which hang for a long time, preventing the user from using their shell.
This is far more serious than data loss, which is not catastrophic: losing
a history item or variable is not a major deal. So fish just attempts to
skip locks on remote filesystems.

Unfortunately Linux does not have a good API for checking if a filesystem
is remote: the best you can do is check the file system's magic number
against a hard-coded list. Today, the list is NFS_SUPER_MAGIC,
SMB_SUPER_MAGIC, SMB2_MAGIC_NUMBER, and CIFS_MAGIC_NUMBER.

Expand it to AFS_SUPER_MAGIC, CODA_SUPER_MAGIC, NCP_SUPER_MAGIC,
NFS_SUPER_MAGIC, OCFS2_SUPER_MAGIC, SMB_SUPER_MAGIC, SMB2_MAGIC_NUMBER,
CIFS_MAGIC_NUMBER, V9FS_MAGIC which is believed to be exhaustive.

ALSO include FUSE_SUPER_MAGIC: if the user's home directory is some FUSE
filesystem, that's kind of sus and the fewer tricks we try to pull, the
better.
This commit is contained in:
Peter Ammon 2024-10-27 18:10:56 -07:00 committed by Peter Ammon
parent 3e3aa08c28
commit e322d3addc

View File

@ -717,12 +717,19 @@ fn path_remoteness(path: &wstr) -> DirRemoteness {
}
// Linux has constants for these like NFS_SUPER_MAGIC, SMB_SUPER_MAGIC, CIFS_MAGIC_NUMBER but
// these are in varying headers. Simply hard code them.
// Note that we treat FUSE filesystems as remote, which means we lock less on such filesystems.
// NOTE: The cast is necessary for 32-bit systems because of the 4-byte CIFS_MAGIC_NUMBER
match usize::try_from(buf.f_type).unwrap() {
0x5346414F | // AFS_SUPER_MAGIC - Andrew Fule System
0x73757245 | // CODA_SUPER_MAGIC - Coda File System
0x564c | // NCP_SUPER_MAGIC - Novell NetWare
0x6969 | // NFS_SUPER_MAGIC
0x7461636f | // OCFS2_SUPER_MAGIC - Oracle Cluster File System
0x517B | // SMB_SUPER_MAGIC
0xFE534D42 | // SMB2_MAGIC_NUMBER - not in the manpage
0xFF534D42 // CIFS_MAGIC_NUMBER
0xFE534D42 | // SMB2_MAGIC_NUMBER
0xFF534D42 | // CIFS_MAGIC_NUMBER
0x01021997 | // V9FS_MAGIC
0x65735546 // FUSE_SUPER_MAGIC
=> DirRemoteness::remote,
_ => {
DirRemoteness::unknown