ret = 0;
} else if (sinfo->flags & BTRFS_BLOCK_GROUP_DATA) {
u64 sinfo_used = btrfs_space_info_used(sinfo, true);
+ u64 trapped = 0;
+
+ /*
+ * The free space of a stripe_alloc group that is trapped in
+ * partially used stripes is already counted as used in the
+ * space_info (bytes_stripe_unusable), and that contribution is
+ * dropped once the group is read-only (see the disarm below).
+ * Asking the rest of the filesystem to absorb it a second time
+ * means a fragmented raid56 data group can never be made
+ * read-only: scrub and device replace, which require it for
+ * raid56, then fail with ENOSPC on a half-full filesystem.
+ */
+ if (READ_ONCE(cache->stripe_unusable_ready))
+ trapped = min(READ_ONCE(cache->stripe_unusable), num_bytes);
/*
* Here we make sure if we mark this bg RO, we still have enough
* free space as buffer.
*/
- if (sinfo_used + num_bytes <= sinfo->total_bytes)
+ if (sinfo_used - trapped + num_bytes <= sinfo->total_bytes)
ret = 0;
} else {
/*