}
/*
- * Arm or disarm stripe_unusable accounting across all raid56 data block
- * groups whose caches are loaded. Same walk as the commit-time rescan.
+ * Arm or disarm stripe_unusable accounting across all raid56 data and
+ * metadata block groups whose caches are loaded. Same walk as the
+ * commit-time rescan.
*/
static void stripe_alloc_sweep_groups(struct btrfs_fs_info *fs_info, bool arm)
{
list_for_each_entry(sinfo, &fs_info->space_info, list) {
int raid;
- if (!(sinfo->flags & BTRFS_BLOCK_GROUP_DATA)) {
- /*
- * Metadata: the scan that maintains the stripe_meta
- * margin and reserve stops with the option, so clear
- * them here or they hold metadata back forever.
- */
- if (!arm && (sinfo->flags & BTRFS_BLOCK_GROUP_METADATA)) {
- spin_lock(&sinfo->lock);
- sinfo->bytes_stripe_margin = 0;
- sinfo->bytes_stripe_reserve = 0;
- btrfs_try_granting_tickets(sinfo);
- spin_unlock(&sinfo->lock);
- }
+ if (!(sinfo->flags & (BTRFS_BLOCK_GROUP_DATA |
+ BTRFS_BLOCK_GROUP_METADATA)))
continue;
+ /*
+ * Metadata: the scan that maintains the stripe_meta margin
+ * and reserve stops with the option, so clear them here or
+ * they hold metadata back forever. The groups themselves
+ * are armed and disarmed below like data groups: raid56
+ * metadata places tree blocks in whole stripes from the
+ * moment the option is on, so its trapped and claimable
+ * bytes count from that moment and stop counting when it
+ * goes off.
+ */
+ if (!arm && (sinfo->flags & BTRFS_BLOCK_GROUP_METADATA)) {
+ spin_lock(&sinfo->lock);
+ sinfo->bytes_stripe_margin = 0;
+ sinfo->bytes_stripe_reserve = 0;
+ btrfs_try_granting_tickets(sinfo);
+ spin_unlock(&sinfo->lock);
}
down_read(&sinfo->groups_sem);
for (raid = 0; raid < BTRFS_NR_RAID_TYPES; raid++) {
btrfs_start_delalloc_roots(fs_info, LONG_MAX, false);
btrfs_wait_ordered_roots(fs_info, U64_MAX, NULL);
+ /*
+ * Tree blocks the legacy allocator placed in the transaction that
+ * was running at the flip are written by that transaction's commit,
+ * into the partly used stripes they were allocated in: under raid56
+ * metadata that commit is the last legacy read-modify-write, and the
+ * metadata RMW reporter says so. Wait for it before arming the
+ * check, which would otherwise report those writes as violations.
+ */
+ btrfs_commit_current_transaction(fs_info->tree_root);
clear_bit(BTRFS_FS_STRIPE_ALLOC_ENABLING, &fs_info->flags);
btrfs_info(fs_info,
"stripe_alloc: writes placed before the policy was enabled have landed");
LIST_HEAD(retire_list);
unsigned long flags;
- if (!btrfs_test_opt(fs_info, STRIPE_ALLOC))
- return;
-
+ /*
+ * No option test: a runtime disable leaves the running transaction's
+ * metadata runs open, and the commit that follows still has to close
+ * and drain them or their block groups never drop their references.
+ * The list is empty when nothing is open, so this costs nothing on a
+ * filesystem that never had the policy.
+ */
spin_lock(&fs_info->open_stripe_lock);
list_for_each_entry(bg, &fs_info->open_stripe_bgs, open_stripe_bg_list)
list_add_tail(&bg->open_stripe_retire_list, &retire_list);