From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B98E31E833; Sat, 1 Aug 2026 17:25:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605135; cv=none; b=H5TVM0HQHIDxegfGDZKAqQsgQr2MHu9/y7YeuKdVVhlXfK6iEnBeioNl0iFEM3TTligdDjrcdCk40mdotr/vfS/BwawZvNCCkVUapr5dN8I9KoKRmIr6S2WHE5nXoCVsfLlSlRyriOvp2IqaJqzkedZJ45b5Vi6SQhYpt1CbdeQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605135; c=relaxed/simple; bh=VfjxbcJL8/gSToXg1vkt8OxQMAH8ZhH17UGWLqGr9a4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Gva9L3GL/n1CZkiatLho3pzrNNrkcYKle2JMOUFz1JW3NKe6Fg/JNZLIUIzFVoDnUDnL9jWa3Lcs+MZUgw4APNBw+nHCH0IT+/3f59xpdsiWrAHqEV9YypC22HO+tFAY5PZFrXu1i6E2YJq6DDmDknDKIBipiKMfbuRhOjjFwqw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mlJpNB6Q; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mlJpNB6Q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CCACA1F00ACA; Sat, 1 Aug 2026 17:25:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605133; bh=ObOE+s2buET3Z5WjVvzdDr2VEYnY9W3nx5j/qB2xlPE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mlJpNB6QEUAT5ad+pHX3Hd3TICxx5IwgG8DZ35ImcVIsjbgYM/D7rN09y0Fgj/RQy UAnkys2OVNkcVaLZ6swxRVfWQ80EwRR0d5M5GBQMyba7cQsk8jfvrpLb6qiYDz1Jv9 nQkiJP0bSAroNXDZYmZu5BIpss4CefkktA2lKwoRioD2R0gY6oC8dSNCRNZxyyj5PS lbjmL/3qT5fcjLMC7S9BuIKRvkl3qMQZDEi5rAQH/9IumIhlJXXAJyxBojK2Qq10co idGqaDsxiJ0rHf89h1b2/HqZCDSOqSejuM7JvjdHvlFPvwzv3FKnGLqGRBzEhvHiWz AslKNAmgooL3Q== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 01/25] md/md-llbitmap: clear flush state after daemon flush Date: Sun, 2 Aug 2026 01:24:55 +0800 Message-ID: <20260801172519.2982121-2-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai llbitmap_flush() sets LLPageFlush on each bitmap page before it queues the daemon worker. The flag tells md_llbitmap_daemon_fn() to ignore the normal barrier_idle expiry check and clean the page immediately. The daemon only tested LLPageFlush. Once a page had been flushed explicitly, the flag stayed set, so later dirty bits on that page also bypassed barrier_idle and were cleaned the next time the daemon ran. That can make a new write look clean much earlier than the configured idle window. Consume LLPageFlush in md_llbitmap_daemon_fn() with test_and_clear_bit() and use the returned value for the current expiry check. The explicit flush sti= ll forces the current daemon pass, while later writes on the same page wait for barrier_idle again. This can be reproduced through normal sysfs operations: 1. Create a small RAID1 with --bitmap=3Dlockless and --assume-clean. 2. Set llbitmap/daemon_sleep=3D1 and llbitmap/barrier_idle=3D10. 3. Toggle md/array_state from active to readonly and back to active to ca= ll llbitmap_flush() without destroying the in-memory bitmap. 4. Write one sector and read llbitmap/bits immediately, after 2 seconds, and after 12 seconds. On the bad kernel the dirty bit is already clean after 2 seconds. With this change it remains dirty until the barrier_idle window expires. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 5a4e2abaa757..131582724e7e 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1066,14 +1066,14 @@ static void md_llbitmap_daemon_fn(struct work_struc= t *work) =20 for (idx =3D 0; idx < llbitmap->nr_pages; idx++) { struct llbitmap_page_ctl *pctl =3D llbitmap->pctl[idx]; + bool flush =3D test_and_clear_bit(LLPageFlush, &pctl->flags); =20 if (idx > 0) { start =3D end + 1; end =3D min(end + PAGE_SIZE, llbitmap->chunks - 1); } =20 - if (!test_bit(LLPageFlush, &pctl->flags) && - time_before(jiffies, pctl->expire)) { + if (!flush && time_before(jiffies, pctl->expire)) { restart =3D true; continue; } --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B1242338595; Sat, 1 Aug 2026 17:25:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605153; cv=none; b=Rj0LNgc4pYWXgPcYRZrjttA7tpqaDIAxLtL9FQ+NL/BZ40v2rHN7qOFgOe9yq5i1je1/8mi5deNVN93WNDtSzRkxFyD0zJF86Dbg0aupHuPRTz1CFZknRLiWNndp6Bgrwn2acovV4q8bvy+fGD+gvC/AggElQvbvlfabFJ8jzEM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605153; c=relaxed/simple; bh=JBy2hAxptUhfnmGWm89fEXpot33TfN5mNSxd3wLMA8E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NMHjntz4zfVoO3yure/MGCrkhPatcj8Qs7J0UJJ+c6y9KL/vE9qEcDwAAdAUsb3tHmY11NAUPaAepgDNCm1k1xdRUF8dHHQfK/h+NwGniX0aaCHeHVdVU1naMPIKaIzXGl24t1mAXu9oBhe7JdYGTisEJeXUyNivepHN8V1Spkc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=e6xRD9LM; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="e6xRD9LM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 383AB1F00AC4; Sat, 1 Aug 2026 17:25:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605152; bh=z+ZkBmM/2h0cWvxullEWJCwx7jlcxedVIL2neZI+hsA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=e6xRD9LM/jQpTux3Ip1Svf+ZBqpPCeSRje0j2rGSkvDgkcdOcalsyBiwfG/VzlyMH ln69txqL8c5iDChoW8h0h7BMxBqLqpj4zxqhMmmsfHYwqc5NAY6UZPzGXzJnT1IWA3 e5kke9ZCl2GIfo8KPjAGLcfJOUIl+Xf8JO9q6tMYjWvjnX21MI2xA8IJ4p1l/05zL3 qUHVGVTCyw3WWeew9kz28L7zhMBqbh82PapIbrulqIVmECCxpXuBCAbsBfrIa4mZei +/uQnGKxfSaOwj6mBWRHiTc+R4LqF549S149215oiUpxPEAci1SAESa3roWf7Pozkd dFUT9Y4GBYK6A== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 02/25] md/md-llbitmap: use GFP_NOIO for cache allocations Date: Sun, 2 Aug 2026 01:24:56 +0800 Message-ID: <20260801172519.2982121-3-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai llbitmap allocates its in-memory page cache and page-control structures from paths that can already be holding MD reconfiguration or bitmap state locks. For example, component_size_store() takes mddev_lock(), update_size() calls the personality resize method, and llbitmap_resize() can grow the page cache through llbitmap_prepare_resize(). Using GFP_KERNEL in those paths allows direct reclaim to enter filesystem or block I/O while MD resize state is locked. That can recurse back into the same array and wait on state that cannot make progress until the resize path finishes. Use GFP_NOIO for the llbitmap object, cached bitmap pages, page controls, page-control arrays, and percpu_ref initialization. Leave the explicit metadata zeroout path unchanged because it is intentional bitmap I/O rather than reclaim-driven allocation. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 131582724e7e..6ab2188bba27 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -521,7 +521,7 @@ static struct page *llbitmap_read_page(struct llbitmap = *llbitmap, int idx) if (page) return page; =20 - page =3D alloc_page(GFP_KERNEL | __GFP_ZERO); + page =3D alloc_page(GFP_NOIO | __GFP_ZERO); if (!page) return ERR_PTR(-ENOMEM); =20 @@ -616,12 +616,12 @@ static int llbitmap_cache_pages(struct llbitmap *llbi= tmap) int i; =20 llbitmap->pctl =3D kmalloc_array(nr_pages, sizeof(void *), - GFP_KERNEL | __GFP_ZERO); + GFP_NOIO | __GFP_ZERO); if (!llbitmap->pctl) return -ENOMEM; =20 size =3D round_up(size, cache_line_size()); - pctl =3D kmalloc_array(nr_pages, size, GFP_KERNEL | __GFP_ZERO); + pctl =3D kmalloc_array(nr_pages, size, GFP_NOIO | __GFP_ZERO); if (!pctl) { kfree(llbitmap->pctl); return -ENOMEM; @@ -640,7 +640,7 @@ static int llbitmap_cache_pages(struct llbitmap *llbitm= ap) } =20 if (percpu_ref_init(&pctl->active, active_release, - PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) { + PERCPU_REF_ALLOW_REINIT, GFP_NOIO)) { __free_page(page); llbitmap_free_pages(llbitmap); return -ENOMEM; @@ -1110,7 +1110,7 @@ static int llbitmap_create(struct mddev *mddev) if (ret) return ret; =20 - llbitmap =3D kzalloc_obj(*llbitmap); + llbitmap =3D kzalloc_obj(*llbitmap, GFP_NOIO); if (!llbitmap) return -ENOMEM; =20 --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6736F338595; Sat, 1 Aug 2026 17:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605157; cv=none; b=IbD4kbP+aqJb2NFTf0+JWBRycBGnvnLqGyFiT13bxTymEtS9mj0sLJjacv1DU6ihfIAPXZ2+hJbchXCE5HtxuTmI7ovLmQ5boYWcAZBohUnVCyrNPgKOBwhOx53POKm/cYxS+SR6p5HaVo5qlQWTDNIxzYrB6gvdF16P8yb70MI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605157; c=relaxed/simple; bh=8sapfSQZEk0WSpT9xE+/HwrwGGMmFblimfx5Kp+dYRc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dLzE5HFXIFGToNuGak9ve0YdUwlGDhyETblufgMchzFxCPtx8U/mhzM1Af6QiRvVoHUwRB9Ty93zLEsHGMehyE6uYNg2YGx0s7JGiPck8z/vMEKrOniDZ14hgE7lv3fpekxyIZKO5xW+5DC52lneEvbEyxWtb5GEQ3lsekCvC7w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ll48teNY; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ll48teNY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B3CD61F00ACA; Sat, 1 Aug 2026 17:25:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605156; bh=DqSYT7eX3wmhQdB5JdvHjPWVbrVbNJP45V+wA83Bgck=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Ll48teNYj/sVjtp122w4B/TBax+0aNWgumdKNy1/T1HG2kyJgMZIOR5L7DuyD+yzo 1sGUFzlL16dammo7t1uAaw4YFHJ0qLEPcKO400+Tdo5lGL3suo7Ft1u0Y48wsJFK3w ip64ocR+bqaNnV8zD/rmvG9QbnyQT+4yAqG70QMYKMqEY3jghCFTLhdaOkJ04Eh6Kd jTiQRhVGKR4da6EwCakSQHK3ggjYlgI8551M9rqErpynPhUtXaqoN691TUBrDO0Llg /2mWAynVTnisVHMzbQ/LewunQiMZ1fz/EBP9R23BjuJRmc99qugjY9YdF93fPzZUT7 yNgRMJMLPxl9g== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 03/25] md/md-llbitmap: only end fully synced chunks Date: Sun, 2 Aug 2026 01:24:57 +0800 Message-ID: <20260801172519.2982121-4-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai llbitmap_cond_end_sync() is called with the sync thread's current sector. That value is an exclusive progress boundary: sectors below it have completed, but the llbitmap chunk containing it can still be in progress. The old code converted that sector directly to the last bit passed to BitmapActionEndsync. If resync had only advanced part-way into a large llbitmap chunk, the in-progress chunk was marked synced and flushed before the rest of the chunk was repaired. A later bitmap-assisted RAID1 resync could then skip the remainder of that chunk and leave stale mirror data behind. This can be reproduced without editing bitmap metadata by creating a large RAID1 with a lockless bitmap so llbitmap naturally selects a 524288-sector chunk (with the default 128 KiB bitmap area, an array just over 16 TiB is enough), making one mirror stale through the normal degraded write/re-add path, and throttling resync so the daemon checkpoint runs while resync is still inside the first chunk. On the bad kernel, bit 0 is ended early and a stale sector later in the same chunk is skipped. With this fix, bit 0 remains Syncing until resync reaches the next chunk boundary. Round the exclusive progress sector down to the nearest llbitmap chunk boundary and end only chunks strictly below that boundary. Also honor the force argument so callers that need an immediate checkpoint are not suppressed by daemon_sleep. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 6ab2188bba27..be580601d5b9 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1450,22 +1450,27 @@ static void llbitmap_cond_end_sync(struct mddev *md= dev, sector_t sector, bool force) { struct llbitmap *llbitmap =3D mddev->bitmap; + sector_t complete; =20 if (sector =3D=3D 0) { llbitmap->last_end_sync =3D jiffies; return; } =20 - if (time_before(jiffies, llbitmap->last_end_sync + - HZ * mddev->bitmap_info.daemon_sleep)) + if (!force && time_before(jiffies, llbitmap->last_end_sync + + HZ * mddev->bitmap_info.daemon_sleep)) return; =20 wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); =20 mddev->curr_resync_completed =3D sector; set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); - llbitmap_state_machine(llbitmap, 0, sector >> llbitmap->chunkshift, - BitmapActionEndsync); + + complete =3D round_down(sector, llbitmap->chunksize); + if (complete) + llbitmap_state_machine(llbitmap, 0, + (complete >> llbitmap->chunkshift) - 1, + BitmapActionEndsync); __llbitmap_flush(mddev); =20 llbitmap->last_end_sync =3D jiffies; --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37B11338595; Sat, 1 Aug 2026 17:26:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605166; cv=none; b=dOxApUXuqd3118eDe8/eTvctaAsiZPKZwbU+EwoP6Ip+7c+otC8w0nbhaoLM6w4AU0/SlYPhfjUA4P+lYCs5tvsenZq4X+02ab3NFlX7CBm9DIw3CZJOQJ61fd6Lz+z3CGT5tZQ69PP3F6gaGvk+8fLQujd3niN+shPuzNOE/KA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605166; c=relaxed/simple; bh=LTFkztd/McgpsPIR/uPOxT8v1TFCYZGx6jvbRYw0/KU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VY0hoJI/2Jin5Mz8Xtk03Y4iSEvOQBM3vzJICdz63/lztHCC35GuJ6YHhgN4kQcAYa0GIR2LkwJYNJC0UvFVOCCSDdaIuzj0ujeIPoyGJN+JNMTanRL3TQqWExSvP+ahC3Kf0h+M03ZkBhwJ88Ibxw0NDf7wNB29YQ32avuY9no= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HgYXEfKZ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HgYXEfKZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 535A11F00AC4; Sat, 1 Aug 2026 17:25:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605165; bh=cBGJhnuC/GXO4gmNekmp+QNeV9Iz6ZZPjuvwuklDMsY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=HgYXEfKZ1Zm14adIJ3eSHRfTHfcDVeLOZ/Ab/nNvQjS+r+bxCx5PYFNvzfeshwfrG 4fj+3+SgRVUG8wCQyPyqKtnB8IIbuXCA9X8jU5uJH+pInmIwwJkMKIF9uYrGWstoKD sFeu77FWmY3FpQlMoDfxMGDCWJzs7J9qGoDw6MLnfXZ4HsQ3BOvX5BsPa7LKOyQ0Q5 YgPtbX7KrpScqLq9Pkeg9zkN7gIyXUxuEv/bx4olSKbduI6tt5vy0WQvsB33/B0B3Y 0o56FDKdTsM02EfWNz4qavWCcM7jywnOX5WVMZp25Rr+rAAtusFgA9/oWz5hZX2u7H KsQKatgPqYIZw== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 04/25] md/raid5: reject zero-sector reshape chunks Date: Sun, 2 Aug 2026 01:24:58 +0800 Message-ID: <20260801172519.2982121-5-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Sashiko reported that RAID5 can accept a reshape chunk size that becomes zero sectors. chunk_size_store() stores the sysfs byte value as n >> 9, so writing a value below 512 bytes sets mddev->new_chunk_sectors to zero. RAID5 then accepted that pending reshape geometry and raid5_start_reshape() installed it into conf->chunk_sectors, letting reshape code divide by zero. Reject zero-sector chunks both in check_reshape(), where normal sysfs requests are validated, and in raid5_start_reshape(), so assembly/resume paths also cannot install zero chunk geometry. Test script: in QEMU, create a plain three-disk RAID5 array with 64K chunks, write/read back a small pattern, write 1 to /sys/block/md0/md/chunk_size, add a fourth disk, and run mdadm --grow --raid-devices=3D4 --backup-file=3D... . The script scans dmesg for divide error/Oops/KASAN signatures. Bad kernel, eb29914412c3: echo 1 > /sys/block/md0/md/chunk_size mdadm --grow /dev/md0 --raid-devices=3D4 --backup-file=3D/root/md0-grow.b= ak Oops: divide error: 0000 [#1] SMP KASAN NOPTI RIP: raid5_get_active_stripe+0x863/0xc10 Call Trace: raid5_sync_request md_do_sync md_thread Kernel panic - not syncing: Fatal exception Fixed kernel: echo 1 > /sys/block/md0/md/chunk_size bash: echo: write error: Invalid argument chunk_write_rc=3D1 grow_rc=3Dskipped RESULT: REJECTED_ZERO_CHUNK_NO_OOPS Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 0c5c9fb0606e..4276b125f94c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -8479,6 +8479,8 @@ static int check_reshape(struct mddev *mddev) return 0; /* nothing to do */ if (has_failed(conf)) return -EINVAL; + if (!mddev->new_chunk_sectors) + return -EINVAL; if (mddev->delta_disks < 0 && mddev->reshape_position =3D=3D MaxSector) { /* We might be able to shrink, but the devices must * be made bigger first. @@ -8522,6 +8524,9 @@ static int raid5_start_reshape(struct mddev *mddev) if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; =20 + if (!mddev->new_chunk_sectors) + return -EINVAL; + if (!check_stripe_cache(mddev)) return -ENOSPC; =20 --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F348F330644; Sat, 1 Aug 2026 17:26:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605171; cv=none; b=E3AuEnGny0rlh8HYxFkQOk5XO31p7gxau1GIQFaQLJqM3CesY+MzzUXB9WdNE90L2dQboEBL24nOu1wScCsSvffQPmqKDRQA1FVXTZI/Va5FZHeq9WjK/K889ioMKqLHa+Vm4bsNC0kG4MDM1dPxGh7ru0Dduu/l56cHdyKzz3g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605171; c=relaxed/simple; bh=VsLNapY/L7K4NelFNagu3Sw+fpWyGhIcurKPIwwyPLU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=R3/05XPMvPcxS+BMpVVxcYNpU6lFkHKTljNgNiJV+fMgQ1j0rc2l1VoKxfmVGBA22vo0UhHmLw9qpNE6zKCNgzSX+8tmWxC22K9fJbb5fGuAUr1wS+z1XRQoXNNXfCF5t4TQ0e+iQOaF1V+VJUzSNyz1WnOiDME98kc2TtmaFUY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Gc5GtjEu; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Gc5GtjEu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2475A1F00ACA; Sat, 1 Aug 2026 17:26:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605169; bh=dCFUedP1skGYzgnqpTqOIQ2im+r3VlOni4SnWA+zMSQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Gc5GtjEuxtYaQY8ELZbalxopUFVfavGJmOVpuqRaj7V7S7Jh57YF409oLzfWcObUo Uu8K+pbx1ZI4Doq/lKPLttIej/tCpysOeZfKOUNebW7CnddQJ2699eefI6TShKJG5k dvTUjURiTycq9dyuyObm2AVMvClqmybbmEtaKoAvHiaQxd6L0pQrZfYyf+a1L2HxVP QVdS60A8QVNiI3Y4Wr2Bd5ng7Emh+LrN7oSPLZP6cHxXeIv5l4pqxnj1dYc1Dm2u/r qRYlEJjPZcbPGWD7u3RGoPJ53zEkEfhIRNonurdlcTbh+6sDBGyKyry8Wkc9cWqYDg 4+UfqD6TQCMuQ== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 05/25] md/raid5: round bitmap stripes with sector division Date: Sun, 2 Aug 2026 01:24:59 +0800 Message-ID: <20260801172519.2982121-6-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai raid5_bitmap_sector_map() aligns the array range to full RAID5 stripe widths before converting it to component sectors. That width is chunk_sectors multiplied by the number of data disks, and it is not always a power of two. Reproduce with a 4-disk RAID5, 1024-sector chunks, and three data disks. The full-stripe width is 3072 sectors. For a one-sector write at array sector 3072, correct rounding gives array range [3072, 6144), which maps to component range [1024, 2048). The old round_down()/round_up() logic instead gives [1024, 4096), which maps to [0, 1024). Use sector_div() based arithmetic so the rounded range is aligned to the actual RAID5 stripe width. The deterministic mapper test now reports the fixed component range as [1024, 2048), while the old mask-based range was [0, 1024). Fixes: 9c89f604476c ("md/raid5: implement pers->bitmap_sector()") Reported-by: Mykola Marzhan Link: https://lore.kernel.org/all/20260726185916.2223460-1-mykola@meshstor.= io/ Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 4276b125f94c..8b3483674398 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5956,8 +5956,11 @@ static void raid5_bitmap_sector(struct mddev *mddev,= sector_t *offset, =20 sectors_per_chunk =3D conf->chunk_sectors * (conf->raid_disks - conf->max_degraded); - start =3D round_down(start, sectors_per_chunk); - end =3D round_up(end, sectors_per_chunk); + sector_div(start, sectors_per_chunk); + start *=3D sectors_per_chunk; + if (sector_div(end, sectors_per_chunk)) + end++; + end *=3D sectors_per_chunk; =20 start =3D raid5_compute_sector(conf, start, 0, &dd_idx, NULL); end =3D raid5_compute_sector(conf, end, 0, &dd_idx, NULL); @@ -5975,8 +5978,10 @@ static void raid5_bitmap_sector(struct mddev *mddev,= sector_t *offset, =20 sectors_per_chunk =3D conf->prev_chunk_sectors * (conf->previous_raid_disks - conf->max_degraded); - prev_start =3D round_down(prev_start, sectors_per_chunk); - prev_end =3D round_down(prev_end, sectors_per_chunk); + sector_div(prev_start, sectors_per_chunk); + prev_start *=3D sectors_per_chunk; + sector_div(prev_end, sectors_per_chunk); + prev_end *=3D sectors_per_chunk; =20 prev_start =3D raid5_compute_sector(conf, prev_start, 1, &dd_idx, NULL); prev_end =3D raid5_compute_sector(conf, prev_end, 1, &dd_idx, NULL); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F6AC338595; Sat, 1 Aug 2026 17:26:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605177; cv=none; b=TpuG+rLKQMVg2DaTcFrbf7VBRUk3EmjHkjRcgYXHe7nQsi0Q8rknScHsS6AgE5/X1Gex3l33uBCiwk3JBE+eDOhUm2BXVVxgh2lylL5fp5gC2aCGNZa6wrhuE6qazjoIAkX0vYNvrG0lx0+xwXxDvNsPpCM29b/xcF4TjzDYM0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605177; c=relaxed/simple; bh=jnyvs/KO6BxTm9w3UPBPbnF/7ysonfXI9GGYn5ayj+M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gOE6iYBb0Ia/gw2XsOuMabtZo4KU8IzJHBbY1qmkVZZnJpTk//4XptP4sHTuhdLnX+hx0AXLypcP+48aOyemSQUIWYevbDBnVomMIISnqlFhUvL5oxCsZJz+kQkvS2eKCM38mIuRzv8jYQ3SxlHTdhvvMNFZBz1b7+evMVYrH6w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FVMN0FOq; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FVMN0FOq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 33C281F00AC4; Sat, 1 Aug 2026 17:26:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605176; bh=VpjaDGraCKKjOgRHEyxek/gzqF6TEcMXbCvzpvy0qjw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FVMN0FOq9fbxsadTkruFMvseUCN1hTfgU8Umwf4t52gMPUctYDAHHt6QeTUG2urmC bkayLh51hR/fU3opOlJj2SUv76BxFhbK9YbhXBR3Xd0LBv1jqjnyculCgrkvAljXXQ fRcPTgPP9fyRPrRIi5yXSCe+CBC+woDYTs+EQ+bXZ2Hzz9VuSxvTuDuGas9WwLJE6l YKdr1OJYZoh6A1UWDEODG+E89/oGrqFbTg2IiZmMoyjE1KdzeNA90ss6pnPTvtTkPu SKI1cNNnVbfbRK2BNFjJ7MIgm1wXgqd9P8SoxGn4TO4BnoK72sMZyMzos3pPQgg+m7 NwXwB3uViMXXg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 06/25] md: add exact bitmap mapping and reshape hooks Date: Sun, 2 Aug 2026 01:25:00 +0800 Message-ID: <20260801172519.2982121-7-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Add bitmap mapping and reshape hooks needed by llbitmap reshape support without teaching md core to account a single bio against multiple bitmap ranges. This also adds the old/new bitmap geometry helpers used by personalities to describe reshape mapping to llbitmap. Signed-off-by: Yu Kuai --- drivers/md/md-bitmap.c | 8 ++++++++ drivers/md/md-bitmap.h | 8 ++++++++ drivers/md/md-llbitmap.c | 8 ++++++++ drivers/md/md.c | 12 ++++++++---- drivers/md/md.h | 4 ++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 0f02e2956398..4c31807e6bcc 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -1730,6 +1730,13 @@ static void bitmap_start_write(struct mddev *mddev, = sector_t offset, } } =20 +static void bitmap_prepare_range(struct mddev *mddev, sector_t *offset, + unsigned long *sectors) +{ + if (mddev->pers->bitmap_sector) + mddev->pers->bitmap_sector(mddev, offset, sectors); +} + static void bitmap_end_write(struct mddev *mddev, sector_t offset, unsigned long sectors) { @@ -3083,6 +3090,7 @@ static struct bitmap_operations bitmap_ops =3D { .flush =3D bitmap_flush, .write_all =3D bitmap_write_all, .dirty_bits =3D bitmap_dirty_bits, + .prepare_range =3D bitmap_prepare_range, .unplug =3D bitmap_unplug, .daemon_work =3D bitmap_daemon_work, =20 diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h index f46674bdfeb9..26cd07737aab 100644 --- a/drivers/md/md-bitmap.h +++ b/drivers/md/md-bitmap.h @@ -93,6 +93,14 @@ struct bitmap_operations { void (*write_all)(struct mddev *mddev); void (*dirty_bits)(struct mddev *mddev, unsigned long s, unsigned long e); + /* Prepare a range for this bitmap implementation. */ + void (*prepare_range)(struct mddev *mddev, + sector_t *offset, + unsigned long *sectors); + void (*reshape_finish)(struct mddev *mddev); + int (*reshape_can_start)(struct mddev *mddev); + void (*reshape_mark)(struct mddev *mddev, sector_t old_pos, + sector_t new_pos); void (*unplug)(struct mddev *mddev, bool sync); void (*daemon_work)(struct mddev *mddev); =20 diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index be580601d5b9..1fa2adf0ada1 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1188,6 +1188,13 @@ static void llbitmap_destroy(struct mddev *mddev) mutex_unlock(&mddev->bitmap_info.mutex); } =20 +static void llbitmap_prepare_range(struct mddev *mddev, sector_t *offset, + unsigned long *sectors) +{ + if (mddev->pers->bitmap_sector) + mddev->pers->bitmap_sector(mddev, offset, sectors); +} + static void llbitmap_start_write(struct mddev *mddev, sector_t offset, unsigned long sectors) { @@ -1785,6 +1792,7 @@ static struct bitmap_operations llbitmap_ops =3D { .update_sb =3D llbitmap_update_sb, .get_stats =3D llbitmap_get_stats, .dirty_bits =3D llbitmap_dirty_bits, + .prepare_range =3D llbitmap_prepare_range, .write_all =3D llbitmap_write_all, =20 .groups =3D md_llbitmap_groups, diff --git a/drivers/md/md.c b/drivers/md/md.c index d1465bcd86c8..3b20a57b8c7e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9361,6 +9361,12 @@ void md_submit_discard_bio(struct mddev *mddev, stru= ct md_rdev *rdev, } EXPORT_SYMBOL_GPL(md_submit_discard_bio); =20 +static void md_bitmap_prepare_range(struct mddev *mddev, sector_t *offset, + unsigned long *sectors) +{ + mddev->bitmap_ops->prepare_range(mddev, offset, sectors); +} + static void md_bitmap_start(struct mddev *mddev, struct md_io_clone *md_io_clone) { @@ -9368,10 +9374,8 @@ static void md_bitmap_start(struct mddev *mddev, mddev->bitmap_ops->start_discard : mddev->bitmap_ops->start_write; =20 - if (mddev->pers->bitmap_sector) - mddev->pers->bitmap_sector(mddev, &md_io_clone->offset, - &md_io_clone->sectors); - + md_bitmap_prepare_range(mddev, &md_io_clone->offset, + &md_io_clone->sectors); fn(mddev, md_io_clone->offset, md_io_clone->sectors); } =20 diff --git a/drivers/md/md.h b/drivers/md/md.h index d8daf0f75cbb..110cf0f8b107 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -798,6 +798,10 @@ struct md_personality /* convert io ranges from array to bitmap */ void (*bitmap_sector)(struct mddev *mddev, sector_t *offset, unsigned long *sectors); + void (*bitmap_sector_map)(struct mddev *mddev, sector_t *offset, + unsigned long *sectors, bool previous); + sector_t (*bitmap_sync_size)(struct mddev *mddev, bool previous); + sector_t (*bitmap_array_sectors)(struct mddev *mddev, bool previous); }; =20 struct md_sysfs_entry { --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E285931E833; Sat, 1 Aug 2026 17:26:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605182; cv=none; b=Q8GfsulCSzP4TdwuQ5Oi7sUGLxHKmnBZhUlxxh5URbNxqZiUi8hCoUu0oOG/R9TQerl6C8TfSKz+DSgzuF8lxQoZ5wbgIMTgOpLSqcmDFbmN2H58IRgn7txG/2cOlS9PytwYD6JxJGBDyk2MfS+azW5yR40oD8TAmI7Ydlfc/Pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605182; c=relaxed/simple; bh=zE6V0rS1CYRh8HHF4UU9C4G8OkNMOGRNXdKiUikz4ss=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ksK+wjoIn0mbPi9JwpcbgUlZM9M9Y4ejsFEYk1CQ3HN6+CGsYw5xSKy9Uxaoi760HI8Kow5lHVGXZkezE/JVqolYs0AQK9fxSo+kwqFdyOOwITXqrVXwfLnN26iqje9sM2H9b7yZocvi65hPgvHE9moJv8goO1/y5RcQEBOklJk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Cen5Us6p; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Cen5Us6p" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 131171F00ACA; Sat, 1 Aug 2026 17:26:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605180; bh=ExNpf8G5K91gwe32QvrS/B9q/xSMdoQA1ID+InSEdgQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Cen5Us6pKda/OFRtqp+XPoVEP425QjVWU0350A8NHXUk/UHIyVjCVlngWCNu6uO8d wybN1I4L0vS0EJXS7V7L05Jvs+C0aLQNayewa63445BGN+wbf8hLIEJe2rb+au/qNp Cr7pAXfz0aPoGvhV5gJFmBisgmw93Ql5nfldQY5KnlC+h5eRrjR4mEKDjbWbOfqwmo Mbl6dwGpKkAYDCmm/oaieeSdjIQEQ5FEN35ODEThpP/b/P0o1sKoq8x3FJUCYe/pk3 1Qlh0F5f1piEijmiSRHygqoBr5hmUVxkQHHCIT5zg7REtr/eLasbx9F1fpPDOYHfQj 7Wi11JsvQu6PA== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 07/25] md: skip bitmap accounting for empty write ranges Date: Sun, 2 Aug 2026 01:25:01 +0800 Message-ID: <20260801172519.2982121-8-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai mkfs.ext4 can submit zero-sector flush/FUA bios. These bios are WRITE bios for md_write_start() purposes, but they do not cover any data sector and must not dirty bitmap bits. md bitmap accounting currently passes such bios to bitmap start_write(). For llbitmap this reaches llbitmap_start_write() with sectors =3D=3D 0, which underflows the end chunk calculation. The new bitmap prepare_range() hook can also turn a non-empty bio into an empty bitmap range when the requested sectors are outside the active bitmap geometry. Treat both cases as not started, so the completion path will not call end_write() for an empty range. Signed-off-by: Yu Kuai --- drivers/md/md.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 3b20a57b8c7e..0b59c676f7c0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9376,6 +9376,8 @@ static void md_bitmap_start(struct mddev *mddev, =20 md_bitmap_prepare_range(mddev, &md_io_clone->offset, &md_io_clone->sectors); + if (!md_io_clone->sectors) + return; fn(mddev, md_io_clone->offset, md_io_clone->sectors); } =20 @@ -9396,7 +9398,8 @@ static void md_end_clone_io(struct bio *bio) struct mddev *mddev =3D md_io_clone->mddev; struct completion *reshape_completion =3D bio->bi_private; =20 - if (bio_data_dir(orig_bio) =3D=3D WRITE && md_bitmap_enabled(mddev, false= )) + if (bio_data_dir(orig_bio) =3D=3D WRITE && md_io_clone->sectors && + md_bitmap_enabled(mddev, false)) md_bitmap_end(mddev, md_io_clone); =20 if (bio->bi_status && !orig_bio->bi_status) @@ -9423,10 +9426,12 @@ static void md_clone_bio(struct mddev *mddev, struc= t bio **bio) md_io_clone =3D container_of(clone, struct md_io_clone, bio_clone); md_io_clone->orig_bio =3D *bio; md_io_clone->mddev =3D mddev; + md_io_clone->sectors =3D 0; if (blk_queue_io_stat(bdev->bd_disk->queue)) md_io_clone->start_time =3D bio_start_io_acct(*bio); =20 - if (bio_data_dir(*bio) =3D=3D WRITE && md_bitmap_enabled(mddev, false)) { + if (bio_data_dir(*bio) =3D=3D WRITE && bio_sectors(*bio) && + md_bitmap_enabled(mddev, false)) { md_io_clone->offset =3D (*bio)->bi_iter.bi_sector; md_io_clone->sectors =3D bio_sectors(*bio); md_io_clone->rw =3D op_stat_group(bio_op(*bio)); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D03935C1A0; Sat, 1 Aug 2026 17:26:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605187; cv=none; b=tfuRlAH9gfl+eXpMIgscfk1GMlKbz1m0pan+sMVqWYzKvL+DpokTyIKoaPaMF4kE+2U6umDMkf9aw1U+TloAuNuKMVtxz6fl95CGXhssDNRSZ5F9Arvqf5q3sHHF1vUjFIjqTjKYoG+p+LlfvTYL3iz/Ru+1M6tXtokHL35Rg+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605187; c=relaxed/simple; bh=orpEeGe/wroRtp1hdmup2wDbmAHVib1uqJnCOTmb1iU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=phg/EblZDEIVN1Oxzb7HLWb61YmlPu6k119mioT/coL96Bd1ZSZo6WqMOC1oFwE7BB5lgSx6OoF6Dez+WDUi2KOheMYdhj0ycJSLdeNniAGibE0oe05ipdZA9HwM5/vzMk/GuYWMJfo1oZUv8kqIX6SVIKxFAwiPw6dFOiASzFI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KJRsM7lD; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KJRsM7lD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B47B1F00AC4; Sat, 1 Aug 2026 17:26:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605186; bh=ngkMyeX+MbZI9WJOsCeLN4qLsT/mnA9+2qua4Y8Gnz4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=KJRsM7lDJZHoipLGNGZKg29053y4U5y5cqKTas5JjcyaKs0QUEbID1lkFvhLm9LQe his3eEyap+G5oy5EDgKVERv4Ja4EIgmVRtTscpOdXJY7VMGXrKtQegnd3Lt/diDOFo AhWABOTzirIl2UGKQJYv3Xjw4VsUI5rVJk/i8UqbPPJsNcSdHyTnxv+q88uSQOgSCC rLpTjwVDURzlRhQUgr3Al78odL3Ro7y4FbPVQaT/vAS3UyQi5nQElZ8Y7jGALJmwX2 SPyN2nDzvACtVStfagAQov8Gd+CYFWW06Hpxx9IJPcqf+o9ALl7q5PRHH0DRyUgNPA uIFbYxHp/irNQ== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 08/25] md: add helper to split bios at reshape offset Date: Sun, 2 Aug 2026 01:25:02 +0800 Message-ID: <20260801172519.2982121-9-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Add mddev_bio_split_at_reshape_offset() so personalities can share reshape-offset bio splitting instead of open-coding the same boundary handling in multiple places. The helper first applies the optional max_sectors limit. If reshape is running and the bio crosses reshape_position, it further limits the front bio to the current reshape boundary so callers can account and submit one side of the reshape at a time. Snapshot reshape_position with READ_ONCE(). RAID5 and RAID10 update this field as reshape progresses, while the I/O path only needs one consistent decision point for the current bio. Using an explicit single load avoids a plain lockless access and prevents the compiler from refetching a different boundary while deciding whether and where to split. When a split is needed, bio_submit_split_bioset() submits the remainder and returns the front bio. Callers must therefore continue processing the returned bio, not the original pointer. Signed-off-by: Yu Kuai --- drivers/md/md.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/md/md.h | 4 ++++ 2 files changed, 43 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 0b59c676f7c0..34e95ef9f2d4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9361,6 +9361,45 @@ void md_submit_discard_bio(struct mddev *mddev, stru= ct md_rdev *rdev, } EXPORT_SYMBOL_GPL(md_submit_discard_bio); =20 +struct bio *mddev_bio_split_at_reshape_offset(struct mddev *mddev, + struct bio *bio, + unsigned int *max_sectors, + struct bio_set *bs) +{ + sector_t boundary; + sector_t start; + sector_t end; + unsigned int split_sectors; + + split_sectors =3D bio_sectors(bio); + if (max_sectors && *max_sectors && *max_sectors < split_sectors) + split_sectors =3D *max_sectors; + + if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) + goto split; + + boundary =3D READ_ONCE(mddev->reshape_position); + start =3D bio->bi_iter.bi_sector; + end =3D bio_end_sector(bio); + if (start >=3D boundary || end <=3D boundary) + goto split; + + if (boundary - start < split_sectors) + split_sectors =3D boundary - start; + +split: + if (max_sectors) + *max_sectors =3D split_sectors; + if (split_sectors < bio_sectors(bio)) { + bio =3D bio_submit_split_bioset(bio, split_sectors, bs); + if (bio) + bio->bi_opf |=3D REQ_NOMERGE; + } + + return bio; +} +EXPORT_SYMBOL_GPL(mddev_bio_split_at_reshape_offset); + static void md_bitmap_prepare_range(struct mddev *mddev, sector_t *offset, unsigned long *sectors) { diff --git a/drivers/md/md.h b/drivers/md/md.h index 110cf0f8b107..ebfc6da83161 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -925,6 +925,10 @@ extern void md_error(struct mddev *mddev, struct md_rd= ev *rdev); extern void md_finish_reshape(struct mddev *mddev); void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev, struct bio *bio, sector_t start, sector_t size); +struct bio *mddev_bio_split_at_reshape_offset(struct mddev *mddev, + struct bio *bio, + unsigned int *max_sectors, + struct bio_set *bs); void md_account_bio(struct mddev *mddev, struct bio **bio); =20 extern bool __must_check md_flush_request(struct mddev *mddev, struct bio = *bio); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12F0D293B75; Sat, 1 Aug 2026 17:26:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605194; cv=none; b=SRkOJwxCeJcJZm09MQzg4MOcnQKaKvbBObVHtSK6ehgEMYrjqD7qc+FapsRSLejqUTfgNQalKnOk3FEMuwOjVv91XI+zqPyzBuM0e3/dblOoBKflVMhWiUJX7L1PcAtpEcqVwDQOH5CveF/5VJ7Na1sm4B9Dgt4XqC626702NiI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605194; c=relaxed/simple; bh=sxztiZsntBGoopWMfkVZWBEcUGCCYqcfpusnDJ0LYVY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fvLIRJCZcfoON64Fwraw5ed1Pk/30r+HqQTH+PeziCqaeyL6zJyAbmGSFWO5mKj11Wbm1oj1OfoQ7ifM9j8jQlIWsiQBJuFOQ2lNFNcDiMTQ/ET64E28U4cJq+xfTJEwvM/LxNOQSo6LM8ykM5QH6HB1nlghQBPsYAXQt8F5dsE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ApRAM8Qw; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ApRAM8Qw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 72CDB1F00ACA; Sat, 1 Aug 2026 17:26:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605192; bh=8T7z6zE1DRCHlXBTFApun4GqHVSJvWoRYVkPWeEGdCY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ApRAM8QwsSNvmrZXzLR6DKlvezQiHkfTXuibYke/kCTA4a+Db7QZFUhxyjMabCqr5 eRgkPSklGFAW7OEbenwpZZUYE5s95dHmzPzhnU5W7WsW+3yZr3BO2M/gnOaIn3DyaC LOnA3v8sJNRN+dyJ2s8xa0YEtWGR7RkkXP1HUs30PqvksFzEoaka0JMnz1k+UnKwhU +EsscKFqOl90YOD413fs32VYkHzSDTPMukoZqZ1Sh9fWLBbTBxgE6U6rwrUXw747++ 6xy4XR+f4CSqZRHps0J+ehDJ/ycQErt98qREnDK38PVwThmZpjGLG4gNAqZVqSa3CX vOlDHWDIDzWnQ== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 09/25] md/md-llbitmap: track bitmap sync_size explicitly Date: Sun, 2 Aug 2026 01:25:03 +0800 Message-ID: <20260801172519.2982121-10-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Track llbitmap's own sync_size instead of always using mddev->resync_max_sectors directly. This is the minimal bookkeeping needed before llbitmap can track old and new reshape geometry independently. Reviewed-by: Su Yue Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 1fa2adf0ada1..3417da288e99 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -287,6 +287,8 @@ struct llbitmap { unsigned long chunksize; /* total number of chunks */ unsigned long chunks; + /* total number of sectors tracked by current bitmap geometry */ + sector_t sync_size; unsigned long last_end_sync; /* * time in seconds that dirty bits will be cleared if the page is not @@ -918,6 +920,7 @@ static int llbitmap_init(struct llbitmap *llbitmap) llbitmap->chunkshift =3D ffz(~chunksize); llbitmap->chunksize =3D chunksize; llbitmap->chunks =3D chunks; + llbitmap->sync_size =3D blocks; mddev->bitmap_info.daemon_sleep =3D DEFAULT_DAEMON_SLEEP; =20 ret =3D llbitmap_cache_pages(llbitmap); @@ -938,6 +941,7 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap) unsigned long daemon_sleep; unsigned long chunksize; unsigned long events; + sector_t sync_size; struct page *sb_page; bitmap_super_t *sb; int ret =3D -EINVAL; @@ -987,6 +991,9 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap) goto out_put_page; } =20 + sync_size =3D le64_to_cpu(sb->sync_size); + if (!sync_size) + sync_size =3D mddev->resync_max_sectors; chunksize =3D le32_to_cpu(sb->chunksize); if (!is_power_of_2(chunksize)) { pr_err("md/llbitmap: %s: chunksize not a power of 2", @@ -1022,8 +1029,9 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap) =20 llbitmap->barrier_idle =3D DEFAULT_BARRIER_IDLE; llbitmap->chunksize =3D chunksize; - llbitmap->chunks =3D DIV_ROUND_UP_SECTOR_T(mddev->resync_max_sectors, chu= nksize); + llbitmap->chunks =3D DIV_ROUND_UP_SECTOR_T(sync_size, chunksize); llbitmap->chunkshift =3D ffz(~chunksize); + llbitmap->sync_size =3D sync_size; ret =3D llbitmap_cache_pages(llbitmap); =20 out_put_page: @@ -1153,6 +1161,7 @@ static int llbitmap_resize(struct mddev *mddev, secto= r_t blocks, int chunksize) llbitmap->chunkshift =3D ffz(~chunksize); llbitmap->chunksize =3D chunksize; llbitmap->chunks =3D chunks; + llbitmap->sync_size =3D blocks; =20 return 0; } @@ -1531,7 +1540,7 @@ static void llbitmap_update_sb(void *data) sb->events =3D cpu_to_le64(mddev->events); sb->state =3D cpu_to_le32(llbitmap->flags); sb->chunksize =3D cpu_to_le32(llbitmap->chunksize); - sb->sync_size =3D cpu_to_le64(mddev->resync_max_sectors); + sb->sync_size =3D cpu_to_le64(llbitmap->sync_size); sb->events_cleared =3D cpu_to_le64(llbitmap->events_cleared); sb->sectors_reserved =3D cpu_to_le32(mddev->bitmap_info.space); sb->daemon_sleep =3D cpu_to_le32(mddev->bitmap_info.daemon_sleep); @@ -1549,6 +1558,7 @@ static int llbitmap_get_stats(void *data, struct md_b= itmap_stats *stats) stats->missing_pages =3D 0; stats->pages =3D llbitmap->nr_pages; stats->file_pages =3D llbitmap->nr_pages; + stats->sync_size =3D llbitmap->sync_size; =20 stats->behind_writes =3D atomic_read(&llbitmap->behind_writes); stats->behind_wait =3D wq_has_sleeper(&llbitmap->behind_wait); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A9699293B75; Sat, 1 Aug 2026 17:26:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605199; cv=none; b=Bip8tnk1X20YmbqJjRAobGJBqd+SjNr5+3A1cMyBhhLFnSeOlvCmona2l8N8VyU1daVwxPdGaUwTHx6m9wGChR3htYwaGEHxUpbRAFdMp4M1BR6aQkrKFljSbHkEJgXn4YddZYHf/1dxZeUGOZogvZJH4wyDi40/CpM0hwSkLCo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605199; c=relaxed/simple; bh=yk7MBIPeUNxvxdvjxe9f9UroH6zmadqsEUO9nnfuDkE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rGR5uwD1+yntyINHl7emOz0he9kUJ0QrBb2EOx3t0RJxpzDSADxDThAxddGAwiYAx8qzl0jC+B8MZ24Ie6/BRp9MbTH/Njj5vAb2cLz/fW3aGJpt/NdYsfU+/CY69F7UgiT0nwlei8c54k3lSxb5zuh5jr6K89mmGOsQHgbzMq0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PW7P4QCq; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PW7P4QCq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C7951F00AC4; Sat, 1 Aug 2026 17:26:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605198; bh=ODxctGXeIkLTt4O0gJZ8fAvQeDr5IJX0zPywdYsaZtg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=PW7P4QCqfGAC+xNMFwqflrGXUNSUBo2iWbUNCO/i1b//ehE6cmvP2X44xbsuejVYP 99rljFECbjm5sC3p7QGEuXvH83QsS/oJ8G0H+En/7gT1VlPk2SAroMMHsyP0rnBcdw KIgmY1zQBF4+jCEo0v4VLd5hD0YDWqpBD9A952K7R3PLt9Rl2nMxCKPwBIaYRZfwxt XddI6uXzTdm/tQRb8158N4YhkguZTzbblzkCDclF7Dq4E5Lb3iDb1mOGLkVwGwHJrP gwRlDuyG+sUC0YS3gKdYrN4BqkiT928qJatRivw7K/kgKKHUxJGLVYjKCV/GnFmFkt B4oSiF7Kpd1eg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 10/25] md/md-llbitmap: allocate page controls independently Date: Sun, 2 Aug 2026 01:25:04 +0800 Message-ID: <20260801172519.2982121-11-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Allocate one llbitmap page-control object at a time and free each object through the same model. Let llbitmap_read_page() return a zeroed page without reading disk when the page index is beyond the current bitmap size, so page-control allocation no longer needs a separate read_existing flag. This keeps the llbitmap page-control lifetime self-consistent and prepares the page-cache code for later in-place growth. Reviewed-by: Su Yue Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 99 +++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 3417da288e99..d12b3dba6ae1 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -512,13 +512,19 @@ static void llbitmap_write(struct llbitmap *llbitmap,= enum llbitmap_state state, llbitmap_set_page_dirty(llbitmap, idx, bit, false); } =20 +static unsigned int llbitmap_used_pages(struct llbitmap *llbitmap, + unsigned long chunks) +{ + return DIV_ROUND_UP(chunks + BITMAP_DATA_OFFSET, PAGE_SIZE); +} + static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) { struct mddev *mddev =3D llbitmap->mddev; struct page *page =3D NULL; struct md_rdev *rdev; =20 - if (llbitmap->pctl && llbitmap->pctl[idx]) + if (llbitmap->pctl && idx < llbitmap->nr_pages && llbitmap->pctl[idx]) page =3D llbitmap->pctl[idx]->page; if (page) return page; @@ -526,6 +532,8 @@ static struct page *llbitmap_read_page(struct llbitmap = *llbitmap, int idx) page =3D alloc_page(GFP_NOIO | __GFP_ZERO); if (!page) return ERR_PTR(-ENOMEM); + if (idx >=3D llbitmap_used_pages(llbitmap, llbitmap->chunks)) + return page; =20 rdev_for_each(rdev, mddev) { sector_t sector; @@ -596,61 +604,78 @@ static void llbitmap_free_pages(struct llbitmap *llbi= tmap) for (i =3D 0; i < llbitmap->nr_pages; i++) { struct llbitmap_page_ctl *pctl =3D llbitmap->pctl[i]; =20 - if (!pctl || !pctl->page) - break; - - __free_page(pctl->page); + if (!pctl) + continue; + if (pctl->page) + __free_page(pctl->page); percpu_ref_exit(&pctl->active); + kfree(pctl); } =20 - kfree(llbitmap->pctl[0]); kfree(llbitmap->pctl); llbitmap->pctl =3D NULL; } =20 -static int llbitmap_cache_pages(struct llbitmap *llbitmap) +static struct llbitmap_page_ctl * +llbitmap_alloc_page_ctl(struct llbitmap *llbitmap, int idx) { struct llbitmap_page_ctl *pctl; - unsigned int nr_pages =3D DIV_ROUND_UP(llbitmap->chunks + - BITMAP_DATA_OFFSET, PAGE_SIZE); + struct page *page; unsigned int size =3D struct_size(pctl, dirty, BITS_TO_LONGS( llbitmap->blocks_per_page)); - int i; - - llbitmap->pctl =3D kmalloc_array(nr_pages, sizeof(void *), - GFP_NOIO | __GFP_ZERO); - if (!llbitmap->pctl) - return -ENOMEM; =20 size =3D round_up(size, cache_line_size()); - pctl =3D kmalloc_array(nr_pages, size, GFP_NOIO | __GFP_ZERO); - if (!pctl) { - kfree(llbitmap->pctl); - return -ENOMEM; + pctl =3D kzalloc(size, GFP_NOIO); + if (!pctl) + return ERR_PTR(-ENOMEM); + + page =3D llbitmap_read_page(llbitmap, idx); + + if (IS_ERR(page)) { + kfree(pctl); + return ERR_CAST(page); } =20 - llbitmap->nr_pages =3D nr_pages; + if (percpu_ref_init(&pctl->active, active_release, + PERCPU_REF_ALLOW_REINIT, GFP_NOIO)) { + __free_page(page); + kfree(pctl); + return ERR_PTR(-ENOMEM); + } =20 - for (i =3D 0; i < nr_pages; i++, pctl =3D (void *)pctl + size) { - struct page *page =3D llbitmap_read_page(llbitmap, i); + pctl->page =3D page; + pctl->state =3D page_address(page); + init_waitqueue_head(&pctl->wait); + return pctl; +} =20 - llbitmap->pctl[i] =3D pctl; +static unsigned int llbitmap_reserved_pages(struct llbitmap *llbitmap) +{ + return DIV_ROUND_UP(llbitmap->mddev->bitmap_info.space << SECTOR_SHIFT, + PAGE_SIZE); +} =20 - if (IS_ERR(page)) { - llbitmap_free_pages(llbitmap); - return PTR_ERR(page); - } +static int llbitmap_alloc_pages(struct llbitmap *llbitmap) +{ + unsigned int used_pages =3D llbitmap_used_pages(llbitmap, llbitmap->chunk= s); + unsigned int nr_pages =3D max(used_pages, llbitmap_reserved_pages(llbitma= p)); + int i; + + llbitmap->pctl =3D kcalloc(nr_pages, sizeof(*llbitmap->pctl), GFP_NOIO); + if (!llbitmap->pctl) + return -ENOMEM; =20 - if (percpu_ref_init(&pctl->active, active_release, - PERCPU_REF_ALLOW_REINIT, GFP_NOIO)) { - __free_page(page); + llbitmap->nr_pages =3D nr_pages; + + for (i =3D 0; i < nr_pages; i++) { + llbitmap->pctl[i] =3D llbitmap_alloc_page_ctl(llbitmap, i); + if (IS_ERR(llbitmap->pctl[i])) { + int ret =3D PTR_ERR(llbitmap->pctl[i]); + + llbitmap->pctl[i] =3D NULL; llbitmap_free_pages(llbitmap); - return -ENOMEM; + return ret; } - - pctl->page =3D page; - pctl->state =3D page_address(page); - init_waitqueue_head(&pctl->wait); } =20 return 0; @@ -923,7 +948,7 @@ static int llbitmap_init(struct llbitmap *llbitmap) llbitmap->sync_size =3D blocks; mddev->bitmap_info.daemon_sleep =3D DEFAULT_DAEMON_SLEEP; =20 - ret =3D llbitmap_cache_pages(llbitmap); + ret =3D llbitmap_alloc_pages(llbitmap); if (ret) return ret; =20 @@ -1032,7 +1057,7 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap) llbitmap->chunks =3D DIV_ROUND_UP_SECTOR_T(sync_size, chunksize); llbitmap->chunkshift =3D ffz(~chunksize); llbitmap->sync_size =3D sync_size; - ret =3D llbitmap_cache_pages(llbitmap); + ret =3D llbitmap_alloc_pages(llbitmap); =20 out_put_page: __free_page(sb_page); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D19C31E833; Sat, 1 Aug 2026 17:26:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605207; cv=none; b=nGwcD1hZSYzE9lflKgxA/5q2xLDHdxeIlcT+N3AZ7XQqisj8Ux71IZGQbIN6+2JkTg3ZuVVo5cfS4cmksgeCsMEBAseAi8sVXY8ec4CknxlFLwj8gshFUIO+xtDhWKAB1uj3bwadTqSRo++AT3eg4fA7tWSIRvJ+qM/KL3GQ9Ds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605207; c=relaxed/simple; bh=HM5aRR6qgXhPD7Vh7gOlklIO1h7bdktPmZBWN0iUMl0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KAlqGywvfsVBj9KX02qZo+/fLYzEQEZYTBmuICEfFb9AgHUQCU8+/sXscKvz/wPmnuX/sMX+oSR81T/MopvvJqjHgEoHvtf+EYB4nd33EdI8rnK/TdDIvFPXO5PhlKYgOsVQMeheiWxIgOXc0EUWQVVhX8stqierDBYG1onnbKQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nRe8+rPD; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nRe8+rPD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8E13A1F00ACA; Sat, 1 Aug 2026 17:26:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605205; bh=cDc+twW8d9Ff9NvWS9YNuO8D+X2RxBbbPYInTgumbME=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=nRe8+rPD1BcHqgcIj9qA06nXevJoibnmmQTEVXFFwEZGTmqLGsUzUV0b3Z1CvWgnA 7f78dVPXhdCSDlBmCtgeADjcKc0MJHysJjBV+rgvQin33AbR/E+lTUs2MD0RQ42Pnq l+qrXkQze+W/DIlzzOIvHP+kcsy0XKoFtjwZ8OWZ7Ox8173EZkzqoV4Ko3OZZo395G nhvt40XQylQW2Mud4doqFqw6X5BHoVZWMxg21QzIuT7sOCKw9jKb/S2boI0j6bNAkh 5PH2bDrdcze5c2VraaR2IrVI0Br3aMKWK41NvDi2hZYjw5TcX83oQPw2lEKkhUR/mw 2rL6roiWfyAfA== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 11/25] md/md-llbitmap: grow the page cache in place for reshape Date: Sun, 2 Aug 2026 01:25:05 +0800 Message-ID: <20260801172519.2982121-12-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Use the page-control helpers to grow llbitmap's cached pages in place for resize and later reshape preparation, instead of rebuilding the whole cache. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 145 +++++++++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 12 deletions(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index d12b3dba6ae1..cf522fae78f8 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -416,6 +416,19 @@ static char state_machine[BitStateCount][BitmapActionC= ount] =3D { }; =20 static void __llbitmap_flush(struct mddev *mddev); +static void llbitmap_flush(struct mddev *mddev); +static void llbitmap_update_sb(void *data); + +static void llbitmap_calculate_chunks(struct mddev *mddev, sector_t blocks, + unsigned long *chunksize, + unsigned long *chunks) +{ + *chunks =3D DIV_ROUND_UP_SECTOR_T(blocks, *chunksize); + while (*chunks > mddev->bitmap_info.space << SECTOR_SHIFT) { + *chunksize =3D *chunksize << 1; + *chunks =3D DIV_ROUND_UP_SECTOR_T(blocks, *chunksize); + } +} =20 static enum llbitmap_state llbitmap_read(struct llbitmap *llbitmap, loff_t= pos) { @@ -655,6 +668,48 @@ static unsigned int llbitmap_reserved_pages(struct llb= itmap *llbitmap) PAGE_SIZE); } =20 +static int llbitmap_expand_pages(struct llbitmap *llbitmap, + unsigned long chunks) +{ + struct llbitmap_page_ctl **pctl; + unsigned int old_nr_pages =3D llbitmap->nr_pages; + unsigned int nr_pages =3D llbitmap_used_pages(llbitmap, chunks); + unsigned int i; + int ret; + + if (nr_pages <=3D old_nr_pages) + return 0; + + pctl =3D kcalloc(nr_pages, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + + if (llbitmap->pctl) + memcpy(pctl, llbitmap->pctl, + array_size(old_nr_pages, sizeof(*pctl))); + + for (i =3D old_nr_pages; i < nr_pages; i++) { + pctl[i] =3D llbitmap_alloc_page_ctl(llbitmap, i); + if (IS_ERR(pctl[i])) + goto err_alloc_ptr; + } + + kfree(llbitmap->pctl); + llbitmap->pctl =3D pctl; + llbitmap->nr_pages =3D nr_pages; + return 0; + +err_alloc_ptr: + ret =3D PTR_ERR(pctl[i]); + while (i-- > old_nr_pages) { + __free_page(pctl[i]->page); + percpu_ref_exit(&pctl[i]->active); + kfree(pctl[i]); + } + kfree(pctl); + return ret; +} + static int llbitmap_alloc_pages(struct llbitmap *llbitmap) { unsigned int used_pages =3D llbitmap_used_pages(llbitmap, llbitmap->chunk= s); @@ -730,6 +785,34 @@ static bool llbitmap_zero_all_disks(struct llbitmap *l= lbitmap) return true; } =20 +static void llbitmap_mark_range(struct llbitmap *llbitmap, + unsigned long start, + unsigned long end, + enum llbitmap_state state) +{ + while (start <=3D end) { + llbitmap_write(llbitmap, state, start); + start++; + } +} + +static int llbitmap_prepare_resize(struct llbitmap *llbitmap, + unsigned long old_chunks, + unsigned long new_chunks, + unsigned long cache_chunks) +{ + int ret; + + llbitmap_flush(llbitmap->mddev); + ret =3D llbitmap_expand_pages(llbitmap, cache_chunks); + if (ret) + return ret; + if (new_chunks > old_chunks) + llbitmap_mark_range(llbitmap, old_chunks, new_chunks - 1, + BitUnwritten); + return 0; +} + static void llbitmap_init_state(struct llbitmap *llbitmap) { struct mddev *mddev =3D llbitmap->mddev; @@ -1026,10 +1109,10 @@ static int llbitmap_read_sb(struct llbitmap *llbitm= ap) goto out_put_page; } =20 - if (chunksize < DIV_ROUND_UP_SECTOR_T(mddev->resync_max_sectors, + if (chunksize < DIV_ROUND_UP_SECTOR_T(sync_size, mddev->bitmap_info.space << SECTOR_SHIFT)) { pr_err("md/llbitmap: %s: chunksize too small %lu < %llu / %lu", - mdname(mddev), chunksize, mddev->resync_max_sectors, + mdname(mddev), chunksize, sync_size, mddev->bitmap_info.space); goto out_put_page; } @@ -1171,24 +1254,62 @@ static int llbitmap_create(struct mddev *mddev) static int llbitmap_resize(struct mddev *mddev, sector_t blocks, int chunk= size) { struct llbitmap *llbitmap =3D mddev->bitmap; + sector_t old_blocks =3D llbitmap->sync_size; + unsigned long old_chunks =3D llbitmap->chunks; unsigned long chunks; + unsigned long cache_chunks; + int ret =3D 0; + unsigned long bitmap_chunksize; + bool reshape; + bool quiesced =3D false; =20 if (chunksize =3D=3D 0) chunksize =3D llbitmap->chunksize; =20 - /* If there is enough space, leave the chunksize unchanged. */ - chunks =3D DIV_ROUND_UP_SECTOR_T(blocks, chunksize); - while (chunks > mddev->bitmap_info.space << SECTOR_SHIFT) { - chunksize =3D chunksize << 1; - chunks =3D DIV_ROUND_UP_SECTOR_T(blocks, chunksize); - } + bitmap_chunksize =3D chunksize; + llbitmap_calculate_chunks(mddev, blocks, &bitmap_chunksize, &chunks); =20 - llbitmap->chunkshift =3D ffz(~chunksize); - llbitmap->chunksize =3D chunksize; - llbitmap->chunks =3D chunks; - llbitmap->sync_size =3D blocks; + reshape =3D mddev->delta_disks || mddev->new_level !=3D mddev->level || + mddev->new_layout !=3D mddev->layout || + mddev->new_chunk_sectors !=3D mddev->chunk_sectors; + if (!reshape && bitmap_chunksize !=3D llbitmap->chunksize) + return -EOPNOTSUPP; + if (blocks =3D=3D old_blocks && chunks =3D=3D llbitmap->chunks) + return 0; =20 + if (mddev->pers->quiesce) { + mddev->pers->quiesce(mddev, 1); + quiesced =3D true; + } + + mutex_lock(&mddev->bitmap_info.mutex); + cache_chunks =3D reshape ? max(old_chunks, chunks) : chunks; + ret =3D llbitmap_prepare_resize(llbitmap, old_chunks, chunks, cache_chunk= s); + if (ret) + goto out; + + if (reshape) { + llbitmap->chunks =3D max(old_chunks, chunks); + } else { + if (blocks < old_blocks && chunks < old_chunks) + llbitmap_mark_range(llbitmap, chunks, old_chunks - 1, + BitUnwritten); + mddev->bitmap_info.chunksize =3D bitmap_chunksize; + llbitmap->chunks =3D chunks; + llbitmap->sync_size =3D blocks; + llbitmap_update_sb(llbitmap); + } + __llbitmap_flush(mddev); + mutex_unlock(&mddev->bitmap_info.mutex); + if (quiesced) + mddev->pers->quiesce(mddev, 0); return 0; + +out: + mutex_unlock(&mddev->bitmap_info.mutex); + if (quiesced) + mddev->pers->quiesce(mddev, 0); + return ret; } =20 static int llbitmap_load(struct mddev *mddev) --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B574231E833; Sat, 1 Aug 2026 17:26:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605211; cv=none; b=ozGTrlqIlW+D+O9IFjYcXuE1TFm44jIvg3xMhy4jYb0Dv5/q5O7hHFHz8zkiDDavBPcwP872541kOCXpXi/2MrMMDhS3xGr9QsldMC5hb112mMDJTj33OaeBHu0vBGW1EkQC9RhcltKsOMWO379or3K3nC/BCy6NrF1Mjre7TE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605211; c=relaxed/simple; bh=P9DUBYd2p9B1u+9uXmIYygnbEadelpwOlThwE3Abd8I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HFub6Vdmo1YG9IbyY6ozLWUb6F9HsfzfAw1FaERn2DCh1kD3WZrkHsraWBFFq6Jw0K8VirwzIV658t25OlpoINr5tud/hBGvh445kh+G47CCKakYgbVNqYqcQHo0jHua5t6+JQ+USUT5sXHA2ePLOxbIA1+9WIx7qdpl8IlKHZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ESqNovsq; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ESqNovsq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A75C51F00AC4; Sat, 1 Aug 2026 17:26:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605210; bh=053e985NNbRHzt9HVeR1ohHEaM224L+1aYxhMTBikEA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ESqNovsqUuLNos/CIU8mUlQvc5p80kBF7w/BalbFeJ1VLvuD/jC573wUJ2Se9Puuu +U0ayvNNKIHBfwUDz7UEnTyddfCHHdD87gTRA7Cy+k6kZcCvqnwafphNH9edvDAjyT 23Rj6YimQ3isqhTIyGkA0pQ4k0I3mCmsqLLSTA9jacJQCAR94TQUoJTtEff8WK/bgZ LqSZ/7ynrzGMV4Xlz3zUqbLNlz7vwIkf+O/xbStgDboJESnvfMrW4apemVQ4Vc75V0 BATtWhlCuiUUZOf7HG3V+kEBYZvD+Ao3jvAEh5cqjdDrykijnxNMhRiQb7pgIPLacM Jr2rCsvNLX7Xg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 12/25] md/md-llbitmap: track target reshape geometry fields Date: Sun, 2 Aug 2026 01:25:06 +0800 Message-ID: <20260801172519.2982121-13-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Track llbitmap bookkeeping for the target reshape geometry while keeping a single live bitmap instance. Add the reshape geometry fields, refresh helper, and update the load and resize paths to keep the target geometry in sync. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index cf522fae78f8..37d1312e3eab 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -289,6 +289,9 @@ struct llbitmap { unsigned long chunks; /* total number of sectors tracked by current bitmap geometry */ sector_t sync_size; + unsigned long reshape_chunksize; + unsigned long reshape_chunks; + sector_t reshape_sync_size; unsigned long last_end_sync; /* * time in seconds that dirty bits will be cleared if the page is not @@ -430,6 +433,39 @@ static void llbitmap_calculate_chunks(struct mddev *md= dev, sector_t blocks, } } =20 +static bool llbitmap_reshaping(struct llbitmap *llbitmap) +{ + return llbitmap->mddev->reshape_position !=3D MaxSector; +} + +static sector_t llbitmap_personality_sync_size(struct llbitmap *llbitmap, + bool previous) +{ + struct mddev *mddev =3D llbitmap->mddev; + + if (!llbitmap_reshaping(llbitmap) || !mddev->private || !mddev->pers || + !mddev->pers->bitmap_sync_size) + return llbitmap->sync_size; + return mddev->pers->bitmap_sync_size(mddev, previous); +} + +static void llbitmap_refresh_reshape(struct llbitmap *llbitmap) +{ + unsigned long old_chunks =3D DIV_ROUND_UP_SECTOR_T(llbitmap->sync_size, + llbitmap->chunksize); + sector_t blocks =3D llbitmap_personality_sync_size(llbitmap, false); + unsigned long chunksize =3D llbitmap->chunksize; + unsigned long chunks =3D DIV_ROUND_UP_SECTOR_T(blocks, chunksize); + + llbitmap->reshape_sync_size =3D blocks; + llbitmap->reshape_chunksize =3D chunksize; + llbitmap->reshape_chunks =3D chunks; + llbitmap_calculate_chunks(llbitmap->mddev, blocks, + &llbitmap->reshape_chunksize, + &llbitmap->reshape_chunks); + llbitmap->chunks =3D max(old_chunks, llbitmap->reshape_chunks); +} + static enum llbitmap_state llbitmap_read(struct llbitmap *llbitmap, loff_t= pos) { unsigned int idx; @@ -1029,6 +1065,7 @@ static int llbitmap_init(struct llbitmap *llbitmap) llbitmap->chunksize =3D chunksize; llbitmap->chunks =3D chunks; llbitmap->sync_size =3D blocks; + llbitmap_refresh_reshape(llbitmap); mddev->bitmap_info.daemon_sleep =3D DEFAULT_DAEMON_SLEEP; =20 ret =3D llbitmap_alloc_pages(llbitmap); @@ -1140,6 +1177,7 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap) llbitmap->chunks =3D DIV_ROUND_UP_SECTOR_T(sync_size, chunksize); llbitmap->chunkshift =3D ffz(~chunksize); llbitmap->sync_size =3D sync_size; + llbitmap_refresh_reshape(llbitmap); ret =3D llbitmap_alloc_pages(llbitmap); =20 out_put_page: @@ -1289,6 +1327,9 @@ static int llbitmap_resize(struct mddev *mddev, secto= r_t blocks, int chunksize) goto out; =20 if (reshape) { + llbitmap->reshape_sync_size =3D blocks; + llbitmap->reshape_chunksize =3D bitmap_chunksize; + llbitmap->reshape_chunks =3D chunks; llbitmap->chunks =3D max(old_chunks, chunks); } else { if (blocks < old_blocks && chunks < old_chunks) @@ -1297,6 +1338,7 @@ static int llbitmap_resize(struct mddev *mddev, secto= r_t blocks, int chunksize) mddev->bitmap_info.chunksize =3D bitmap_chunksize; llbitmap->chunks =3D chunks; llbitmap->sync_size =3D blocks; + llbitmap_refresh_reshape(llbitmap); llbitmap_update_sb(llbitmap); } __llbitmap_flush(mddev); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24A7C293B75; Sat, 1 Aug 2026 17:26:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605220; cv=none; b=gDPw4LCQE9GQqBboGrpUucTQTR0aDvvTR+UWcJSu5PKLpb5WL0345IA1Dk+mIza87XfF/f3JBiQXpe/iBONZ5POzbqopFQZ+PaOTuaFZYO10favuBQ9BjHLOSDlU3VJ52TZ0Zrb4SifNC53NjORAa8MAoSmeOrqUorJithtJ7gs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605220; c=relaxed/simple; bh=gMAZOUU1RAHcRFS6oit2lQ0Z3i8Lf6X+JxkLbh56zug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u5oJCMScQ2Z3EoPyeReGbTJGY6BocD/J6PnzEmrTuH+OZi+qEVVK7yhRjvZw/NsFnMGL8SBvdq994UHW4ArO5iZOM8oT5IZ1XpfIMRk68gFNGsq1wWd82DYH70Bh0t0RNDWfnSq2OYt4UilXledCXuPMkapxbxg9p8k7e/ouBd8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aavnY4Qp; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aavnY4Qp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1CBDD1F00AC4; Sat, 1 Aug 2026 17:26:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605218; bh=88/Yg7HG6sR0d7UBoCaiHtmMN56BWEV6IpinjNf43Uo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aavnY4Qp2ymqiq6ERFp5G3j3uzkXaXOtERW43wwlEUSN4rIlkmBGHm924nG7cAdba t/DrT9aGfq0CgfSi6YBKzXP4jLB+2tVAfAyKZnis+VXkdaeJQkyLrAA0utkU3TYq56 BwR1Cu5Un2iIgPauWLz4qBkByWw4ZwjYf6Lp9I1Q5dx80TQsd10Y+l4Z2H3Icr+lkf LCncgwjvtFg9sXiZkNWfKsYz+V3MBqImg9cOmo1ajNbVlPOm4rVV6afa1x8y85e4e7 jQOG6GERR/vwzrmTR1iiFKhSCDUEUOTU8mOAKNB8icr0IUer30Ww/JMtHXLqKR78fj LSlC/JO8OuJeg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 13/25] md/md-llbitmap: finish reshape geometry Date: Sun, 2 Aug 2026 01:25:07 +0800 Message-ID: <20260801172519.2982121-14-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Commit the staged llbitmap geometry when reshape finishes. When assembling a stopped reshape, md_run() creates the bitmap before publishing mddev->pers. llbitmap_read_sb() can therefore only initialize the reshape fields from the old on-disk sync size. Refresh the staged reshape geometry again from llbitmap_load(), after mddev->pers is available, and expand the in-memory page controls before replaying bitmap state. Reproduce on the old kernel by creating a RAID10 llbitmap with four active disks and two spares, growing it to six disks, then stopping and assembling while reshape is still running. The llbitmap chunk count was 32704 before grow, 49056 during reshape, then rolled back to 32704 after reassemble. The fixed kernel kept the target geometry across the same stop/reassemble flow: 65440 chunks before grow, 98160 during reshape, and 98160 after reassemble. Reported-by: Mykola Marzhan Link: https://lore.kernel.org/all/20260726185916.2223460-1-mykola@meshstor.= io/ Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 37d1312e3eab..f41f9ba2063b 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1358,11 +1358,20 @@ static int llbitmap_load(struct mddev *mddev) { enum llbitmap_action action =3D BitmapActionReload; struct llbitmap *llbitmap =3D mddev->bitmap; + int ret; =20 if (test_and_clear_bit(BITMAP_STALE, &llbitmap->flags)) action =3D BitmapActionStale; =20 + mutex_lock(&mddev->bitmap_info.mutex); + llbitmap_refresh_reshape(llbitmap); + ret =3D llbitmap_expand_pages(llbitmap, llbitmap->chunks); + if (ret) { + mutex_unlock(&mddev->bitmap_info.mutex); + return ret; + } llbitmap_state_machine(llbitmap, 0, llbitmap->chunks - 1, action); + mutex_unlock(&mddev->bitmap_info.mutex); return 0; } =20 @@ -1694,6 +1703,30 @@ static void llbitmap_dirty_bits(struct mddev *mddev,= unsigned long s, llbitmap_state_machine(mddev->bitmap, s, e, BitmapActionStartwrite); } =20 +static void llbitmap_reshape_finish(struct mddev *mddev) +{ + struct llbitmap *llbitmap =3D mddev->bitmap; + + if (mddev->pers->quiesce) + mddev->pers->quiesce(mddev, 1); + + mutex_lock(&mddev->bitmap_info.mutex); + llbitmap_flush(mddev); + + llbitmap->chunksize =3D llbitmap->reshape_chunksize; + llbitmap->chunkshift =3D ffz(~llbitmap->chunksize); + llbitmap->chunks =3D llbitmap->reshape_chunks; + llbitmap->sync_size =3D llbitmap->reshape_sync_size; + llbitmap_refresh_reshape(llbitmap); + mddev->bitmap_info.chunksize =3D llbitmap->chunksize; + llbitmap_update_sb(llbitmap); + __llbitmap_flush(mddev); + mutex_unlock(&mddev->bitmap_info.mutex); + + if (mddev->pers->quiesce) + mddev->pers->quiesce(mddev, 0); +} + static void llbitmap_write_sb(struct llbitmap *llbitmap) { int nr_blocks =3D DIV_ROUND_UP(BITMAP_DATA_OFFSET, llbitmap->io_size); @@ -1991,6 +2024,7 @@ static struct bitmap_operations llbitmap_ops =3D { .get_stats =3D llbitmap_get_stats, .dirty_bits =3D llbitmap_dirty_bits, .prepare_range =3D llbitmap_prepare_range, + .reshape_finish =3D llbitmap_reshape_finish, .write_all =3D llbitmap_write_all, =20 .groups =3D md_llbitmap_groups, --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EBDB1293B75; Sat, 1 Aug 2026 17:27:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605224; cv=none; b=kUM63R1jqwMqVxbwgGxf7EoN3NtdwkKLOyakxLX3tZvjwvej85xJ5FUWPFs1wEhdqtCvhdAk2OdYNjaoiMhrJ5701XoVxjrSjDT+me29rYAeNr0Is9jPI22NRMwkCzjbCyoy5Kp42Qlb+ujTs4SjWtGCKYIhl4AQoPEDoH2sKYk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605224; c=relaxed/simple; bh=sO9EYDUrItlHhOotGDUWGCyNs1Mb1pCqLVgtYIaCn3Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RqxHkmv2JsYAqfh4qJw7cF+5HKi/aJaC8PyRIbZ7i5HhsIlJWhpSUpNbEndH3Y3i7xn54rPOAJrRgoWhgr1R85wckdPYvBTuVHBtOjMDWyM55Kuv08SWFKHz4JM18i3Wf/JlyxlfC/QOpCH3/iDxbxNhUHiLE9+q96YHb0NFRA4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hHxD/Wuc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hHxD/Wuc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2B511F00ACA; Sat, 1 Aug 2026 17:26:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605222; bh=8ssnwNWUL+M+KHIJhOdALPLvpAvLDAqMXaJ+Jj9nOyU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=hHxD/Wucz26nasvUkt9FKVGh/w26OOKMgX7UJ0lqACSl/VHg33Dm53ZXK7cmYALVU XLMNOjEwAnZJnA0zwCotaAPEMQrAHFOaN+QivCK9ZZ24ZtlaIiMcUYyPihPKEbrz8a EUVXkr9S6GPxlm6C69KJvFRP6j7IHfbx/G78iD4rQibP/VMu5nQRd3NtaHLOetJnZ3 SyCEbSSVRkvIK/2Qdzxo/qy7YSiHYD/KCQ1cgrc1IUrmnAuCunkqEgGJOYNSycE9vW 74TWpi7kaAiCFD7d9FhBRWZbYUOjabPjmdEan+hFwdKHlmvRaaK77UlpQ/+OJOefXW Ztct7R1x1YHqw== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 14/25] md/md-llbitmap: refuse reshape while llbitmap still needs sync Date: Sun, 2 Aug 2026 01:25:08 +0800 Message-ID: <20260801172519.2982121-15-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Reject reshape when llbitmap still contains NeedSync or Syncing bits. This keeps reshape from starting until the current llbitmap state has been reconciled. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index f41f9ba2063b..3b121b372cd8 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1703,6 +1703,29 @@ static void llbitmap_dirty_bits(struct mddev *mddev,= unsigned long s, llbitmap_state_machine(mddev->bitmap, s, e, BitmapActionStartwrite); } =20 +static int llbitmap_reshape_can_start(struct mddev *mddev) +{ + struct llbitmap *llbitmap =3D mddev->bitmap; + unsigned long chunk; + int ret =3D 0; + + if (!llbitmap) + return 0; + + mutex_lock(&mddev->bitmap_info.mutex); + for (chunk =3D 0; chunk < llbitmap->chunks; chunk++) { + enum llbitmap_state state =3D llbitmap_read(llbitmap, chunk); + + if (state =3D=3D BitNeedSync || state =3D=3D BitSyncing) { + ret =3D -EBUSY; + break; + } + } + mutex_unlock(&mddev->bitmap_info.mutex); + + return ret; +} + static void llbitmap_reshape_finish(struct mddev *mddev) { struct llbitmap *llbitmap =3D mddev->bitmap; @@ -2025,6 +2048,7 @@ static struct bitmap_operations llbitmap_ops =3D { .dirty_bits =3D llbitmap_dirty_bits, .prepare_range =3D llbitmap_prepare_range, .reshape_finish =3D llbitmap_reshape_finish, + .reshape_can_start =3D llbitmap_reshape_can_start, .write_all =3D llbitmap_write_all, =20 .groups =3D md_llbitmap_groups, --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA6523B6BF0; Sat, 1 Aug 2026 17:27:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605227; cv=none; b=Zfk0q67FGbwww4tsAWNbvSXHlaM0bvCKsREplw5aZN92dPFOlmtz8jzQA3NJtooC0n4ZV/EqgCHhRIOX5MTP1fahDLCWgVlxiGUkfLjF9Y5ARfNUwcLHTDUdnzJMmAL+0wBomHDOXs6gH07p8FagOXyuQnQ9qqQU3g/CXK2OQlQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605227; c=relaxed/simple; bh=mfGOIXGvo4zi7djipiv1tFalQ31ZzlIXGCj8rK65u9w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B1axZcY5n3WUfUeJTfpzXO3PB02lxjj3QCgOffGVCv0K/QHf+XK0C0792kK4/Da2vmwjDoHAz/jEnUzQz9zeJIxQQJf2XsLgDwlRCfuwnxWgJdIXynVGXpwazvidimQ6mVdZFMD3+48hpdO2s+bkF9v7j27HL44lCUI52xseX24= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WdigaIcO; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WdigaIcO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 64E431F00AC4; Sat, 1 Aug 2026 17:27:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605225; bh=UGxDvHEe20eING+EcorLxYgHB71n3BmVpRGRRbq0hEw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WdigaIcOjMcpCYrQ1zHtpsmfNkqifUczKGzkeKXfxJHvIbxRQHiNsEvGiW3moJDAX JH79YkjoXNmGzZEvl9+l+WRvgxoGDZPQGrOuAogSfyRUf2vROnlc3NFDhKT2NDb+dy PmsYmzMZ352HCpRZcwRmZGLk8OGgo+hHG8rUuKEI9bJfxX2IO1sCB/T/En51uT/I2I qKuQvdgUuPVYTW5cUGjqy9HZ5xTihAp9Sx9Gtl3rH6DDCH77t/gcWq0+KTq6ft8tmV D19fnNlxoqfSk/Tamde/SQYcl5PXe4Hr+hB6F5OOySBMccPRy2vq8toP7ewyEEBrKw CdZYku/FV2Edg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 15/25] md/md-llbitmap: add reshape range mapping helpers Date: Sun, 2 Aug 2026 01:25:09 +0800 Message-ID: <20260801172519.2982121-16-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Teach llbitmap to choose old versus new geometry during reshape and to encode exact bitmap ranges for the active geometry. This is the mapping groundwork for checkpoint remapping. Range preparation now distinguishes writes from discards. Normal writes must cover every touched bitmap chunk, while discards may only mark fully covered chunks unwritten. Without this distinction, a discard that starts or ends inside a chunk can make live data look unwritten after the range has been mapped and floored. Reproduce that with a RAID1 llbitmap using 128-sector chunks. A discard starting halfway into chunk 8 with a 128-sector length changed clean bits from 16352 to 16350 and unwritten bits from 0 to 2, even though no chunk was fully discarded. With discard-specific range encoding, both counts stay unchanged for the same test. Range preparation also clamps the pre-map range in the same coordinate space as the incoming IO. RAID5 receives array-sector offsets but tracks llbitmap sync size in component sectors, so steady-state RAID5 must use bitmap_array_sectors() before mapping and keep the existing sync-size clamp after mapping. Reproduce that with a 4-disk RAID5 llbitmap created --assume-clean. A write below dev_sectors changed dirty bits from 0 to 512, but a write at seek=3D2094080 left the count at 512. With the array-sector pre-map limit, writing at seek=3Dcomponent_size + 65536 increased dirty bits from 512 to 1024. Reported-by: Mykola Marzhan Link: https://lore.kernel.org/all/20260726185916.2223460-1-mykola@meshstor.= io/ Signed-off-by: Yu Kuai --- drivers/md/md-bitmap.c | 2 +- drivers/md/md-bitmap.h | 3 +- drivers/md/md-llbitmap.c | 137 +++++++++++++++++++++++++++++++++++---- drivers/md/md.c | 10 +-- 4 files changed, 134 insertions(+), 18 deletions(-) diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 4c31807e6bcc..52dfbca28b64 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -1731,7 +1731,7 @@ static void bitmap_start_write(struct mddev *mddev, s= ector_t offset, } =20 static void bitmap_prepare_range(struct mddev *mddev, sector_t *offset, - unsigned long *sectors) + unsigned long *sectors, bool discard) { if (mddev->pers->bitmap_sector) mddev->pers->bitmap_sector(mddev, offset, sectors); diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h index 26cd07737aab..97cdd7cea5dd 100644 --- a/drivers/md/md-bitmap.h +++ b/drivers/md/md-bitmap.h @@ -96,7 +96,8 @@ struct bitmap_operations { /* Prepare a range for this bitmap implementation. */ void (*prepare_range)(struct mddev *mddev, sector_t *offset, - unsigned long *sectors); + unsigned long *sectors, + bool discard); void (*reshape_finish)(struct mddev *mddev); int (*reshape_can_start)(struct mddev *mddev); void (*reshape_mark)(struct mddev *mddev, sector_t old_pos, diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 3b121b372cd8..eed3e248b730 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include =20 @@ -433,22 +434,28 @@ static void llbitmap_calculate_chunks(struct mddev *m= ddev, sector_t blocks, } } =20 -static bool llbitmap_reshaping(struct llbitmap *llbitmap) -{ - return llbitmap->mddev->reshape_position !=3D MaxSector; -} - static sector_t llbitmap_personality_sync_size(struct llbitmap *llbitmap, bool previous) { struct mddev *mddev =3D llbitmap->mddev; =20 - if (!llbitmap_reshaping(llbitmap) || !mddev->private || !mddev->pers || + if (READ_ONCE(mddev->reshape_position) =3D=3D MaxSector || + !mddev->private || !mddev->pers || !mddev->pers->bitmap_sync_size) return llbitmap->sync_size; return mddev->pers->bitmap_sync_size(mddev, previous); } =20 +static sector_t llbitmap_logical_size(struct llbitmap *llbitmap, bool prev= ious) +{ + struct mddev *mddev =3D llbitmap->mddev; + + if (!mddev->private || !mddev->pers || + !mddev->pers->bitmap_array_sectors) + return llbitmap_personality_sync_size(llbitmap, previous); + return mddev->pers->bitmap_array_sectors(mddev, previous); +} + static void llbitmap_refresh_reshape(struct llbitmap *llbitmap) { unsigned long old_chunks =3D DIV_ROUND_UP_SECTOR_T(llbitmap->sync_size, @@ -466,6 +473,80 @@ static void llbitmap_refresh_reshape(struct llbitmap *= llbitmap) llbitmap->chunks =3D max(old_chunks, llbitmap->reshape_chunks); } =20 +static void llbitmap_map_layout(struct llbitmap *llbitmap, sector_t *offse= t, + unsigned long *sectors, bool previous) +{ + sector_t limit =3D llbitmap_logical_size(llbitmap, previous); + sector_t start =3D *offset; + sector_t end =3D start + *sectors; + + if (start >=3D limit) { + *sectors =3D 0; + return; + } + if (end > limit) + end =3D limit; + + *offset =3D start; + *sectors =3D end - start; + if (!*sectors) + return; + + if (llbitmap->mddev->pers->bitmap_sector_map) + llbitmap->mddev->pers->bitmap_sector_map(llbitmap->mddev, offset, + sectors, previous); + else if (!previous && llbitmap->mddev->pers->bitmap_sector) + llbitmap->mddev->pers->bitmap_sector(llbitmap->mddev, offset, + sectors); +} + +static void llbitmap_encode_range(struct llbitmap *llbitmap, sector_t *off= set, + unsigned long *sectors, bool previous) +{ + unsigned long chunksize =3D previous ? llbitmap->chunksize : + llbitmap->reshape_chunksize; + u64 start; + u64 end; + + if (!*sectors) { + *offset =3D 0; + return; + } + + start =3D div64_u64(*offset, chunksize); + end =3D div64_u64(*offset + *sectors - 1, chunksize); + *offset =3D (sector_t)start << llbitmap->chunkshift; + *sectors =3D (end - start + 1) << llbitmap->chunkshift; +} + +static void llbitmap_encode_discard_range(struct llbitmap *llbitmap, + sector_t *offset, + unsigned long *sectors, + bool previous) +{ + unsigned long chunksize =3D previous ? llbitmap->chunksize : + llbitmap->reshape_chunksize; + sector_t end =3D *offset + *sectors; + u64 start; + u64 last; + + if (!*sectors) { + *offset =3D 0; + return; + } + + start =3D DIV_ROUND_UP_SECTOR_T(*offset, chunksize); + last =3D div64_u64(end, chunksize); + if (start >=3D last) { + *offset =3D 0; + *sectors =3D 0; + return; + } + + *offset =3D (sector_t)start << llbitmap->chunkshift; + *sectors =3D (last - start) << llbitmap->chunkshift; +} + static enum llbitmap_state llbitmap_read(struct llbitmap *llbitmap, loff_t= pos) { unsigned int idx; @@ -1394,11 +1475,35 @@ static void llbitmap_destroy(struct mddev *mddev) mutex_unlock(&mddev->bitmap_info.mutex); } =20 +static bool llbitmap_map_previous(struct llbitmap *llbitmap, sector_t offs= et, + unsigned long sectors) +{ + struct mddev *mddev =3D llbitmap->mddev; + sector_t boundary =3D READ_ONCE(mddev->reshape_position); + + if (boundary =3D=3D MaxSector) + return false; + + WARN_ON_ONCE(sectors && offset < boundary && offset + sectors > boundary); + + return mddev->reshape_backwards ? offset < boundary : offset >=3D boundar= y; +} + static void llbitmap_prepare_range(struct mddev *mddev, sector_t *offset, - unsigned long *sectors) + unsigned long *sectors, bool discard) { - if (mddev->pers->bitmap_sector) - mddev->pers->bitmap_sector(mddev, offset, sectors); + struct llbitmap *llbitmap =3D mddev->bitmap; + bool previous; + + if (!llbitmap) + return; + + previous =3D llbitmap_map_previous(llbitmap, *offset, *sectors); + llbitmap_map_layout(llbitmap, offset, sectors, previous); + if (discard) + llbitmap_encode_discard_range(llbitmap, offset, sectors, previous); + else + llbitmap_encode_range(llbitmap, offset, sectors, previous); } =20 static void llbitmap_start_write(struct mddev *mddev, sector_t offset, @@ -1567,7 +1672,11 @@ static bool llbitmap_blocks_synced(struct mddev *mdd= ev, sector_t offset) { struct llbitmap *llbitmap =3D mddev->bitmap; unsigned long p =3D offset >> llbitmap->chunkshift; - enum llbitmap_state c =3D llbitmap_read(llbitmap, p); + enum llbitmap_state c; + + if (p >=3D llbitmap->chunks) + return false; + c =3D llbitmap_read(llbitmap, p); =20 return c =3D=3D BitClean || c =3D=3D BitDirty || c =3D=3D BitCleanUnwritt= en; } @@ -1577,7 +1686,11 @@ static sector_t llbitmap_skip_sync_blocks(struct mdd= ev *mddev, sector_t offset) struct llbitmap *llbitmap =3D mddev->bitmap; unsigned long p =3D offset >> llbitmap->chunkshift; int blocks =3D llbitmap->chunksize - (offset & (llbitmap->chunksize - 1)); - enum llbitmap_state c =3D llbitmap_read(llbitmap, p); + enum llbitmap_state c; + + if (p >=3D llbitmap->chunks) + return 0; + c =3D llbitmap_read(llbitmap, p); =20 /* always skip unwritten blocks */ if (c =3D=3D BitUnwritten) @@ -1622,6 +1735,8 @@ static bool llbitmap_start_sync(struct mddev *mddev, = sector_t offset, * if md_do_sync() loop more times. */ *blocks =3D llbitmap->chunksize - (offset & (llbitmap->chunksize - 1)); + if (p >=3D llbitmap->chunks) + return false; state =3D llbitmap_state_machine(llbitmap, p, p, BitmapActionStartsync); return state =3D=3D BitSyncing || state =3D=3D BitSyncingUnwritten; } diff --git a/drivers/md/md.c b/drivers/md/md.c index 34e95ef9f2d4..30d9f9c02e73 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9401,20 +9401,20 @@ struct bio *mddev_bio_split_at_reshape_offset(struc= t mddev *mddev, EXPORT_SYMBOL_GPL(mddev_bio_split_at_reshape_offset); =20 static void md_bitmap_prepare_range(struct mddev *mddev, sector_t *offset, - unsigned long *sectors) + unsigned long *sectors, bool discard) { - mddev->bitmap_ops->prepare_range(mddev, offset, sectors); + mddev->bitmap_ops->prepare_range(mddev, offset, sectors, discard); } =20 static void md_bitmap_start(struct mddev *mddev, struct md_io_clone *md_io_clone) { - md_bitmap_fn *fn =3D unlikely(md_io_clone->rw =3D=3D STAT_DISCARD) ? - mddev->bitmap_ops->start_discard : + bool discard =3D md_io_clone->rw =3D=3D STAT_DISCARD; + md_bitmap_fn *fn =3D discard ? mddev->bitmap_ops->start_discard : mddev->bitmap_ops->start_write; =20 md_bitmap_prepare_range(mddev, &md_io_clone->offset, - &md_io_clone->sectors); + &md_io_clone->sectors, discard); if (!md_io_clone->sectors) return; fn(mddev, md_io_clone->offset, md_io_clone->sectors); --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AEA71293B75; Sat, 1 Aug 2026 17:27:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605232; cv=none; b=hBUNT3symId2+kfEXCANAVS+SpzjmDURuoM7rAr+DFBnpROGv1E3H6k5jCGwEoGXtD0tUAUPKCD6//LyQQEI+Di28hOF6FbI+l2u4yUVWsdPH/wu6erBaOjWi+zMpaw1CS5hN5886RnXAXqD41pozoTwpROTvaO5C8HCzAIUqAs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605232; c=relaxed/simple; bh=AGxXCfcDngyf1D9ahtN5F4K28VS7MxneMJ/exnidUwA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z5y+C17WjuBBQO8RgIg/VPOsZwnbMcCrPOkiAfOwHiVkqH8HOs5NOuI1NS/uoJ+FWlFtYCXWWA5iFORLMPrXrkQBIIhWO6ejhwShoVD39xLoDmjew7+AjojU2K33JC/Lj609wfKVExltawZdRz7ueYzXypRh646Wk1DDyK+TZbk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UzC1/MYh; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UzC1/MYh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2BB471F00ACA; Sat, 1 Aug 2026 17:27:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605231; bh=xTPhGjYKCzWKWwLWCkcQX9ZclRZsTm5cHvS2aXKeVsQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=UzC1/MYhfDFfEqkZTsfUfRtvhEqI+djvdFjo4QJtSWVOAwQX3MSLQa8tBwtqEMLlB IGuBHKzulGxRpGR5jQmJRp/ELbn3SilR5bRI5xcitf9VuizHb8IPIm3xZN4eU0+m0c xX4PVy7rHyZqGFhRw1UK8Mde9TLdq4AoPEFbp50xiLmbte08qH+4U/JkhKGxTpw4ZU W86TwyBMkFYUcan4NCgmMUAauZeOT83sRZa6hbM+4ryQ9fHryKigYqgdPoyd/gyFWb E2XzpQC1RyxvKeBToL3KDKV37jq3jx0NBQAG3x1eqgL9iTmdMwDsrmVufzk5bPj8wh kPmYjYDvy3qPg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 16/25] md/md-llbitmap: don't skip reshape ranges from bitmap state Date: Sun, 2 Aug 2026 01:25:10 +0800 Message-ID: <20260801172519.2982121-17-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Reshape progress is tracked by array metadata rather than llbitmap. Do not let llbitmap skip_sync_blocks() suppress reshape ranges based on stale bitmap state before the corresponding checkpoint is persisted. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index eed3e248b730..5597b1afcb58 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1692,6 +1692,14 @@ static sector_t llbitmap_skip_sync_blocks(struct mdd= ev *mddev, sector_t offset) return 0; c =3D llbitmap_read(llbitmap, p); =20 + /* + * Reshape progress is tracked by array metadata rather than llbitmap. + * Skipping reshape ranges from stale bitmap state can lose data after a + * restart before the corresponding bits are checkpointed to disk. + */ + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) + return 0; + /* always skip unwritten blocks */ if (c =3D=3D BitUnwritten) return blocks; --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C8ECC3B52FF; Sat, 1 Aug 2026 17:27:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605237; cv=none; b=D+6TT0R+mOpajwIAXlTrwZsyovwEGEIs21MDCv4K3/RwKgz9Z/TA5GeXynVuihBgym9oqDv6G9ZR2lnsCSKmludEtLvVOtvL3pNthr68StgU4rQCW2fsM29bfjXUQT20SociItBeB0f3+mEMBXoIlYW4/zRjXsl677BnuXPE6LQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605237; c=relaxed/simple; bh=YOlD7GwqBf9wylKt0lk3sdeZdW2Nx6DtS5ZP6iFIXcw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i388B2SjZpJonEue0XmKF89sKcQX63T53QVy6cS/bm4pH/Hzdpj5nmm1MSoWpFEl1a+/XrqqA9Br+Z+TyanRYCki4l1X1gm5fs6H7H/MMuKRKpdVQyZKrxqb1itCowFG0fnoFd7osspPcdbD5sQFLJ+ably0AuSNaxhJK/FiQv4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WYU/DyUo; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WYU/DyUo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02A991F00AC4; Sat, 1 Aug 2026 17:27:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605235; bh=P8VinnoG1EPs15+qW8iwy8KD/CzrQphXexLexiueQ8g=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WYU/DyUoKBbYcrVzS4Vu+7IUvSf+yW5t0IqKtFJQQLYRyp6D7h4p/huwswITcazwC gsMWYanIxC+v2AD7xXE0VAR9OqTp2Nmkhdq7BaF3SSRCuRkrvfWnKsmCVFjw8ZGtwS vZiBihqFnTkDM6rpgiKng+uM+5uCsXl/mSSZvpVjpeELggyCHs4NirQkvkEPSDqNJQ e4UsxRaSKA5iWKiRVvHYQH0PFhmA6oOeg7svvNlkfA/qYqeVncS14mtdbnDDiHgmKm O0van/b8fokje51oFrGEDe/0LcL2UTxwCGXuvcfH4uAavQkn3V+h6tdd+Y8Urv05K5 dqs7TGHj0r4Kw== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 17/25] md/md-llbitmap: remap checkpointed bits as reshape progresses Date: Sun, 2 Aug 2026 01:25:11 +0800 Message-ID: <20260801172519.2982121-18-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Merge checkpointed old llbitmap state forward as reshape_position advances and record the checkpoint remap through reshape_mark(). Normal write accounting can run while the reshape thread checkpoints a new reshape position. llbitmap_reshape_mark() reads old state bytes, merges them into destination bits, and writes the result back. If llbitmap_start_write() or llbitmap_start_discard() updates the same state bytes at the same time, the two read/modify/write paths can overwrite each other and lose the state from one side. Serialize only this state-byte race with a rwlock. Normal I/O takes the read side around llbitmap_state_machine(), after page active references are rais= ed, so concurrent normal I/O updates still run in parallel. Reshape checkpointi= ng takes the write side only while merging the checkpointed range, avoiding pa= ge suspension and avoiding a sleeping mutex in the I/O accounting path. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 204 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 5597b1afcb58..c3f6e807f739 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -302,6 +302,11 @@ struct llbitmap { /* fires on first BitDirty state */ struct timer_list pending_timer; struct work_struct daemon_work; + /* + * Serialize reshape checkpoint remapping against normal I/O bitmap + * updates without blocking concurrent I/O updates on each other. + */ + rwlock_t reshape_lock; =20 unsigned long flags; __u64 events_cleared; @@ -498,6 +503,14 @@ static void llbitmap_map_layout(struct llbitmap *llbit= map, sector_t *offset, else if (!previous && llbitmap->mddev->pers->bitmap_sector) llbitmap->mddev->pers->bitmap_sector(llbitmap->mddev, offset, sectors); + + limit =3D llbitmap_personality_sync_size(llbitmap, previous); + start =3D *offset; + end =3D start + *sectors; + if (start >=3D limit) + *sectors =3D 0; + else if (end > limit) + *sectors =3D limit - start; } =20 static void llbitmap_encode_range(struct llbitmap *llbitmap, sector_t *off= set, @@ -930,6 +943,33 @@ static int llbitmap_prepare_resize(struct llbitmap *ll= bitmap, return 0; } =20 +static enum llbitmap_state +llbitmap_rmerge_state(struct llbitmap *llbitmap, + enum llbitmap_state dst, + enum llbitmap_state src) +{ + bool level_456 =3D raid_is_456(llbitmap->mddev); + + if (dst =3D=3D BitNeedSync || dst =3D=3D BitSyncing || + src =3D=3D BitNeedSync || src =3D=3D BitSyncing) + return BitNeedSync; + + if (dst =3D=3D BitDirty || src =3D=3D BitDirty) + return BitDirty; + + /* + * Reshape generates valid target parity/data for both already-written + * and not-yet-written regions in the checkpointed range, so a mix of + * clean and unwritten still results in a clean destination bit. + */ + if (level_456 && ((dst =3D=3D BitClean && src =3D=3D BitUnwritten) || + (src =3D=3D BitClean && dst =3D=3D BitUnwritten))) + return BitClean; + if (dst =3D=3D BitClean || src =3D=3D BitClean) + return BitClean; + return BitUnwritten; +} + static void llbitmap_init_state(struct llbitmap *llbitmap) { struct mddev *mddev =3D llbitmap->mddev; @@ -1294,6 +1334,7 @@ static void md_llbitmap_daemon_fn(struct work_struct = *work) =20 if (llbitmap->mddev->degraded) return; + retry: start =3D 0; end =3D min(llbitmap->chunks, PAGE_SIZE - BITMAP_DATA_OFFSET) - 1; @@ -1355,6 +1396,7 @@ static int llbitmap_create(struct mddev *mddev) =20 timer_setup(&llbitmap->pending_timer, llbitmap_pending_timer_fn, 0); INIT_WORK(&llbitmap->daemon_work, md_llbitmap_daemon_fn); + rwlock_init(&llbitmap->reshape_lock); atomic_set(&llbitmap->behind_writes, 0); init_waitqueue_head(&llbitmap->behind_wait); =20 @@ -1520,7 +1562,9 @@ static void llbitmap_start_write(struct mddev *mddev,= sector_t offset, page_start++; } =20 + read_lock(&llbitmap->reshape_lock); llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); + read_unlock(&llbitmap->reshape_lock); } =20 static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1552,7 +1596,9 @@ static void llbitmap_start_discard(struct mddev *mdde= v, sector_t offset, page_start++; } =20 + read_lock(&llbitmap->reshape_lock); llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); + read_unlock(&llbitmap->reshape_lock); } =20 static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, @@ -1849,6 +1895,136 @@ static int llbitmap_reshape_can_start(struct mddev = *mddev) return ret; } =20 +struct llbitmap_reshape_range { + sector_t offset; + unsigned long sectors; + sector_t start; + sector_t end; +}; + +static enum llbitmap_state +llbitmap_reshape_init_dst(struct llbitmap *llbitmap, unsigned long dst, + const struct llbitmap_reshape_range *new) +{ + u64 bit_start =3D (u64)dst * llbitmap->reshape_chunksize; + u64 bit_end =3D bit_start + llbitmap->reshape_chunksize; + + if (!llbitmap->mddev->reshape_backwards) + return bit_start < new->offset ? llbitmap_read(llbitmap, dst) : + BitUnwritten; + return bit_end > new->end ? llbitmap_read(llbitmap, dst) : BitUnwritten; +} + +static void llbitmap_reshape_dst_range(struct llbitmap *llbitmap, + unsigned long dst, + const struct llbitmap_reshape_range *new, + struct llbitmap_reshape_range *dst_range) +{ + sector_t dst_bit_start =3D (sector_t)dst * llbitmap->reshape_chunksize; + + dst_range->start =3D max(dst_bit_start, new->offset); + dst_range->end =3D min(dst_bit_start + llbitmap->reshape_chunksize, + new->end); + dst_range->offset =3D dst_range->start; + dst_range->sectors =3D dst_range->end - dst_range->start; +} + +static void llbitmap_reshape_map_range(struct llbitmap *llbitmap, + sector_t lo, sector_t hi, + bool previous, + struct llbitmap_reshape_range *range) +{ + range->offset =3D lo; + range->sectors =3D hi - lo; + llbitmap_map_layout(llbitmap, &range->offset, &range->sectors, previous); + range->start =3D range->offset; + range->end =3D range->offset + range->sectors; +} + +static bool llbitmap_reshape_src_range(const struct llbitmap_reshape_range= *old, + const struct llbitmap_reshape_range *new, + const struct llbitmap_reshape_range *dst, + struct llbitmap_reshape_range *src) +{ + if (!old->sectors) + return false; + + src->start =3D old->offset + + mul_u64_u64_div_u64(dst->start - new->offset, + old->sectors, new->sectors); + src->end =3D old->offset + + mul_u64_u64_div_u64_roundup(dst->end - new->offset, + old->sectors, new->sectors); + if (src->end > old->end) + src->end =3D old->end; + src->offset =3D src->start; + src->sectors =3D src->end - src->start; + + return src->sectors; +} + +static enum llbitmap_state llbitmap_rmerge_src(struct llbitmap *llbitmap, + enum llbitmap_state state, + const struct llbitmap_reshape_range *src) +{ + unsigned long bit =3D div64_u64(src->start, llbitmap->chunksize); + unsigned long end =3D div64_u64(src->end - 1, llbitmap->chunksize); + + while (bit <=3D end) { + enum llbitmap_state src_state =3D llbitmap_read(llbitmap, bit); + + state =3D llbitmap_rmerge_state(llbitmap, state, src_state); + bit++; + } + + return state; +} + +static void llbitmap_reshape_merge(struct llbitmap *llbitmap, + const struct llbitmap_reshape_range *old, + const struct llbitmap_reshape_range *new) +{ + unsigned long dst_start; + unsigned long dst_end; + unsigned long dst; + bool backwards =3D false; + + if (!new->sectors) + return; + + dst_start =3D div64_u64(new->offset, llbitmap->reshape_chunksize); + dst_end =3D div64_u64(new->end - 1, llbitmap->reshape_chunksize); + if (old->sectors) { + unsigned long src_start =3D div64_u64(old->offset, + llbitmap->chunksize); + unsigned long src_end =3D div64_u64(old->end - 1, + llbitmap->chunksize); + + backwards =3D src_start < dst_start && src_end >=3D dst_start; + } + + dst =3D backwards ? dst_end : dst_start; + while (true) { + struct llbitmap_reshape_range dst_range; + struct llbitmap_reshape_range src; + enum llbitmap_state state; + + llbitmap_reshape_dst_range(llbitmap, dst, new, &dst_range); + state =3D llbitmap_reshape_init_dst(llbitmap, dst, new); + if (llbitmap_reshape_src_range(old, new, &dst_range, &src)) + state =3D llbitmap_rmerge_src(llbitmap, state, &src); + else + state =3D llbitmap_rmerge_state(llbitmap, state, BitUnwritten); + llbitmap_write(llbitmap, state, dst); + if (dst =3D=3D (backwards ? dst_start : dst_end)) + break; + if (backwards) + dst--; + else + dst++; + } +} + static void llbitmap_reshape_finish(struct mddev *mddev) { struct llbitmap *llbitmap =3D mddev->bitmap; @@ -1873,6 +2049,33 @@ static void llbitmap_reshape_finish(struct mddev *md= dev) mddev->pers->quiesce(mddev, 0); } =20 +static void llbitmap_reshape_mark(struct mddev *mddev, sector_t old_pos, + sector_t new_pos) +{ + struct llbitmap *llbitmap =3D mddev->bitmap; + sector_t lo; + sector_t hi; + struct llbitmap_reshape_range old; + struct llbitmap_reshape_range new; + + if (!llbitmap || old_pos =3D=3D new_pos) + return; + + lo =3D min(old_pos, new_pos); + hi =3D max(old_pos, new_pos); + if (!hi) + return; + + llbitmap_reshape_map_range(llbitmap, lo, hi, true, &old); + llbitmap_reshape_map_range(llbitmap, lo, hi, false, &new); + if (!new.sectors) + return; + + write_lock(&llbitmap->reshape_lock); + llbitmap_reshape_merge(llbitmap, &old, &new); + write_unlock(&llbitmap->reshape_lock); +} + static void llbitmap_write_sb(struct llbitmap *llbitmap) { int nr_blocks =3D DIV_ROUND_UP(BITMAP_DATA_OFFSET, llbitmap->io_size); @@ -2172,6 +2375,7 @@ static struct bitmap_operations llbitmap_ops =3D { .prepare_range =3D llbitmap_prepare_range, .reshape_finish =3D llbitmap_reshape_finish, .reshape_can_start =3D llbitmap_reshape_can_start, + .reshape_mark =3D llbitmap_reshape_mark, .write_all =3D llbitmap_write_all, =20 .groups =3D md_llbitmap_groups, --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E35573B6BF9; Sat, 1 Aug 2026 17:27:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605241; cv=none; b=Cfr2pqwDdyLAPU1OYBLC3qT+gE8g2i37IOSkmLRD5IL8g7vbTN3kCSr7AiBiD9HP79a/mXfyXaajw8eBpjDB55PMwi9KtfiH5+0/snRqpyBAbXptMBhqbvX+ObB0nZzcLewn8F1wwVZ2e3EXC4odbk+84G0FOk9HOlAuopRAvBc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605241; c=relaxed/simple; bh=7FTKGZTRyOZwKq/qPfzjV/ahAF95exR/B+f+biBkaSE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eexoCsVrtn9c5Ca2TOxzCUSZe24CZXGH6gBzceb8G0GekjZoMdf9AQp8JpUWRzCrgxXY4Y6AzG+Vq8kASGzXJTaMi58O4oHli2hZY+tcO3oJtPRA7O489vhTn19n3P+043kytwaweWbtyr7wQQfl6u1kYwwTG2K4OPNcRLhcEuo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aCKZJjvR; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aCKZJjvR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 115271F00ACA; Sat, 1 Aug 2026 17:27:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605240; bh=83L+HPs490fFhgkwH8pp6yRZPknCWQXSXuf2hUFRwEw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aCKZJjvR420hJyXlHU7YnN3lBJwOju1I4WpSHLwlLv/1XtGk8WEKeP7ijQMwzm3U4 yEUELsXzRxb4VLM0GpH94+677rlaU+GFJwskWneLuD69lT2Rj3F0FgTkoNVuM1RkCK +FWNfM8vXqOHU9UgbMfyZL9q62bLUywM5tTtUdfpgNlnLGRFQbPBXPNf91YXMffRNn GwBBSgDIlQnP1L3DTsMlF14UvODhx8BGn56vKXWMrSWEibuiK3W2HK8WVqRc9Tgg5D TnJkVzOwoAowJ1fiNKTFAqtsQorbSL6GlIIlgKW1Awks5qkd3shH7fBzxCxIMmY3ht NO8zPk2COXbHQ== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 18/25] md/md-llbitmap: clamp state-machine walks to tracked bits Date: Sun, 2 Aug 2026 01:25:12 +0800 Message-ID: <20260801172519.2982121-19-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai llbitmap_state_machine() can be called with an end bit beyond llbitmap->chunks. In particular, llbitmap_cond_end_sync() passes sector >> chunkshift, and sector can reach the tracked boundary exactly. Clamp the state-machine range to llbitmap->chunks so it cannot walk past the tracked bitmap. Signed-off-by: Yu Kuai --- drivers/md/md-llbitmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index c3f6e807f739..27418bc001c1 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1012,7 +1012,10 @@ static enum llbitmap_state llbitmap_state_machine(st= ruct llbitmap *llbitmap, llbitmap_init_state(llbitmap); return BitNone; } - + if (start >=3D llbitmap->chunks) + return BitNone; + if (end >=3D llbitmap->chunks) + end =3D llbitmap->chunks - 1; while (start <=3D end) { enum llbitmap_state c =3D llbitmap_read(llbitmap, start); =20 --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68F8B35C1A0; Sat, 1 Aug 2026 17:27:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605250; cv=none; b=oO0cQ7m/PLH43uXtRuBes7yEWJc31WK8pT9dXhfbC6K+WzF5qorM4Bp2PAGueA9QgroKOtOqVlR3qHKHojvkinDBbmGnIXHqTbXMgtvCPcCrlysR3RPc1VPnLyhXRZECvdlGjzwY98YgBzPoy+kiGZ6hxtrZICgVbtf3RN0nDeQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605250; c=relaxed/simple; bh=9C6q7S0E1ahrUuz++7upELMaFcosc9FD7lcWdA6zY9s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bTxrTHVFrFdDUqL4SK89yYyLaPlhV3eOpEjT0JdApmYejDBPRrHQRgK32elkV9Q4LyvdOd4oSx6+NveVHdKYDdoXqx+B2qov0rD8iEoEJBwYVv6cMY+zIc4nSwwb9hfqUaE7Vx9v7ii7GR9E4lR0N4vNzU6AErTGRnWiDPyCojU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iw2q02zf; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iw2q02zf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2749E1F00AC4; Sat, 1 Aug 2026 17:27:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605249; bh=ABIG+s6muV9rWcz7rbS1gaHI9hWl4JHjo3sBY4cNOvg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iw2q02zfc8xcDhpG3vRZm/7z4yMLY8eNzYRwhM2noQgmlGsdM49IJg3LjmX4lX19S LGStLF/3yyj7zdWPnUuOU7iiRls3+clq77SPXh7t5SpBm9A34x9qEmCTRt1tzyhL+q WqX965Od3kGv1OrSPq3OBcPNpjIo99FvuKFxNLYFjbAtxjNzUy67mqaqNzam76zQfA i3reYYhPmxoX/msVNFAfFnS/V5xFaY93Jm1WlKaCDyPhAce6/JHuikawoGk76uLYIh MMRKAnDWCCHNzsO3BBna1ECKlPVmcKZlhBJk0X9G4ZCuKEvujfZMbr69hmQvMwVj9a W7A7/iY3xlntA== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 19/25] md/raid10: reject llbitmap reshape when md chunk shrinks Date: Sun, 2 Aug 2026 01:25:13 +0800 Message-ID: <20260801172519.2982121-20-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai llbitmap reshape keeps one live bitmap and cannot safely make an existing bitmap bit cover a smaller data range. The llbitmap chunksize itself will not shrink when mddev->chunk_sectors stays the same or grows. However, shrinking mddev->chunk_sectors can shrink the effective data range covered by each bit for the RAID10 reshape geometry. Reject that reshape while llbitmap is active. Signed-off-by: Yu Kuai --- drivers/md/raid10.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 0a3cfdd3f5df..1242b8d3bb6b 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -4284,6 +4284,10 @@ static int raid10_check_reshape(struct mddev *mddev) =20 if (conf->geo.far_copies !=3D 1 && !conf->geo.far_offset) return -EINVAL; + if (mddev->bitmap_id =3D=3D ID_LLBITMAP && + mddev->new_chunk_sectors && + mddev->new_chunk_sectors < mddev->chunk_sectors) + return -EOPNOTSUPP; =20 if (setup_geo(&geo, mddev, geo_start) !=3D conf->copies) /* mustn't change number of copies */ --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EBD323B71D3; Sat, 1 Aug 2026 17:27:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605254; cv=none; b=fnFF0iUfHmdpozpXGjkQeX1Uki/M2Fic139UKJRLvHNiO6sMLKjD6Jj1unFlDQmDYWy6PuRyPQ/IrpGeZy6hm9qBFZ73i08rtRhllodKlFMe25S2TAH7o7OPJoA7HdwII5+57BWeDx6cn6dkEvsBIhPDhA1vydPb6++hn51ZKxI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605254; c=relaxed/simple; bh=jWmDY+JcgU6hiQ+w5whTXYiG5hB5v7D7ObqFVFNBgtU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o4wM3m/0rLwFzwX1wE+MDAVeWnrK/2vDE/5E4v5tcMbAsKekiYTXkcAZ8v2xT30zwx+nvxj9Aylmus03yIQVxOnmLt6UB0iVxROsvhOsLsQarHB3u+P/4x6sCHgV83K0WlTqX4r1URI+JeSCcfEpqSbYc2H3QJAxJUo+mC7xao8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eiQBGMTc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eiQBGMTc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 85BE61F00ACA; Sat, 1 Aug 2026 17:27:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605252; bh=lObO1E/A9QymwsBQlLWma+ph5LTnPnw2QV9lQjO4Hks=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=eiQBGMTcSlKd/LssJxcCVttYOURqIofPovSsLQE5Cx8TxCRiY9XZbCn74CLkpcrst oB7uRT3spFAXGmPODmWiE1capiA9hqrnYMDfGaZs+1Psfw3TMuvV1RxvqyFMluI9Ly uDFLUrfSYHfAC41cQsqX4DwjKszyNO86o4nvnZknLDJdRbc7zkvM9AKdEQdie8BmvG QzrFSjddU+Ne5ahmnhqvMvgwKiVhlJRbvo+regFeKQ/SDQ2hQXK8aORVR5JhSks25R a5NqO95LtZhmMBPWv1ady/rjvfNt56Rs1x9IW2Hat6LXQJsFzoaBCd/dXYFaXh1KnH 7kF0YQnvTCtZw== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 20/25] md/raid10: wire llbitmap reshape lifecycle Date: Sun, 2 Aug 2026 01:25:14 +0800 Message-ID: <20260801172519.2982121-21-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Prepare llbitmap before RAID10 starts growing, checkpoint the bitmap before advancing reshape_position, finish the llbitmap geometry update when reshape completes, and export the old and new tracked sizes. Signed-off-by: Yu Kuai --- drivers/md/raid10.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1242b8d3bb6b..e50e4adee389 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -4394,6 +4394,12 @@ static int raid10_start_reshape(struct mddev *mddev) =20 if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_ops->reshape_can_start) { + ret =3D mddev->bitmap_ops->reshape_can_start(mddev); + if (ret) + return ret; + } =20 if (setup_geo(&new, mddev, geo_start) !=3D conf->copies) return -EINVAL; @@ -4707,6 +4713,13 @@ static sector_t reshape_request(struct mddev *mddev,= sector_t sector_nr, time_after(jiffies, conf->reshape_checkpoint + 10*HZ)) { /* Need to update reshape_position in metadata */ wait_barrier(conf, false); + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_ops->reshape_mark && + conf->reshape_safe !=3D conf->reshape_progress) { + mddev->bitmap_ops->reshape_mark(mddev, conf->reshape_safe, + conf->reshape_progress); + mddev->bitmap_ops->unplug(mddev, true); + } mddev->reshape_position =3D conf->reshape_progress; if (mddev->reshape_backwards) mddev->curr_resync_completed =3D raid10_size(mddev, 0, 0) @@ -4905,9 +4918,19 @@ static void reshape_request_write(struct mddev *mdde= v, struct r10bio *r10_bio) =20 static void end_reshape(struct r10conf *conf) { + struct mddev *mddev =3D conf->mddev; + if (test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) return; =20 + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_ops->reshape_mark && + conf->reshape_safe !=3D conf->reshape_progress) { + mddev->bitmap_ops->reshape_mark(mddev, conf->reshape_safe, + conf->reshape_progress); + mddev->bitmap_ops->unplug(mddev, true); + } + spin_lock_irq(&conf->device_lock); conf->prev =3D conf->geo; md_finish_reshape(conf->mddev); @@ -5039,10 +5062,15 @@ static void end_reshape_request(struct r10bio *r10_= bio) static void raid10_finish_reshape(struct mddev *mddev) { struct r10conf *conf =3D mddev->private; + bool llbitmap =3D mddev->bitmap_id =3D=3D ID_LLBITMAP && + md_bitmap_enabled(mddev, false); =20 if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) return; =20 + if (llbitmap && mddev->bitmap_ops->reshape_finish) + mddev->bitmap_ops->reshape_finish(mddev); + if (mddev->delta_disks > 0) { if (mddev->resync_offset > mddev->resync_max_sectors) { mddev->resync_offset =3D mddev->resync_max_sectors; @@ -5069,6 +5097,15 @@ static void raid10_finish_reshape(struct mddev *mdde= v) mddev->reshape_backwards =3D 0; } =20 +static sector_t raid10_bitmap_sync_size(struct mddev *mddev, bool previous) +{ + struct r10conf *conf =3D mddev->private; + + if (previous) + return raid10_size(mddev, 0, 0); + return raid10_size(mddev, 0, conf->geo.raid_disks); +} + static struct md_personality raid10_personality =3D { .head =3D { @@ -5095,6 +5132,8 @@ static struct md_personality raid10_personality =3D .start_reshape =3D raid10_start_reshape, .finish_reshape =3D raid10_finish_reshape, .update_reshape_pos =3D raid10_update_reshape_pos, + .bitmap_sync_size =3D raid10_bitmap_sync_size, + .bitmap_array_sectors =3D raid10_bitmap_sync_size, }; =20 static int __init raid10_init(void) --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB32E3B3898; Sat, 1 Aug 2026 17:27:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605258; cv=none; b=bJCDThJI0LBKqRV6uBmcfALcLVZ0PdfyM91Zpnm9aenib7wOrBa9uiRgcBVJRQd7J2WTv5U1CWJczs6vIiILkq7M3r0m+lVaJ+YAXu54HVf3Yyndl2sGZAcOT0TvwDwl2wUnLJIdR7HdOkd+nWMNKZokcTXmgc8R7NXoWEusvuA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605258; c=relaxed/simple; bh=DFz9j/LUqMTB/KJD4y+MuD1SvAJ4inz3anY4ukvjgEc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eEhLO9oyIPkij/0/VKN0RUUA31W0bpbSlepDbHFqsPeZlJ+nKNHmMWQwb4jxuYH8xyxt/87NkerzvJuppses1t2GIvdk5+Way/BakGpseHkxEL4gUqhbpBF2OqP3Gzmnj1D/Xfk1cLILm2TW8SAx4bbBGFhG8SjWJs1puAnbCYA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=H8BYrer9; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H8BYrer9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 97C1D1F00AC4; Sat, 1 Aug 2026 17:27:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605257; bh=A7JHketKneKBfUVY/rm7ha78+U5Bqu5XSZlfyCTdK3g=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=H8BYrer9WfQt3gPEv2tnHMXjkhqhcfXA3xo3L/HIENKUOAQpKq1QarZIe260IdFrU 6sAuUTqjVOrdXpKE80iTI2vDzfKck+IAZBlEJ5xXyjvyb/71bsZrW19g8TUcRIZCTm DD4odz9TsXqhm1e88Rwe6ERdjJVMUg+68gzY9DvJr47GktCFvNak1MuKTf5K3QhLIZ uQqN9T4hgJA3bTcPbnOlHApWx8ipc5LVLCckpDsNSKuR/sBKrswwNRkJ1xNxBxuG5I afvjjfptSk+OVKaR128KoG8Vq2wtOUxI7PE31kw+kKBP0sl1BKfYXZtP3g0qtqz8LO oUpHm1TCeE7qQ== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 21/25] md/raid10: split reshape bios before bitmap accounting Date: Sun, 2 Aug 2026 01:25:15 +0800 Message-ID: <20260801172519.2982121-22-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Use the shared mddev_bio_split_at_reshape_offset() helper so RAID10 submits only one-side bios to llbitmap during reshape. Signed-off-by: Yu Kuai --- drivers/md/raid10.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index e50e4adee389..61900ace190f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1886,6 +1886,7 @@ static bool raid10_make_request(struct mddev *mddev, = struct bio *bio) { struct r10conf *conf =3D mddev->private; sector_t chunk_mask =3D (conf->geo.chunk_mask & conf->prev.chunk_mask); + const int rw =3D bio_data_dir(bio); int chunk_sects =3D chunk_mask + 1; int sectors =3D bio_sectors(bio); =20 @@ -1911,6 +1912,15 @@ static bool raid10_make_request(struct mddev *mddev,= struct bio *bio) sectors =3D chunk_sects - (bio->bi_iter.bi_sector & (chunk_sects - 1)); + + bio =3D mddev_bio_split_at_reshape_offset(mddev, bio, §ors, + &conf->bio_split); + if (!bio) { + if (rw =3D=3D WRITE) + md_write_end(mddev); + return true; + } + if (!__make_request(mddev, bio, sectors)) md_write_end(mddev); =20 --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B7803ACA65; Sat, 1 Aug 2026 17:27:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605264; cv=none; b=Mrc/VstvpE9r1ohSTKZsjvqXN61IwkzEs7JGzcMQAsTFwldCXI49ScwSBxxEiMKt4KNW6angczmOeLA1TGgIKgpfKTgvV3cNTmmGivULhj+vs2lq8SNyFixGukp88ln4H/3V1dJhp5Lwd30pJtLnCUKVUUk5ZgeYU14KsYI3fwM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605264; c=relaxed/simple; bh=UOdCJnz3XTTPYDn0pGXqNCXAj3POqv6rmXOZ1gRctXw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Kug3Sdayyn/ul6mRHh1yDc392P3UpOFeadEp07EYj/IByDcdvBo+RnSPiAc2kJeQU7ciKB3ACnm+h6e35elSHA5ez5Y1zYvk8KhXw7L/2ocxjwSPe9pP1bRMMd34ycp6YmQJdBJTdT2hGLnyvpuqtzvVhOvYrkNe493X+Fp5IS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Sxay5rh9; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Sxay5rh9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9B661F00ACA; Sat, 1 Aug 2026 17:27:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605262; bh=kZcgrDKhiEDQJB/H5CCjU6tq0doXsg+SETN1gxdb3Nk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Sxay5rh9JKkvQYTYRwQ1E8V3HE+bgiZiMIEgdJ42gTjOJ6H/lkQozmhTxd9974chz /L60CIljZXOLDyfHe4Kl0ReZKk4LiQOfmoZh5Kfy+3TnlUgilq2eGHU2aURlufe7Yd OOpGuwp5Qcud+bbNWrAUfCLu0YHn93wo9SE3IGJiVDM0bJo6f5a9eEeCX0Bx43G74Q gd92OivwFjc8ITfCDgzSAwVAS8L1qBt+Xlm7Wk7dKmpSLweTsXSbuh6eYDycvrb0TG kBdwp220u5oH2029w5z7rEWbS2f1444aAt2MX52ZQYPKZPcH53lJPzxAATceIgF4L6 xbWGKc0xPuZrA== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 22/25] md/raid5: add exact old and new llbitmap mapping helpers Date: Sun, 2 Aug 2026 01:25:16 +0800 Message-ID: <20260801172519.2982121-23-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Teach RAID5 to export exact old and new llbitmap mappings and the corresponding sync and array sizes for reshape-aware bitmap users. Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 72 +++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 8b3483674398..af7775278af6 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5942,28 +5942,46 @@ static enum reshape_loc get_reshape_loc(struct mdde= v *mddev, return LOC_BEHIND_RESHAPE; } =20 -static void raid5_bitmap_sector(struct mddev *mddev, sector_t *offset, - unsigned long *sectors) +static void raid5_bitmap_sector_map(struct mddev *mddev, sector_t *offset, + unsigned long *sectors, + bool previous) { struct r5conf *conf =3D mddev->private; sector_t start =3D *offset; sector_t end =3D start + *sectors; - sector_t prev_start =3D start; - sector_t prev_end =3D end; int sectors_per_chunk; - enum reshape_loc loc; int dd_idx; =20 - sectors_per_chunk =3D conf->chunk_sectors * - (conf->raid_disks - conf->max_degraded); + if (previous) + sectors_per_chunk =3D conf->prev_chunk_sectors * + (conf->previous_raid_disks - conf->max_degraded); + else + sectors_per_chunk =3D conf->chunk_sectors * + (conf->raid_disks - conf->max_degraded); sector_div(start, sectors_per_chunk); start *=3D sectors_per_chunk; if (sector_div(end, sectors_per_chunk)) end++; end *=3D sectors_per_chunk; =20 - start =3D raid5_compute_sector(conf, start, 0, &dd_idx, NULL); - end =3D raid5_compute_sector(conf, end, 0, &dd_idx, NULL); + start =3D raid5_compute_sector(conf, start, previous, &dd_idx, NULL); + end =3D raid5_compute_sector(conf, end, previous, &dd_idx, NULL); + *offset =3D start; + *sectors =3D end - start; +} + +static void raid5_bitmap_sector(struct mddev *mddev, sector_t *offset, + unsigned long *sectors) +{ + struct r5conf *conf =3D mddev->private; + sector_t start =3D *offset; + sector_t end =3D start + *sectors; + sector_t prev_start =3D start; + unsigned long prev_sectors =3D end - start; + enum reshape_loc loc; + + raid5_bitmap_sector_map(mddev, &start, sectors, false); + end =3D start + *sectors; =20 /* * For LOC_INSIDE_RESHAPE, this IO will wait for reshape to make @@ -5972,19 +5990,10 @@ static void raid5_bitmap_sector(struct mddev *mddev= , sector_t *offset, loc =3D get_reshape_loc(mddev, conf, prev_start); if (likely(loc !=3D LOC_AHEAD_OF_RESHAPE)) { *offset =3D start; - *sectors =3D end - start; return; } =20 - sectors_per_chunk =3D conf->prev_chunk_sectors * - (conf->previous_raid_disks - conf->max_degraded); - sector_div(prev_start, sectors_per_chunk); - prev_start *=3D sectors_per_chunk; - sector_div(prev_end, sectors_per_chunk); - prev_end *=3D sectors_per_chunk; - - prev_start =3D raid5_compute_sector(conf, prev_start, 1, &dd_idx, NULL); - prev_end =3D raid5_compute_sector(conf, prev_end, 1, &dd_idx, NULL); + raid5_bitmap_sector_map(mddev, &prev_start, &prev_sectors, true); =20 /* * for LOC_AHEAD_OF_RESHAPE, reshape can make progress before this IO @@ -5992,7 +6001,7 @@ static void raid5_bitmap_sector(struct mddev *mddev, = sector_t *offset, * we set bits for both. */ *offset =3D min(start, prev_start); - *sectors =3D max(end, prev_end) - *offset; + *sectors =3D max(end, prev_start + prev_sectors) - *offset; } =20 static enum stripe_result make_stripe_request(struct mddev *mddev, @@ -9059,6 +9068,20 @@ static void raid5_prepare_suspend(struct mddev *mdde= v) wake_up(&conf->wait_for_reshape); } =20 +static sector_t raid5_bitmap_sync_size(struct mddev *mddev, bool previous) +{ + return mddev->dev_sectors; +} + +static sector_t raid5_bitmap_array_sectors(struct mddev *mddev, bool previ= ous) +{ + struct r5conf *conf =3D mddev->private; + + if (previous) + return raid5_size(mddev, 0, 0); + return raid5_size(mddev, mddev->dev_sectors, conf->raid_disks); +} + static struct md_personality raid6_personality =3D { .head =3D { @@ -9088,6 +9111,9 @@ static struct md_personality raid6_personality =3D .change_consistency_policy =3D raid5_change_consistency_policy, .prepare_suspend =3D raid5_prepare_suspend, .bitmap_sector =3D raid5_bitmap_sector, + .bitmap_sector_map =3D raid5_bitmap_sector_map, + .bitmap_sync_size =3D raid5_bitmap_sync_size, + .bitmap_array_sectors =3D raid5_bitmap_array_sectors, }; static struct md_personality raid5_personality =3D { @@ -9118,6 +9144,9 @@ static struct md_personality raid5_personality =3D .change_consistency_policy =3D raid5_change_consistency_policy, .prepare_suspend =3D raid5_prepare_suspend, .bitmap_sector =3D raid5_bitmap_sector, + .bitmap_sector_map =3D raid5_bitmap_sector_map, + .bitmap_sync_size =3D raid5_bitmap_sync_size, + .bitmap_array_sectors =3D raid5_bitmap_array_sectors, }; =20 static struct md_personality raid4_personality =3D @@ -9149,6 +9178,9 @@ static struct md_personality raid4_personality =3D .change_consistency_policy =3D raid5_change_consistency_policy, .prepare_suspend =3D raid5_prepare_suspend, .bitmap_sector =3D raid5_bitmap_sector, + .bitmap_sector_map =3D raid5_bitmap_sector_map, + .bitmap_sync_size =3D raid5_bitmap_sync_size, + .bitmap_array_sectors =3D raid5_bitmap_array_sectors, }; =20 static int __init raid5_init(void) --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6FF73BADB2; Sat, 1 Aug 2026 17:27:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605268; cv=none; b=pjHA+IZc1kgBFYB0LT2nukIjoKGlHsvtO92BwtVG//EUWvq6L8kJJuwQ9BD8jiDubASE7aPmom7I1sknKSzwC1mhotqXgQPVgElGJ0sUVMZJ7h/FxwBMKwNO/CqtwRqR/CrspUX9+bZxg3CaFhLbZULzkiSVObQsAhm6mjeoHbs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605268; c=relaxed/simple; bh=/UNI4Q8H4Ps2aEhWVyhudcCJ/CpqWR7iJufJt9Rwx7I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=e9bgwmTF8OJjmeP/POOQDb6h0QrPj+0wDBYKafXm7ulRQEgMhc7+aiIHrivlxaKFbIAAuiFFDHAWS8E6MjDoY5xADBBDSqS0G9Ur7rIxvuRiGvIaRRsV5fLJP1pOZ+lBdxCYHnkmunt14UzZbOIYhNXPh4RMDijtsclUZlvSTQc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hPgU4dtb; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hPgU4dtb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AF4331F00AC4; Sat, 1 Aug 2026 17:27:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605267; bh=RobKo1bwRrF0wRV96ba0Qp14plvpIJ0oDIqYiCVbVu0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=hPgU4dtbRMO7BYc+fMgwO6CdyqrzyCwTuXAZDdGWmbYc4/W95XglYwBGXfY8NQIDJ Ao43WUK4zpfi3m4J7jyHzibJJylauabJ68+TvnJFddu1+tSEhNx69NyqDu+B9zrqE9 wwDMC+scccotsPny3NCxNsRN5HdBYC4pFhtaq8RgrR0E5oQfKOR9eU6kEi6g7i3IRu 8eIgOXOHQECwWoBaCAQllelFx+ATCB1SxfgJbaOs1Aa6cMH6W2qcBViME0W22R7a9c O93e9hp0hQZjRfk9weN8PRNUXN5SzXJ0zfJ1WXrE7MzB5kwIzY6ZQCSwwLdNrhOKNK ZfXImqwv3OuYg== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 23/25] md/raid5: reject llbitmap reshape when md chunk shrinks Date: Sun, 2 Aug 2026 01:25:17 +0800 Message-ID: <20260801172519.2982121-24-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai llbitmap reshape keeps one live bitmap and cannot safely make an existing bitmap bit cover a smaller data range. The llbitmap chunksize itself will not shrink when mddev->chunk_sectors stays the same or grows. However, shrinking mddev->chunk_sectors shrinks sectors_per_chunk used by raid5_bitmap_sector_map(). That can shrink the effective data range covered by each bit across the old and new RAID5 geometry. Reject that reshape while llbitmap is active. Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index af7775278af6..5697570120da 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -8511,6 +8511,9 @@ static int check_reshape(struct mddev *mddev) if (!check_stripe_cache(mddev)) return -ENOSPC; =20 + if (mddev->bitmap_id =3D=3D ID_LLBITMAP && + mddev->new_chunk_sectors < mddev->chunk_sectors) + return -EOPNOTSUPP; if (mddev->new_chunk_sectors > mddev->chunk_sectors || mddev->delta_disks > 0) if (resize_chunks(conf, --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA30B3A255F; Sat, 1 Aug 2026 17:27:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605275; cv=none; b=GnMB//PxjapNTMiB4W3OS1tg6yzMLgvtz/SvakZiFVoO4d9CzhbpLsOHpiZUDcYTJx6n/7Nu5jHU7CYaO+7DGiGv5epifqhNuRuKa2LOB+TyqHdGlT0bTlSbFQwNwt50VXfB+6PXje54TmxwfR3L/KC9oFAC22zZTILSLwOYtC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605275; c=relaxed/simple; bh=dSMPFFrNnIpq6Ajl4K/SxZMVhYsiE7k2iux6vOEEFOc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qiERDvR7zO2XwEbb65IoMXFHwK0NN6HY5nqna/+VzAb5clsd1ttsdbeeLQ7bjde0wCWa7woWQ681KrwHf3UbryzmFp/7/kVhdDjUrjXJVGFVHAK/ErArxxVjxRvfjfEvpT8pJb2ApVkUZRm5CBRjb2km4ls45lG/Ed0u+qtg4nE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SIx69zj2; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SIx69zj2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4A311F00ACA; Sat, 1 Aug 2026 17:27:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605274; bh=YErTVhEdLrDTATmI4QmDta7aPerA8rMa18xOkzkcMJ0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SIx69zj21yySRy0ndb2r45b/pBgL83pJ1PPnM68I3rssL3gzobteqhOnVX46W/Do6 AHpm5d2utrc22E3usf9mRxb5YVFTcH3b30MY5WVfp1F4AaFggFfJDwF7dMOuGdVbHO DIz7M/72Q8kF8UiZAGYVVrtqKx2tW/F7qYrApf4OAIaDWltxY6mFy7PPX1xNF4IG7p FvtPVPrdnGmPxPjkMmSzFbY9LEDxqE0Y2yN7wGPIwiPEttnP4h9kD4TUhE0oweWYA2 l+3JhrusnEi67es/2Et3ON6q7Vff6MpJtUYCVNHo5SntxHAOLQiahsycNZ7cr2Mhvx stI8u1c8xW9vA== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 24/25] md/raid5: wire llbitmap reshape lifecycle Date: Sun, 2 Aug 2026 01:25:18 +0800 Message-ID: <20260801172519.2982121-25-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai Prepare llbitmap before RAID5 reshape starts, checkpoint the bitmap before advancing reshape_position, and finish the llbitmap geometry update when reshape completes. Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5697570120da..896aa522f446 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -6433,6 +6433,13 @@ static sector_t reshape_request(struct mddev *mddev,= sector_t sector_nr, int *sk || test_bit(MD_RECOVERY_INTR, &mddev->recovery)); if (atomic_read(&conf->reshape_stripes) !=3D 0) return 0; + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_ops->reshape_mark && + conf->reshape_safe !=3D conf->reshape_progress) { + mddev->bitmap_ops->reshape_mark(mddev, conf->reshape_safe, + conf->reshape_progress); + mddev->bitmap_ops->unplug(mddev, true); + } mddev->reshape_position =3D conf->reshape_progress; mddev->curr_resync_completed =3D sector_nr; if (!mddev->reshape_backwards) @@ -6542,6 +6549,13 @@ static sector_t reshape_request(struct mddev *mddev,= sector_t sector_nr, int *sk || test_bit(MD_RECOVERY_INTR, &mddev->recovery)); if (atomic_read(&conf->reshape_stripes) !=3D 0) goto ret; + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_ops->reshape_mark && + conf->reshape_safe !=3D conf->reshape_progress) { + mddev->bitmap_ops->reshape_mark(mddev, conf->reshape_safe, + conf->reshape_progress); + mddev->bitmap_ops->unplug(mddev, true); + } mddev->reshape_position =3D conf->reshape_progress; mddev->curr_resync_completed =3D sector_nr; if (!mddev->reshape_backwards) @@ -8579,6 +8593,12 @@ static int raid5_start_reshape(struct mddev *mddev) mdname(mddev)); return -EINVAL; } + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_id =3D=3D ID_LLBITMAP) { + i =3D mddev->bitmap_ops->resize(mddev, mddev->dev_sectors, 0); + if (i) + return i; + } =20 atomic_set(&conf->reshape_stripes, 0); spin_lock_irq(&conf->device_lock); @@ -8663,10 +8683,19 @@ static int raid5_start_reshape(struct mddev *mddev) */ static void end_reshape(struct r5conf *conf) { + struct mddev *mddev =3D conf->mddev; =20 if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { struct md_rdev *rdev; =20 + if (md_bitmap_enabled(mddev, false) && + mddev->bitmap_ops->reshape_mark && + conf->reshape_safe !=3D conf->reshape_progress) { + mddev->bitmap_ops->reshape_mark(mddev, conf->reshape_safe, + conf->reshape_progress); + mddev->bitmap_ops->unplug(mddev, true); + } + spin_lock_irq(&conf->device_lock); conf->previous_raid_disks =3D conf->raid_disks; md_finish_reshape(conf->mddev); @@ -8693,8 +8722,16 @@ static void raid5_finish_reshape(struct mddev *mddev) { struct r5conf *conf =3D mddev->private; struct md_rdev *rdev; + bool llbitmap =3D mddev->bitmap_id =3D=3D ID_LLBITMAP && + md_bitmap_enabled(mddev, false); =20 if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + if (llbitmap && mddev->bitmap_ops->reshape_finish) + mddev->bitmap_ops->reshape_finish(mddev); + if (llbitmap) { + mddev->resync_offset =3D 0; + mddev->resync_max_sectors =3D mddev->dev_sectors; + } =20 if (mddev->delta_disks <=3D 0) { int d; --=20 2.51.0 From nobody Sat Aug 1 21:31:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4510C3BBA03; Sat, 1 Aug 2026 17:27:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605279; cv=none; b=VVsrsUCX3GabpwQvXcejlkFATL751JqYcct6wujm7lbSulHTLKCmNPZkFoJev8OguTew/3NGAr6YjK/WtUCZZ/O4bqbf1tIDEaTsSbqk6Na1rP8Cb/DDHCuAw3dauN+MNRMEq782EVZYwFdeUHinpdH1lNRI98FCW6smGuZQSUI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785605279; c=relaxed/simple; bh=SnoXFkre/tus+jLL0QefuZLY51AVPhhnVMSXBVffu30=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=htiAehEKKe0c7L8XGtYmlgq/aA3y16ClGoMlvCojaM39ddiKuqBJiOLuXpXgTSTEXgiA/QmAn9MK96PxvaIFDE+sWEDFaxeSP+Xey2CoZJ7UXO4mEhQgfr6HH/FnWFN2yAFsDotVWjGRaaY0BWw2sHNyGtGEURyG5rEi7BNnM4g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nbej/YFw; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Nbej/YFw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 22ADF1F00AC4; Sat, 1 Aug 2026 17:27:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785605278; bh=YLcxogMF0Z5kTX0xm+jXmH5SCSYzBlu+Y6zSYOVRMfg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Nbej/YFwz3r8huA2CqlQSo7+dXx3Tr7l/d8tHHYoZq2lJNJTBW6qXUYtLfwxEsQL7 MH1TvhWppCKKA9vsgB9VOPYmBzKn/exzVPbM2n148hZRQ6IYOX45ZG8BUjWJ2k184F tuFFPC/TKeRDceWnUnRtL6tT7zqcOvNXcUILBuCGFph0W7eihTZldc18S7a1b5LfSY +u0gMGAqW7xlFFr7zBM61hKQu6ALbzgaV3lTwHfobMHEwZOwMj826XK2LfEZhk6Upf 0YtN4svrL/vjbeDEWbVcJCAyHgy78wPyT1TJzsTrcTfTwk25/dEZPhr2G+g+8Y2Mg5 C3gNn1ucJzIeA== From: Yu Kuai To: Song Liu Cc: Li Nan , Xiao Ni , Mykola Marzhan , Su Yue , linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 25/25] md/raid5: split reshape bios before bitmap accounting Date: Sun, 2 Aug 2026 01:25:19 +0800 Message-ID: <20260801172519.2982121-26-yukuai@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260801172519.2982121-1-yukuai@kernel.org> References: <20260801172519.2982121-1-yukuai@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Yu Kuai RAID5 maps array sectors through different geometries before and after the reshape position. During llbitmap reshape, md core cannot account one bio against both geometries as a single bitmap range, because the old and new bitmap mappings can cover different chunks. Split bios that cross reshape_position before md_account_bio(), so the bitmap only sees ranges that belong to one side of the reshape boundary. mddev_bio_split_at_reshape_offset() uses bio_submit_split_bioset(), which submits the remainder immediately and returns the front split bio. If that front bio later has to wait for reshape, md_handle_request() must not retry the original bio pointer, because after the split that pointer is the already-submitted remainder. Track whether the split happened, clear the temporary BLK_STS_RESOURCE status after the internal clone completion, and resubmit the front bio directly after the reshape wait. Keep the old return-false retry path for unsplit bios, where md_handle_request() still owns the same bio. Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 896aa522f446..9b47d9a277f9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -6148,9 +6148,11 @@ static bool raid5_make_request(struct mddev *mddev, = struct bio * bi) struct r5conf *conf =3D mddev->private; const int rw =3D bio_data_dir(bi); struct stripe_request_ctx *ctx; + struct bio *front_bio; sector_t logical_sector; enum stripe_result res; int s, stripe_cnt; + bool split =3D false; bool on_wq; =20 if (unlikely(bi->bi_opf & REQ_PREFLUSH)) { @@ -6184,6 +6186,18 @@ static bool raid5_make_request(struct mddev *mddev, = struct bio * bi) return true; } =20 + front_bio =3D bi; + bi =3D mddev_bio_split_at_reshape_offset(mddev, bi, NULL, + &conf->bio_split); + if (!bi) { + if (rw =3D=3D WRITE) + md_write_end(mddev); + return true; + } + if (bi !=3D front_bio) + split =3D true; + front_bio =3D bi; + logical_sector =3D bi->bi_iter.bi_sector & ~((sector_t)RAID5_STRIPE_SECTO= RS(conf)-1); bi->bi_next =3D NULL; =20 @@ -6284,6 +6298,11 @@ static bool raid5_make_request(struct mddev *mddev, = struct bio * bi) bio_endio(bi); =20 wait_for_completion(&done); + front_bio->bi_status =3D BLK_STS_OK; + if (split) { + submit_bio_noacct(front_bio); + return true; + } return false; } =20 --=20 2.51.0