From nobody Sun Feb 8 13:11:06 2026 Received: from mail-yw1-f195.google.com (mail-yw1-f195.google.com [209.85.128.195]) (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 19DFF318ED7 for ; Tue, 13 Jan 2026 20:55:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768337738; cv=none; b=MM+YzLfWMHHDMdmDII3+v8JmB8GI/bDZO2sukLEVp1wsnp39qMjSNuf4Niks62pRA4IiTjZyjKJ1xiiCW0O5gHb1xL7Ce5HEfLd32j9RgchyHQbDgAyrW7+SZldeCKJuXCYz0TxYGnAbkIJWpWf64K+GoY0bgUSXlhiMnEdesaM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768337738; c=relaxed/simple; bh=sij+zoexnWppQ2ihhwPzrCR1FqbRGPbuFYgbLfSeL3k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Wd90hLJq1UiWdRpwmfaFg540+rWKnnfvA/dF2e34PQGCMKWVCuFXqpUtYcIuEE5ureVQ3eWvnTpVwOj50hc+4nOST9GMwaL/HwajTXw+7Y53fEXL9rHhm+Duc3dNt9tgxFPqHFWhiieYeXcfnhk8Meq5eU/uNFjF6MZCO+Bwu1g= 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=Boh8UKif; arc=none smtp.client-ip=209.85.128.195 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="Boh8UKif" Received: by mail-yw1-f195.google.com with SMTP id 00721157ae682-78d6a3c3b77so3009047b3.0 for ; Tue, 13 Jan 2026 12:55:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768337736; x=1768942536; 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=3g1ZsvGsx2nm1P4yPpEV7+WbS+tP/MjMFVscDshGg3U=; b=Boh8UKifb+Ambd+K4HEqec6AqBaQIHM2eL42UuErenNG2V5wyNbpMYPbV0+ouUbtmW yXN7HXULy8hCXuazpztUrousURijbhI3/ExRe5KuHThwcm0D3izcCBeHTxBMiGO1AUuX yS3j7lGh+R/x/C8PpFz9QRqcuulnCWds652jzWlLUNHgFiR6sR7Rjzpv5gJ5EJIhzReZ 2h0bQxhNFrMB8WvCHjmzhv0kf2VqvBMryPVDaUtfvnjLo1jS6GLkCn1qjWU5W7HwfEWo cmea+jhmUAMR+DZ2SemzcS9r0/tcdhJ+YyTEWV7W8raOKDh3hfwyg5etkGzacI4Q6Xzq DEGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768337736; x=1768942536; 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=3g1ZsvGsx2nm1P4yPpEV7+WbS+tP/MjMFVscDshGg3U=; b=lFHmACjrSF8LIRytCgW4AFVeqdp0dwWFsL5CptVOKwHeXln8E+zsiajIPvqNaq2AKI tOK2FsQfC+oOYX2I0BzXoT2BfT13RkofvOwzm5u7oBRhUvxYYeuVuiY4hsbk8O2v/A/G bJdEluuCW1tCIoXo0PnojXYJ05g4dy5IprYrJ6y0xJQPWjzKZ36uNq85/TYjs5XFVTcR W9mn7YY3hrTwGhJKiGe+OV+ZRiQCHWgc0lshzClVDOWDZ4e3QST2nsRcJr4RipMsmfUJ 84gxb13Xk0Nx3IOpwUyku5dfqnaEWlup5kNGuIjQDFy2CAFT624R9GezT80jAbph2H+D jDFA== X-Forwarded-Encrypted: i=1; AJvYcCUttzFR4DmZWFxPqJQdqzUJ3+oWpE2KCLaIBwZ0yFUVG0Kj9h3tuCF7ibEdmhVsJ6dgANjWrj2ZMNLoOv4=@vger.kernel.org X-Gm-Message-State: AOJu0YziZOPA26vq9npsY7wvHA+hkJMRbE3WQKslFRKEPTWVZbyizKvV gWjYqW/Pb5CjRkGXI82WO4pSbpHBPlbtqC0jb7QtKqlkBAc5r8atEzJy X-Gm-Gg: AY/fxX7KF8NIWmd/5LRxw1Cvnv9jRhiRJknUFA2RYG/e7KPySV6fDiz7hWmXRjOKEaL K5YFqcmI2rqATtAyI/nLTs+2cHz1gbH7HBSEvHxe9wuKJTnQqiRh3goFW+JaTgwAmfnotPyY1dO W8in6QuZMTZYuT0mG0NGipCxnJqXxZQ4d2jB1J/nqrxm7KBYIbBZr04S/VKi9aSWBzdLD77O+VJ avXiiDIbvtp3lPARMa8bk4fq8dRjipB1RkD16hf45Cd13UB6C5Y7TUJTovSo7VrlZ2/Xj7GjD96 WKrGwmy5Dtup4qzPDaxzqxHfSGogoExvjsusj63Wm1TgL1dr7qTaEfXbdT8OUMAtyKJX2NkELc/ i7pEiFf34Qy+QexC0D88jZnjecSLbbCrW4AiGOU0B3p7NUc3b1uiJIhnYuXaaA0VNZoMhpWKz5+ fWuSt2YCk94SpbGyAx4MFiUlq+NZ9YwjJT X-Received: by 2002:a05:690e:c42:b0:646:69a2:d400 with SMTP id 956f58d0204a3-648f61f8d26mr3813349d50.10.1768337736012; Tue, 13 Jan 2026 12:55:36 -0800 (PST) Received: from newman.cs.purdue.edu ([128.10.127.250]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-6470d8b2623sm9712831d50.20.2026.01.13.12.55.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Jan 2026 12:55:35 -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 v4] btrfs: reset block group size class when it becomes empty Date: Tue, 13 Jan 2026 20:55:32 +0000 Message-Id: <20260113205532.42625-1-jiashengjiangcool@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260112185001.GA450687@zen.localdomain> References: <20260112185001.GA450687@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. Fixes: 52bb7a2166af ("btrfs: introduce size class to block group allocator") Signed-off-by: Jiasheng Jiang Reviewed-by: Boris Burkov --- Changelog: 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