cp(1): fix performance issue for large non-sparse file copies
PR252358 reported a serious performance problem when copying a large non-sparse file on a UFS file system. This problem seems to have been caused by a large number of SEEK_HOLE operations, with one done for each copy_file_range(2) call. This patch modifies cp(1) to use a large (SSIZE_MAX) len argument, reducing the number of system calls and resolving the performance issue. While here, convert the type of the "rcount" from "int" to "ssize_t" so that it is consistent with that returned by both read(2) and copy_file_range(2). PR: 252358 Reviewed by: asomers Differential Revision: https://reviews.freebsd.org/D27937
This commit is contained in:
parent
9c43bd646e
commit
c98a764c68
@ -74,11 +74,10 @@ __FBSDID("$FreeBSD$");
|
|||||||
*/
|
*/
|
||||||
#define BUFSIZE_SMALL (MAXPHYS)
|
#define BUFSIZE_SMALL (MAXPHYS)
|
||||||
|
|
||||||
static int
|
static ssize_t
|
||||||
copy_fallback(int from_fd, int to_fd, char *buf, size_t bufsize)
|
copy_fallback(int from_fd, int to_fd, char *buf, size_t bufsize)
|
||||||
{
|
{
|
||||||
int rcount;
|
ssize_t rcount, wresid, wcount = 0;
|
||||||
ssize_t wresid, wcount = 0;
|
|
||||||
char *bufp;
|
char *bufp;
|
||||||
|
|
||||||
rcount = read(from_fd, buf, bufsize);
|
rcount = read(from_fd, buf, bufsize);
|
||||||
@ -100,10 +99,10 @@ copy_file(const FTSENT *entp, int dne)
|
|||||||
static char *buf = NULL;
|
static char *buf = NULL;
|
||||||
static size_t bufsize;
|
static size_t bufsize;
|
||||||
struct stat *fs;
|
struct stat *fs;
|
||||||
ssize_t wcount;
|
ssize_t rcount, wcount;
|
||||||
size_t wresid;
|
size_t wresid;
|
||||||
off_t wtotal;
|
off_t wtotal;
|
||||||
int ch, checkch, from_fd, rcount, rval, to_fd;
|
int ch, checkch, from_fd, rval, to_fd;
|
||||||
char *bufp;
|
char *bufp;
|
||||||
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
|
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
|
||||||
char *p;
|
char *p;
|
||||||
@ -236,7 +235,7 @@ copy_file(const FTSENT *entp, int dne)
|
|||||||
do {
|
do {
|
||||||
if (use_copy_file_range) {
|
if (use_copy_file_range) {
|
||||||
rcount = copy_file_range(from_fd, NULL,
|
rcount = copy_file_range(from_fd, NULL,
|
||||||
to_fd, NULL, bufsize, 0);
|
to_fd, NULL, SSIZE_MAX, 0);
|
||||||
if (rcount < 0 && errno == EINVAL) {
|
if (rcount < 0 && errno == EINVAL) {
|
||||||
/* Prob a non-seekable FD */
|
/* Prob a non-seekable FD */
|
||||||
use_copy_file_range = 0;
|
use_copy_file_range = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user