mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
copy_file_range: Call vn_rdwr() at least once
This ensures that we invoke VOP_READ on the input file even if it's empty, which in turn helps ensure that filesystems update the atime of the file. PR: 274615 Reviewed by: olce, rmacklem, kib MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D43524
This commit is contained in:
parent
c1326c01df
commit
08f3d5b60c
|
@ -3339,7 +3339,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
|
||||||
off_t startoff, endoff, xfer, xfer2;
|
off_t startoff, endoff, xfer, xfer2;
|
||||||
u_long blksize;
|
u_long blksize;
|
||||||
int error, interrupted;
|
int error, interrupted;
|
||||||
bool cantseek, readzeros, eof, lastblock, holetoeof, sparse;
|
bool cantseek, readzeros, eof, first, lastblock, holetoeof, sparse;
|
||||||
ssize_t aresid, r = 0;
|
ssize_t aresid, r = 0;
|
||||||
size_t copylen, len, savlen;
|
size_t copylen, len, savlen;
|
||||||
off_t outsize;
|
off_t outsize;
|
||||||
|
@ -3480,6 +3480,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
|
||||||
endts.tv_sec++;
|
endts.tv_sec++;
|
||||||
} else
|
} else
|
||||||
timespecclear(&endts);
|
timespecclear(&endts);
|
||||||
|
first = true;
|
||||||
holetoeof = eof = false;
|
holetoeof = eof = false;
|
||||||
while (len > 0 && error == 0 && !eof && interrupted == 0) {
|
while (len > 0 && error == 0 && !eof && interrupted == 0) {
|
||||||
endoff = 0; /* To shut up compilers. */
|
endoff = 0; /* To shut up compilers. */
|
||||||
|
@ -3581,10 +3582,17 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
|
||||||
*/
|
*/
|
||||||
xfer -= (*inoffp % blksize);
|
xfer -= (*inoffp % blksize);
|
||||||
}
|
}
|
||||||
/* Loop copying the data block. */
|
|
||||||
while (copylen > 0 && error == 0 && !eof && interrupted == 0) {
|
/*
|
||||||
|
* Loop copying the data block. If this was our first attempt
|
||||||
|
* to copy anything, allow a zero-length block so that the VOPs
|
||||||
|
* get a chance to update metadata, specifically the atime.
|
||||||
|
*/
|
||||||
|
while (error == 0 && ((copylen > 0 && !eof) || first) &&
|
||||||
|
interrupted == 0) {
|
||||||
if (copylen < xfer)
|
if (copylen < xfer)
|
||||||
xfer = copylen;
|
xfer = copylen;
|
||||||
|
first = false;
|
||||||
error = vn_lock(invp, LK_SHARED);
|
error = vn_lock(invp, LK_SHARED);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -3594,7 +3602,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp,
|
||||||
curthread);
|
curthread);
|
||||||
VOP_UNLOCK(invp);
|
VOP_UNLOCK(invp);
|
||||||
lastblock = false;
|
lastblock = false;
|
||||||
if (error == 0 && aresid > 0) {
|
if (error == 0 && (xfer == 0 || aresid > 0)) {
|
||||||
/* Stop the copy at EOF on the input file. */
|
/* Stop the copy at EOF on the input file. */
|
||||||
xfer -= aresid;
|
xfer -= aresid;
|
||||||
eof = true;
|
eof = true;
|
||||||
|
|
Loading…
Reference in a new issue