Page MenuHomeFreeBSD

vfs: stop refing freed mount points in vop_stdgetwritemount
ClosedPublic

Authored by mjg on Aug 25 2019, 4:24 AM.
Tags
None
Referenced Files
F106162082: D21411.diff
Thu, Dec 26, 10:08 AM
Unknown Object (File)
Nov 23 2024, 4:45 AM
Unknown Object (File)
Nov 19 2024, 12:40 AM
Unknown Object (File)
Oct 14 2024, 5:41 PM
Unknown Object (File)
Sep 24 2024, 8:49 AM
Unknown Object (File)
Sep 22 2024, 11:36 PM
Unknown Object (File)
Sep 21 2024, 4:45 AM
Unknown Object (File)
Sep 6 2024, 12:58 AM
Subscribers

Details

Summary

The address is read without any locks held and can be stale. This alone is not a big problem since mounts are type-stable. However, changing the refcount can possibly mess with the structure after it got reassigned for another mount point (which also clears the count). Moreover the current code makes it impossible to ensure everyone is done with the mount point at least in terms of modifying it (excluding locking).

This will be of significance with other patches.

Diff Detail

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

Event Timeline

sys/kern/vfs_default.c
597 ↗(On Diff #61251)

So what about this comment ?

sys/kern/vfs_default.c
597 ↗(On Diff #61251)

Caller-visible state is roughly the same in that the mount point is either NULL or what was found at the time, but it can be stale. So the comment can be reworded to be clear or removed altogether. I don't think it is that useful in the first place as the only real consumer drops the vnode interlock anyway again making the vnode suspetible to losing the mp.

sys/kern/vfs_default.c
597 ↗(On Diff #61251)

Can it be ? Now that you both ref and check vp->v_mount under the mnt lock, I suspect that the vnode cannot be removed from the mnt queue behind us, and then the mp cannot be reused since we keep the reference.

sys/kern/vfs_default.c
597 ↗(On Diff #61251)
  • original code refs in a very racy manner possibly having to backpedal from it - this is taken care of
  • even with reference taken the vnode mount point can still be changed to NULL, therefore a refed (but stale) mount can still be returned

I think the comment was stating both of these, with the first no longer being the case.

So how about either removing this comment altogether or replacing it with +/-:

/*
 * Note that despite the reference held ->v_mount can still become NULL after drop
 * the lock because of forced unmount, which is not a problem.
 */
sys/kern/vfs_default.c
597 ↗(On Diff #61251)

This is better. For the case 2, it was possible that mp was reused for different mount, which is not allowed after you added the lock. It can only be that the vnode is reclaimed and no longer associated with the mp, but mp cannot be reused for anything yet.

sys/kern/vfs_default.c
597 ↗(On Diff #61251)

yes, but that's in part what backpedalling was for

So how about this:

Note that having a reference does not prevent forced unmount from setting ->v_mount to NULL after the lock gets release.
kib added inline comments.
sys/kern/vfs_default.c
597 ↗(On Diff #61251)

It is still somewhat implicit, by describing what does occur (and which is relatively obvious), instead of describing what consequences the consumer should cope with.

This revision is now accepted and ready to land.Aug 31 2019, 5:54 PM
sys/kern/vfs_default.c
597 ↗(On Diff #61251)

Ok, how about this:

Note that having a reference does not prevent forced unmount from setting ->v_mount to NULL after the lock gets released. This is of no consequence for typical consumers (most notably vn_start_write) since the in this case the vnode is VI_DOOMED. The only thing to do is to unref the returned moint point (if any).
sys/kern/vfs_default.c
597 ↗(On Diff #61251)

... the vnode is VI_DOOMED, and the mount point itself is at some stage of unmount.

Note that having a reference does not prevent forced unmount from setting ->v_mount to NULL after the lock gets released. This is of no consequence for typical consumers (most notably vn_start_write) since in this case the vnode is VI_DOOMED. Unmount might have progressed far enough that its completion is only delayed by the reference obtained here. The consumer only needs to concern itself with dropping it.