With dedupe, writes are likely to produce metadata but no data, which means
producing more delayed_refs, and this can ends up aborting a transaction
because it needs to allocate enough free space from global_rsv to turn
delayed_refs into real extent tree's nodes/leaves and global_rsv is used up.
So we must take the worst case for throttling delayed refs in this dedup case,
ie, allocating one leaf on each delayed ref head update.
Signed-off-by: Liu Bo <bo.li.liu@xxxxxxxxxx>
---
fs/btrfs/extent-tree.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f14db92..df3a645 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2661,6 +2661,19 @@ static inline u64 heads_to_leaves(struct btrfs_root *root, u64 heads)
{
u64 num_bytes;
+ /*
+ * For deduplication it's a special case where we must be very careful
+ * on throttling the number of delayed_refs, just because with dedupe,
+ * we're likely to produce _only_ metadata but no data, which results in
+ * quite a lot of delayed_refs, and consequently global_rsv may be used
+ * up and we get a RO btrfs.
+ *
+ * So we have to take the worst case -- one leaf for updating a ref head
+ * and its related refs.
+ */
+ if (root->fs_info->dedup_bs != 0)
+ return heads;
+
num_bytes = heads * (sizeof(struct btrfs_extent_item) +
sizeof(struct btrfs_extent_inline_ref));
if (!btrfs_fs_incompat(root->fs_info, SKINNY_METADATA))
--
1.8.2.1
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html