git: b70042adfebb - main - nfscl: Check for mmap(2)'d file before doing direct output

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Mon, 20 Dec 2021 21:13:28 UTC
The branch main has been updated by rmacklem:

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

commit b70042adfebbc4ee90d6a88dd6dc34d3f8ed5c37
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2021-12-20 21:08:51 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2021-12-20 21:10:26 +0000

    nfscl: Check for mmap(2)'d file before doing direct output
    
    Commit 867c27c23a5c modified the NFS client so that
    it does IO_APPEND writes directly to the NFS server,
    bypassing the buffer cache.  However, this could result
    in stale data in client pages when the file is mmap(2)'d.
    As such, the NFS client needs to call vm_object_is_active()
    to check if the file is mmap(2)'d and only do direct
    output if the file is not mmap(2)'d.
    
    This patch adds this check.
    
    Although a simple patch, I have given it a long MFC,
    since the related commit 867c27c23a5c made a significant
    semantics change and, as such, has a long MFC.
    
    MFC after:      3 months
---
 sys/fs/nfsclient/nfs_clbio.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index c3339617acce..06b51c050d34 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -1001,12 +1001,24 @@ ncl_write(struct vop_write_args *ap)
 	if (uio->uio_resid == 0)
 		return (0);
 
+	/*
+	 * If the file in not mmap()'d, do IO_APPEND writing via a
+	 * synchronous direct write.  This can result in a significant
+	 * performance improvement.
+	 * If the file is mmap()'d, this cannot be done, since there
+	 * is no way to maintain consistency between the file on the
+	 * NFS server and the file's mmap()'d pages.
+	 */
+	NFSLOCKNODE(np);
 	if (vp->v_type == VREG && ((newnfs_directio_enable && (ioflag &
-	    IO_DIRECT)) || (ioflag & IO_APPEND))) {
+	    IO_DIRECT)) || ((ioflag & IO_APPEND) &&
+	    (vp->v_object == NULL || !vm_object_is_active(vp->v_object))))) {
+		NFSUNLOCKNODE(np);
 		if ((ioflag & IO_APPEND) != 0)
 			ioflag |= IO_SYNC;
 		return nfs_directio_write(vp, uio, cred, ioflag);
 	}
+	NFSUNLOCKNODE(np);
 
 	/*
 	 * Maybe this should be above the vnode op call, but so long as