Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Mar 2026 12:46:14 +0000
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 2b256f00aaee - main - p9fs: locking improvements for p9fs_stat_vnode_dotl()
Message-ID:  <69b01296.23915.81ee5f2@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=2b256f00aaee4713b8e6f0e3c0f3493065f710c4

commit 2b256f00aaee4713b8e6f0e3c0f3493065f710c4
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-03-05 12:35:43 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-03-10 12:44:34 +0000

    p9fs: locking improvements for p9fs_stat_vnode_dotl()
    
    If the vnode is share-locked:
    - Use vn_delayed_setsize() to avoid calling vnode_pager_setsize() with
      the vnode only shared locked.
    - Interlock the vnode to get exclusive mode for updating the node
      fields.
    
    Reciprocally, interlock the vnode in p9fs_getattr_dotl() to observe the
    consistent values on read.
    
    PR:     293492
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D55665
---
 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 e64d7840f7f9..c6d35548e9ed 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,


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69b01296.23915.81ee5f2>