Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102982515
D40907.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D40907.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D40907: vfs_busy(): Update the description of mount crossing
Attached
Detach File
Event Timeline
Log In to Comment