[PATCH] copy_file_range: New function to copy file data
Florian Weimer
fweimer@redhat.com
Thu Dec 21 18:07:00 GMT 2017
On 12/21/2017 06:04 PM, Adhemerval Zanella wrote:
>> + struct stat64 instat;
>> + struct stat64 outstat;
>> + if (fstat64 (infd, &instat) != 0 || fstat64 (outfd, &outstat) != 0)
>> + return -1;
>> + if (S_ISDIR (instat.st_mode) || S_ISDIR (outstat.st_mode))
>> + {
>> + __set_errno (EISDIR);
>> + return -1;
>> + }
>
> To follow the pattern you can put 'instat' and 'outstat' in its own scope.
Agreed.
>> + if (read_count < 0)
>> + {
>> + if (copied > 0)
>> + /* Report the number of bytes copied so far. */
>> + return copied;
>> + return -1;
>> + }> + if (pinoff != 0)
>> + *pinoff += read_count;
>
> pinoff != NULL.
Oh, right.
>> +
>> + /* Write the buffer part which was read to the destination. */
>> + char *end = buf + read_count;
>> + for (char *p = buf; p < end; )
>> + {
>> + ssize_t write_count;
>> + if (poutoff == NULL)
>> + write_count = write (outfd, p, end - p);
>> + else
>> + write_count = __libc_pwrite64 (outfd, p, end - p, *poutoff);
>> + if (write_count < 0)
>> + {
>> + /* Adjust the input read position to match what we have
>> + written, so that the caller can pick up after the
>> + error. */
>> + size_t written = p - buf;
>> + /* NB: This needs to be signed so that we can form the
>> + negative value below. */
>> + ssize_t overread = read_count - written;
>> + if (pinoff == NULL)
>> + {
>> + if (overread > 0)
>> + {
>> + /* We are on an error recovery path, so we
>> + cannot deal with failure here. */
>> + int save_errno = errno;
>> + (void) __libc_lseek64 (infd, -overread, SEEK_CUR);
>> + __set_errno (save_errno);
>
> Should we really handle errors here? Using current man pages EBADF, ENXIO,
> ESPIPE can't really happen because of previous checks. EINVAL and EOVERFLOW
> due resulting file offset would be negative or beyond the end of a seekable
> device is also unlikely due the fact we are using the results of a previous
> partial write to calculate the required offset. I am not sure if it can
> really fail here.
Theoretically, I assume that with enough memory pressure, the seek might
have to re-read on-disk data structures, and then anything can happen.
This is why I don't want to assert on the error. Perhaps more likely is
a file descriptor race condition which closes the descriptor under us,
but then the application is screwed anyway.
We cannot report the error in all cases because with a partial write, we
need to report the number of written bytes (because that effect has
already happened and is visible by other means).
So I think the code is okay as it is now, all things considering.
Thanks,
Florian
More information about the Libc-alpha
mailing list