1. 15 Feb, 2023 31 commits
  2. 13 Feb, 2023 9 commits
    • Filipe Manana's avatar
      btrfs: add an api to delete a specific entry from the lru cache · d588adae
      Filipe Manana authored
      In order to replace the open coded name cache in send with the lru cache,
      we need an API for the lru cache to delete a specific entry for which we
      did a previous lookup. This adds the API for it, and a next patch in the
      series will use it.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      d588adae
    • Filipe Manana's avatar
      btrfs: allow a generation number to be associated with lru cache entries · 0da0c560
      Filipe Manana authored
      This allows an optional generation number to be associated to each entry
      of the lru cache. Entries with the same key but different generations, are
      stored in the linked list to which the maple tree points to. This is meant
      to be used when there's a small number of different generations, so the
      impact of searching a linked list is negligible. The goal is to get rid of
      the open coded name cache in the send code (which uses a radix tree and
      a similar linked list of values/entries) and use instead the lru cache
      module. For that particular use case we have at most 2 generations that
      are associated to each key (inode number): one generation for the send
      root and another generation for the parent root. The actual migration of
      the send name cache is done in the next patch in the series.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      0da0c560
    • Filipe Manana's avatar
      btrfs: send: cache information about created directories · e8a7f49d
      Filipe Manana authored
      During an incremental send, when processing the reference for an inode
      we need to check if the directory where the new reference is located was
      already created before creating the new reference. This check, which is
      done by the helper did_create_dir(), can be expensive if the directory
      has many entries, since it consists in searching the send root's b+tree
      and visiting every single dir index key until we either find one which
      points to an inode with a number smaller than the current inode's number
      or until we visited all index keys. So it doesn't scale well for very
      large directories.
      
      So improve on this by caching created directories using a lru cache, and
      limiting its size to 64 entries, which results in using at most 4096
      bytes of memory. The caching is optional, if we fail to allocate memory,
      we just proceed as before and use the existing slower path.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      e8a7f49d
    • Filipe Manana's avatar
      btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems · 6273ee62
      Filipe Manana authored
      The lru cache is backed by a maple tree, which uses the unsigned long
      type for keys, and that type has a width of 32 bits on 32 bits systems
      and a width of 64 bits on 64 bits systems.
      
      Currently there is only one user of the lru cache, the send backref cache,
      which uses a sector number as a key, a logical address right shifted by
      fs_info->sectorsize_bits, so a 32 bits width is not yet a problem (the
      same happens with the radix tree we use to track extent buffers,
      fs_info->buffer_radix).
      
      However the next patches in the series will start using the lru cache for
      cases where inode numbers are the keys, and the inode numbers are always
      64 bits, even if we are running on a 32 bits system.
      
      So adapt the lru cache to allow multiple values under the same key, by
      having the maple tree store a head entry that points to a list of entries
      instead of pointing to a single entry. This is a similar approach to what
      we currently do for the name cache in send (which uses a radix tree that
      has indexes with an unsigned long type as well), and will allow later to
      use the lru cache for the send name cache as well.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      6273ee62
    • Filipe Manana's avatar
      btrfs: send: genericize the backref cache to allow it to be reused · 90b90d4a
      Filipe Manana authored
      The backref cache is a cache backed by a maple tree and a linked list to
      keep track of temporal access to cached entries (the LRU entry always at
      the head of the list). This type of caching method is going to be useful
      in other scenarios, so make the cache implementation more generic and
      move it into its own header and source files.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      90b90d4a
    • Filipe Manana's avatar
      btrfs: send: initialize all the red black trees earlier · d307d2f3
      Filipe Manana authored
      After we allocate the send context object and before we initialize all
      the red black trees, we can jump to the 'out' label if some errors happen,
      and then under the 'out' label we use RB_EMPTY_ROOT() against some of the
      those trees, which we have not yet initialized. This happens to work out
      ok because the send context object was initialized to zeroes with kzalloc
      and the RB_ROOT initializer just happens to have the following definition:
      
          #define RB_ROOT (struct rb_root) { NULL, }
      
      But it's really neither clean nor a good practice as RB_ROOT is supposed
      to be opaque and in case it changes or we change those red black trees to
      some other data structure, it leaves us in a precarious situation.
      
      So initialize all the red black trees immediately after allocating the
      send context and before any jump into the 'out' label.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      d307d2f3
    • Filipe Manana's avatar
      btrfs: send: iterate waiting dir move rbtree only once when processing refs · 8c139e1d
      Filipe Manana authored
      When processing the new references for an inode, we unnecessarily iterate
      twice the waiting dir moves rbtree, once with is_waiting_for_move() and
      if we found an entry in the rbtree, we iterate it again with a call to
      get_waiting_dir_move(). This is pointless, we can make this simpler and
      more efficient by calling only get_waiting_dir_move(), so just do that.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      8c139e1d
    • Filipe Manana's avatar
      btrfs: send: reduce searches on parent root when checking if dir can be removed · 474e4761
      Filipe Manana authored
      During an incremental send, every time we remove a reference (dentry) for
      an inode and the parent directory does not exists anymore in the send
      root, we go check if we can remove the directory by making a call to
      can_rmdir(). This helper can only return true (value 1) if all dentries
      were already removed, and for that it always does a search on the parent
      root for dir index keys - if it finds any dentry referring to an inode
      with a number higher then the inode currently being processed, then the
      directory can not be removed and it must return false (value 0).
      
      However that means if a directory that was deleted had 1000 dentries, and
      each one pointed to an inode with a number higher then the number of the
      directory's inode, we end up doing 1000 searches on the parent root.
      Typically files are created in a directory after the directory was created
      and therefore they get an higher inode number than the directory. It's
      also common to have the each dentry pointing to an inode with a higher
      number then the inodes the previous dentries point to, for example when
      creating a series of files inside a directory, a very common pattern.
      
      So improve on that by having the first call to can_rmdir() for a directory
      to check the number of the inode that the last dentry points to and cache
      that inode number in the orphan dir structure. Then every subsequent call
      to can_rmdir() can avoid doing a search on the parent root if the number
      of the inode currently being processed is smaller than cached inode number
      at the directory's orphan dir structure.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      474e4761
    • Filipe Manana's avatar
      btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir() · 78cf1a95
      Filipe Manana authored
      At can_rmdir() we start by searching the orphan dirs rbtree for an orphan
      dir object for the target directory. Later when iterating over the dir
      index keys, if we find that any dir entry points to inode for which there
      is a pending dir move or the inode was not yet processed, we exit because
      we can't remove the directory yet. However we end up always calling
      add_orphan_dir_info(), which will iterate again the rbtree and if there is
      already an orphan dir object (created by the first call to can_rmdir()),
      it returns the existing object. This is unnecessary work because in case
      there is already an existing orphan dir object, we got a reference to it
      at the start of can_rmdir(). So skip the call to add_orphan_dir_info()
      if we already have a reference for an orphan dir object.
      
      This patch is part of a larger patchset and the changelog of the last
      patch in the series contains a sample performance test and results.
      The patches that comprise the patchset are the following:
      
        btrfs: send: directly return from did_overwrite_ref() and simplify it
        btrfs: send: avoid unnecessary generation search at did_overwrite_ref()
        btrfs: send: directly return from will_overwrite_ref() and simplify it
        btrfs: send: avoid extra b+tree searches when checking reference overrides
        btrfs: send: remove send_progress argument from can_rmdir()
        btrfs: send: avoid duplicated orphan dir allocation and initialization
        btrfs: send: avoid unnecessary orphan dir rbtree search at can_rmdir()
        btrfs: send: reduce searches on parent root when checking if dir can be removed
        btrfs: send: iterate waiting dir move rbtree only once when processing refs
        btrfs: send: initialize all the red black trees earlier
        btrfs: send: genericize the backref cache to allow it to be reused
        btrfs: adapt lru cache to allow for 64 bits keys on 32 bits systems
        btrfs: send: cache information about created directories
        btrfs: allow a generation number to be associated with lru cache entries
        btrfs: add an api to delete a specific entry from the lru cache
        btrfs: send: use the lru cache to implement the name cache
        btrfs: send: update size of roots array for backref cache entries
        btrfs: send: cache utimes operations for directories if possible
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      78cf1a95