Page MenuHomeFreeBSD

D40907.diff
No OneTemporary

D40907.diff

diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -756,10 +756,12 @@
* Mark a mount point as busy. Used to synchronize access and to delay
* unmounting. Eventually, mountlist_mtx is not released on failure.
*
- * vfs_busy() is a custom lock, it can block the caller.
- * vfs_busy() only sleeps if the unmount is active on the mount point.
- * For a mountpoint mp, vfs_busy-enforced lock is before lock of any
- * vnode belonging to mp.
+ * vfs_busy() is a custom lock, it can block the caller. vfs_busy() only sleeps
+ * if the unmount is active on the mount point.
+ *
+ * To manipulate 'v_mountedhere' or cross such mounts, please use
+ * vn_busy_mountedhere(), vn_cross_single_mount() or vn_cross_mounts() depending
+ * on your needs instead of rolling your own solution.
*
* Lookup uses vfs_busy() to traverse mount points.
* root fs var fs
@@ -769,29 +771,25 @@
*
* Within each file system, the lock order is C->A->B and F->D->E.
*
- * When traversing across mounts, the system follows that lock order:
+ * When traversing across mounts, no lock order should be established between
+ * the covered vnode and the 'v_mountedhere' mount (B and F).
*
- * C->A->B
- * |
- * +->F->D->E
+ * To illustrate, here are the inner workings of the lookup() process for
+ * namei("/var"):
+ * 1. VOP_LOOKUP() obtains B while A is held.
+ * 2. A is released in order to avoid some deadlock propagation up to the root
+ * vnode in case a NFS server is not responding (see the corresponding
+ * comment in vfs_lookup()).
+ * 3. vfs_busy_mountedhere() obtains F, which may require releasing B.
+ * 4. VOP_UNLOCK() releases lock on B, if not released at 2.
+ * 5. VFS_ROOT() obtains lock on D while F is held.
+ * 6. vfs_unbusy() releases F.
+ * 7. A is relocked while D is held with vn_lock_pair().
*
- * The lookup() process for namei("/var") illustrates the process:
- * 1. VOP_LOOKUP() obtains B while A is held
- * 2. vfs_busy() obtains a shared lock on F while A and B are held
- * 3. vput() releases lock on B
- * 4. vput() releases lock on A
- * 5. VFS_ROOT() obtains lock on D while shared lock on F is held
- * 6. vfs_unbusy() releases shared lock on F
- * 7. vn_lock() obtains lock on deadfs vnode vp_crossmp instead of A.
- * Attempt to lock A (instead of vp_crossmp) while D is held would
- * violate the global order, causing deadlocks.
- *
- * dounmount() locks B while F is drained. Note that for stacked
- * filesystems, D and B in the example above may be the same lock,
- * which introdues potential lock order reversal deadlock between
- * dounmount() and step 5 above. These filesystems may avoid the LOR
- * by setting VV_CROSSLOCK on the covered vnode so that lock B will
- * remain held until after step 5.
+ * dounmount() does not anymore lock B while F is drained. Note that for
+ * stacked filesystems, D and B in the example above may be the same lock, but
+ * no lock order reversal can occur anymore since there is no ordering between
+ * B and F.
*/
int
vfs_busy(struct mount *mp, int flags)

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 20, 11:23 AM (22 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14737053
Default Alt Text
D40907.diff (3 KB)

Event Timeline