From nobody Sun Feb 8 17:03:57 2026 Received: from mail-ot1-f66.google.com (mail-ot1-f66.google.com [209.85.210.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C808E1BC08F for ; Wed, 14 Jan 2026 01:13:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768353224; cv=none; b=h5K3TSwBMzujHyJbMHWgGNi1lmTx4KqaCQE8nVdRI9yUOkN2akqCsvt8/XQuwjD2H6e0URj9g7BzJwH3Xb54j/a2TOj5H7qw3/yPkIP8i6iskLF/0aVuvgCHE7GmnB04E4P+7XpK/0HBXRBbS4WGqSsQvCIxlHVJ8qsIZbOR8Dg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768353224; c=relaxed/simple; bh=LPF0sxafEG7ny8XUQpeOqbK63tgsdTi5cz2VL+rh5ZQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=hooDLtBl3Kh7P2+EP2oyOyNaNxdeTKafFdgEf/n05H2KS2HeyGs7byNixzt/gkjDb/qxLDNEzPVOyc1tojJHKTbDeIoIXC+KD5APU3dQ1ILtBlTDBAF0Fu11KoVwFqg7VPfM+cOXBi+sNtZydGU9HueKr6BhKfUJace74sLSr70= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ntCZN9Nt; arc=none smtp.client-ip=209.85.210.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ntCZN9Nt" Received: by mail-ot1-f66.google.com with SMTP id 46e09a7af769-7ce2b14202fso3517436a34.3 for ; Tue, 13 Jan 2026 17:13:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768353222; x=1768958022; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=np59BT8UQoyo4NCHoG7Gy1aCxaoQiBPKFat5KdX+siY=; b=ntCZN9NtYghEl+NYjw8h3IVAPVc+O7oDRH7klTatogNdYtOc1+KNJfmDXRz574WnAG orfkYiHgqbC3gqUnfO2x7A0hyXpGN0WNUzOlaK3qF6qfjJL/65JqjXRK27xv98ttF0Or 7/Nb4dLI5HpdJcSRQxuKwExJ5WAUKl8K4OMHYYzV7m2JQmE0yOPS5ZRenVCc7VvqETWo jB8w0mxLLV4OQ8aoSC6nRR5LAHL7WFL2r7QDPdCBZ/k2hIKw2D57VL51d8yGPROMz9QT EtxUyhRYrc+XaR0R0kaUPKg972/cFO4myee1j7N2/r+6OC+ff293cgNU3SvGKUxw9bNi MpKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768353222; x=1768958022; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=np59BT8UQoyo4NCHoG7Gy1aCxaoQiBPKFat5KdX+siY=; b=sIUYS7Wg2n7jazpenlTamxFMFJQXkrmZN/GbDl2Pzejw9n1Xkj3AW1Rk6TtLdc/shK cRZ1y3igRLxUjwlrSVkwXoi626/2Tvka2Bb3HQAYnSQKQ6WuxIsvcTRucvRMrGnmODbR FI6fHL3hufGWFXGl0rHRdQsF/ltLkL57sHISwDyFIhr0xTY+pDVR6u5u2zAR0y6FzQcq /mXuSfEPCfDGwkw6FIPHirVMRMXAS90dvAAKHPZoImQ94QGWHtdP9cpWVB+pPRH+ZelR kylrSxfP32M643MV7rJ0ji45UEa8X2Xh9A2m4xNJMScX5024ywsdx4X8DWZsvRZu+cNq cpVg== X-Forwarded-Encrypted: i=1; AJvYcCVz8e1h+vHjvosyUoD+QNzhv/EMj/VSWPdnfqx3BV5gRbae2IJh7X2d4GQnOAfbl0PXKSntpRps0CP9C/Q=@vger.kernel.org X-Gm-Message-State: AOJu0YyTDA6xyCsxjZGmxxcRKulyEnNOesm/3b03P3CmaEVJP6Z+G73u 4QMoXZ6D/jD1AvULBizML2R33TO9ZAM5WhRtcNy5IHCyfuz6ZIltuYlq X-Gm-Gg: AY/fxX6mXzD2O03SwgY7iQS680fM/B0mqzaKAJirOYuwckllOppStsBfmUWW5CDjXvi uDNTu21n11u7MIMR2rr/1MtRoJfkU6QAeLWwsMeB0MElK3sa7jvWS7ZH1UQTUXkpZiVqZt6Bn6A 56sGkpMuoz/vKeEe7g+7przco7kiX2jaalenW/j8Ti/tw/RLt/hVbc+ITnqrcyzx9a5qwZJ25na 6h0Y7o2XHSvNr6Z4g0XUSZsnxJ0+Bltqen+KUXkMrvzytJ1KBzYA+aYNA52+Pl7ZhfXBu0Lpavi NWfmjQaVjM0rKJFJOwUB2NF4tIoJzqM+MIy01geThkjHsLDDq3Wwo/8949+LUGdsm1BIDOmT083 AEzhJCgQpypnv0fJLjfWElJSvaDnFaa4KPBCKOBm89oXW1igRJJrOpT/Dzyvjzdqc4ZfkpVhYIT P8z6AyRlj1LbYRddydolNg1Ogkb9Atbksc X-Received: by 2002:a05:6830:44a7:b0:7cf:c613:d311 with SMTP id 46e09a7af769-7cfcb6997f3mr246667a34.34.1768353221562; Tue, 13 Jan 2026 17:13:41 -0800 (PST) Received: from newman.cs.purdue.edu ([128.10.127.250]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7ce478ede38sm16705215a34.26.2026.01.13.17.13.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Jan 2026 17:13:40 -0800 (PST) From: Jiasheng Jiang To: boris@bur.io Cc: clm@fb.com, dsterba@suse.com, fdmanana@kernel.org, jiashengjiangcool@gmail.com, linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5] btrfs: reset block group size class when it becomes empty Date: Wed, 14 Jan 2026 01:13:38 +0000 Message-Id: <20260114011338.44172-1-jiashengjiangcool@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260113215705.GB1048609@zen.localdomain> References: <20260113215705.GB1048609@zen.localdomain> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Differential analysis of block-group.c shows an inconsistency in how block group size classes are managed. Currently, btrfs_use_block_group_size_class() sets a block group's size class to specialize it for a specific allocation size. However, this size class remains "stale" even if the block group becomes completely empty (both used and reserved bytes reach zero). This happens in two scenarios: 1. When space reservations are freed (e.g., due to errors or transaction aborts) via btrfs_free_reserved_bytes(). 2. When the last extent in a block group is freed via btrfs_update_block_group(). While size classes are advisory, a stale size class can cause find_free_extent to unnecessarily skip candidate block groups during initial search loops. This undermines the purpose of size classes=E2=80=94to reduce fragmentation=E2=80=94by keeping block groups restricted to a specif= ic size class when they could be reused for any size. Fix this by resetting the size class to BTRFS_BG_SZ_NONE whenever a block group's used and reserved counts both reach zero. This ensures that empty block groups are fully available for any allocation size in the next cycle. Signed-off-by: Jiasheng Jiang --- Changelog: v4 -> v5: 1. Remove the Fixes tag. v3 -> v4: 1. Introduced btrfs_maybe_reset_size_class() helper to unify the logic. 2. Expanded the fix to include btrfs_update_block_group() to handle cases w= here the last extent in a block group is freed. 3. Refined the commit message to clarify that size classes are advisory and= their stale state impacts allocation efficiency rather than causing absolu= te allocation failures. v2 -> v3: 1. Corrected the "Fixes" tag to 52bb7a2166af. 2. Updated the commit message to reflect that the performance impact is wor= kload-dependent. 3. Added mention that the issue can lead to unnecessary allocation of new b= lock groups. v1 -> v2: 1. Inlined btrfs_maybe_reset_size_class() function. 2. Moved check below the reserved bytes decrement in btrfs_free_reserved_by= tes(). --- fs/btrfs/block-group.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 08b14449fabe..343d7724939f 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -3675,6 +3675,14 @@ int btrfs_write_dirty_block_groups(struct btrfs_tran= s_handle *trans) return ret; } =20 +static void btrfs_maybe_reset_size_class(struct btrfs_block_group *cache) +{ + lockdep_assert_held(&cache->lock); + if (btrfs_block_group_should_use_size_class(cache) && + cache->used =3D=3D 0 && cache->reserved =3D=3D 0) + cache->size_class =3D BTRFS_BG_SZ_NONE; +} + int btrfs_update_block_group(struct btrfs_trans_handle *trans, u64 bytenr, u64 num_bytes, bool alloc) { @@ -3739,6 +3747,7 @@ int btrfs_update_block_group(struct btrfs_trans_handl= e *trans, old_val -=3D num_bytes; cache->used =3D old_val; cache->pinned +=3D num_bytes; + btrfs_maybe_reset_size_class(cache); btrfs_space_info_update_bytes_pinned(space_info, num_bytes); space_info->bytes_used -=3D num_bytes; space_info->disk_used -=3D num_bytes * factor; @@ -3867,6 +3876,7 @@ void btrfs_free_reserved_bytes(struct btrfs_block_gro= up *cache, u64 num_bytes, spin_lock(&cache->lock); bg_ro =3D cache->ro; cache->reserved -=3D num_bytes; + btrfs_maybe_reset_size_class(cache); if (is_delalloc) cache->delalloc_bytes -=3D num_bytes; spin_unlock(&cache->lock); --=20 2.25.1