* Re: [GIT PULL] md-7.2-20260531
From: Yu Kuai @ 2026-06-02 3:07 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-raid, linux-block, Abd-Alrhman Masalkhi, Benjamin Marzinski,
Chen Cheng, Christoph Hellwig, Li Nan, Thorsten Blum, yukuai
In-Reply-To: <753dfdb4-7d68-4183-af3f-d51e92d4dd31@kernel.dk>
Hi,
在 2026/6/2 2:55, Jens Axboe 写道:
> On 5/31/26 5:26 AM, Yu Kuai wrote:
>> Hi Jens,
>>
>> Please consider pulling the following changes into your for-7.2/block
>> branch.
>>
>> This pull request contains:
>>
>> Bug Fixes:
>> - Only requeue dm-raid bios when dm is suspending. (Benjamin Marzinski)
>> - Reset raid10 read_slot when reusing r10bio for discard. (Chen Cheng)
>> - Fix raid1/raid10 deadlock in read error recovery path. (Abd-Alrhman Masalkhi)
>> - Fix raid1/raid10 error-path detection with md_cloned_bio(). (Abd-Alrhman Masalkhi)
>> - Fix raid1/raid10 bio accounting for split md cloned bios. (Abd-Alrhman Masalkhi)
>> - Fix raid1 nr_pending leak in REQ_ATOMIC bad-block path. (Abd-Alrhman Masalkhi)
>>
>> Improvements:
>> - Skip redundant raid_disks updates when the value is unchanged. (Abd-Alrhman Masalkhi)
>>
>> Cleanups:
>> - Update MAINTAINERS email addresses. (Yu Kuai, Li Nan)
>> - Clean up raid1 read error handling. (Christoph Hellwig)
>> - Move the exceed_read_errors condition out of fix_read_error(). (Christoph Hellwig)
>> - Use str_plural() in raid0 dump_zones(). (Thorsten Blum)
> Pulled, thanks.
>
> Side note - emails from you with the new email address all end up in
> spam. I just noticed some of them this morning. But I think you want to
> ensure that the DKIM etc part of your email is all kosher, gmail flags
> all of it.
Thanks a lot for the notice, we'll look into this.
>
--
Thansk,
Kuai
^ permalink raw reply
* Re: [GIT PULL] md-7.2-20260531
From: Jens Axboe @ 2026-06-01 18:55 UTC (permalink / raw)
To: Yu Kuai
Cc: linux-raid, linux-block, Abd-Alrhman Masalkhi, Benjamin Marzinski,
Chen Cheng, Christoph Hellwig, Li Nan, Thorsten Blum
In-Reply-To: <20260531112618.160409-1-yukuai@fygo.io>
On 5/31/26 5:26 AM, Yu Kuai wrote:
> Hi Jens,
>
> Please consider pulling the following changes into your for-7.2/block
> branch.
>
> This pull request contains:
>
> Bug Fixes:
> - Only requeue dm-raid bios when dm is suspending. (Benjamin Marzinski)
> - Reset raid10 read_slot when reusing r10bio for discard. (Chen Cheng)
> - Fix raid1/raid10 deadlock in read error recovery path. (Abd-Alrhman Masalkhi)
> - Fix raid1/raid10 error-path detection with md_cloned_bio(). (Abd-Alrhman Masalkhi)
> - Fix raid1/raid10 bio accounting for split md cloned bios. (Abd-Alrhman Masalkhi)
> - Fix raid1 nr_pending leak in REQ_ATOMIC bad-block path. (Abd-Alrhman Masalkhi)
>
> Improvements:
> - Skip redundant raid_disks updates when the value is unchanged. (Abd-Alrhman Masalkhi)
>
> Cleanups:
> - Update MAINTAINERS email addresses. (Yu Kuai, Li Nan)
> - Clean up raid1 read error handling. (Christoph Hellwig)
> - Move the exceed_read_errors condition out of fix_read_error(). (Christoph Hellwig)
> - Use str_plural() in raid0 dump_zones(). (Thorsten Blum)
Pulled, thanks.
Side note - emails from you with the new email address all end up in
spam. I just noticed some of them this morning. But I think you want to
ensure that the DKIM etc part of your email is all kosher, gmail flags
all of it.
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH] raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
From: Abd-Alrhman Masalkhi @ 2026-06-01 9:13 UTC (permalink / raw)
To: John Garry, song, yukuai, linan122, martin.petersen, axboe
Cc: linux-raid, linux-kernel
In-Reply-To: <8f8ca66c-aaa6-4b51-bcd7-54203603ba8a@oracle.com>
hi,
On Mon, Jun 01, 2026 at 10:05 +0100, John Garry wrote:
> On 01/06/2026 10:03, Abd-Alrhman Masalkhi wrote:
>>>> +++ b/drivers/md/raid1.c
>>>> @@ -1580,8 +1580,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
>>>> * complexity of supporting that is not worth
>>>> * the benefit.
>>>> */
>>>> - if (bio->bi_opf & REQ_ATOMIC)
>>>> + if (bio->bi_opf & REQ_ATOMIC) {
>>>> + rdev_dec_pending(rdev, mddev);
>>> It's not so nice that we have 2x locations that does the
>>> rdev_dec_pending work
>>>
>> Are you suggesting deferring atomic_inc(&rdev->nr_pending) until after
>> the if (test_bit(WriteErrorSeen, &rdev->flags)) {..} block? The patch
>> is already in md-7.2; should I send a separate cleanup patch?
>
> I'm not suggesting any further change. I am just mentioning that it is
> unfortunate that we have 2x locations which does the decrement, which
> makes error handling harder to follow.
You are absolutely right. Having two decrement paths makes the error
handling harder to follow. Thanks for pointing that out.
--
Best Regards,
Abd-Alrhman
^ permalink raw reply
* Re: [PATCH] raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
From: John Garry @ 2026-06-01 9:05 UTC (permalink / raw)
To: Abd-Alrhman Masalkhi, song, yukuai, linan122, martin.petersen,
axboe
Cc: linux-raid, linux-kernel
In-Reply-To: <m2h5nmljj6.fsf@gmail.com>
On 01/06/2026 10:03, Abd-Alrhman Masalkhi wrote:
>>> +++ b/drivers/md/raid1.c
>>> @@ -1580,8 +1580,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
>>> * complexity of supporting that is not worth
>>> * the benefit.
>>> */
>>> - if (bio->bi_opf & REQ_ATOMIC)
>>> + if (bio->bi_opf & REQ_ATOMIC) {
>>> + rdev_dec_pending(rdev, mddev);
>> It's not so nice that we have 2x locations that does the
>> rdev_dec_pending work
>>
> Are you suggesting deferring atomic_inc(&rdev->nr_pending) until after
> the if (test_bit(WriteErrorSeen, &rdev->flags)) {..} block? The patch
> is already in md-7.2; should I send a separate cleanup patch?
I'm not suggesting any further change. I am just mentioning that it is
unfortunate that we have 2x locations which does the decrement, which
makes error handling harder to follow.
^ permalink raw reply
* Re: [PATCH] raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
From: Abd-Alrhman Masalkhi @ 2026-06-01 9:03 UTC (permalink / raw)
To: John Garry, song, yukuai, linan122, martin.petersen, axboe
Cc: linux-raid, linux-kernel
In-Reply-To: <d9c769f5-19a3-4724-b805-3e2f30541c64@oracle.com>
hi,
Thank you for the feedback.
On Mon, Jun 01, 2026 at 09:43 +0100, John Garry wrote:
> On 30/05/2026 16:14, Abd-Alrhman Masalkhi wrote:
>> In raid1_write_request(), each per-mirror loop iteration begins by
>> incrementing rdev->nr_pending. If a REQ_ATOMIC write encounters a
>> badblock within the requested range, the code jumps to err_handle
>> without dropping the reference taken for the current mirror.
>>
>> err_handle's cleanup loop will only decrements for k < i and
>> r1_bio->bios[k] is non-NULL. The current slot is therefore skipped,
>> leaving its nr_pending reference leaked permanently. The reference
>> prevents the rdev from ever being removed, since raid1_remove_conf()
>> refuses to remove an rdev with nr_pending > 0.
>>
>> Fix this by calling rdev_dec_pending() before jumping to err_handle.
>>
>> Fixes: f2a38abf5f1c ("md/raid1: Atomic write support")
>> Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
>
> FWIW,
>
> Reviewed-by: John Garry <john.g.garry@oracle.com>
>
>> ---
>> drivers/md/raid1.c | 4 +++-
>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
>> index 181400e147c0..0084bbc24076 100644
>> --- a/drivers/md/raid1.c
>> +++ b/drivers/md/raid1.c
>> @@ -1580,8 +1580,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
>> * complexity of supporting that is not worth
>> * the benefit.
>> */
>> - if (bio->bi_opf & REQ_ATOMIC)
>> + if (bio->bi_opf & REQ_ATOMIC) {
>> + rdev_dec_pending(rdev, mddev);
>
> It's not so nice that we have 2x locations that does the
> rdev_dec_pending work
>
Are you suggesting deferring atomic_inc(&rdev->nr_pending) until after
the if (test_bit(WriteErrorSeen, &rdev->flags)) {..} block? The patch
is already in md-7.2; should I send a separate cleanup patch?
>> goto err_handle;
>> + }
>>
>> good_sectors = first_bad - r1_bio->sector;
>> if (good_sectors < max_sectors)
>
--
Best Regards,
Abd-Alrhman
^ permalink raw reply
* Re: [PATCH] raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
From: John Garry @ 2026-06-01 8:43 UTC (permalink / raw)
To: Abd-Alrhman Masalkhi, song, yukuai, linan122, martin.petersen,
axboe
Cc: linux-raid, linux-kernel
In-Reply-To: <20260530151411.4119-1-abd.masalkhi@gmail.com>
On 30/05/2026 16:14, Abd-Alrhman Masalkhi wrote:
> In raid1_write_request(), each per-mirror loop iteration begins by
> incrementing rdev->nr_pending. If a REQ_ATOMIC write encounters a
> badblock within the requested range, the code jumps to err_handle
> without dropping the reference taken for the current mirror.
>
> err_handle's cleanup loop will only decrements for k < i and
> r1_bio->bios[k] is non-NULL. The current slot is therefore skipped,
> leaving its nr_pending reference leaked permanently. The reference
> prevents the rdev from ever being removed, since raid1_remove_conf()
> refuses to remove an rdev with nr_pending > 0.
>
> Fix this by calling rdev_dec_pending() before jumping to err_handle.
>
> Fixes: f2a38abf5f1c ("md/raid1: Atomic write support")
> Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
FWIW,
Reviewed-by: John Garry <john.g.garry@oracle.com>
> ---
> drivers/md/raid1.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 181400e147c0..0084bbc24076 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -1580,8 +1580,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
> * complexity of supporting that is not worth
> * the benefit.
> */
> - if (bio->bi_opf & REQ_ATOMIC)
> + if (bio->bi_opf & REQ_ATOMIC) {
> + rdev_dec_pending(rdev, mddev);
It's not so nice that we have 2x locations that does the
rdev_dec_pending work
> goto err_handle;
> + }
>
> good_sectors = first_bad - r1_bio->sector;
> if (good_sectors < max_sectors)
^ permalink raw reply
* Re: [PATCH 2/2] md/raid1: move the exceed_read_errors condition out of fix_read_error
From: Xiao Ni @ 2026-06-01 5:53 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Song Liu, Yu Kuai, Li Nan, Xiao Ni, linux-raid
In-Reply-To: <20260529054308.2720300-3-hch@lst.de>
On Fri, May 29, 2026 at 1:45 PM Christoph Hellwig <hch@lst.de> wrote:
>
> This condition much better fits into the only caller, limiting
> fix_read_error to actually fix up data devices after a read error.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> drivers/md/raid1.c | 10 ++++------
> 1 file changed, 4 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 8fad1692cf66..e510ad7eef32 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -2411,11 +2411,6 @@ static void fix_read_error(struct r1conf *conf, struct r1bio *r1_bio)
> struct mddev *mddev = conf->mddev;
> struct md_rdev *rdev = conf->mirrors[read_disk].rdev;
>
> - if (exceed_read_errors(mddev, rdev)) {
> - r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
> - return;
> - }
> -
> while(sectors) {
> int s = sectors;
> int d = read_disk;
> @@ -2652,7 +2647,10 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
> md_error(mddev, rdev);
> } else {
> freeze_array(conf, 1);
> - fix_read_error(conf, r1_bio);
> + if (exceed_read_errors(mddev, rdev))
> + r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
> + else
> + fix_read_error(conf, r1_bio);
> unfreeze_array(conf);
> }
>
> --
> 2.53.0
>
>
This patch looks good to me.
Reviewed-by: Xiao Ni <xiao@kernel.org>
^ permalink raw reply
* Re: [PATCH 1/2] md/raid1: cleanup handle_read_error
From: Xiao Ni @ 2026-06-01 5:51 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Song Liu, Yu Kuai, Li Nan, Xiao Ni, linux-raid
In-Reply-To: <20260529054308.2720300-2-hch@lst.de>
On Fri, May 29, 2026 at 1:46 PM Christoph Hellwig <hch@lst.de> wrote:
>
> Unwind the main conditional with duplicate conditions and initialize
> variables at initialization time where possible.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> drivers/md/raid1.c | 34 ++++++++++++++++------------------
> 1 file changed, 16 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 64d970e2ef50..8fad1692cf66 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -2627,35 +2627,33 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
>
> static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
> {
> + struct md_rdev *rdev = conf->mirrors[r1_bio->read_disk].rdev;
> + struct bio *bio = r1_bio->bios[r1_bio->read_disk];
> struct mddev *mddev = conf->mddev;
> - struct bio *bio;
> - struct md_rdev *rdev;
> sector_t sector;
>
> clear_bit(R1BIO_ReadError, &r1_bio->state);
> - /* we got a read error. Maybe the drive is bad. Maybe just
> - * the block and we can fix it.
> - * We freeze all other IO, and try reading the block from
> - * other devices. When we find one, we re-write
> - * and check it that fixes the read error.
> - * This is all done synchronously while the array is
> - * frozen
> - */
>
> - bio = r1_bio->bios[r1_bio->read_disk];
> bio_put(bio);
> r1_bio->bios[r1_bio->read_disk] = NULL;
>
> - rdev = conf->mirrors[r1_bio->read_disk].rdev;
> - if (mddev->ro == 0
> - && !test_bit(FailFast, &rdev->flags)) {
> + /*
> + * We got a read error. Maybe the drive is bad. Maybe just the block
> + * and we can fix it.
> + *
> + * If allowed, freeze all other IO, and try reading the block from other
> + * devices. If we find one, we re-write and check it that fixes the
> + * read error. This is all done synchronously while the array is
> + * frozen.
> + */
> + if (mddev->ro) {
> + r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
> + } else if (test_bit(FailFast, &rdev->flags)) {
> + md_error(mddev, rdev);
> + } else {
> freeze_array(conf, 1);
> fix_read_error(conf, r1_bio);
> unfreeze_array(conf);
> - } else if (mddev->ro == 0 && test_bit(FailFast, &rdev->flags)) {
> - md_error(mddev, rdev);
> - } else {
> - r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
> }
>
> rdev_dec_pending(rdev, conf->mddev);
> --
> 2.53.0
>
>
Yes, it's more readable. This patch is good to me.
Reviewed-by: Xiao Ni <xiao@kernel.org>
^ permalink raw reply
* [PATCH] raid10: badblock-aware reshape write error handling
From: ghuicao @ 2026-06-01 5:46 UTC (permalink / raw)
To: song, yukuai; +Cc: linan122, xiao, linux-raid, linux-kernel, Cao Guanghui
From: Cao Guanghui <caoguanghui@kylinos.cn>
Replace the FIXME in end_reshape_write(). Instead of failing the device
immediately on write errors during reshape, attempt to record badblocks
using new_data_offset with is_new=1.
rdev_set_badblocks() returns true on success. On failure (e.g., badblocks
table full), it has already called md_error() internally to degrade the
device. Queue WantReplacement for member devices regardless of badblock
recording success, but skip this for replacement devices to avoid
replacement loops.
On successful write, clear stale badblock records at the new location
since data has migrated.
Signed-off-by: Cao Guanghui <caoguanghui@kylinos.cn>
---
drivers/md/raid10.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 4901ebe45c87..08d58a1c680e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -4991,9 +4991,30 @@ static void end_reshape_write(struct bio *bio)
conf->mirrors[d].rdev;
if (bio->bi_status) {
- /* FIXME should record badblock */
- md_error(mddev, rdev);
- }
+ set_bit(WriteErrorSeen, &rdev->flags);
+
+ /* rdev_set_badblocks returns true on success.
+ * On failure, it has already called md_error() internally.
+ * Use is_new=1 as reshape writes target the new layout
+ * (new_data_offset).
+ */
+ if (rdev_set_badblocks(rdev, r10_bio->devs[slot].addr,
+ r10_bio->sectors, 1)) {
+ /* Queue async replacement for member devices
+ * For replacement devices, do not trigger WantReplacement
+ * to avoid circular replacement storms.
+ */
+ if (!repl) {
+ if (!test_and_set_bit(WantReplacement, &rdev->flags))
+ set_bit(MD_RECOVERY_NEEDED,
+ &rdev->mddev->recovery);
+ }
+ }
+ } else {
+ /* Write succeeded, clear stale badblock records */
+ rdev_clear_badblocks(rdev, r10_bio->devs[slot].addr,
+ r10_bio->sectors, 1);
+ }
rdev_dec_pending(rdev, mddev);
end_reshape_request(r10_bio);
--
2.25.1
^ permalink raw reply related
* Re: --bitmap=lockless across server reboot
From: Yu Kuai @ 2026-05-31 11:50 UTC (permalink / raw)
To: Anton Gavriliuk; +Cc: linux-raid, yukuai
In-Reply-To: <CAAiJnjoh9rTHh4gRu2=7A4C7EFP4yfBED94qmeS_ATDyB0yevQ@mail.gmail.com>
Hi,
在 2026/5/25 23:08, Anton Gavriliuk 写道:
> Hhmm.... I just re-checked it with latest kernel (7.1-rc5) on Fedora
> Server 44, and now it works, log below. I don't remember on which
> kernel I saw that issue (7.1-rc3 or 7.1-rc4)
If the latest kernel works well, then it's fine. llbitmap is still
under experimental stage, and there will be patches for bug fix and
features.
>
> BTW, earlier you mentioned that you are working on raid5 performance
> improvements,
>
> "“BTW we're working on performance
> improvement for large raid5 arrays for at most 64 disks, results looks great.
> However, it might take sometime before we push our work to upstream.”
>
> Are there any progress ?, I'm very interested to test on PCIe 5.0 NVMe drives.
Yes, but we'll keep those improvements downstream for sometime. We have plans
to push them to upstream but it'll wait for about 1 or 2 years :)
>
> This is Fedora Server 44 (up to date) with compiled kernel 7.1-rc5
>
> [root@qdevice ~]# cat /etc/*release
> Fedora release 44 (Forty Four)
> NAME="Fedora Linux"
> VERSION="44 (Server Edition)"
> RELEASE_TYPE=stable
> ID=fedora
> VERSION_ID=44
> VERSION_CODENAME=""
> PRETTY_NAME="Fedora Linux 44 (Server Edition)"
> ANSI_COLOR="0;38;2;60;110;180"
> LOGO=fedora-logo-icon
> CPE_NAME="cpe:/o:fedoraproject:fedora:44"
> HOME_URL="https://fedoraproject.org/"
> DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f44/"
> SUPPORT_URL="https://ask.fedoraproject.org/"
> BUG_REPORT_URL="https://bugzilla.redhat.com/"
> REDHAT_BUGZILLA_PRODUCT="Fedora"
> REDHAT_BUGZILLA_PRODUCT_VERSION=44
> REDHAT_SUPPORT_PRODUCT="Fedora"
> REDHAT_SUPPORT_PRODUCT_VERSION=44
> SUPPORT_END=2027-05-19
> VARIANT="Server Edition"
> VARIANT_ID=server
> Fedora release 44 (Forty Four)
> Fedora release 44 (Forty Four)
> [root@qdevice ~]#
> [root@qdevice ~]# uname -a
> Linux qdevice 7.1.0-rc5 #1 SMP PREEMPT_DYNAMIC Mon May 25 15:02:20
> EEST 2026 x86_64 GNU/Linux
> [root@qdevice ~]#
> [root@qdevice mdadm]# lsblk
> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
> nvme6n1 259:1 0 447.1G 0 disk
> ├─nvme6n1p1 259:2 0 1G 0 part /boot/efi
> ├─nvme6n1p2 259:3 0 1G 0 part /boot
> ├─nvme6n1p3 259:4 0 220G 0 part /
> ├─nvme6n1p4 259:5 0 1G 0 part
> └─nvme6n1p5 259:6 0 220G 0 part
> nvme3n1 259:10 0 2.9T 0 disk
> nvme1n1 259:11 0 2.9T 0 disk
> nvme0n1 259:12 0 2.9T 0 disk
> nvme4n1 259:16 0 2.9T 0 disk
> nvme2n1 259:17 0 2.9T 0 disk
> nvme5n1 259:18 0 2.9T 0 disk
> [root@qdevice mdadm]#
> [root@qdevice mdadm]# mdadm --create --verbose /dev/md0 --level=6
> --bitmap=lockless --raid-devices=6 /dev/nvme0n1 /dev/nvme1n1
> /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 /dev/nvme5n1
> mdadm: Experimental lockless bitmap, use at your own risk!
> mdadm: layout defaults to left-symmetric
> mdadm: layout defaults to left-symmetric
> mdadm: chunk size defaults to 512K
> mdadm: /dev/nvme0n1 appears to be part of a raid array:
> level=raid6 devices=5 ctime=Wed May 20 12:45:26 2026
> mdadm: /dev/nvme1n1 appears to be part of a raid array:
> level=raid6 devices=5 ctime=Wed May 20 12:45:26 2026
> mdadm: /dev/nvme2n1 appears to be part of a raid array:
> level=raid6 devices=5 ctime=Wed May 20 12:45:26 2026
> mdadm: /dev/nvme3n1 appears to be part of a raid array:
> level=raid6 devices=5 ctime=Wed May 20 12:45:26 2026
> mdadm: /dev/nvme4n1 appears to be part of a raid array:
> level=raid6 devices=5 ctime=Wed May 20 12:45:26 2026
> mdadm: /dev/nvme5n1 appears to be part of a raid array:
> level=raid6 devices=6 ctime=Wed May 20 11:45:38 2026
> mdadm: size set to 3125484544K
> Continue creating array [y/N]? y
> mdadm: Defaulting to version 1.2 metadata
> mdadm: array /dev/md0 started.
> [root@qdevice mdadm]#
> [root@qdevice mdadm]# lsblk
> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
> nvme6n1 259:1 0 447.1G 0 disk
> ├─nvme6n1p1 259:2 0 1G 0 part /boot/efi
> ├─nvme6n1p2 259:3 0 1G 0 part /boot
> ├─nvme6n1p3 259:4 0 220G 0 part /
> ├─nvme6n1p4 259:5 0 1G 0 part
> └─nvme6n1p5 259:6 0 220G 0 part
> nvme3n1 259:10 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme1n1 259:11 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme0n1 259:12 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme4n1 259:16 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme2n1 259:17 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme5n1 259:18 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> [root@qdevice mdadm]#
> [root@qdevice mdadm]# reboot
> [root@qdevice mdadm]#
>
> After reboot,
>
> [root@qdevice ~]# lsblk
> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
> nvme6n1 259:1 0 447.1G 0 disk
> ├─nvme6n1p1 259:2 0 1G 0 part /boot/efi
> ├─nvme6n1p2 259:3 0 1G 0 part /boot
> ├─nvme6n1p3 259:4 0 220G 0 part /
> ├─nvme6n1p4 259:5 0 1G 0 part
> └─nvme6n1p5 259:6 0 220G 0 part
> nvme2n1 259:9 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme1n1 259:10 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme4n1 259:15 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme0n1 259:16 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme3n1 259:17 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> nvme5n1 259:18 0 2.9T 0 disk
> └─md0 9:0 0 11.6T 0 raid6
> [root@qdevice ~]#
>
>
> Anton
>
> пн, 25 мая 2026 г. в 08:32, Yu Kuai <yukuai@fnnas.com>:
>> Hi,
>>
>> 在 2026/5/20 1:28, Anton Gavriliuk 写道:
>>> Hi
>>>
>>> Does md-raid lockless bitmap support server's reboot ?
>> Yes, of course it should support reboot.
>>
>>> I don't see md-raid6 created with --bitmap=lockless after reboot.
>> Do you check kernel log if there is any failure log? And do you try
>> mdadm -a manually?
>>
>> BTW, pPlease report with your environment and test script in details,
>> especially kernel version and mdadm version.
>>
>>> Anton
>>>
>> --
>> Thansk,
>> Kuai
--
Thansk,
Kuai
^ permalink raw reply
* [GIT PULL] md-7.2-20260531
From: Yu Kuai @ 2026-05-31 11:26 UTC (permalink / raw)
To: Jens Axboe
Cc: Yu Kuai, linux-raid, linux-block, Abd-Alrhman Masalkhi,
Benjamin Marzinski, Chen Cheng, Christoph Hellwig, Li Nan,
Thorsten Blum
Hi Jens,
Please consider pulling the following changes into your for-7.2/block
branch.
This pull request contains:
Bug Fixes:
- Only requeue dm-raid bios when dm is suspending. (Benjamin Marzinski)
- Reset raid10 read_slot when reusing r10bio for discard. (Chen Cheng)
- Fix raid1/raid10 deadlock in read error recovery path. (Abd-Alrhman Masalkhi)
- Fix raid1/raid10 error-path detection with md_cloned_bio(). (Abd-Alrhman Masalkhi)
- Fix raid1/raid10 bio accounting for split md cloned bios. (Abd-Alrhman Masalkhi)
- Fix raid1 nr_pending leak in REQ_ATOMIC bad-block path. (Abd-Alrhman Masalkhi)
Improvements:
- Skip redundant raid_disks updates when the value is unchanged. (Abd-Alrhman Masalkhi)
Cleanups:
- Update MAINTAINERS email addresses. (Yu Kuai, Li Nan)
- Clean up raid1 read error handling. (Christoph Hellwig)
- Move the exceed_read_errors condition out of fix_read_error(). (Christoph Hellwig)
- Use str_plural() in raid0 dump_zones(). (Thorsten Blum)
Thanks,
Kuai
---
The following changes since commit be34ec59ef061a1cc435a3e066ad71ca675c7fcd:
block: unexport bio_{set,check}_pages_dirty (2026-05-15 08:46:45 -0600)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux.git tags/md-7.2-20260531
for you to fetch changes up to 717359a168bb66ac95f6161715d17e491ee86ca7:
md/raid0: use str_plural helper in dump_zones (2026-05-31 19:09:20 +0800)
----------------------------------------------------------------
Abd-Alrhman Masalkhi (5):
md: skip redundant raid_disks update when value is unchanged
md/raid1,raid10: fix deadlock in read error recovery path
md/raid1,raid10: fix error-path detection with md_cloned_bio()
md/raid1,raid10: fix bio accounting for split md cloned bios
raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
Benjamin Marzinski (1):
dm-raid: only requeue bios when dm is suspending
Chen Cheng (1):
md/raid10: reset read_slot when reusing r10bio for discard
Christoph Hellwig (2):
md/raid1: cleanup handle_read_error
md/raid1: move the exceed_read_errors condition out of fix_read_error
Li Nan (1):
MAINTAINERS: Update Li Nan's E-mail address
Thorsten Blum (1):
md/raid0: use str_plural helper in dump_zones
Yu Kuai (1):
MAINTAINERS: update Yu Kuai's email address
MAINTAINERS | 6 ++---
drivers/md/dm-raid.c | 6 +++++
drivers/md/md.c | 32 ++++++++++++++++----------
drivers/md/md.h | 7 ++++++
drivers/md/raid0.c | 3 ++-
drivers/md/raid1.c | 63 ++++++++++++++++++++++++++++------------------------
drivers/md/raid10.c | 29 +++++++++++++++---------
drivers/md/raid5.c | 7 ++++--
8 files changed, 96 insertions(+), 57 deletions(-)
^ permalink raw reply
* Re: [PATCH v3 0/2] md/raid10: fix r10bio width mismatches across reshape
From: Yu Kuai @ 2026-05-31 10:46 UTC (permalink / raw)
To: Chen Cheng, linux-raid, yukuai; +Cc: linux-kernel
In-Reply-To: <20260525015520.2565423-1-chencheng@fnnas.com>
Hi,
在 2026/5/25 9:55, Chen Cheng 写道:
> From: Chen Cheng <chencheng@fnnas.com>
>
> Hi,
>
> This series fixes slab out-of-bounds accesses in raid10 when reshape changes
> the number of raid disks while regular I/O is still reusing r10bio objects
> allocated under the previous geometry.
>
> The bug is reproducible with a simple 4-disk to 5-disk reshape under write
> load, for example:
>
> mdadm -C /dev/md777 -l10 -n4 /dev/sda /dev/sdb /dev/sdc /dev/sdd
> mkfs.ext4 /dev/md777
> mount /dev/md777 /mnt/test
> fsstress -d /mnt/test -n 24000 -p 8 -l 24 &
> mdadm /dev/md777 --add /dev/sde
> mdadm --grow /dev/md777 --raid-devices=5 \
> --backup-file=/tmp/md-reshape-backup
>
> Without these changes, an r10bio allocated under the old geometry can later be
> reused, initialized, or freed after conf->geo.raid_disks has switched to the
> new geometry. This creates width mismatches between the object and the current
> devs[] walk/initialization width, which can trigger KASAN reports such as
> slab-out-of-bounds in __make_request(), put_all_bios(), or find_bio_disk().
>
> This series addresses the problem in two steps:
>
> 1. make the regular r10bio pool fixed-size across reshape transitions, and
> move the pool rebuild into the freeze window before the live geometry
> switch;
>
> 2. track the number of valid devs[] entries in each reused r10bio and use
> that recorded width when walking devs[] after reshape.
>
>
> Changes in v3:
> - Replace freeze_array()/unfreeze_array() in raid10_start_reshape() with
> mddev_suspend_and_lock_nointr()/mddev_unlock_and_resume(). freeze_array()
> returns when nr_pending == nr_queued, which still allows retry-list items
> to hold pool objects; mddev_suspend() provides the correct upper-layer
> quiesce interface. (Suggested by Yu Kuai)
>
>
> Changes in v2:
> - add this cover letter
> - convert r10bio_pool to a fixed-size kmalloc mempool
> - rebuild r10bio_pool inside the freeze window before switching live reshape
> geometry
> - switch raid10_quiesce() to freeze_array()/unfreeze_array()
>
>
> Testing:
> - reproduced the original KASAN slab-out-of-bounds on 4-disk -> 5-disk
> raid10 reshape with fsstress
> - verified that this series fixes that reproducer
> - exercised the 5-disk -> 4-disk reshape direction as well
>
> Thanks,
> Chen Cheng
>
> Chen Cheng (2):
> md/raid10: make r10bio_pool use fixed-size objects
> md/raid10: bound reused r10bio devs[] walks by used_nr_devs
>
> drivers/md/raid10.c | 65 ++++++++++++++++++++++++++++++++++-----------
> drivers/md/raid10.h | 4 ++-
> 2 files changed, 53 insertions(+), 16 deletions(-)
This patch does not apply cleanly on md-7.2, please rebase first.
>
--
Thansk,
Kuai
^ permalink raw reply
* Re: [PATCH v3 1/2] md/raid10: make r10bio_pool use fixed-size objects
From: Yu Kuai @ 2026-05-31 10:36 UTC (permalink / raw)
To: Chen Cheng, linux-raid, yukuai; +Cc: linux-kernel
In-Reply-To: <20260525015520.2565423-2-chencheng@fnnas.com>
Hi,
在 2026/5/25 9:55, Chen Cheng 写道:
> From: Chen Cheng <chencheng@fnnas.com>
>
> raid10 currently allocates r10bio_pool objects with conf->geo.raid_disks,
> which makes regular r10bio objects geometry-dependent.
>
> That model breaks down across reshape. mempool objects are preallocated and
> reused, so a reshape that changes the number of raid disks can leave old
> r10bio objects in the regular I/O pool with a devs[] array sized for the
> previous geometry. After the geometry switch, those stale objects may be
> reused or later freed under the new layout, creating a width mismatch
> between the reused r10bio and the current array geometry.
>
> For example, during a 4-disk to 5-disk reshape, an r10bio allocated before
> the geometry switch has room for only 4 devs[] entries. After reshape
> updates conf->geo.raid_disks to 5, that stale object can be reused under
> the new geometry. Code such as __make_request(), put_all_bios(), and
> find_bio_disk() may then access devs[] using the new geometry and step
> past the end of the old 4-slot object, leading to slab out-of-bounds
> accesses.
>
> The root problem is that regular r10bio pool objects are geometry-dependent,
> while mempool elements are preallocated and reused across requests.
>
> Switch r10bio_pool to a fixed-size kmalloc mempool so regular I/O objects no
> longer carry an allocation width tied to the current geometry. Use the same
> fixed-size allocation rule for the standalone r10bio allocated from
> r10buf_pool_alloc().
>
> Signed-off-by: Chen Cheng <chencheng@fnnas.com>
> ---
> drivers/md/raid10.c | 57 ++++++++++++++++++++++++++++++++++-----------
> drivers/md/raid10.h | 2 +-
> 2 files changed, 45 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
> index 39085e7dd6d2..64677dbe5152 100644
> --- a/drivers/md/raid10.c
> +++ b/drivers/md/raid10.c
> @@ -101,17 +101,32 @@ static void end_reshape(struct r10conf *conf);
> static inline struct r10bio *get_resync_r10bio(struct bio *bio)
> {
> return get_resync_pages(bio)->raid_bio;
> }
>
> -static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
> +static inline unsigned int calc_r10bio_pool_disks(struct mddev *mddev)
> {
> - struct r10conf *conf = data;
> - int size = offsetof(struct r10bio, devs[conf->geo.raid_disks]);
> + /* If delta_disks < 0, use bigger r10bio->devs[] is ok. */
> + return mddev->raid_disks + max(0, mddev->delta_disks);
> +}
> +
> +static inline int calc_r10bio_size(struct mddev *mddev)
> +{
> + return offsetof(struct r10bio, devs[calc_r10bio_pool_disks(mddev)]);
> +}
> +
> +static mempool_t *create_r10bio_pool(struct mddev *mddev)
> +{
> + int size = calc_r10bio_size(mddev);
> +
> + return mempool_create_kmalloc_pool(NR_RAID_BIOS, size);
> +}
> +
> +static struct r10bio *alloc_r10bio(struct mddev *mddev, gfp_t gfp_flags)
> +{
> + int size = calc_r10bio_size(mddev);
>
> - /* allocate a r10bio with room for raid_disks entries in the
> - * bios array */
> return kzalloc(size, gfp_flags);
> }
>
> #define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9)
> /* amount of memory to reserve for resync requests */
> @@ -135,11 +150,11 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
> struct bio *bio;
> int j;
> int nalloc, nalloc_rp;
> struct resync_pages *rps;
>
> - r10_bio = r10bio_pool_alloc(gfp_flags, conf);
> + r10_bio = alloc_r10bio(conf->mddev, gfp_flags);
> if (!r10_bio)
> return NULL;
>
> if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery) ||
> test_bit(MD_RECOVERY_RESHAPE, &conf->mddev->recovery))
> @@ -275,11 +290,11 @@ static void put_all_bios(struct r10conf *conf, struct r10bio *r10_bio)
> static void free_r10bio(struct r10bio *r10_bio)
> {
> struct r10conf *conf = r10_bio->mddev->private;
>
> put_all_bios(conf, r10_bio);
> - mempool_free(r10_bio, &conf->r10bio_pool);
> + mempool_free(r10_bio, conf->r10bio_pool);
> }
>
> static void put_buf(struct r10bio *r10_bio)
> {
> struct r10conf *conf = r10_bio->mddev->private;
> @@ -1529,11 +1544,11 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
> static void __make_request(struct mddev *mddev, struct bio *bio, int sectors)
> {
> struct r10conf *conf = mddev->private;
> struct r10bio *r10_bio;
>
> - r10_bio = mempool_alloc(&conf->r10bio_pool, GFP_NOIO);
> + r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
>
> r10_bio->master_bio = bio;
> r10_bio->sectors = sectors;
>
> r10_bio->mddev = mddev;
> @@ -1721,11 +1736,11 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
> last_stripe_index *= geo->far_copies;
> end_disk_offset = (bio_end & geo->chunk_mask) +
> (last_stripe_index << geo->chunk_shift);
>
> retry_discard:
> - r10_bio = mempool_alloc(&conf->r10bio_pool, GFP_NOIO);
> + r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
> r10_bio->mddev = mddev;
> r10_bio->state = 0;
> r10_bio->sectors = 0;
> memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) * geo->raid_disks);
> wait_blocked_dev(mddev, r10_bio);
> @@ -3821,11 +3836,11 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
> static void raid10_free_conf(struct r10conf *conf)
> {
> if (!conf)
> return;
>
> - mempool_exit(&conf->r10bio_pool);
> + mempool_destroy(conf->r10bio_pool);
> kfree(conf->mirrors);
> kfree(conf->mirrors_old);
> kfree(conf->mirrors_new);
> safe_put_page(conf->tmppage);
> bioset_exit(&conf->bio_split);
> @@ -3868,13 +3883,12 @@ static struct r10conf *setup_conf(struct mddev *mddev)
> if (!conf->tmppage)
> goto out;
>
> conf->geo = geo;
> conf->copies = copies;
> - err = mempool_init(&conf->r10bio_pool, NR_RAID_BIOS, r10bio_pool_alloc,
> - rbio_pool_free, conf);
> - if (err)
> + conf->r10bio_pool = create_r10bio_pool(mddev);
> + if (!conf->r10bio_pool)
> goto out;
>
> err = bioset_init(&conf->bio_split, BIO_POOL_SIZE, 0, 0);
> if (err)
> goto out;
> @@ -4363,10 +4377,11 @@ static int raid10_start_reshape(struct mddev *mddev)
> struct geom new;
> struct r10conf *conf = mddev->private;
> struct md_rdev *rdev;
> int spares = 0;
> int ret;
> + mempool_t *new_pool;
>
> if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
> return -EBUSY;
>
> if (setup_geo(&new, mddev, geo_start) != conf->copies)
> @@ -4398,11 +4413,23 @@ static int raid10_start_reshape(struct mddev *mddev)
> return -EINVAL;
>
> if (spares < mddev->delta_disks)
> return -EINVAL;
>
> + mddev_unlock(mddev);
> + mddev_suspend_and_lock_nointr(mddev);
This is weird, unless there is a strong reason, this is not acceptable to
unlock and then lock again.
Please check all the callers of pers->start_reshape, and if it's possible
to suspend before the lock.
> conf->offset_diff = min_offset_diff;
> + if (mddev->delta_disks > 0) {
> + new_pool = create_r10bio_pool(mddev);
> + if (!new_pool) {
> + mddev_unlock_and_resume(mddev);
> + mddev_lock_nointr(mddev);
> + return -ENOMEM;
> + }
> + mempool_destroy(conf->r10bio_pool);
> + conf->r10bio_pool = new_pool;
> + }
> spin_lock_irq(&conf->device_lock);
> if (conf->mirrors_new) {
> memcpy(conf->mirrors_new, conf->mirrors,
> sizeof(struct raid10_info)*conf->prev.raid_disks);
> smp_mb();
> @@ -4415,20 +4442,24 @@ static int raid10_start_reshape(struct mddev *mddev)
> smp_mb();
> if (mddev->reshape_backwards) {
> sector_t size = raid10_size(mddev, 0, 0);
> if (size < mddev->array_sectors) {
> spin_unlock_irq(&conf->device_lock);
> + mddev_unlock_and_resume(mddev);
> + mddev_lock_nointr(mddev);
> pr_warn("md/raid10:%s: array size must be reduce before number of disks\n",
> mdname(mddev));
> return -EINVAL;
> }
> mddev->resync_max_sectors = size;
> conf->reshape_progress = size;
> } else
> conf->reshape_progress = 0;
> conf->reshape_safe = conf->reshape_progress;
> spin_unlock_irq(&conf->device_lock);
> + mddev_unlock_and_resume(mddev);
> + mddev_lock_nointr(mddev);
>
> if (mddev->delta_disks && mddev->bitmap) {
> struct mdp_superblock_1 *sb = NULL;
> sector_t oldsize, newsize;
>
> diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
> index ec79d87fb92f..b711626a5db7 100644
> --- a/drivers/md/raid10.h
> +++ b/drivers/md/raid10.h
> @@ -85,11 +85,11 @@ struct r10conf {
> int have_replacement; /* There is at least one
> * replacement device.
> */
> wait_queue_head_t wait_barrier;
>
> - mempool_t r10bio_pool;
> + mempool_t *r10bio_pool;
> mempool_t r10buf_pool;
> struct page *tmppage;
> struct bio_set bio_split;
>
> /* When taking over an array from a different personality, we store
--
Thansk,
Kuai
^ permalink raw reply
* Re: [PATCH] raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
From: Yu Kuai @ 2026-05-31 10:21 UTC (permalink / raw)
To: Abd-Alrhman Masalkhi, song, yukuai, john.g.garry, martin.petersen,
axboe
Cc: linux-raid, linux-kernel
In-Reply-To: <20260530151411.4119-1-abd.masalkhi@gmail.com>
在 2026/5/30 23:14, Abd-Alrhman Masalkhi 写道:
> In raid1_write_request(), each per-mirror loop iteration begins by
> incrementing rdev->nr_pending. If a REQ_ATOMIC write encounters a
> badblock within the requested range, the code jumps to err_handle
> without dropping the reference taken for the current mirror.
>
> err_handle's cleanup loop will only decrements for k < i and
> r1_bio->bios[k] is non-NULL. The current slot is therefore skipped,
> leaving its nr_pending reference leaked permanently. The reference
> prevents the rdev from ever being removed, since raid1_remove_conf()
> refuses to remove an rdev with nr_pending > 0.
>
> Fix this by calling rdev_dec_pending() before jumping to err_handle.
>
> Fixes: f2a38abf5f1c ("md/raid1: Atomic write support")
> Signed-off-by: Abd-Alrhman Masalkhi<abd.masalkhi@gmail.com>
> ---
> drivers/md/raid1.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
Applied to md-7.2
--
Thansk,
Kuai
^ permalink raw reply
* Re: two small RAID1 cleanups
From: Yu Kuai @ 2026-05-31 10:19 UTC (permalink / raw)
To: Christoph Hellwig, Song Liu, yukuai; +Cc: Li Nan, Xiao Ni, linux-raid
In-Reply-To: <20260529054308.2720300-1-hch@lst.de>
在 2026/5/29 13:42, Christoph Hellwig 写道:
> Hi all,
>
> this series has two little cleanups that helped me understand the
> code when reading through it.
>
> Diffstat:
> raid1.c | 44 ++++++++++++++++++++------------------------
> 1 file changed, 20 insertions(+), 24 deletions(-)
Applied to md-7.2
--
Thansk,
Kuai
^ permalink raw reply
* [PATCH] raid1: fix nr_pending leak in REQ_ATOMIC bad-block error path
From: Abd-Alrhman Masalkhi @ 2026-05-30 15:14 UTC (permalink / raw)
To: song, yukuai, linan122, john.g.garry, martin.petersen, axboe
Cc: linux-raid, linux-kernel, Abd-Alrhman Masalkhi
In raid1_write_request(), each per-mirror loop iteration begins by
incrementing rdev->nr_pending. If a REQ_ATOMIC write encounters a
badblock within the requested range, the code jumps to err_handle
without dropping the reference taken for the current mirror.
err_handle's cleanup loop will only decrements for k < i and
r1_bio->bios[k] is non-NULL. The current slot is therefore skipped,
leaving its nr_pending reference leaked permanently. The reference
prevents the rdev from ever being removed, since raid1_remove_conf()
refuses to remove an rdev with nr_pending > 0.
Fix this by calling rdev_dec_pending() before jumping to err_handle.
Fixes: f2a38abf5f1c ("md/raid1: Atomic write support")
Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
---
drivers/md/raid1.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 181400e147c0..0084bbc24076 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1580,8 +1580,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
* complexity of supporting that is not worth
* the benefit.
*/
- if (bio->bi_opf & REQ_ATOMIC)
+ if (bio->bi_opf & REQ_ATOMIC) {
+ rdev_dec_pending(rdev, mddev);
goto err_handle;
+ }
good_sectors = first_bad - r1_bio->sector;
if (good_sectors < max_sectors)
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 30/34] md-bitmap: Convert read_file_page and write_file_page to bh_submit()
From: Jan Kara @ 2026-05-30 11:58 UTC (permalink / raw)
To: Matthew Wilcox (Oracle)
Cc: Jan Kara, Christian Brauner, Christoph Hellwig, linux-fsdevel,
linux-raid
In-Reply-To: <20260528173150.1093780-31-willy@infradead.org>
On Thu 28-05-26 18:31:43, Matthew Wilcox (Oracle) wrote:
> Avoid an extra indirect function call by using bh_submit() instead of
> submit_bh().
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Cc: linux-raid@vger.kernel.org
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> drivers/md/md-bitmap.c | 27 ++++++++++++++-------------
> 1 file changed, 14 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
> index 028b9ca8ce52..7d778fe1c47c 100644
> --- a/drivers/md/md-bitmap.c
> +++ b/drivers/md/md-bitmap.c
> @@ -502,6 +502,18 @@ static void write_sb_page(struct bitmap *bitmap, unsigned long pg_index,
> static void md_bitmap_file_kick(struct bitmap *bitmap);
>
> #ifdef CONFIG_MD_BITMAP_FILE
> +static void end_bitmap_write(struct bio *bio)
> +{
> + struct buffer_head *bh;
> + bool uptodate = bio_endio_bh(bio, &bh);
> + struct bitmap *bitmap = bh->b_private;
> +
> + if (!uptodate)
> + set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
> + if (atomic_dec_and_test(&bitmap->pending_writes))
> + wake_up(&bitmap->write_wait);
> +}
> +
> static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
> {
> struct buffer_head *bh = page_buffers(page);
> @@ -510,7 +522,7 @@ static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
> atomic_inc(&bitmap->pending_writes);
> set_buffer_locked(bh);
> set_buffer_mapped(bh);
> - submit_bh(REQ_OP_WRITE | REQ_SYNC, bh);
> + bh_submit(bh, REQ_OP_WRITE | REQ_SYNC, end_bitmap_write);
> bh = bh->b_this_page;
> }
>
> @@ -519,16 +531,6 @@ static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
> atomic_read(&bitmap->pending_writes) == 0);
> }
>
> -static void end_bitmap_write(struct buffer_head *bh, int uptodate)
> -{
> - struct bitmap *bitmap = bh->b_private;
> -
> - if (!uptodate)
> - set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
> - if (atomic_dec_and_test(&bitmap->pending_writes))
> - wake_up(&bitmap->write_wait);
> -}
> -
> static void free_buffers(struct page *page)
> {
> struct buffer_head *bh;
> @@ -592,12 +594,11 @@ static int read_file_page(struct file *file, unsigned long index,
> else
> count -= blocksize;
>
> - bh->b_end_io = end_bitmap_write;
> bh->b_private = bitmap;
> atomic_inc(&bitmap->pending_writes);
> set_buffer_locked(bh);
> set_buffer_mapped(bh);
> - submit_bh(REQ_OP_READ, bh);
> + bh_submit(bh, REQ_OP_READ, end_bitmap_write);
> }
> blk_cur++;
> bh = bh->b_this_page;
> --
> 2.47.3
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* [PATCH 2/2] md/raid1: move the exceed_read_errors condition out of fix_read_error
From: Christoph Hellwig @ 2026-05-29 5:43 UTC (permalink / raw)
To: Song Liu, Yu Kuai; +Cc: Li Nan, Xiao Ni, linux-raid
In-Reply-To: <20260529054308.2720300-1-hch@lst.de>
This condition much better fits into the only caller, limiting
fix_read_error to actually fix up data devices after a read error.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/md/raid1.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 8fad1692cf66..e510ad7eef32 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2411,11 +2411,6 @@ static void fix_read_error(struct r1conf *conf, struct r1bio *r1_bio)
struct mddev *mddev = conf->mddev;
struct md_rdev *rdev = conf->mirrors[read_disk].rdev;
- if (exceed_read_errors(mddev, rdev)) {
- r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
- return;
- }
-
while(sectors) {
int s = sectors;
int d = read_disk;
@@ -2652,7 +2647,10 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
md_error(mddev, rdev);
} else {
freeze_array(conf, 1);
- fix_read_error(conf, r1_bio);
+ if (exceed_read_errors(mddev, rdev))
+ r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
+ else
+ fix_read_error(conf, r1_bio);
unfreeze_array(conf);
}
--
2.53.0
^ permalink raw reply related
* [PATCH 1/2] md/raid1: cleanup handle_read_error
From: Christoph Hellwig @ 2026-05-29 5:42 UTC (permalink / raw)
To: Song Liu, Yu Kuai; +Cc: Li Nan, Xiao Ni, linux-raid
In-Reply-To: <20260529054308.2720300-1-hch@lst.de>
Unwind the main conditional with duplicate conditions and initialize
variables at initialization time where possible.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/md/raid1.c | 34 ++++++++++++++++------------------
1 file changed, 16 insertions(+), 18 deletions(-)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 64d970e2ef50..8fad1692cf66 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2627,35 +2627,33 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
{
+ struct md_rdev *rdev = conf->mirrors[r1_bio->read_disk].rdev;
+ struct bio *bio = r1_bio->bios[r1_bio->read_disk];
struct mddev *mddev = conf->mddev;
- struct bio *bio;
- struct md_rdev *rdev;
sector_t sector;
clear_bit(R1BIO_ReadError, &r1_bio->state);
- /* we got a read error. Maybe the drive is bad. Maybe just
- * the block and we can fix it.
- * We freeze all other IO, and try reading the block from
- * other devices. When we find one, we re-write
- * and check it that fixes the read error.
- * This is all done synchronously while the array is
- * frozen
- */
- bio = r1_bio->bios[r1_bio->read_disk];
bio_put(bio);
r1_bio->bios[r1_bio->read_disk] = NULL;
- rdev = conf->mirrors[r1_bio->read_disk].rdev;
- if (mddev->ro == 0
- && !test_bit(FailFast, &rdev->flags)) {
+ /*
+ * We got a read error. Maybe the drive is bad. Maybe just the block
+ * and we can fix it.
+ *
+ * If allowed, freeze all other IO, and try reading the block from other
+ * devices. If we find one, we re-write and check it that fixes the
+ * read error. This is all done synchronously while the array is
+ * frozen.
+ */
+ if (mddev->ro) {
+ r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
+ } else if (test_bit(FailFast, &rdev->flags)) {
+ md_error(mddev, rdev);
+ } else {
freeze_array(conf, 1);
fix_read_error(conf, r1_bio);
unfreeze_array(conf);
- } else if (mddev->ro == 0 && test_bit(FailFast, &rdev->flags)) {
- md_error(mddev, rdev);
- } else {
- r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
}
rdev_dec_pending(rdev, conf->mddev);
--
2.53.0
^ permalink raw reply related
* two small RAID1 cleanups
From: Christoph Hellwig @ 2026-05-29 5:42 UTC (permalink / raw)
To: Song Liu, Yu Kuai; +Cc: Li Nan, Xiao Ni, linux-raid
Hi all,
this series has two little cleanups that helped me understand the
code when reading through it.
Diffstat:
raid1.c | 44 ++++++++++++++++++++------------------------
1 file changed, 20 insertions(+), 24 deletions(-)
^ permalink raw reply
* Re: [PATCH v4 0/2] lib/raid: replace __get_free_pages() call with kvmalloc()
From: Andrew Morton @ 2026-05-28 22:03 UTC (permalink / raw)
To: Mike Rapoport (Microsoft)
Cc: Christoph Hellwig, David Laight, Li Nan, Song Liu, Xiao Ni,
Yu Kuai, linux-kernel, linux-mm, linux-raid, Christoph Hellwig
In-Reply-To: <20260528-lib-v4-0-4e3ad1277279@kernel.org>
On Thu, 28 May 2026 12:52:59 +0300 "Mike Rapoport (Microsoft)" <rppt@kernel.org> wrote:
> Subject: [PATCH v4 0/2] lib/raid: replace __get_free_pages() call with kvmalloc()
I'll rewrite this to "... kmalloc()"
^ permalink raw reply
* Re: [PATCH 0/8] ARM crc64 and XOR using NEON intrinsics
From: Eric Biggers @ 2026-05-28 20:35 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, linux-crypto, linux-raid, Ard Biesheuvel,
Christoph Hellwig, Russell King, Arnd Bergmann
In-Reply-To: <20260422171655.3437334-10-ardb+git@google.com>
On Wed, Apr 22, 2026 at 07:16:56PM +0200, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
>
> This is a follow-up to both [0] and [1], both of which included patch #1
> of this series, which introduces the asm/neon-intrinsics.h header on
> 32-bit ARM. The remaining changes rely on this.
>
> The purpose of this series is to streamline / clean up the use of NEON
> intrinsics on 32-bit ARM, by sharing more code, clean up Make rules and
> finally, getting rid of the hacked up types.h header, which does some
> nasty things that are only needed when building NEON intrinsics code.
>
> Patches #2 and #3 replace the ARM autovectorized XOR implementation with
> the NEON intrinsics version used by arm64.
>
> Patches #4 and #5 enable the arm64 NEON intrinsics implementation of
> crc64 on 32-bit ARM.
>
> Patches #6 and #7 drop the direct includes of <arm_neon.h> and perform
> some additional cleanup to reduce the delta between ARM and arm64 code
> and Make rules.
>
> It would probably be easiest to take all these changes through a single
> tree, and the CRC tree seems like a suitable candidate, if Eric agrees.
>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Eric Biggers <ebiggers@kernel.org>
>
> [0] https://lore.kernel.org/all/20260331074940.55502-7-ardb+git@google.com/
> [1] https://lore.kernel.org/all/20260330144630.33026-7-ardb@kernel.org/
>
> Ard Biesheuvel (8):
> ARM: Add a neon-intrinsics.h header like on arm64
> xor/arm: Replace vectorized implementation with arm64's intrinsics
> xor/arm64: Use shared NEON intrinsics implementation from 32-bit ARM
> lib/crc: Turn NEON intrinsics crc64 implementation into common code
> lib/crc: arm: Enable arm64's NEON intrinsics implementation of crc64
> crypto: aegis128 - Use neon-intrinsics.h on ARM too
> lib/raid6: Include asm/neon-intrinsics.h rather than arm_neon.h
> ARM: Remove hacked-up asm/types.h header
Applied patches 1-6 to
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=crc-next
- Eric
^ permalink raw reply
* [PATCH v2 30/34] md-bitmap: Convert read_file_page and write_file_page to bh_submit()
From: Matthew Wilcox (Oracle) @ 2026-05-28 17:31 UTC (permalink / raw)
To: Jan Kara
Cc: Matthew Wilcox (Oracle), Christian Brauner, Christoph Hellwig,
linux-fsdevel, linux-raid
In-Reply-To: <20260528173150.1093780-1-willy@infradead.org>
Avoid an extra indirect function call by using bh_submit() instead of
submit_bh().
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: linux-raid@vger.kernel.org
---
drivers/md/md-bitmap.c | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 028b9ca8ce52..7d778fe1c47c 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -502,6 +502,18 @@ static void write_sb_page(struct bitmap *bitmap, unsigned long pg_index,
static void md_bitmap_file_kick(struct bitmap *bitmap);
#ifdef CONFIG_MD_BITMAP_FILE
+static void end_bitmap_write(struct bio *bio)
+{
+ struct buffer_head *bh;
+ bool uptodate = bio_endio_bh(bio, &bh);
+ struct bitmap *bitmap = bh->b_private;
+
+ if (!uptodate)
+ set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
+ if (atomic_dec_and_test(&bitmap->pending_writes))
+ wake_up(&bitmap->write_wait);
+}
+
static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
{
struct buffer_head *bh = page_buffers(page);
@@ -510,7 +522,7 @@ static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
atomic_inc(&bitmap->pending_writes);
set_buffer_locked(bh);
set_buffer_mapped(bh);
- submit_bh(REQ_OP_WRITE | REQ_SYNC, bh);
+ bh_submit(bh, REQ_OP_WRITE | REQ_SYNC, end_bitmap_write);
bh = bh->b_this_page;
}
@@ -519,16 +531,6 @@ static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
atomic_read(&bitmap->pending_writes) == 0);
}
-static void end_bitmap_write(struct buffer_head *bh, int uptodate)
-{
- struct bitmap *bitmap = bh->b_private;
-
- if (!uptodate)
- set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
- if (atomic_dec_and_test(&bitmap->pending_writes))
- wake_up(&bitmap->write_wait);
-}
-
static void free_buffers(struct page *page)
{
struct buffer_head *bh;
@@ -592,12 +594,11 @@ static int read_file_page(struct file *file, unsigned long index,
else
count -= blocksize;
- bh->b_end_io = end_bitmap_write;
bh->b_private = bitmap;
atomic_inc(&bitmap->pending_writes);
set_buffer_locked(bh);
set_buffer_mapped(bh);
- submit_bh(REQ_OP_READ, bh);
+ bh_submit(bh, REQ_OP_READ, end_bitmap_write);
}
blk_cur++;
bh = bh->b_this_page;
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v4 1/2] xor: use kmalloc() in calibrate_xor_blocks()
From: Christoph Hellwig @ 2026-05-28 12:47 UTC (permalink / raw)
To: Mike Rapoport (Microsoft)
Cc: Andrew Morton, Christoph Hellwig, David Laight, Li Nan, Song Liu,
Xiao Ni, Yu Kuai, linux-kernel, linux-mm, linux-raid
In-Reply-To: <20260528-lib-v4-1-4e3ad1277279@kernel.org>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH v4 1/2] xor: use kmalloc() in calibrate_xor_blocks()
From: Hannes Reinecke @ 2026-05-28 9:55 UTC (permalink / raw)
To: Mike Rapoport (Microsoft), Andrew Morton
Cc: Christoph Hellwig, David Laight, Li Nan, Song Liu, Xiao Ni,
Yu Kuai, linux-kernel, linux-mm, linux-raid
In-Reply-To: <20260528-lib-v4-1-4e3ad1277279@kernel.org>
On 5/28/26 11:53, Mike Rapoport (Microsoft) wrote:
> The xor benchmark allocates 4 pages for a scratch buffer that is used
> purely as a CPU-only XOR working area.
>
> This buffer can be allocated with kmalloc() as there's nothing special
> about it to go directly to the page allocator.
>
> kmalloc() provides a better API than ancient __get_free_pages().
> kmalloc() does not require ugly casts and kfree() does not need to know the
> size of the freed object.
>
> There is no performance difference because kmalloc() redirects allocations
> of such size to the page allocator.
>
> Replace __get_free_pages() call with kmalloc().
>
> Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> ---
> lib/raid/xor/xor-core.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox