@@ -1921,8 +1921,7 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
19211921 level = -1 ;
19221922 ULIST_ITER_INIT (& uiter );
19231923 while (1 ) {
1924- bool is_shared ;
1925- bool cached ;
1924+ const unsigned long prev_ref_count = ctx -> refs .nnodes ;
19261925
19271926 walk_ctx .bytenr = bytenr ;
19281927 ret = find_parent_nodes (& walk_ctx , & shared );
@@ -1940,21 +1939,36 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
19401939 ret = 0 ;
19411940
19421941 /*
1943- * If our data extent was not directly shared (without multiple
1944- * reference items), than it might have a single reference item
1945- * with a count > 1 for the same offset, which means there are 2
1946- * (or more) file extent items that point to the data extent -
1947- * this happens when a file extent item needs to be split and
1948- * then one item gets moved to another leaf due to a b+tree leaf
1949- * split when inserting some item. In this case the file extent
1950- * items may be located in different leaves and therefore some
1951- * of the leaves may be referenced through shared subtrees while
1952- * others are not. Since our extent buffer cache only works for
1953- * a single path (by far the most common case and simpler to
1954- * deal with), we can not use it if we have multiple leaves
1955- * (which implies multiple paths).
1942+ * More than one extent buffer (bytenr) may have been added to
1943+ * the ctx->refs ulist, in which case we have to check multiple
1944+ * tree paths in case the first one is not shared, so we can not
1945+ * use the path cache which is made for a single path. Multiple
1946+ * extent buffers at the current level happen when:
1947+ *
1948+ * 1) level -1, the data extent: If our data extent was not
1949+ * directly shared (without multiple reference items), then
1950+ * it might have a single reference item with a count > 1 for
1951+ * the same offset, which means there are 2 (or more) file
1952+ * extent items that point to the data extent - this happens
1953+ * when a file extent item needs to be split and then one
1954+ * item gets moved to another leaf due to a b+tree leaf split
1955+ * when inserting some item. In this case the file extent
1956+ * items may be located in different leaves and therefore
1957+ * some of the leaves may be referenced through shared
1958+ * subtrees while others are not. Since our extent buffer
1959+ * cache only works for a single path (by far the most common
1960+ * case and simpler to deal with), we can not use it if we
1961+ * have multiple leaves (which implies multiple paths).
1962+ *
1963+ * 2) level >= 0, a tree node/leaf: We can have a mix of direct
1964+ * and indirect references on a b+tree node/leaf, so we have
1965+ * to check multiple paths, and the extent buffer (the
1966+ * current bytenr) may be shared or not. One example is
1967+ * during relocation as we may get a shared tree block ref
1968+ * (direct ref) and a non-shared tree block ref (indirect
1969+ * ref) for the same node/leaf.
19561970 */
1957- if (level == -1 && ctx -> refs .nnodes > 1 )
1971+ if (( ctx -> refs .nnodes - prev_ref_count ) > 1 )
19581972 ctx -> use_path_cache = false;
19591973
19601974 if (level >= 0 )
@@ -1964,18 +1978,45 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
19641978 if (!node )
19651979 break ;
19661980 bytenr = node -> val ;
1967- level ++ ;
1968- cached = lookup_backref_shared_cache (ctx , root , bytenr , level ,
1969- & is_shared );
1970- if (cached ) {
1971- ret = (is_shared ? 1 : 0 );
1972- break ;
1981+ if (ctx -> use_path_cache ) {
1982+ bool is_shared ;
1983+ bool cached ;
1984+
1985+ level ++ ;
1986+ cached = lookup_backref_shared_cache (ctx , root , bytenr ,
1987+ level , & is_shared );
1988+ if (cached ) {
1989+ ret = (is_shared ? 1 : 0 );
1990+ break ;
1991+ }
19731992 }
19741993 shared .share_count = 0 ;
19751994 shared .have_delayed_delete_refs = false;
19761995 cond_resched ();
19771996 }
19781997
1998+ /*
1999+ * If the path cache is disabled, then it means at some tree level we
2000+ * got multiple parents due to a mix of direct and indirect backrefs or
2001+ * multiple leaves with file extent items pointing to the same data
2002+ * extent. We have to invalidate the cache and cache only the sharedness
2003+ * result for the levels where we got only one node/reference.
2004+ */
2005+ if (!ctx -> use_path_cache ) {
2006+ int i = 0 ;
2007+
2008+ level -- ;
2009+ if (ret >= 0 && level >= 0 ) {
2010+ bytenr = ctx -> path_cache_entries [level ].bytenr ;
2011+ ctx -> use_path_cache = true;
2012+ store_backref_shared_cache (ctx , root , bytenr , level , ret );
2013+ i = level + 1 ;
2014+ }
2015+
2016+ for ( ; i < BTRFS_MAX_LEVEL ; i ++ )
2017+ ctx -> path_cache_entries [i ].bytenr = 0 ;
2018+ }
2019+
19792020 /*
19802021 * Cache the sharedness result for the data extent if we know our inode
19812022 * has more than 1 file extent item that refers to the data extent.
0 commit comments