The branch stable/14 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e3b27cc3546fb39ec579d023b3520d15a1628021

commit e3b27cc3546fb39ec579d023b3520d15a1628021
Author:     Mark Johnston <[email protected]>
AuthorDate: 2024-04-04 15:18:03 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2024-05-08 13:06:16 +0000

    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
    
    (cherry picked from commit 08f3d5b60cdfff434e391d96cdffc5a90c550b07)
---
 sys/kern/vfs_vnops.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 51386d0e9581..1171b72a3a96 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -3341,7 +3341,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t 
*inoffp,
        off_t startoff, endoff, xfer, xfer2;
        u_long blksize;
        int error, interrupted;
-       bool cantseek, readzeros, eof, lastblock, holetoeof, sparse;
+       bool cantseek, readzeros, eof, first, lastblock, holetoeof, sparse;
        ssize_t aresid, r = 0;
        size_t copylen, len, savlen;
        off_t outsize;
@@ -3482,6 +3482,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t 
*inoffp,
                endts.tv_sec++;
        } else
                timespecclear(&endts);
+       first = true;
        holetoeof = eof = false;
        while (len > 0 && error == 0 && !eof && interrupted == 0) {
                endoff = 0;                     /* To shut up compilers. */
@@ -3583,10 +3584,17 @@ vn_generic_copy_file_range(struct vnode *invp, off_t 
*inoffp,
                         */
                        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)
                                xfer = copylen;
+                       first = false;
                        error = vn_lock(invp, LK_SHARED);
                        if (error != 0)
                                goto out;
@@ -3596,7 +3604,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t 
*inoffp,
                            curthread);
                        VOP_UNLOCK(invp);
                        lastblock = false;
-                       if (error == 0 && aresid > 0) {
+                       if (error == 0 && (xfer == 0 || aresid > 0)) {
                                /* Stop the copy at EOF on the input file. */
                                xfer -= aresid;
                                eof = true;

Reply via email to