From nobody Sun Nov 14 01:26:06 2021 X-Original-To: dev-commits-src-branches@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 DAC3A184E28B; Sun, 14 Nov 2021 01:26:06 +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 4HsF5V5nTyz4Sy1; Sun, 14 Nov 2021 01:26:06 +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 A666E1DCF6; Sun, 14 Nov 2021 01:26:06 +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 1AE1Q6Fi077557; Sun, 14 Nov 2021 01:26:06 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1AE1Q6hb077556; Sun, 14 Nov 2021 01:26:06 GMT (envelope-from git) Date: Sun, 14 Nov 2021 01:26:06 GMT Message-Id: <202111140126.1AE1Q6hb077556@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Rick Macklem Subject: git: d4c5187bb179 - stable/13 - nfscl: Add setting n_localmodtime to the Write RPC code List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: d4c5187bb17925578532c98da55310250c4715d5 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=d4c5187bb17925578532c98da55310250c4715d5 commit d4c5187bb17925578532c98da55310250c4715d5 Author: Rick Macklem AuthorDate: 2021-10-31 00:08:28 +0000 Commit: Rick Macklem CommitDate: 2021-11-14 01:21:50 +0000 nfscl: Add setting n_localmodtime to the Write RPC code Similar to commit 2be417843a, I believe there could be a race between the NFS client VOP_LOOKUP() and file Writing that could result in stale file attributes being loaded into the NFS vnode by VOP_LOOKUP(). I have not been able to reproduce a failure due to this race, but I believe that there are two possibilities: The Lookup RPC happens while VOP_WRITE() is being executed and loads stale file attributes after VOP_WRITE() returns when it has already completed the Write/Commit RPC(s). --> For this case, setting the local modify timestamp at the end of VOP_WRITE() should ensure that stale file attributes are not loaded. The Lookup RPC occurs after VOP_WRITE() has returned, while asynchronous Write/Commit RPCs are in progress and then is blocked by the vnode held by VOP_OPEN/VOP_CLOSE/VOP_FSYNC which will flush writes via ncl_flush() or ncl_vinvalbuf(), clearing the NMODIFIED flag (which indicates Writes-in-progress). The VOP_LOOKUP() then acquires the NFS vnode lock and fills in stale file attributes. --> Setting the local modify timestamp in ncl_flsuh() and ncl_vinvalbuf() when they clear NMODIFIED should ensure that stale file attributes are not loaded. This patch does the above. PR: 259071 (cherry picked from commit 50dcff0816e5e4aa94f51ce27da5121e49902996) --- sys/fs/nfsclient/nfs_clbio.c | 18 +++++++++++++++--- sys/fs/nfsclient/nfs_clvnops.c | 7 +++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c index 10a76f0a4b83..250d01d88948 100644 --- a/sys/fs/nfsclient/nfs_clbio.c +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -907,6 +907,7 @@ ncl_write(struct vop_write_args *ap) int bp_cached, n, on, error = 0, error1, save2, wouldcommit; size_t orig_resid, local_resid; off_t orig_size, tmp_off; + struct timespec ts; KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, @@ -1284,7 +1285,12 @@ again: break; } while (uio->uio_resid > 0 && n > 0); - if (error != 0) { + if (error == 0) { + nanouptime(&ts); + NFSLOCKNODE(np); + np->n_localmodtime = ts; + NFSUNLOCKNODE(np); + } else { if (ioflag & IO_UNIT) { VATTR_NULL(&vattr); vattr.va_size = orig_size; @@ -1356,6 +1362,7 @@ ncl_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg) struct nfsmount *nmp = VFSTONFS(vp->v_mount); int error = 0, slpflag, slptimeo; bool old_lock; + struct timespec ts; ASSERT_VOP_LOCKED(vp, "ncl_vinvalbuf"); @@ -1400,16 +1407,21 @@ ncl_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg) } if (NFSHASPNFS(nmp)) { nfscl_layoutcommit(vp, td); + nanouptime(&ts); /* * Invalidate the attribute cache, since writes to a DS * won't update the size attribute. */ NFSLOCKNODE(np); np->n_attrstamp = 0; - } else + } else { + nanouptime(&ts); NFSLOCKNODE(np); - if (np->n_directio_asyncwr == 0) + } + if (np->n_directio_asyncwr == 0 && (np->n_flag & NMODIFIED) != 0) { + np->n_localmodtime = ts; np->n_flag &= ~NMODIFIED; + } NFSUNLOCKNODE(np); out: ncl_excl_finish(vp, old_lock); diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 8da0186c3c62..0ab02af9e5e8 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -2833,6 +2833,7 @@ ncl_flush(struct vnode *vp, int waitfor, struct thread *td, #endif struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; u_int bvecsize = 0, bveccount; + struct timespec ts; if (called_from_renewthread != 0) slptimeo = hz; @@ -3153,6 +3154,12 @@ done: vn_printf(vp, "ncl_flush failed"); error = called_from_renewthread != 0 ? EIO : EBUSY; } + if (error == 0) { + nanouptime(&ts); + NFSLOCKNODE(np); + np->n_localmodtime = ts; + NFSUNLOCKNODE(np); + } return (error); }