Author: rmacklem
Date: Thu Oct  1 00:33:44 2020
New Revision: 366302
URL: https://svnweb.freebsd.org/changeset/base/366302

Log:
  Clip the "len" argument to vn_generic_copy_file_range() at a
  hole size boundary.
  
  By clipping the len argument of vn_generic_copy_file_range() to end at
  an exact multiple of hole size, holes are more likely to be maintained
  during the copy.
  A hole can still straddle the boundary at the end of the
  copy range, resulting in a block being allocated in the
  output file as it is being grown in size, but this will reduce the
  likelyhood of this happening.
  
  While here, also modify setting of blksize to better handle the
  case where _PC_MIN_HOLE_SIZE is returned as 1.
  
  Reviewed by:  asomers
  Differential Revision:        https://reviews.freebsd.org/D26570

Modified:
  head/sys/kern/vfs_vnops.c

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c   Wed Sep 30 22:41:24 2020        (r366301)
+++ head/sys/kern/vfs_vnops.c   Thu Oct  1 00:33:44 2020        (r366302)
@@ -3020,7 +3020,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
        int error;
        bool cantseek, readzeros, eof, lastblock;
        ssize_t aresid;
-       size_t copylen, len, savlen;
+       size_t copylen, len, rem, savlen;
        char *dat;
        long holein, holeout;
 
@@ -3089,7 +3089,17 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *
         * This value is clipped at 4Kbytes and 1Mbyte.
         */
        blksize = MAX(holein, holeout);
-       if (blksize == 0)
+
+       /* Clip len to end at an exact multiple of hole size. */
+       if (blksize > 1) {
+               rem = *inoffp % blksize;
+               if (rem > 0)
+                       rem = blksize - rem;
+               if (len - rem > blksize)
+                       len = savlen = rounddown(len - rem, blksize) + rem;
+       }
+
+       if (blksize <= 1)
                blksize = MAX(invp->v_mount->mnt_stat.f_iosize,
                    outvp->v_mount->mnt_stat.f_iosize);
        if (blksize < 4096)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to