svn commit: r354574 - head/sys/kern

Rick Macklem rmacklem at FreeBSD.org
Sun Nov 10 01:08:15 UTC 2019


Author: rmacklem
Date: Sun Nov 10 01:08:14 2019
New Revision: 354574
URL: https://svnweb.freebsd.org/changeset/base/354574

Log:
  Update copy_file_range(2) to be Linux5 compatible.
  
  The current linux man page and testing done on a fairly recent linux5.n
  kernel have identified two changes to the semantics of the linux
  copy_file_range system call.
  Since the copy_file_range(2) system call is intended to be linux compatible
  and is only currently in head/current and not used by any commands,
  it seems appropriate to update the system call to be compatible with
  the current linux one.
  The first of these semantic changes was changed to be compatible with
  linux5.n by r354564.
  For the second semantic change, the old linux man page stated that, if
  infd and outfd referred to the same file, EBADF should be returned.
  Now, the semantics is to allow infd and outfd to refer to the same file
  so long as the byte ranges defined by the input file offset, output file offset
  and len does not overlap. If the byte ranges do overlap, EINVAL should be
  returned.
  This patch modifies copy_file_range(2) to be linux5.n compatible for this
  semantic change.

Modified:
  head/sys/kern/vfs_syscalls.c
  head/sys/kern/vfs_vnops.c

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c	Sat Nov  9 22:25:45 2019	(r354573)
+++ head/sys/kern/vfs_syscalls.c	Sun Nov 10 01:08:14 2019	(r354574)
@@ -4838,7 +4838,7 @@ kern_copy_file_range(struct thread *td, int infd, off_
 	outvp = outfp->f_vnode;
 	/* Sanity check the f_flag bits. */
 	if ((outfp->f_flag & (FWRITE | FAPPEND)) != FWRITE ||
-	    (infp->f_flag & FREAD) == 0 || invp == outvp) {
+	    (infp->f_flag & FREAD) == 0) {
 		error = EBADF;
 		goto out;
 	}
@@ -4846,6 +4846,17 @@ kern_copy_file_range(struct thread *td, int infd, off_
 	/* If len == 0, just return 0. */
 	if (len == 0)
 		goto out;
+
+	/*
+	 * If infp and outfp refer to the same file, the byte ranges cannot
+	 * overlap.
+	 */
+	if (invp == outvp && ((savinoff <= savoutoff && savinoff + len >
+	    savoutoff) || (savinoff > savoutoff && savoutoff + len >
+	    savinoff))) {
+		error = EINVAL;
+		goto out;
+	}
 
 	/* Range lock the byte ranges for both invp and outvp. */
 	for (;;) {

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Sat Nov  9 22:25:45 2019	(r354573)
+++ head/sys/kern/vfs_vnops.c	Sun Nov 10 01:08:14 2019	(r354574)
@@ -2699,8 +2699,6 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, 
 	    uvalout < (uint64_t)*outoffp || invp->v_type != VREG ||
 	    outvp->v_type != VREG)
 		error = EINVAL;
-	else if (invp == outvp)
-		error = EBADF;
 	if (error != 0)
 		goto out;
 


More information about the svn-src-head mailing list