git: a18c403fbddb - main - unionfs: remove LK_UPGRADE if falling back to the standard lock
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 18 Apr 2023 01:35:41 UTC
The branch main has been updated by jah:
URL: https://cgit.FreeBSD.org/src/commit/?id=a18c403fbddb0fa9650f133a026f40ad33751134
commit a18c403fbddb0fa9650f133a026f40ad33751134
Author: Jason A. Harmening <jah@FreeBSD.org>
AuthorDate: 2023-01-16 21:46:59 +0000
Commit: Jason A. Harmening <jah@FreeBSD.org>
CommitDate: 2023-04-18 01:31:40 +0000
unionfs: remove LK_UPGRADE if falling back to the standard lock
The LK_UPGRADE operation may have temporarily dropped the upper or
lower vnode's lock. If the unionfs vnode was reclaimed during that
window, its lock field will be reset to no longer point at the
upper/lower vnode lock, so the lock operation will use the standard
lock stored in v_lock. Remove LK_UPGRADE from the flags in this case
to avoid a lockmgr assertion, as this lock has not been previously
owned by the calling thread.
Reported by: pho
Tested by: pho
Reviewed by: kib, markj
Differential Revision: https://reviews.freebsd.org/D39272
---
sys/fs/unionfs/union_vnops.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 04d788959892..f78e653280a4 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -2010,7 +2010,7 @@ unionfs_lock(struct vop_lock1_args *ap)
vdrop(lvp);
if (uhold != 0)
vdrop(uvp);
- return (vop_stdlock(ap));
+ goto unionfs_lock_fallback;
}
}
@@ -2043,7 +2043,7 @@ unionfs_lock(struct vop_lock1_args *ap)
VOP_UNLOCK(lvp);
vdrop(lvp);
}
- return (vop_stdlock(ap));
+ goto unionfs_lock_fallback;
}
if (error != 0 && lvp != NULLVP) {
/* rollback */
@@ -2065,6 +2065,22 @@ unionfs_lock(struct vop_lock1_args *ap)
unionfs_lock_null_vnode:
ap->a_flags |= LK_INTERLOCK;
return (vop_stdlock(ap));
+
+unionfs_lock_fallback:
+ /*
+ * If we reach this point, we've discovered the unionfs vnode
+ * has been reclaimed while the upper/lower vnode locks were
+ * temporarily dropped. Such temporary droppage may happen
+ * during the course of an LK_UPGRADE operation itself, and in
+ * that case LK_UPGRADE must be cleared as the unionfs vnode's
+ * lock has been reset to point to the standard v_lock field,
+ * which has not previously been held.
+ */
+ if (flags & LK_UPGRADE) {
+ ap->a_flags &= ~LK_TYPE_MASK;
+ ap->a_flags |= LK_EXCLUSIVE;
+ }
+ return (vop_stdlock(ap));
}
static int