[PATCH v8 13/14] Btrfs: fix dedupe 'ENOSPC' problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux