@@ -138,6 +138,7 @@ struct share_check {
138
138
u64 root_objectid ;
139
139
u64 inum ;
140
140
int share_count ;
141
+ bool have_delayed_delete_refs ;
141
142
};
142
143
143
144
static inline int extent_is_shared (struct share_check * sc )
@@ -820,16 +821,11 @@ static int add_delayed_refs(const struct btrfs_fs_info *fs_info,
820
821
struct preftrees * preftrees , struct share_check * sc )
821
822
{
822
823
struct btrfs_delayed_ref_node * node ;
823
- struct btrfs_delayed_extent_op * extent_op = head -> extent_op ;
824
824
struct btrfs_key key ;
825
- struct btrfs_key tmp_op_key ;
826
825
struct rb_node * n ;
827
826
int count ;
828
827
int ret = 0 ;
829
828
830
- if (extent_op && extent_op -> update_key )
831
- btrfs_disk_key_to_cpu (& tmp_op_key , & extent_op -> key );
832
-
833
829
spin_lock (& head -> lock );
834
830
for (n = rb_first_cached (& head -> ref_tree ); n ; n = rb_next (n )) {
835
831
node = rb_entry (n , struct btrfs_delayed_ref_node ,
@@ -855,10 +851,16 @@ static int add_delayed_refs(const struct btrfs_fs_info *fs_info,
855
851
case BTRFS_TREE_BLOCK_REF_KEY : {
856
852
/* NORMAL INDIRECT METADATA backref */
857
853
struct btrfs_delayed_tree_ref * ref ;
854
+ struct btrfs_key * key_ptr = NULL ;
855
+
856
+ if (head -> extent_op && head -> extent_op -> update_key ) {
857
+ btrfs_disk_key_to_cpu (& key , & head -> extent_op -> key );
858
+ key_ptr = & key ;
859
+ }
858
860
859
861
ref = btrfs_delayed_node_to_tree_ref (node );
860
862
ret = add_indirect_ref (fs_info , preftrees , ref -> root ,
861
- & tmp_op_key , ref -> level + 1 ,
863
+ key_ptr , ref -> level + 1 ,
862
864
node -> bytenr , count , sc ,
863
865
GFP_ATOMIC );
864
866
break ;
@@ -884,13 +886,22 @@ static int add_delayed_refs(const struct btrfs_fs_info *fs_info,
884
886
key .offset = ref -> offset ;
885
887
886
888
/*
887
- * Found a inum that doesn't match our known inum, we
888
- * know it's shared.
889
+ * If we have a share check context and a reference for
890
+ * another inode, we can't exit immediately. This is
891
+ * because even if this is a BTRFS_ADD_DELAYED_REF
892
+ * reference we may find next a BTRFS_DROP_DELAYED_REF
893
+ * which cancels out this ADD reference.
894
+ *
895
+ * If this is a DROP reference and there was no previous
896
+ * ADD reference, then we need to signal that when we
897
+ * process references from the extent tree (through
898
+ * add_inline_refs() and add_keyed_refs()), we should
899
+ * not exit early if we find a reference for another
900
+ * inode, because one of the delayed DROP references
901
+ * may cancel that reference in the extent tree.
889
902
*/
890
- if (sc && sc -> inum && ref -> objectid != sc -> inum ) {
891
- ret = BACKREF_FOUND_SHARED ;
892
- goto out ;
893
- }
903
+ if (sc && count < 0 )
904
+ sc -> have_delayed_delete_refs = true;
894
905
895
906
ret = add_indirect_ref (fs_info , preftrees , ref -> root ,
896
907
& key , 0 , node -> bytenr , count , sc ,
@@ -920,7 +931,7 @@ static int add_delayed_refs(const struct btrfs_fs_info *fs_info,
920
931
}
921
932
if (!ret )
922
933
ret = extent_is_shared (sc );
923
- out :
934
+
924
935
spin_unlock (& head -> lock );
925
936
return ret ;
926
937
}
@@ -1023,7 +1034,8 @@ static int add_inline_refs(const struct btrfs_fs_info *fs_info,
1023
1034
key .type = BTRFS_EXTENT_DATA_KEY ;
1024
1035
key .offset = btrfs_extent_data_ref_offset (leaf , dref );
1025
1036
1026
- if (sc && sc -> inum && key .objectid != sc -> inum ) {
1037
+ if (sc && sc -> inum && key .objectid != sc -> inum &&
1038
+ !sc -> have_delayed_delete_refs ) {
1027
1039
ret = BACKREF_FOUND_SHARED ;
1028
1040
break ;
1029
1041
}
@@ -1033,6 +1045,7 @@ static int add_inline_refs(const struct btrfs_fs_info *fs_info,
1033
1045
ret = add_indirect_ref (fs_info , preftrees , root ,
1034
1046
& key , 0 , bytenr , count ,
1035
1047
sc , GFP_NOFS );
1048
+
1036
1049
break ;
1037
1050
}
1038
1051
default :
@@ -1122,7 +1135,8 @@ static int add_keyed_refs(struct btrfs_root *extent_root,
1122
1135
key .type = BTRFS_EXTENT_DATA_KEY ;
1123
1136
key .offset = btrfs_extent_data_ref_offset (leaf , dref );
1124
1137
1125
- if (sc && sc -> inum && key .objectid != sc -> inum ) {
1138
+ if (sc && sc -> inum && key .objectid != sc -> inum &&
1139
+ !sc -> have_delayed_delete_refs ) {
1126
1140
ret = BACKREF_FOUND_SHARED ;
1127
1141
break ;
1128
1142
}
@@ -1522,6 +1536,9 @@ static bool lookup_backref_shared_cache(struct btrfs_backref_shared_cache *cache
1522
1536
{
1523
1537
struct btrfs_backref_shared_cache_entry * entry ;
1524
1538
1539
+ if (!cache -> use_cache )
1540
+ return false;
1541
+
1525
1542
if (WARN_ON_ONCE (level >= BTRFS_MAX_LEVEL ))
1526
1543
return false;
1527
1544
@@ -1557,6 +1574,19 @@ static bool lookup_backref_shared_cache(struct btrfs_backref_shared_cache *cache
1557
1574
return false;
1558
1575
1559
1576
* is_shared = entry -> is_shared ;
1577
+ /*
1578
+ * If the node at this level is shared, than all nodes below are also
1579
+ * shared. Currently some of the nodes below may be marked as not shared
1580
+ * because we have just switched from one leaf to another, and switched
1581
+ * also other nodes above the leaf and below the current level, so mark
1582
+ * them as shared.
1583
+ */
1584
+ if (* is_shared ) {
1585
+ for (int i = 0 ; i < level ; i ++ ) {
1586
+ cache -> entries [i ].is_shared = true;
1587
+ cache -> entries [i ].gen = entry -> gen ;
1588
+ }
1589
+ }
1560
1590
1561
1591
return true;
1562
1592
}
@@ -1573,6 +1603,9 @@ static void store_backref_shared_cache(struct btrfs_backref_shared_cache *cache,
1573
1603
struct btrfs_backref_shared_cache_entry * entry ;
1574
1604
u64 gen ;
1575
1605
1606
+ if (!cache -> use_cache )
1607
+ return ;
1608
+
1576
1609
if (WARN_ON_ONCE (level >= BTRFS_MAX_LEVEL ))
1577
1610
return ;
1578
1611
@@ -1648,6 +1681,7 @@ int btrfs_is_data_extent_shared(struct btrfs_root *root, u64 inum, u64 bytenr,
1648
1681
.root_objectid = root -> root_key .objectid ,
1649
1682
.inum = inum ,
1650
1683
.share_count = 0 ,
1684
+ .have_delayed_delete_refs = false,
1651
1685
};
1652
1686
int level ;
1653
1687
@@ -1669,6 +1703,7 @@ int btrfs_is_data_extent_shared(struct btrfs_root *root, u64 inum, u64 bytenr,
1669
1703
/* -1 means we are in the bytenr of the data extent. */
1670
1704
level = -1 ;
1671
1705
ULIST_ITER_INIT (& uiter );
1706
+ cache -> use_cache = true;
1672
1707
while (1 ) {
1673
1708
bool is_shared ;
1674
1709
bool cached ;
@@ -1698,6 +1733,24 @@ int btrfs_is_data_extent_shared(struct btrfs_root *root, u64 inum, u64 bytenr,
1698
1733
extent_gen > btrfs_root_last_snapshot (& root -> root_item ))
1699
1734
break ;
1700
1735
1736
+ /*
1737
+ * If our data extent was not directly shared (without multiple
1738
+ * reference items), than it might have a single reference item
1739
+ * with a count > 1 for the same offset, which means there are 2
1740
+ * (or more) file extent items that point to the data extent -
1741
+ * this happens when a file extent item needs to be split and
1742
+ * then one item gets moved to another leaf due to a b+tree leaf
1743
+ * split when inserting some item. In this case the file extent
1744
+ * items may be located in different leaves and therefore some
1745
+ * of the leaves may be referenced through shared subtrees while
1746
+ * others are not. Since our extent buffer cache only works for
1747
+ * a single path (by far the most common case and simpler to
1748
+ * deal with), we can not use it if we have multiple leaves
1749
+ * (which implies multiple paths).
1750
+ */
1751
+ if (level == -1 && tmp -> nnodes > 1 )
1752
+ cache -> use_cache = false;
1753
+
1701
1754
if (level >= 0 )
1702
1755
store_backref_shared_cache (cache , root , bytenr ,
1703
1756
level , false);
@@ -1713,6 +1766,7 @@ int btrfs_is_data_extent_shared(struct btrfs_root *root, u64 inum, u64 bytenr,
1713
1766
break ;
1714
1767
}
1715
1768
shared .share_count = 0 ;
1769
+ shared .have_delayed_delete_refs = false;
1716
1770
cond_resched ();
1717
1771
}
1718
1772
0 commit comments