From nobody Tue Nov 16 17:14:55 2021 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id AE49C1889856; Tue, 16 Nov 2021 17:14:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Htt3M3rG6z3C90; Tue, 16 Nov 2021 17:14:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 648F111645; Tue, 16 Nov 2021 17:14:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1AGHEtBk084292; Tue, 16 Nov 2021 17:14:55 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1AGHEtBA084291; Tue, 16 Nov 2021 17:14:55 GMT (envelope-from git) Date: Tue, 16 Nov 2021 17:14:55 GMT Message-Id: <202111161714.1AGHEtBA084291@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 8ef0c11e7ce7 - main - nfsclient: upgrade vnode lock in VOP_OPEN()/VOP_CLOSE() if we need to flush buffers List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 8ef0c11e7ce79106130012cb929a8324045f7ff9 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=8ef0c11e7ce79106130012cb929a8324045f7ff9 commit 8ef0c11e7ce79106130012cb929a8324045f7ff9 Author: Konstantin Belousov AuthorDate: 2021-11-15 20:24:46 +0000 Commit: Konstantin Belousov CommitDate: 2021-11-16 17:13:29 +0000 nfsclient: upgrade vnode lock in VOP_OPEN()/VOP_CLOSE() if we need to flush buffers VOP_FSYNC() asserts that the vnode is exclusively locked for NFS. If we try to execute file with recently modified content, the assert is triggered. Reviewed by: rmacklem Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32999 --- sys/fs/nfsclient/nfs_clvnops.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index d4545cf2d840..920bf2524c01 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -647,6 +647,11 @@ nfs_open(struct vop_open_args *ap) NFSLOCKNODE(np); if (np->n_flag & NMODIFIED) { NFSUNLOCKNODE(np); + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp)) + return (EBADF); + } error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); if (error == EINTR || error == EIO) { if (NFS_ISV4(vp)) @@ -683,6 +688,11 @@ nfs_open(struct vop_open_args *ap) if (vp->v_type == VDIR) np->n_direofoffset = 0; NFSUNLOCKNODE(np); + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp)) + return (EBADF); + } error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); if (error == EINTR || error == EIO) { if (NFS_ISV4(vp)) @@ -703,6 +713,11 @@ nfs_open(struct vop_open_args *ap) (vp->v_type == VREG)) { if (np->n_directio_opens == 0) { NFSUNLOCKNODE(np); + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp)) + return (EBADF); + } error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); if (error) { if (NFS_ISV4(vp)) @@ -748,6 +763,11 @@ nfs_open(struct vop_open_args *ap) if (vp->v_writecount <= -1) { if ((obj = vp->v_object) != NULL && vm_object_mightbedirty(obj)) { + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp)) + return (EBADF); + } VM_OBJECT_WLOCK(obj); vm_object_page_clean(obj, 0, 0, OBJPC_SYNC); VM_OBJECT_WUNLOCK(obj); @@ -831,6 +851,11 @@ nfs_close(struct vop_close_args *ap) * mmap'ed writes or via write(). */ if (nfs_clean_pages_on_close && vp->v_object) { + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp) && ap->a_fflag != FNONBLOCK) + return (EBADF); + } VM_OBJECT_WLOCK(vp->v_object); vm_object_page_clean(vp->v_object, 0, 0, 0); VM_OBJECT_WUNLOCK(vp->v_object); @@ -855,11 +880,22 @@ nfs_close(struct vop_close_args *ap) * traditional vnode locking implemented for Vnode Ops. */ int cm = newnfs_commit_on_close ? 1 : 0; + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp) && ap->a_fflag != FNONBLOCK) + return (EBADF); + } error = ncl_flush(vp, MNT_WAIT, ap->a_td, cm, 0); /* np->n_flag &= ~NMODIFIED; */ } else if (NFS_ISV4(vp)) { if (nfscl_mustflush(vp) != 0) { int cm = newnfs_commit_on_close ? 1 : 0; + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp) && ap->a_fflag != + FNONBLOCK) + return (EBADF); + } error = ncl_flush(vp, MNT_WAIT, ap->a_td, cm, 0); /* @@ -869,6 +905,12 @@ nfs_close(struct vop_close_args *ap) */ } } else { + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); + if (VN_IS_DOOMED(vp) && ap->a_fflag != + FNONBLOCK) + return (EBADF); + } error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); } NFSLOCKNODE(np);