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. MFC after: 2 weeks Reviewed by: khng Differential Revision: https://reviews.freebsd.org/D31829
This commit is contained in:
parent
92de737996
commit
c5128c48df
@ -3162,6 +3162,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;
|
||||
@ -3258,7 +3259,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. */
|
||||
@ -3327,8 +3336,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);
|
||||
@ -3391,8 +3409,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;
|
||||
|
@ -616,6 +616,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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user