Page MenuHomeFreeBSD

Make getfsstat(2) not skip filesystems being unmounted if passed MNT_WAIT flag.
ClosedPublic

Authored by trasz on Sep 25 2016, 10:39 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, Apr 7, 10:55 AM
Unknown Object (File)
Sun, Apr 7, 8:20 AM
Unknown Object (File)
Sun, Apr 7, 8:16 AM
Unknown Object (File)
Sun, Apr 7, 3:37 AM
Unknown Object (File)
Feb 15 2024, 11:37 AM
Unknown Object (File)
Feb 1 2024, 9:45 PM
Unknown Object (File)
Jan 9 2024, 12:28 PM
Unknown Object (File)
Dec 31 2023, 1:42 PM
Subscribers

Details

Summary

As it is now, the getfsstat(2) syscall will skip filesystems that are
in the process of being unmounted, even if the unmount would eventually
fail due to eg the filesystem being busy.

This behaviour breaks autounmountd(8) - if you try to manually unmount
a mounted filesystem, using 'automount -u', and the autounmountd attempts
to refresh the filesystem list in that very moment, it would conclude that
the filesystem got unmounted and not try to unmount it afterwards.

This behaviour depends on MNT_WAIT flag being passed to getfsstat(2).
This makes getfsstat(2) "hang" in case of hung mount - eg NFS with the server
being offline - and it's the same thing that would happen with MNT_WAIT
anyway.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

trasz retitled this revision from to Make getfsstat(2) not skip filesystems being unmounted if passed MNT_WAIT flag..
trasz updated this object.
trasz edited the test plan for this revision. (Show Details)
trasz added a reviewer: kib.

Erm, this code seems to have stupid bugs. Namely, MNT_WAIT and other constants are not flags. So the test for MNT_LAZY always implies MNT_WAIT etc. I think this must be untangles in kern_getfsstat() before your fix can be elaborated more.

Did you reviewed the callers ?

trasz updated this object.
trasz edited edge metadata.

Fixed version.

sys/kern/vfs_syscalls.c
485 ↗(On Diff #21791)

If MNT_WAIT was specified to the vfs_busy() call, and error is returned, then mp might become unmounted and removed from the list. In this case, calculation of nmp below is wrong.

Is it enough to just replace the loop with TAILQ_FOREACH_SAFE()?

In D8030#174387, @trasz wrote:

Is it enough to just replace the loop with TAILQ_FOREACH_SAFE()?

Of course no. What would prevent the struct mount referenced by the temp pointer from being unmounted ?

Make sure the mp doesn't get freed.

kib requested changes to this revision.Oct 30 2016, 11:37 AM
kib edited edge metadata.

The mount point structure is never freed since the uma zone is type-stable. Also vfs_busy() manages the references itself.

Please re-read the description of the issue, it has nothing to do with the free of the mp. It is about mp being removed from the global list on umount, and the iterator both loosing the position and TAILQ_NEXT() dereferencing wrong pointer.

This revision now requires changes to proceed.Oct 30 2016, 11:37 AM
trasz edited edge metadata.

Okay, I think I get it now. How about this one?

sys/kern/vfs_syscalls.c
469 ↗(On Diff #21809)

Please use style. Fill the line up to column 72 at least, before splitting.

485 ↗(On Diff #21809)

vfs_busy() returns error, and not a boolean. use if (vfs_busy() != 0) {

487 ↗(On Diff #21809)

Sometimes you free random memory.
A comment should be added explaining why restart is needed.

trasz edited edge metadata.

Fixes suggested by kib@.

kib edited edge metadata.

I suggest asking Peter to test this with a load where parallel unmounts and fstatfs(2) (e.g. df(1)) are used.

This revision is now accepted and ready to land.Oct 31 2016, 3:46 PM
This revision was automatically updated to reflect the committed changes.