Patch "btrfs: send: avoid unnecessary backref lookups when finding clone source" has been added to the 4.19-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    btrfs: send: avoid unnecessary backref lookups when finding clone source

to the 4.19-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     btrfs-send-avoid-unnecessary-backref-lookups-when-fi.patch
and it can be found in the queue-4.19 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d2685359f36d8f2468fd98c915db59231997cd89
Author: Filipe Manana <fdmanana@xxxxxxxx>
Date:   Tue Nov 1 16:15:44 2022 +0000

    btrfs: send: avoid unnecessary backref lookups when finding clone source
    
    [ Upstream commit 22a3c0ac8ed0043af209a15928ae4c4855b0a4c4 ]
    
    At find_extent_clone(), unless we are given an inline extent, a file
    extent item that represents hole or an extent that starts beyond the
    i_size, we always do backref walking to look for clone sources, unless
    if we have more than SEND_MAX_EXTENT_REFS (64) known references on the
    extent.
    
    However if we know we only have one reference in the extent item and only
    one clone source (the send root), then it's pointless to do the backref
    walking to search for clone sources, as we can't clone from any other
    root. So skip the backref walking in that case.
    
    The following test was run on a non-debug kernel (Debian's default kernel
    config):
    
       $ cat test.sh
       #!/bin/bash
    
       DEV=/dev/sdi
       MNT=/mnt/sdi
    
       mkfs.btrfs -f $DEV
       mount $DEV $MNT
    
       # Create an extent tree that's not too small and none of the
       # extents is shared.
       for ((i = 1; i <= 50000; i++)); do
          xfs_io -f -c "pwrite 0 4K" $MNT/file_$i > /dev/null
          echo -ne "\r$i files created..."
       done
       echo
    
       btrfs subvolume snapshot -r $MNT $MNT/snap
    
       start=$(date +%s%N)
       btrfs send $MNT/snap > /dev/null
       end=$(date +%s%N)
    
       dur=$(( (end - start) / 1000000 ))
       echo -e "\nsend took $dur milliseconds"
    
       umount $MNT
    
    Before this change:
    
       send took 5389 milliseconds
    
    After this change:
    
       send took 4519 milliseconds  (-16.1%)
    
    Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx>
    Signed-off-by: David Sterba <dsterba@xxxxxxxx>
    Stable-dep-of: 63d5429f68a3 ("btrfs: replace strncpy() with strscpy()")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index eb2f8e84ffc9..80d248e88761 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -1306,6 +1306,7 @@ static int find_extent_clone(struct send_ctx *sctx,
 	u64 disk_byte;
 	u64 num_bytes;
 	u64 extent_item_pos;
+	u64 extent_refs;
 	u64 flags = 0;
 	struct btrfs_file_extent_item *fi;
 	struct extent_buffer *eb = path->nodes[0];
@@ -1373,14 +1374,22 @@ static int find_extent_clone(struct send_ctx *sctx,
 
 	ei = btrfs_item_ptr(tmp_path->nodes[0], tmp_path->slots[0],
 			    struct btrfs_extent_item);
+	extent_refs = btrfs_extent_refs(tmp_path->nodes[0], ei);
 	/*
 	 * Backreference walking (iterate_extent_inodes() below) is currently
 	 * too expensive when an extent has a large number of references, both
 	 * in time spent and used memory. So for now just fallback to write
 	 * operations instead of clone operations when an extent has more than
 	 * a certain amount of references.
+	 *
+	 * Also, if we have only one reference and only the send root as a clone
+	 * source - meaning no clone roots were given in the struct
+	 * btrfs_ioctl_send_args passed to the send ioctl - then it's our
+	 * reference and there's no point in doing backref walking which is
+	 * expensive, so exit early.
 	 */
-	if (btrfs_extent_refs(tmp_path->nodes[0], ei) > SEND_MAX_EXTENT_REFS) {
+	if ((extent_refs == 1 && sctx->clone_roots_cnt == 1) ||
+	    extent_refs > SEND_MAX_EXTENT_REFS) {
 		ret = -ENOENT;
 		goto out;
 	}



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux