Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

statfs.f_fsid is not unique to a mountpoint #1492

Closed
therealkenc opened this issue Dec 12, 2016 · 10 comments
Closed

statfs.f_fsid is not unique to a mountpoint #1492

therealkenc opened this issue Dec 12, 2016 · 10 comments

Comments

@therealkenc
Copy link
Collaborator

therealkenc commented Dec 12, 2016

Right now statfs(2) returns a f_fsid of 0x00000001 for all mount points. This is okay as it goes: "Nobody knows what f_fsid is supposed to contain". There is only an implicit guarantee that (f_fsid, ino) is unique.

However, stat(2) on WSL returns different results for stat.st_dev depending on what mount the file resides. Running stat(1) on / gives device 0x01 and /home gives device 0x10 on my system.

Unfortunately, all Unices (Linux, FreeBSD, OSX) also appear to make the implicit guarantee that if the stat.st_dev of a file is different, then the statfs.f_fsid of the mount point for the file must also be different. Some filesystem-centric code appears to use this fact to map files to mount points without pathwalking1.

Request is to stuff whatever lives in stat.st_dev for a given mount point directory that lives in /proc/mounts (/, /home, /root, etc) into the statfs.f_fsid returned for that path.


1which is technically problematic because on Unix, parents can be `unlink()ed` and `rename()d` out from under you
@fpqc
Copy link

fpqc commented Dec 12, 2016

@therealkenc I noticed something on real Linux at least: Parents cannot be renamed or unlinked if there is a root shell with pwd a subdirectory. It only happens with root shells, not ordinary user shells. Maybe that's another reason why it's not a problem on Linux or other Unices?

The error iirc when you try to do it is the "Access Denied: The device or resource is busy" one

@therealkenc
Copy link
Collaborator Author

therealkenc commented Dec 12, 2016

Hence the small print. "NFS Silly Renamed" edit actually ext4 too.

@therealkenc
Copy link
Collaborator Author

therealkenc commented Dec 12, 2016

Damn, I knew you were allowed to rename parents out from under files (now look what you've done). Following test case succeeds on Real Linux™, but fails on WSL. Doesn't matter root or otherwise, natch. This is on VolFS but I bet DriveFS fares no better.

And all I wanted was a unique ID in statfs.f_fsid...

// silly-rename.c
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, const char* argv[]) {
  const char msg[] = "amy's parent morton renamed to maura\n";
  int fd, ret;

  mkdir("/tmp/morton", 0777);
  fd = open("/tmp/morton/amy", O_CREAT|O_RDWR, 0666);
  ret = rename("/tmp/morton/", "/tmp/maura/");
  if (ret < 0) {
    perror("rename failed: ");
  } else {
    write(fd, msg, sizeof(msg) - 1);
  }
  close(fd);
}

strace on WSL:

mkdir("/tmp/morton", 0777)              = 0
open("/tmp/morton/amy", O_RDWR|O_CREAT, 0666) = 3
rename("/tmp/morton/", "/tmp/maura/")   = -1 EACCES (Permission denied)

strace on Ubuntu:

mkdir("/tmp/morton", 0777)              = 0
open("/tmp/morton/amy", O_RDWR|O_CREAT, 0666) = 3
rename("/tmp/morton/", "/tmp/maura/")   = 0

@therealkenc
Copy link
Collaborator Author

therealkenc commented Dec 12, 2016

Hmm. Is my last post a manifestation of #1420 or different? If it's a dup please don't lose sight of statfs.f_fsid.

@benhillis
Copy link
Member

I'll take a look at the f_fsid issue and report back.

@therealkenc
Copy link
Collaborator Author

therealkenc commented Dec 15, 2016

For what it is worth (maybe save you some time), on Real Linux, statfs.f_fsid is tied into the /dev/block mechanism, which doesn't exist in WSL. So one could re-characterize the OP title as "libblkid-dev doesn't work on WSL". But if I do that, you're going to say "WSL doesn't support block devices" and send me to User Voice purgatory. I don't need block devices, just a block id equivalent. Which you are doing sort of anyway, because regular file stat.st_dev is getting populated. It doesn't matter from a semantics standpoint what statfs.f_fsid contains -- just so long as it is unique to a mount point. Indeed from a clean room man statfs standpoint, 'Linux' (whatever that means) makes no guarantees about what lives there. The only practical difficulty at the moment is that WSL presents /, /home, /root etc as different filesystems but statfs.f_fsid is the same for all of them. Appreciate you taking a look.

@benhillis
Copy link
Member

@therealkenc - Unless I'm misinterpreting what you're saying I don't think that even Linux makes the guarantee that if stat.st_dev is different that the statfs.f_fsid must be different. Take /proc and /sys mountpoints:

Different st_dev values:

root@UBUNTU-SERVER:/# stat /proc
Device: 4h/4d   Inode: 1           Links: 208
root@UBUNTU-SERVER:/# stat /sys
Device: 11h/17d Inode: 1           Links: 13

Equal statfs.f_fsid values

strace -v df /proc
statfs("/proc", {f_type="PROC_SUPER_MAGIC", f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096, f_flags=4142}) = 0
strace -v df /sys
statfs("/sys", {f_type="SYSFS_MAGIC", f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096, f_flags=4142}) = 0

@therealkenc
Copy link
Collaborator Author

Interesting. The code in question uses statfs.f_fsid as a fallback to other libblkid-dev stuff that is failing, and I didn't try /proc (or was it /sys) at the time I wrote the OP. I'll follow up with precisely what went wrong when I get a chance. But you are absolutely correct, it seems there is no such guarantee.

@therealkenc
Copy link
Collaborator Author

therealkenc commented Dec 21, 2016

Narrowing scope entirely to statfs.f_fsid here to stay focused, it appears that ext4, at least, spits out unique ids (checked on a VM). So really this is about whether lxfs has "ext4-like behavior" or is its own dog. The latter is perfectly legal from man statfs standpoint. The former is probably what many devs assume. Mostly counting angels now because app layer people are supposed to use libblkid-dev anyway.

The code in question is here at line 1039 for what it is worth. It only gets that far in the posix_get_fsid() function because the immediately preceding lines have failed and we've run out of options for a unique filesystem identifier. Whatever is going wrong there would be a different issue though, and this thread is muddled enough already. It can be filed separately. Feel free to mark this as linux-behavior, with the unusual caveat that there is no lxfs on Real Linux.

@therealkenc
Copy link
Collaborator Author

therealkenc commented May 1, 2018

From circa Christmas 2016:

Unless I'm misinterpreting what you're saying I don't think that even Linux makes the guarantee that if stat.st_dev is different that the statfs.f_fsid must be different.

After working with some unrelated WSL filesystem stuff recently, I think it is fair to call the crux of my OP linux-behavior. It is unusual for different /home and / mount points to have the same statfs.f_fsid on Linux, but there is nothing which guarantees that they are different. The code cited above is making a fundamental assumption that the filesystem is backed by a block device; and really that's just a bad assumption. Putting this to bed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants