diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2025-08-06 11:48:21 -0700 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2025-09-15 23:17:35 -0700 |
| commit | 12d03a04446a8da4f5dc3cacd6888416687dd8a2 (patch) | |
| tree | 0de3012f937cb0b4fda1e25f4921e1fcbad89efb | |
| parent | cp: refactor copying to return bytes copied (diff) | |
| download | coreutils-12d03a04446a8da4f5dc3cacd6888416687dd8a2.tar.gz coreutils-12d03a04446a8da4f5dc3cacd6888416687dd8a2.zip | |
cp: don’t allocate a separate zero buffer
* src/copy-file-data.c (write_zeros): New args abuf, buf_size.
Use the lazily-allocated buffer, which most likely already exists,
rather than allocating a separate buffer just for zeros.
This makes the code more reentrant as there is no longer
a need for static storage here. Although there is some CPU
overhead due to the need to zero out the buffer for each file,
the overhead is relatively small as the buffer is smallish
and should be cached. All callers changed.
| -rw-r--r-- | src/copy-file-data.c | 32 |
1 files changed, 11 insertions, 21 deletions
diff --git a/src/copy-file-data.c b/src/copy-file-data.c index fb0b1dc40..513699e96 100644 --- a/src/copy-file-data.c +++ b/src/copy-file-data.c @@ -271,29 +271,19 @@ sparse_copy (int src_fd, int dest_fd, char **abuf, size_t buf_size, /* Write N_BYTES zero bytes to file descriptor FD. Return true if successful. Upon write failure, set errno and return false. */ static bool -write_zeros (int fd, off_t n_bytes) +write_zeros (int fd, off_t n_bytes, char **abuf, idx_t buf_size) { - static char *zeros; - static size_t nz = IO_BUFSIZE; - - /* Attempt to use a relatively large calloc'd source buffer for - efficiency, but if that allocation fails, resort to a smaller - statically allocated one. */ - if (zeros == nullptr) + char *zeros = nullptr; + while (n_bytes) { - static char fallback[1024]; - zeros = calloc (nz, 1); - if (zeros == nullptr) + idx_t n = MIN (buf_size, n_bytes); + if (!zeros) { - zeros = fallback; - nz = sizeof fallback; + if (!*abuf) + *abuf = xalignalloc (getpagesize (), buf_size); + zeros = memset (*abuf, 0, n); } - } - - while (n_bytes) - { - size_t n = MIN (nz, n_bytes); - if ((full_write (fd, zeros, n)) != n) + if (full_write (fd, zeros, n) != n) return false; n_bytes -= n; } @@ -397,7 +387,7 @@ lseek_copy (int src_fd, int dest_fd, char **abuf, size_t buf_size, /* When not inducing holes and when there is a hole between the end of the previous extent and the beginning of the current one, write zeros to the destination file. */ - if (! write_zeros (dest_fd, ext_hole_size)) + if (! write_zeros (dest_fd, ext_hole_size, abuf, buf_size)) { error (0, errno, _("%s: write failed"), quotef (dst_name)); @@ -601,7 +591,7 @@ copy_file_data (int ifd, struct stat const *ist, off_t ipos, char const *iname, ? (errno = EOVERFLOW, true) : make_holes ? ftruncate (ofd, oend) < 0 - : !write_zeros (ofd, hole_size)) + : !write_zeros (ofd, hole_size, &buf, buf_size)) { error (0, errno, _("failed to extend %s"), quoteaf (oname)); result = -1; |
