Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Oct 2020 01:04:28 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r366557 - head/sys/kern
Message-ID:  <202010090104.09914S2U011334@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Fri Oct  9 01:04:28 2020
New Revision: 366557
URL: https://svnweb.freebsd.org/changeset/base/366557

Log:
  Make vn_generic_copy_file_range() interruptible via a signal.
  
  Without this patch, when vn_generic_copy_file_range() is
  doing a large copy, it will remain in the function for a
  considerable amount of time, delaying handling of any
  outstanding signals until the copy completes.
  
  This patch adds checks for signals that need to be
  processed after each successful data copy cycle.
  When sig_intr() returns non-zero, vn_generic_copy_file_range()
  will return.
  The check "if (len < savlen)" ensures that some data
  has been copied, so that progress will be made.
  
  Note that, since copy_file_range(2) is allowed to
  return fewer bytes copied than requested, it
  will never return EINTR/ERESTART when sig_intr()
  returns non-zero.
  
  Reviewed by:	kib, asomers
  Differential Revision:	https://reviews.freebsd.org/D26620

Modified:
  head/sys/kern/vfs_vnops.c

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Fri Oct  9 00:27:45 2020	(r366556)
+++ head/sys/kern/vfs_vnops.c	Fri Oct  9 01:04:28 2020	(r366557)
@@ -3017,7 +3017,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 	struct uio io;
 	off_t startoff, endoff, xfer, xfer2;
 	u_long blksize;
-	int error;
+	int error, interrupted;
 	bool cantseek, readzeros, eof, lastblock;
 	ssize_t aresid;
 	size_t copylen, len, rem, savlen;
@@ -3027,6 +3027,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 	holein = holeout = 0;
 	savlen = len = *lenp;
 	error = 0;
+	interrupted = 0;
 	dat = NULL;
 
 	error = vn_lock(invp, LK_SHARED);
@@ -3116,7 +3117,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 	 * support holes on the server, but do not support FIOSEEKHOLE.
 	 */
 	eof = false;
-	while (len > 0 && error == 0 && !eof) {
+	while (len > 0 && error == 0 && !eof && interrupted == 0) {
 		endoff = 0;			/* To shut up compilers. */
 		cantseek = true;
 		startoff = *inoffp;
@@ -3177,6 +3178,8 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 					*inoffp += xfer;
 					*outoffp += xfer;
 					len -= xfer;
+					if (len < savlen)
+						interrupted = sig_intr();
 				}
 			}
 			copylen = MIN(len, endoff - startoff);
@@ -3198,7 +3201,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 			xfer -= (*inoffp % blksize);
 		}
 		/* Loop copying the data block. */
-		while (copylen > 0 && error == 0 && !eof) {
+		while (copylen > 0 && error == 0 && !eof && interrupted == 0) {
 			if (copylen < xfer)
 				xfer = copylen;
 			error = vn_lock(invp, LK_SHARED);
@@ -3239,6 +3242,8 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
 					*outoffp += xfer;
 					copylen -= xfer;
 					len -= xfer;
+					if (len < savlen)
+						interrupted = sig_intr();
 				}
 			}
 			xfer = blksize;



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