• Filipe Manana's avatar
    btrfs: send: avoid double extent tree search when finding clone source · f73853c7
    Filipe Manana authored
    At find_extent_clone() we search twice for the extent item corresponding
    to the data extent that the current file extent items points to:
    
    1) Once with a call to extent_from_logical();
    
    2) Once again during backref walking, through iterate_extent_inodes()
       which eventually leads to find_parent_nodes() where we will search
       again the extent tree for the same extent item.
    
    The extent tree can be huge, so doing this one extra search for every
    extent we want to send adds up and it's expensive.
    
    The first call is there since the send code was introduced and it
    accomplishes two things:
    
    1) Check that the extent is flagged as a data extent in the extent tree.
       But it can not be anything else, otherwise we wouldn't have a file
       extent item in the send root pointing to it.
       This was probably added to catch bugs in the early days where send was
       yet too young and the interaction with everything else was far from
       perfect;
    
    2) Check how many direct references there are on the extent, and if
       there's too many (more than SEND_MAX_EXTENT_REFS), avoid doing the
       backred walking as it may take too long and slowdown send.
    
    So improve on this by having a callback in the backref walking code that
    is called when it finds the extent item in the extent tree, and have those
    checks done in the callback. When the callback returns anything different
    from 0, it stops the backref walking code. This way we do a single search
    on the extent tree for the extent item of our data extent.
    
    Also, before this change we were only checking the number of references on
    the data extent against SEND_MAX_EXTENT_REFS, but after starting backref
    walking we will end up resolving backrefs for extent buffers in the path
    from a leaf having a file extent item pointing to our data extent, up to
    roots of trees from which the extent buffer is accessible from, due to
    shared subtrees resulting from snapshoting. We were therefore allowing for
    the possibility for send taking too long due to some node in the path from
    the leaf to a root node being shared too many times. After this change we
    check for reference counts being greater than SEND_MAX_EXTENT_REFS for
    both data extents and metadata extents.
    
    This change is part of a patchset comprised of the following patches:
    
      01/17 btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
      02/17 btrfs: fix inode list leak during backref walking at find_parent_nodes()
      03/17 btrfs: fix ulist leaks in error paths of qgroup self tests
      04/17 btrfs: remove pointless and double ulist frees in error paths of qgroup tests
      05/17 btrfs: send: avoid unnecessary path allocations when finding extent clone
      06/17 btrfs: send: update comment at find_extent_clone()
      07/17 btrfs: send: drop unnecessary backref context field initializations
      08/17 btrfs: send: avoid unnecessary backref lookups when finding clone source
      09/17 btrfs: send: optimize clone detection to increase extent sharing
      10/17 btrfs: use a single argument for extent offset in backref walking functions
      11/17 btrfs: use a structure to pass arguments to backref walking functions
      12/17 btrfs: reuse roots ulist on each leaf iteration for iterate_extent_inodes()
      13/17 btrfs: constify ulist parameter of ulist_next()
      14/17 btrfs: send: cache leaf to roots mapping during backref walking
      15/17 btrfs: send: skip unnecessary backref iterations
      16/17 btrfs: send: avoid double extent tree search when finding clone source
      17/17 btrfs: send: skip resolution of our own backref when finding clone source
    
    Performance test results are in the changelog of patch 17/17.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    f73853c7
backref.h 16.5 KB