git: db4caf69d734 - stable/15 - p9fs: locking improvements for p9fs_stat_vnode_dotl()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 17 Mar 2026 00:38:25 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=db4caf69d73498b137070e90415c3e8b399f3544
commit db4caf69d73498b137070e90415c3e8b399f3544
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-03-05 12:35:43 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-03-15 06:58:57 +0000
p9fs: locking improvements for p9fs_stat_vnode_dotl()
PR: 293492
(cherry picked from commit 2b256f00aaee4713b8e6f0e3c0f3493065f710c4)
---
sys/fs/p9fs/p9fs_vnops.c | 42 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/sys/fs/p9fs/p9fs_vnops.c b/sys/fs/p9fs/p9fs_vnops.c
index ad1eb50276e3..81cc0e3439e6 100644
--- a/sys/fs/p9fs/p9fs_vnops.c
+++ b/sys/fs/p9fs/p9fs_vnops.c
@@ -896,6 +896,7 @@ p9fs_getattr_dotl(struct vop_getattr_args *ap)
/* Basic info */
VATTR_NULL(vap);
+ VI_LOCK(vp);
vap->va_atime.tv_sec = inode->i_atime;
vap->va_mtime.tv_sec = inode->i_mtime;
vap->va_ctime.tv_sec = inode->i_ctime;
@@ -916,6 +917,7 @@ p9fs_getattr_dotl(struct vop_getattr_args *ap)
vap->va_filerev = inode->data_version;
vap->va_vaflags = 0;
vap->va_bytes = inode->blocks * P9PROTO_TGETATTR_BLK;
+ VI_UNLOCK(vp);
return (0);
}
@@ -951,16 +953,36 @@ p9fs_stat_vnode_dotl(struct p9_stat_dotl *stat, struct vnode *vp)
{
struct p9fs_node *np;
struct p9fs_inode *inode;
+ bool excl_locked;
np = P9FS_VTON(vp);
inode = &np->inode;
+ /*
+ * This function might be called with the vnode only shared
+ * locked. Then, interlock the vnode to ensure the exclusive
+ * access to the inode fields: the thread either owns
+ * exclusive vnode lock, or shared vnode lock plus interlock.
+ *
+ * If the vnode is locked exclusive, do not take the
+ * interlock. We directly call vnode_pager_setsize(), which
+ * needs the vm_object lock, and that lock is before vnode
+ * interlock in the lock order.
+ */
ASSERT_VOP_LOCKED(vp, __func__);
+ excl_locked = VOP_ISLOCKED(vp) == LK_EXCLUSIVE;
+ if (!excl_locked)
+ VI_LOCK(vp);
+
/* Update the pager size if file size changes on host */
if (inode->i_size != stat->st_size) {
inode->i_size = stat->st_size;
- if (vp->v_type == VREG)
- vnode_pager_setsize(vp, inode->i_size);
+ if (vp->v_type == VREG) {
+ if (excl_locked)
+ vnode_pager_setsize(vp, inode->i_size);
+ else
+ vn_delayed_setsize_locked(vp);
+ }
}
inode->i_mtime = stat->st_mtime_sec;
@@ -979,11 +1001,12 @@ p9fs_stat_vnode_dotl(struct p9_stat_dotl *stat, struct vnode *vp)
inode->gen = stat->st_gen;
inode->data_version = stat->st_data_version;
- ASSERT_VOP_LOCKED(vp, __func__);
/* Setting a flag if file changes based on qid version */
if (np->vqid.qid_version != stat->qid.version)
np->flags |= P9FS_NODE_MODIFIED;
memcpy(&np->vqid, &stat->qid, sizeof(stat->qid));
+ if (!excl_locked)
+ VI_UNLOCK(vp);
return (0);
}
@@ -2213,12 +2236,25 @@ p9fs_putpages(struct vop_putpages_args *ap)
return (rtvals[0]);
}
+static int
+p9fs_delayed_setsize(struct vop_delayed_setsize_args *ap)
+{
+ struct vnode *vp;
+ struct p9fs_node *np;
+
+ vp = ap->a_vp;
+ np = P9FS_VTON(vp);
+ vnode_pager_setsize(vp, np->inode.i_size);
+ return (0);
+}
+
struct vop_vector p9fs_vnops = {
.vop_default = &default_vnodeops,
.vop_lookup = p9fs_lookup,
.vop_open = p9fs_open,
.vop_close = p9fs_close,
.vop_access = p9fs_access,
+ .vop_delayed_setsize = p9fs_delayed_setsize,
.vop_getattr = p9fs_getattr_dotl,
.vop_setattr = p9fs_setattr_dotl,
.vop_reclaim = p9fs_reclaim,