Index: sys/kern/vfs_vnops.c =================================================================== --- sys/kern/vfs_vnops.c +++ sys/kern/vfs_vnops.c @@ -3268,9 +3268,9 @@ outvp->v_mount->mnt_stat.f_iosize); if (blksize < 4096) blksize = 4096; - else if (blksize > 1024 * 1024) - blksize = 1024 * 1024; - dat = malloc(blksize, M_TEMP, M_WAITOK); + else if (blksize > maxphys) + blksize = maxphys; + dat = malloc(maxphys, M_TEMP, M_WAITOK); /* * If VOP_IOCTL(FIOSEEKHOLE) works for invp, use it and FIOSEEKDATA @@ -3377,14 +3377,21 @@ error = 0; } - xfer = blksize; - if (cantseek) { + /* + * We only need to copy in chunks of size _PC_MIN_HOLE_SIZE if + * FIOSEEKDATA or FIOSEEKHOLE return an error and we are going + * to fall back on the "all bytes 0" method. + */ + if (__predict_false(cantseek)) { + xfer = blksize; /* * Set first xfer to end at a block boundary, so that * holes are more likely detected in the loop below via * the for all bytes 0 method. */ xfer -= (*inoffp % blksize); + } else { + xfer = blksize = maxphys; } /* Loop copying the data block. */ while (copylen > 0 && error == 0 && !eof && interrupted == 0) {