@@ -1921,8 +1921,7 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
1921
1921
level = -1 ;
1922
1922
ULIST_ITER_INIT (& uiter );
1923
1923
while (1 ) {
1924
- bool is_shared ;
1925
- bool cached ;
1924
+ const unsigned long prev_ref_count = ctx -> refs .nnodes ;
1926
1925
1927
1926
walk_ctx .bytenr = bytenr ;
1928
1927
ret = find_parent_nodes (& walk_ctx , & shared );
@@ -1940,21 +1939,36 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
1940
1939
ret = 0 ;
1941
1940
1942
1941
/*
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.
1956
1970
*/
1957
- if (level == -1 && ctx -> refs .nnodes > 1 )
1971
+ if (( ctx -> refs .nnodes - prev_ref_count ) > 1 )
1958
1972
ctx -> use_path_cache = false;
1959
1973
1960
1974
if (level >= 0 )
@@ -1964,18 +1978,45 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
1964
1978
if (!node )
1965
1979
break ;
1966
1980
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
+ }
1973
1992
}
1974
1993
shared .share_count = 0 ;
1975
1994
shared .have_delayed_delete_refs = false;
1976
1995
cond_resched ();
1977
1996
}
1978
1997
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
+
1979
2020
/*
1980
2021
* Cache the sharedness result for the data extent if we know our inode
1981
2022
* has more than 1 file extent item that refers to the data extent.
0 commit comments