Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Sep 2021 00:08:40 GMT
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: ed03973908e5 - stable/13 - VOP_COPY_FILE_RANGE: Add a COPY_FILE_RANGE_TIMEO1SEC flag
Message-ID:  <202109240008.18O08e6K009436@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by rmacklem:

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

commit ed03973908e5b9cfe41a156f8b78445c332fc864
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2021-09-08 00:35:26 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2021-09-24 00:04:29 +0000

    VOP_COPY_FILE_RANGE: Add a COPY_FILE_RANGE_TIMEO1SEC flag
    
    Although it is not specified in the RFCs, the concept that
    the NFSv4 server should reply to an RPC request within a
    reasonable time is accepted practice within the NFSv4 community.
    
    Without this patch, the NFSv4.2 server attempts to reply to
    a Copy operation within 1second by limiting the copy to
    vfs.nfs.maxcopyrange bytes (default 10Mbytes). This is crude at
    best, given the large variation in I/O subsystem performance.
    
    This patch adds a kernel only flag COPY_FILE_RANGE_TIMEO1SEC
    that the NFSv4.2 can specify, which tells VOP_COPY_FILE_RANGE()
    to return after approximately 1 second with a partial result and
    implements this in vn_generic_copy_file_range(), used by
    vop_stdcopyfilerange().
    
    Modifying the NFSv4.2 server to set this flag will be done in
    a separate patch.  Also under consideration is exposing the
    COPY_FILE_RANGE_TIMEO1SEC to userland for use on the FreeBSD
    copy_file_range(2) syscall.
    
    Although this technically does change the VFS/VOP KAPI, I do not
    think the MFC will cause problems.
    
    (cherry picked from commit c5128c48df3c2f3828432aff2ea536bb9c887e14)
---
 sys/kern/vfs_vnops.c | 31 +++++++++++++++++++++++++++++--
 sys/sys/vnode.h      |  4 ++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 8f5442bf3429..8ff78b9d6319 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -3142,6 +3142,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
 	size_t copylen, len, rem, savlen;
 	char *dat;
 	long holein, holeout;
+	struct timespec curts, endts;
 
 	holein = holeout = 0;
 	savlen = len = *lenp;
@@ -3238,7 +3239,15 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
 	 * in the inner loop where the data copying is done.
 	 * Note that some file systems such as NFSv3, NFSv4.0 and NFSv4.1 may
 	 * support holes on the server, but do not support FIOSEEKHOLE.
+	 * The kernel flag COPY_FILE_RANGE_TIMEO1SEC is used to indicate
+	 * that this function should return after 1second with a partial
+	 * completion.
 	 */
+	if ((flags & COPY_FILE_RANGE_TIMEO1SEC) != 0) {
+		getnanouptime(&endts);
+		endts.tv_sec++;
+	} else
+		timespecclear(&endts);
 	holetoeof = eof = false;
 	while (len > 0 && error == 0 && !eof && interrupted == 0) {
 		endoff = 0;			/* To shut up compilers. */
@@ -3307,8 +3316,17 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
 					*inoffp += xfer;
 					*outoffp += xfer;
 					len -= xfer;
-					if (len < savlen)
+					if (len < savlen) {
 						interrupted = sig_intr();
+						if (timespecisset(&endts) &&
+						    interrupted == 0) {
+							getnanouptime(&curts);
+							if (timespeccmp(&curts,
+							    &endts, >=))
+								interrupted =
+								    EINTR;
+						}
+					}
 				}
 			}
 			copylen = MIN(len, endoff - startoff);
@@ -3371,8 +3389,17 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
 					*outoffp += xfer;
 					copylen -= xfer;
 					len -= xfer;
-					if (len < savlen)
+					if (len < savlen) {
 						interrupted = sig_intr();
+						if (timespecisset(&endts) &&
+						    interrupted == 0) {
+							getnanouptime(&curts);
+							if (timespeccmp(&curts,
+							    &endts, >=))
+								interrupted =
+								    EINTR;
+						}
+					}
 				}
 			}
 			xfer = blksize;
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 8336fd859781..4a2581cb3db3 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -613,6 +613,10 @@ typedef void vop_getpages_iodone_t(void *, vm_page_t *, int, int);
 #define	VN_OPEN_NAMECACHE	0x00000004
 #define	VN_OPEN_INVFS		0x00000008
 
+/* copy_file_range kernel flags */
+#define	COPY_FILE_RANGE_KFLAGS		0xff000000
+#define	COPY_FILE_RANGE_TIMEO1SEC	0x01000000	/* Return after 1sec. */
+
 /*
  * Public vnode manipulation functions.
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202109240008.18O08e6K009436>