Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146944987
D39444.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D39444.diff
View Options
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -388,7 +388,8 @@
KASSERT(dvp != NULL || (vp->v_vflag & VV_ROOT) != 0,
("%s: NULL dvp for non-root vp %p", __func__, vp));
- vn_lock_pair(lowervp, false, uppervp, false);
+ vn_lock_pair(lowervp, false, LK_EXCLUSIVE, uppervp, false,
+ LK_EXCLUSIVE);
error = insmntque1(vp, mp);
if (error != 0) {
unionfs_nodeget_cleanup(vp, unp);
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1273,7 +1273,7 @@
* Use vn_lock_pair to avoid establishing an ordering between vnodes
* from different filesystems.
*/
- vn_lock_pair(vp, false, newdp, false);
+ vn_lock_pair(vp, false, LK_EXCLUSIVE, newdp, false, LK_EXCLUSIVE);
VI_LOCK(vp);
vp->v_iflag &= ~VI_MOUNT;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -3753,50 +3753,74 @@
/*
* Lock pair of vnodes vp1, vp2, avoiding lock order reversal.
- * vp1_locked indicates whether vp1 is exclusively locked; if not, vp1
- * must be unlocked. Same for vp2 and vp2_locked. One of the vnodes
- * can be NULL.
+ * vp1_locked indicates whether vp1 is locked; if not, vp1 must be
+ * unlocked. Same for vp2 and vp2_locked. One of the vnodes can be
+ * NULL.
*
- * The function returns with both vnodes exclusively locked, and
- * guarantees that it does not create lock order reversal with other
- * threads during its execution. Both vnodes could be unlocked
- * temporary (and reclaimed).
+ * The function returns with both vnodes exclusively or shared locked,
+ * according to corresponding lkflags, and guarantees that it does not
+ * create lock order reversal with other threads during its execution.
+ * Both vnodes could be unlocked temporary (and reclaimed).
+ *
+ * If requesting shared locking, locked vnode lock must not be recursed.
*/
void
-vn_lock_pair(struct vnode *vp1, bool vp1_locked, struct vnode *vp2,
- bool vp2_locked)
+vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1,
+ struct vnode *vp2, bool vp2_locked, int lkflags2)
{
int error;
+ MPASS(lkflags1 == LK_SHARED || lkflags1 == LK_EXCLUSIVE);
+ MPASS(lkflags2 == LK_SHARED || lkflags2 == LK_EXCLUSIVE);
+
if (vp1 == NULL && vp2 == NULL)
return;
+
if (vp1 != NULL) {
- if (vp1_locked)
- ASSERT_VOP_ELOCKED(vp1, "vp1");
- else
+ if (lkflags1 == LK_SHARED &&
+ (vp1->v_vnlock->lock_object.lo_flags & LK_NOSHARE) != 0)
+ lkflags1 = LK_EXCLUSIVE;
+ if (vp1_locked && VOP_ISLOCKED(vp1) != LK_EXCLUSIVE) {
+ ASSERT_VOP_LOCKED(vp1, "vp1");
+ if (lkflags1 == LK_EXCLUSIVE) {
+ VOP_UNLOCK(vp1);
+ ASSERT_VOP_UNLOCKED(vp1,
+ "vp1 shared recursed");
+ vp1_locked = false;
+ }
+ } else if (!vp1_locked)
ASSERT_VOP_UNLOCKED(vp1, "vp1");
} else {
vp1_locked = true;
}
+
if (vp2 != NULL) {
- if (vp2_locked)
- ASSERT_VOP_ELOCKED(vp2, "vp2");
- else
+ if (lkflags2 == LK_SHARED &&
+ (vp2->v_vnlock->lock_object.lo_flags & LK_NOSHARE) != 0)
+ lkflags2 = LK_EXCLUSIVE;
+ if (vp2_locked && VOP_ISLOCKED(vp2) != LK_EXCLUSIVE) {
+ ASSERT_VOP_LOCKED(vp2, "vp2");
+ if (lkflags2 == LK_EXCLUSIVE) {
+ VOP_UNLOCK(vp2);
+ ASSERT_VOP_UNLOCKED(vp2,
+ "vp2 shared recursed");
+ vp2_locked = false;
+ }
+ } else if (!vp2_locked)
ASSERT_VOP_UNLOCKED(vp2, "vp2");
} else {
vp2_locked = true;
}
+
if (!vp1_locked && !vp2_locked) {
- vn_lock(vp1, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(vp1, lkflags1 | LK_RETRY);
vp1_locked = true;
}
- for (;;) {
- if (vp1_locked && vp2_locked)
- break;
+ while (!vp1_locked || !vp2_locked) {
if (vp1_locked && vp2 != NULL) {
if (vp1 != NULL) {
- error = VOP_LOCK1(vp2, LK_EXCLUSIVE | LK_NOWAIT,
+ error = VOP_LOCK1(vp2, lkflags2 | LK_NOWAIT,
__FILE__, __LINE__);
if (error == 0)
break;
@@ -3804,12 +3828,12 @@
vp1_locked = false;
vn_lock_pair_pause("vlp1");
}
- vn_lock(vp2, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(vp2, lkflags2 | LK_RETRY);
vp2_locked = true;
}
if (vp2_locked && vp1 != NULL) {
if (vp2 != NULL) {
- error = VOP_LOCK1(vp1, LK_EXCLUSIVE | LK_NOWAIT,
+ error = VOP_LOCK1(vp1, lkflags1 | LK_NOWAIT,
__FILE__, __LINE__);
if (error == 0)
break;
@@ -3817,14 +3841,22 @@
vp2_locked = false;
vn_lock_pair_pause("vlp2");
}
- vn_lock(vp1, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(vp1, lkflags1 | LK_RETRY);
vp1_locked = true;
}
}
- if (vp1 != NULL)
- ASSERT_VOP_ELOCKED(vp1, "vp1 ret");
- if (vp2 != NULL)
- ASSERT_VOP_ELOCKED(vp2, "vp2 ret");
+ if (vp1 != NULL) {
+ if (lkflags1 == LK_EXCLUSIVE)
+ ASSERT_VOP_ELOCKED(vp1, "vp1 ret");
+ else
+ ASSERT_VOP_LOCKED(vp1, "vp1 ret");
+ }
+ if (vp2 != NULL) {
+ if (lkflags2 == LK_EXCLUSIVE)
+ ASSERT_VOP_ELOCKED(vp2, "vp2 ret");
+ else
+ ASSERT_VOP_LOCKED(vp2, "vp2 ret");
+ }
}
int
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -757,8 +757,8 @@
bool vn_isdisk(struct vnode *vp);
int _vn_lock(struct vnode *vp, int flags, const char *file, int line);
#define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__)
-void vn_lock_pair(struct vnode *vp1, bool vp1_locked, struct vnode *vp2,
- bool vp2_locked);
+void vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1,
+ struct vnode *vp2, bool vp2_locked, int lkflags2);
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp);
int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode,
u_int vn_open_flags, struct ucred *cred, struct file *fp);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -3323,7 +3323,7 @@
if (vp != NULL) {
VOP_UNLOCK(dvp);
ffs_syncvnode(vp, MNT_NOWAIT, 0);
- vn_lock_pair(dvp, false, vp, true);
+ vn_lock_pair(dvp, false, LK_EXCLUSIVE, vp, true, LK_EXCLUSIVE);
if (dvp->v_data == NULL)
goto out;
}
@@ -3335,7 +3335,8 @@
VOP_UNLOCK(dvp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_data == NULL) {
- vn_lock_pair(dvp, false, vp, true);
+ vn_lock_pair(dvp, false, LK_EXCLUSIVE, vp, true,
+ LK_EXCLUSIVE);
goto out;
}
ACQUIRE_LOCK(ump);
@@ -3345,7 +3346,8 @@
VOP_UNLOCK(vp);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
if (dvp->v_data == NULL) {
- vn_lock_pair(dvp, true, vp, false);
+ vn_lock_pair(dvp, true, LK_EXCLUSIVE, vp, false,
+ LK_EXCLUSIVE);
goto out;
}
}
@@ -3360,7 +3362,7 @@
journal_check_space(ump);
FREE_LOCK(ump);
- vn_lock_pair(dvp, false, vp, false);
+ vn_lock_pair(dvp, false, LK_EXCLUSIVE, vp, false, LK_EXCLUSIVE);
out:
ndp->ni_dvp_seqc = vn_seqc_read_any(dvp);
if (vp != NULL)
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -235,7 +235,7 @@
if (vp1 != NULL)
VOP_UNLOCK(vp1);
error = ufs_sync_nlink1(mp);
- vn_lock_pair(vp, false, vp1, false);
+ vn_lock_pair(vp, false, LK_EXCLUSIVE, vp1, false, LK_EXCLUSIVE);
return (error);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 8, 12:22 AM (15 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29387577
Default Alt Text
D39444.diff (7 KB)
Attached To
Mode
D39444: vn_lock_pair(): allow to request shared locking
Attached
Detach File
Event Timeline
Log In to Comment