* cleanup the RAID5 XOR library
From: Christoph Hellwig @ 2026-02-26 15:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
Catalin Marinas, Will Deacon, Huacai Chen, WANG Xuerui,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
David S. Miller, Andreas Larsson, Richard Weinberger,
Anton Ivanov, Johannes Berg, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Herbert Xu,
Dan Williams, Chris Mason, David Sterba, Arnd Bergmann, Song Liu,
Yu Kuai, Li Nan, linux-alpha, linux-kernel, linux-arm-kernel,
loongarch, linuxppc-dev, linux-riscv, linux-s390, sparclinux,
linux-um, linux-crypto, linux-btrfs, linux-arch, linux-raid
Hi all,
the XOR library used for the RAID5 parity is a bit of a mess right now.
The main file sits in crypto/ despite not being cryptography and not
using the crypto API, with the generic implementations sitting in
include/asm-generic and the arch implementations sitting in an asm/
header in theory. The latter doesn't work for many cases, so
architectures often build the code directly into the core kernel, or
create another module for the architecture code.
Changes this to a single module in lib/ that also contains the
architecture optimizations, similar to the library work Eric Biggers
has done for the CRC and crypto libraries later. After that it changes
to better calling conventions that allow for smarter architecture
implementations (although none is contained here yet), and uses
static_call to avoid indirection function call overhead.
A git tree is also available here:
git://git.infradead.org/users/hch/misc.git xor-improvements
Gitweb:
https://git.infradead.org/?p=users/hch/misc.git;a=shortlog;h=refs/heads/xor-improvements
Diffstat:
arch/arm64/include/asm/xor.h | 73 --
arch/loongarch/include/asm/xor.h | 68 --
arch/loongarch/include/asm/xor_simd.h | 34 -
arch/loongarch/lib/xor_simd_glue.c | 72 --
arch/powerpc/include/asm/xor.h | 47 -
arch/powerpc/include/asm/xor_altivec.h | 22
arch/powerpc/lib/xor_vmx.h | 22
arch/powerpc/lib/xor_vmx_glue.c | 63 --
arch/riscv/include/asm/xor.h | 68 --
arch/s390/include/asm/xor.h | 21
arch/sparc/include/asm/xor.h | 9
arch/sparc/include/asm/xor_64.h | 79 ---
arch/um/include/asm/xor.h | 24
arch/x86/include/asm/xor_64.h | 28 -
b/arch/alpha/Kconfig | 1
b/arch/arm/Kconfig | 1
b/arch/arm/lib/Makefile | 5
b/arch/arm64/Kconfig | 1
b/arch/arm64/lib/Makefile | 6
b/arch/loongarch/Kconfig | 1
b/arch/loongarch/lib/Makefile | 2
b/arch/powerpc/Kconfig | 1
b/arch/powerpc/lib/Makefile | 5
b/arch/riscv/Kconfig | 1
b/arch/riscv/lib/Makefile | 1
b/arch/s390/Kconfig | 1
b/arch/s390/lib/Makefile | 2
b/arch/sparc/Kconfig | 1
b/arch/sparc/include/asm/asm-prototypes.h | 1
b/arch/sparc/lib/Makefile | 2
b/arch/um/Kconfig | 1
b/arch/x86/Kconfig | 1
b/crypto/Kconfig | 2
b/crypto/Makefile | 1
b/crypto/async_tx/async_xor.c | 16
b/fs/btrfs/raid56.c | 27 -
b/include/asm-generic/Kbuild | 1
b/include/linux/raid/xor.h | 28 -
b/lib/Kconfig | 1
b/lib/Makefile | 2
b/lib/raid/Kconfig | 7
b/lib/raid/Makefile | 2
b/lib/raid/xor/Makefile | 50 ++
b/lib/raid/xor/alpha/xor.c | 46 -
b/lib/raid/xor/alpha/xor_arch.h | 22
b/lib/raid/xor/arm/xor-neon-glue.c | 19
b/lib/raid/xor/arm/xor-neon.c | 22
b/lib/raid/xor/arm/xor.c | 105 ----
b/lib/raid/xor/arm/xor_arch.h | 22
b/lib/raid/xor/arm64/xor-neon-glue.c | 26 +
b/lib/raid/xor/arm64/xor-neon.c | 94 +--
b/lib/raid/xor/arm64/xor-neon.h | 6
b/lib/raid/xor/arm64/xor_arch.h | 21
b/lib/raid/xor/loongarch/xor_arch.h | 33 +
b/lib/raid/xor/loongarch/xor_simd_glue.c | 37 +
b/lib/raid/xor/powerpc/xor_arch.h | 22
b/lib/raid/xor/powerpc/xor_vmx.c | 40 -
b/lib/raid/xor/powerpc/xor_vmx.h | 10
b/lib/raid/xor/powerpc/xor_vmx_glue.c | 28 +
b/lib/raid/xor/riscv/xor-glue.c | 25 +
b/lib/raid/xor/riscv/xor_arch.h | 17
b/lib/raid/xor/s390/xor.c | 15
b/lib/raid/xor/s390/xor_arch.h | 13
b/lib/raid/xor/sparc/xor-niagara-glue.c | 33 +
b/lib/raid/xor/sparc/xor-niagara.S | 346 --------------
b/lib/raid/xor/sparc/xor-sparc32.c | 32 -
b/lib/raid/xor/sparc/xor-vis-glue.c | 34 +
b/lib/raid/xor/sparc/xor-vis.S | 348 ++++++++++++++
b/lib/raid/xor/sparc/xor_arch.h | 35 +
b/lib/raid/xor/um/xor_arch.h | 9
b/lib/raid/xor/x86/xor-avx.c | 52 --
b/lib/raid/xor/x86/xor-mmx.c | 120 +---
b/lib/raid/xor/x86/xor-sse.c | 105 +---
b/lib/raid/xor/x86/xor_arch.h | 36 +
b/lib/raid/xor/xor-32regs-prefetch.c | 267 ++++++++++
b/lib/raid/xor/xor-32regs.c | 217 ++++++++
b/lib/raid/xor/xor-8regs-prefetch.c | 146 +++++
b/lib/raid/xor/xor-8regs.c | 103 ++++
b/lib/raid/xor/xor-core.c | 187 +++++++
b/lib/raid/xor/xor_impl.h | 60 ++
crypto/xor.c | 174 -------
include/asm-generic/xor.h | 738 ------------------------------
82 files changed, 2033 insertions(+), 2433 deletions(-)
^ permalink raw reply
* Re: [PATCH] block: remove bdev_nonrot()
From: Damien Le Moal @ 2026-02-26 12:27 UTC (permalink / raw)
To: Paul Menzel
Cc: Jens Axboe, linux-block, Song Liu, Yu Kuai, linux-raid,
Martin K . Petersen, linux-scsi, target-devel, David Sterba,
linux-btrfs, Theodore Ts'o, linux-ext4, Andreas Dilger,
Andrew Morton, Chris Li, Kairui Song, linux-mm
In-Reply-To: <5b8c1811-c9d9-469a-b8d0-992814a11b9a@molgen.mpg.de>
On 2/26/26 19:04, Paul Menzel wrote:
> Dear Damien,
>
>
> Thank you for your patch.
>
>
> Am 26.02.26 um 08:54 schrieb Damien Le Moal:
>> bdev_nonrot() is simply the negative return value of bdev_rot().
>> So replace all call sites of bdev_nonrot() with calls to bdev_rot()
>> and remove bdev_nonrot().
>
> Is the generated code different now?
I did not check but I doubt there is any difference at all.
This is more about having a single helper function for bdevs that is consistent
with the helper for request queues (blk_queue_rot()) which directly reflects the
setting of a block device BLK_FEAT_ROTATIONAL queue feature. This way is also in
my opinion simpler as you do not get your brain overheating when seeing things
like "!bdev_nonrot()" :)
> Is it worth the change, as it looks quite subjective if you prefer the
> one or the other way?
I think it is a nice cleanup, but I will let Jens and other maintainers decide
on the worth of this patch.
> My point above aside, the diff looks good.
>
> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Thanks.
--
Damien Le Moal
Western Digital Research
^ permalink raw reply
* Re: [PATCH] block: remove bdev_nonrot()
From: Paul Menzel @ 2026-02-26 10:04 UTC (permalink / raw)
To: Damien Le Moal
Cc: Jens Axboe, linux-block, Song Liu, Yu Kuai, linux-raid,
Martin K . Petersen, linux-scsi, target-devel, David Sterba,
linux-btrfs, Theodore Ts'o, linux-ext4, Andreas Dilger,
Andrew Morton, Chris Li, Kairui Song, linux-mm
In-Reply-To: <20260226075448.2229655-1-dlemoal@kernel.org>
Dear Damien,
Thank you for your patch.
Am 26.02.26 um 08:54 schrieb Damien Le Moal:
> bdev_nonrot() is simply the negative return value of bdev_rot().
> So replace all call sites of bdev_nonrot() with calls to bdev_rot()
> and remove bdev_nonrot().
Is the generated code different now?
Is it worth the change, as it looks quite subjective if you prefer the
one or the other way?
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> ---
> drivers/md/raid1.c | 2 +-
> drivers/md/raid10.c | 2 +-
> drivers/md/raid5.c | 2 +-
> drivers/target/target_core_file.c | 2 +-
> drivers/target/target_core_iblock.c | 2 +-
> fs/btrfs/volumes.c | 4 ++--
> fs/ext4/mballoc-test.c | 2 +-
> fs/ext4/mballoc.c | 2 +-
> include/linux/blkdev.h | 5 -----
> mm/swapfile.c | 2 +-
> 10 files changed, 10 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 181400e147c0..cda6af0712b9 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -1878,7 +1878,7 @@ static bool raid1_add_conf(struct r1conf *conf, struct md_rdev *rdev, int disk,
> if (info->rdev)
> return false;
>
> - if (bdev_nonrot(rdev->bdev)) {
> + if (!bdev_rot(rdev->bdev)) {
> set_bit(Nonrot, &rdev->flags);
> WRITE_ONCE(conf->nonrot_disks, conf->nonrot_disks + 1);
> }
> diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
> index 0653b5d8545a..cfbd345805ca 100644
> --- a/drivers/md/raid10.c
> +++ b/drivers/md/raid10.c
> @@ -806,7 +806,7 @@ static struct md_rdev *read_balance(struct r10conf *conf,
> if (!do_balance)
> break;
>
> - nonrot = bdev_nonrot(rdev->bdev);
> + nonrot = !bdev_rot(rdev->bdev);
> has_nonrot_disk |= nonrot;
> pending = atomic_read(&rdev->nr_pending);
> if (min_pending > pending && nonrot) {
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index a8e8d431071b..ba9d6d05b089 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -7541,7 +7541,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
> rdev_for_each(rdev, mddev) {
> if (test_bit(Journal, &rdev->flags))
> continue;
> - if (bdev_nonrot(rdev->bdev)) {
> + if (!bdev_rot(rdev->bdev)) {
> conf->batch_bio_dispatch = false;
> break;
> }
> diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
> index 3ae1f7137d9d..d6e3e5214652 100644
> --- a/drivers/target/target_core_file.c
> +++ b/drivers/target/target_core_file.c
> @@ -173,7 +173,7 @@ static int fd_configure_device(struct se_device *dev)
> */
> dev->dev_attrib.max_write_same_len = 0xFFFF;
>
> - if (bdev_nonrot(bdev))
> + if (!bdev_rot(bdev))
> dev->dev_attrib.is_nonrot = 1;
> } else {
> if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
> diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
> index 3c92f94497b4..1087d1d17c36 100644
> --- a/drivers/target/target_core_iblock.c
> +++ b/drivers/target/target_core_iblock.c
> @@ -148,7 +148,7 @@ static int iblock_configure_device(struct se_device *dev)
> else
> dev->dev_attrib.max_write_same_len = 0xFFFF;
>
> - if (bdev_nonrot(bd))
> + if (!bdev_rot(bd))
> dev->dev_attrib.is_nonrot = 1;
>
> target_configure_write_atomic_from_bdev(&dev->dev_attrib, bd);
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 6fb0c4cd50ff..c6e49eb74f3a 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -694,7 +694,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
> set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
> }
>
> - if (!bdev_nonrot(file_bdev(bdev_file)))
> + if (bdev_rot(file_bdev(bdev_file)))
> fs_devices->rotating = true;
>
> if (bdev_max_discard_sectors(file_bdev(bdev_file)))
> @@ -2919,7 +2919,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
>
> atomic64_add(device->total_bytes, &fs_info->free_chunk_space);
>
> - if (!bdev_nonrot(device->bdev))
> + if (bdev_rot(device->bdev))
> fs_devices->rotating = true;
>
> orig_super_total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
> diff --git a/fs/ext4/mballoc-test.c b/fs/ext4/mballoc-test.c
> index 9fbdf6a09489..b9f22e3a8d5c 100644
> --- a/fs/ext4/mballoc-test.c
> +++ b/fs/ext4/mballoc-test.c
> @@ -72,7 +72,7 @@ static int mbt_mb_init(struct super_block *sb)
> ext4_fsblk_t block;
> int ret;
>
> - /* needed by ext4_mb_init->bdev_nonrot(sb->s_bdev) */
> + /* needed by ext4_mb_init->bdev_rot(sb->s_bdev) */
> sb->s_bdev = kzalloc_obj(*sb->s_bdev);
> if (sb->s_bdev == NULL)
> return -ENOMEM;
> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index 20e9fdaf4301..8a4dfe19878c 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -3836,7 +3836,7 @@ int ext4_mb_init(struct super_block *sb)
> spin_lock_init(&lg->lg_prealloc_lock);
> }
>
> - if (bdev_nonrot(sb->s_bdev))
> + if (!bdev_rot(sb->s_bdev))
> sbi->s_mb_max_linear_groups = 0;
> else
> sbi->s_mb_max_linear_groups = MB_DEFAULT_LINEAR_LIMIT;
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index d463b9b5a0a5..e439d6fa8484 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -1467,11 +1467,6 @@ static inline bool bdev_rot(struct block_device *bdev)
> return blk_queue_rot(bdev_get_queue(bdev));
> }
>
> -static inline bool bdev_nonrot(struct block_device *bdev)
> -{
> - return !bdev_rot(bdev);
> -}
> -
> static inline bool bdev_synchronous(struct block_device *bdev)
> {
> return bdev->bd_disk->queue->limits.features & BLK_FEAT_SYNCHRONOUS;
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 94af29d1de88..60e21414624b 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -3460,7 +3460,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
> if (si->bdev && bdev_synchronous(si->bdev))
> si->flags |= SWP_SYNCHRONOUS_IO;
>
> - if (si->bdev && bdev_nonrot(si->bdev)) {
> + if (si->bdev && !bdev_rot(si->bdev)) {
> si->flags |= SWP_SOLIDSTATE;
> } else {
> atomic_inc(&nr_rotate_swap);
My point above aside, the diff looks good.
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Kind regards,
Paul
^ permalink raw reply
* Re: [PATCH 1/1] md/raid5: don't set bi_status for requeued IO in STRIPE_WAIT_RESHAPE
From: Yang Xiuwei @ 2026-02-26 8:28 UTC (permalink / raw)
To: Yu Kuai; +Cc: song, snitzer, xni, linux-raid
In-Reply-To: <71e50b0e-0669-4a40-84d5-3c3061dfb229@fnnas.com>
Hi,
On 2026/2/3 17:51, Yang Xiuwei wrote:
>> When reshape is interrupted, IO that needs to be requeued incorrectly
>> sets bi->bi_status to BLK_STS_RESOURCE. This causes md_free_cloned_bio()
>> to copy the error status to the original bio, which is wrong because
>> requeued IO should be retried, not failed.
>>
>> This was found during LVM testing where reshape operations under I/O
>> load would cause I/O errors and filesystem corruption.
>>
>> Remove the bi_status assignment to prevent incorrect error marking.
>>
>> Fixes: 41425f96d7aa ("dm-raid456, md/raid456: fix a deadlock for dm-raid456 while io concurrent with reshape")
>>
>> Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>
>> ---
>> drivers/md/raid5.c | 1 -
>> 1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
>> index 8dc98f545969..128c0b7e9f54 100644
>> --- a/drivers/md/raid5.c
>> +++ b/drivers/md/raid5.c
>> @@ -6038,7 +6038,6 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
>> raid5_release_stripe(sh);
>> out:
>> if (ret == STRIPE_SCHEDULE_AND_RETRY && reshape_interrupted(mddev)) {
>> - bi->bi_status = BLK_STS_RESOURCE;
On 2026/2/26 13:44, Yu Kuai wrote:
> This will make the problem much worse, you should notice this bio is returned directly
> to user, because reshape is interrupted and nothing can be read or write, and you're
> returning wrong data to user.
Thanks for your review and feedback.
I will carefully re-read the relevant code logic, especially:
- The complete flow of DM layer requeue mechanism
- The bio handling path in the reshape flow
- Verify whether the bio will be requeued rather than directly returned to the user
Best regards,
Yang Xiuwei
^ permalink raw reply
* [PATCH] block: remove bdev_nonrot()
From: Damien Le Moal @ 2026-02-26 7:54 UTC (permalink / raw)
To: Jens Axboe, linux-block, Song Liu, Yu Kuai, linux-raid,
Martin K . Petersen, linux-scsi, target-devel, David Sterba,
linux-btrfs, Theodore Ts'o, linux-ext4, Andreas Dilger,
Andrew Morton, Chris Li, Kairui Song, linux-mm
bdev_nonrot() is simply the negative return value of bdev_rot().
So replace all call sites of bdev_nonrot() with calls to bdev_rot()
and remove bdev_nonrot().
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
drivers/md/raid1.c | 2 +-
drivers/md/raid10.c | 2 +-
drivers/md/raid5.c | 2 +-
drivers/target/target_core_file.c | 2 +-
drivers/target/target_core_iblock.c | 2 +-
fs/btrfs/volumes.c | 4 ++--
fs/ext4/mballoc-test.c | 2 +-
fs/ext4/mballoc.c | 2 +-
include/linux/blkdev.h | 5 -----
mm/swapfile.c | 2 +-
10 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 181400e147c0..cda6af0712b9 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1878,7 +1878,7 @@ static bool raid1_add_conf(struct r1conf *conf, struct md_rdev *rdev, int disk,
if (info->rdev)
return false;
- if (bdev_nonrot(rdev->bdev)) {
+ if (!bdev_rot(rdev->bdev)) {
set_bit(Nonrot, &rdev->flags);
WRITE_ONCE(conf->nonrot_disks, conf->nonrot_disks + 1);
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 0653b5d8545a..cfbd345805ca 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -806,7 +806,7 @@ static struct md_rdev *read_balance(struct r10conf *conf,
if (!do_balance)
break;
- nonrot = bdev_nonrot(rdev->bdev);
+ nonrot = !bdev_rot(rdev->bdev);
has_nonrot_disk |= nonrot;
pending = atomic_read(&rdev->nr_pending);
if (min_pending > pending && nonrot) {
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index a8e8d431071b..ba9d6d05b089 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7541,7 +7541,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
rdev_for_each(rdev, mddev) {
if (test_bit(Journal, &rdev->flags))
continue;
- if (bdev_nonrot(rdev->bdev)) {
+ if (!bdev_rot(rdev->bdev)) {
conf->batch_bio_dispatch = false;
break;
}
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 3ae1f7137d9d..d6e3e5214652 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -173,7 +173,7 @@ static int fd_configure_device(struct se_device *dev)
*/
dev->dev_attrib.max_write_same_len = 0xFFFF;
- if (bdev_nonrot(bdev))
+ if (!bdev_rot(bdev))
dev->dev_attrib.is_nonrot = 1;
} else {
if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 3c92f94497b4..1087d1d17c36 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -148,7 +148,7 @@ static int iblock_configure_device(struct se_device *dev)
else
dev->dev_attrib.max_write_same_len = 0xFFFF;
- if (bdev_nonrot(bd))
+ if (!bdev_rot(bd))
dev->dev_attrib.is_nonrot = 1;
target_configure_write_atomic_from_bdev(&dev->dev_attrib, bd);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 6fb0c4cd50ff..c6e49eb74f3a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -694,7 +694,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
}
- if (!bdev_nonrot(file_bdev(bdev_file)))
+ if (bdev_rot(file_bdev(bdev_file)))
fs_devices->rotating = true;
if (bdev_max_discard_sectors(file_bdev(bdev_file)))
@@ -2919,7 +2919,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
atomic64_add(device->total_bytes, &fs_info->free_chunk_space);
- if (!bdev_nonrot(device->bdev))
+ if (bdev_rot(device->bdev))
fs_devices->rotating = true;
orig_super_total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
diff --git a/fs/ext4/mballoc-test.c b/fs/ext4/mballoc-test.c
index 9fbdf6a09489..b9f22e3a8d5c 100644
--- a/fs/ext4/mballoc-test.c
+++ b/fs/ext4/mballoc-test.c
@@ -72,7 +72,7 @@ static int mbt_mb_init(struct super_block *sb)
ext4_fsblk_t block;
int ret;
- /* needed by ext4_mb_init->bdev_nonrot(sb->s_bdev) */
+ /* needed by ext4_mb_init->bdev_rot(sb->s_bdev) */
sb->s_bdev = kzalloc_obj(*sb->s_bdev);
if (sb->s_bdev == NULL)
return -ENOMEM;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 20e9fdaf4301..8a4dfe19878c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -3836,7 +3836,7 @@ int ext4_mb_init(struct super_block *sb)
spin_lock_init(&lg->lg_prealloc_lock);
}
- if (bdev_nonrot(sb->s_bdev))
+ if (!bdev_rot(sb->s_bdev))
sbi->s_mb_max_linear_groups = 0;
else
sbi->s_mb_max_linear_groups = MB_DEFAULT_LINEAR_LIMIT;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d463b9b5a0a5..e439d6fa8484 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1467,11 +1467,6 @@ static inline bool bdev_rot(struct block_device *bdev)
return blk_queue_rot(bdev_get_queue(bdev));
}
-static inline bool bdev_nonrot(struct block_device *bdev)
-{
- return !bdev_rot(bdev);
-}
-
static inline bool bdev_synchronous(struct block_device *bdev)
{
return bdev->bd_disk->queue->limits.features & BLK_FEAT_SYNCHRONOUS;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 94af29d1de88..60e21414624b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -3460,7 +3460,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
if (si->bdev && bdev_synchronous(si->bdev))
si->flags |= SWP_SYNCHRONOUS_IO;
- if (si->bdev && bdev_nonrot(si->bdev)) {
+ if (si->bdev && !bdev_rot(si->bdev)) {
si->flags |= SWP_SOLIDSTATE;
} else {
atomic_inc(&nr_rotate_swap);
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 1/1] md/raid5: don't set bi_status for requeued IO in STRIPE_WAIT_RESHAPE
From: Yu Kuai @ 2026-02-26 5:44 UTC (permalink / raw)
To: Yang Xiuwei, song, snitzer, xni, yukuai; +Cc: linux-raid
In-Reply-To: <20260203095156.2349174-1-yangxiuwei@kylinos.cn>
Hi,
在 2026/2/3 17:51, Yang Xiuwei 写道:
> When reshape is interrupted, IO that needs to be requeued incorrectly
> sets bi->bi_status to BLK_STS_RESOURCE. This causes md_free_cloned_bio()
> to copy the error status to the original bio, which is wrong because
> requeued IO should be retried, not failed.
>
> This was found during LVM testing where reshape operations under I/O
> load would cause I/O errors and filesystem corruption.
>
> Remove the bi_status assignment to prevent incorrect error marking.
>
> Fixes: 41425f96d7aa ("dm-raid456, md/raid456: fix a deadlock for dm-raid456 while io concurrent with reshape")
>
> Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>
> ---
> drivers/md/raid5.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 8dc98f545969..128c0b7e9f54 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -6038,7 +6038,6 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
> raid5_release_stripe(sh);
> out:
> if (ret == STRIPE_SCHEDULE_AND_RETRY && reshape_interrupted(mddev)) {
> - bi->bi_status = BLK_STS_RESOURCE;
This will make the problem much worse, you should notice this bio is returned directly
to user, because reshape is interrupted and nothing can be read or write, and you're
returning wrong data to user.
> ret = STRIPE_WAIT_RESHAPE;
> pr_err_ratelimited("dm-raid456: io across reshape position while reshape can't make progress");
> }
--
Thansk,
Kuai
^ permalink raw reply
* Re: [PATCH] md: suppress spurious superblock update error message for dm-raid
From: Yu Kuai @ 2026-02-26 5:35 UTC (permalink / raw)
To: Chen Cheng, linux-raid, yukuai; +Cc: linux-kernel, pmenzel, tj.iam.tj
In-Reply-To: <20260210133847.269986-1-chencheng@fnnas.com>
Hi,
在 2026/2/10 21:38, Chen Cheng 写道:
> dm-raid has external metadata management (mddev->external = 1) and
> no persistent superblock (mddev->persistent = 0). For these arrays,
> there's no superblock to update, so the error message is spurious.
>
> The error appears as:
> [ 123.456789] md_update_sb: can't update sb for read-only array md0
>
> Link: https://lore.kernel.org/all/20260128082430.96788-1-tj.iam.tj@proton.me/
> Fixes: 6a5cb53aaa1d ("md: don't ignore read-only array in md_update_sb()")
> Signed-off-by: Chen Cheng <chencheng@fnnas.com>
> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
The Link and Fixes tag is incorrect, applied with following commit message:
md: suppress spurious superblock update error message for dm-raid
dm-raid has external metadata management (mddev->external = 1) and
no persistent superblock (mddev->persistent = 0). For these arrays,
there's no superblock to update, so the error message is spurious.
The error appears as:
md_update_sb: can't update sb for read-only array md0
Fixes: 8c9e376b9d1a ("md: warn about updating super block failure")
Reported-by: Tj <tj.iam.tj@proton.me>
Closes: https://lore.kernel.org/all/20260128082430.96788-1-tj.iam.tj@proton.me/
Signed-off-by: Chen Cheng <chencheng@fnnas.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Link: https://lore.kernel.org/linux-raid/20260210133847.269986-1-chencheng@fnnas.com
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
> ---
> drivers/md/md.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 6d73f6e196a..e30b658641e 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -2790,7 +2790,9 @@ void md_update_sb(struct mddev *mddev, int force_change)
> if (!md_is_rdwr(mddev)) {
> if (force_change)
> set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
> - pr_err("%s: can't update sb for read-only array %s\n", __func__, mdname(mddev));
> + if (!mddev_is_dm(mddev))
> + pr_err_ratelimited("%s: can't update sb for read-only array %s\n",
> + __func__, mdname(mddev));
> return;
> }
>
--
Thansk,
Kuai
^ permalink raw reply
* Re: [PATCH v2] md/raid10: fix deadlock with check operation and nowait requests
From: Yu Kuai @ 2026-02-26 5:24 UTC (permalink / raw)
To: Josh Hunt, song, linan122, linux-raid, yukuai; +Cc: ncroxon, stable
In-Reply-To: <20260210165126.3963677-1-johunt@akamai.com>
Hi,
在 2026/2/11 0:51, Josh Hunt 写道:
> When an array check is running it will raise the barrier at which point
> normal requests will become blocked and increment the nr_pending value to
> signal there is work pending inside of wait_barrier(). NOWAIT requests
> do not block and so will return immediately with an error, and additionally
> do not increment nr_pending in wait_barrier(). Upstream change
> 43806c3d5b9b ("raid10: cleanup memleak at raid10_make_request") added a
> call to raid_end_bio_io() to fix a memory leak when NOWAIT requests hit
> this condition. raid_end_bio_io() eventually calls allow_barrier() and
> it will unconditionally do an atomic_dec_and_test(&conf->nr_pending) even
> though the corresponding increment on nr_pending didn't happen in the
> NOWAIT case.
>
> This can be easily seen by starting a check operation while an application is
> doing nowait IO on the same array. This results in a deadlocked state due to
> nr_pending value underflowing and so the md resync thread gets stuck waiting
> for nr_pending to == 0.
>
> Output of r10conf state of the array when we hit this condition:
>
> crash> struct r10conf.barrier,nr_pending,nr_waiting,nr_queued <addr of r10conf>
> barrier = 1,
> nr_pending = {
> counter = -41
> },
> nr_waiting = 15,
> nr_queued = 0,
>
> Example of md_sync thread stuck waiting on raise_barrier() and other requests
> stuck in wait_barrier():
>
> md1_resync
> [<0>] raise_barrier+0xce/0x1c0
> [<0>] raid10_sync_request+0x1ca/0x1ed0
> [<0>] md_do_sync+0x779/0x1110
> [<0>] md_thread+0x90/0x160
> [<0>] kthread+0xbe/0xf0
> [<0>] ret_from_fork+0x34/0x50
> [<0>] ret_from_fork_asm+0x1a/0x30
>
> kworker/u1040:2+flush-253:4
> [<0>] wait_barrier+0x1de/0x220
> [<0>] regular_request_wait+0x30/0x180
> [<0>] raid10_make_request+0x261/0x1000
> [<0>] md_handle_request+0x13b/0x230
> [<0>] __submit_bio+0x107/0x1f0
> [<0>] submit_bio_noacct_nocheck+0x16f/0x390
> [<0>] ext4_io_submit+0x24/0x40
> [<0>] ext4_do_writepages+0x254/0xc80
> [<0>] ext4_writepages+0x84/0x120
> [<0>] do_writepages+0x7a/0x260
> [<0>] __writeback_single_inode+0x3d/0x300
> [<0>] writeback_sb_inodes+0x1dd/0x470
> [<0>] __writeback_inodes_wb+0x4c/0xe0
> [<0>] wb_writeback+0x18b/0x2d0
> [<0>] wb_workfn+0x2a1/0x400
> [<0>] process_one_work+0x149/0x330
> [<0>] worker_thread+0x2d2/0x410
> [<0>] kthread+0xbe/0xf0
> [<0>] ret_from_fork+0x34/0x50
> [<0>] ret_from_fork_asm+0x1a/0x30
>
> Fixes: 43806c3d5b9b ("raid10: cleanup memleak at raid10_make_request")
> Cc: stable@vger.kernel.org
> Signed-off-by: Josh Hunt <johunt@akamai.com>
> ---
> drivers/md/raid10.c | 40 +++++++++++++++++++++++++++-------------
> 1 file changed, 27 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
> index 9debb20cf129..b05066dde693 100644
> --- a/drivers/md/raid10.c
> +++ b/drivers/md/raid10.c
> @@ -68,6 +68,7 @@
> */
>
> static void allow_barrier(struct r10conf *conf);
> +static void allow_barrier_nowait(struct r10conf *conf);
> static void lower_barrier(struct r10conf *conf);
> static int _enough(struct r10conf *conf, int previous, int ignore);
> static int enough(struct r10conf *conf, int ignore);
> @@ -317,7 +318,7 @@ static void reschedule_retry(struct r10bio *r10_bio)
> * operation and are ready to return a success/failure code to the buffer
> * cache layer.
> */
> -static void raid_end_bio_io(struct r10bio *r10_bio)
> +static void raid_end_bio_io(struct r10bio *r10_bio, bool adjust_pending)
> {
> struct bio *bio = r10_bio->master_bio;
> struct r10conf *conf = r10_bio->mddev->private;
> @@ -332,7 +333,10 @@ static void raid_end_bio_io(struct r10bio *r10_bio)
> * Wake up any possible resync thread that waits for the device
> * to go idle.
> */
> - allow_barrier(conf);
> + if (adjust_pending)
> + allow_barrier(conf);
> + else
> + allow_barrier_nowait(conf);
>
> free_r10bio(r10_bio);
> }
> @@ -414,7 +418,7 @@ static void raid10_end_read_request(struct bio *bio)
> uptodate = 1;
> }
> if (uptodate) {
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> rdev_dec_pending(rdev, conf->mddev);
> } else {
> /*
> @@ -446,7 +450,7 @@ static void one_write_done(struct r10bio *r10_bio)
> if (test_bit(R10BIO_MadeGood, &r10_bio->state))
> reschedule_retry(r10_bio);
> else
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> }
> }
> }
> @@ -1030,13 +1034,23 @@ static bool wait_barrier(struct r10conf *conf, bool nowait)
> return ret;
> }
>
> -static void allow_barrier(struct r10conf *conf)
> +static void __allow_barrier(struct r10conf *conf, bool adjust_pending)
> {
> - if ((atomic_dec_and_test(&conf->nr_pending)) ||
> + if ((adjust_pending && atomic_dec_and_test(&conf->nr_pending)) ||
> (conf->array_freeze_pending))
> wake_up_barrier(conf);
> }
>
> +static void allow_barrier(struct r10conf *conf)
> +{
> + __allow_barrier(conf, true);
> +}
> +
> +static void allow_barrier_nowait(struct r10conf *conf)
> +{
> + __allow_barrier(conf, false);
> +}
> +
> static void freeze_array(struct r10conf *conf, int extra)
> {
> /* stop syncio and normal IO and wait for everything to
> @@ -1184,7 +1198,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
> }
>
> if (!regular_request_wait(mddev, conf, bio, r10_bio->sectors)) {
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, false);
> return;
> }
>
> @@ -1195,7 +1209,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
> mdname(mddev), b,
> (unsigned long long)r10_bio->sector);
> }
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> return;
> }
> if (err_rdev)
> @@ -1240,7 +1254,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
> return;
> err_handle:
> atomic_dec(&rdev->nr_pending);
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> }
>
> static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
> @@ -1372,7 +1386,7 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
>
> sectors = r10_bio->sectors;
> if (!regular_request_wait(mddev, conf, bio, sectors)) {
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, false);
There really is problem, however the analyze seems a bit wrong.
The master_bio is already handled with bio_wouldblock_error(), it's wrong
to call raid_end_bio_io() directly. Looks like this problem can be fixed by
calling free_r10bio() instead.
> return;
> }
>
> @@ -1523,7 +1537,7 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
> }
> }
>
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> }
>
> static void __make_request(struct mddev *mddev, struct bio *bio, int sectors)
> @@ -2952,7 +2966,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
> if (test_bit(R10BIO_WriteError,
> &r10_bio->state))
> close_write(r10_bio);
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> }
> }
> }
> @@ -2987,7 +3001,7 @@ static void raid10d(struct md_thread *thread)
> if (test_bit(R10BIO_WriteError,
> &r10_bio->state))
> close_write(r10_bio);
> - raid_end_bio_io(r10_bio);
> + raid_end_bio_io(r10_bio, true);
> }
> }
>
--
Thansk,
Kuai
^ permalink raw reply
* Re: [PATCH 3/5] md: add fallback to correct bitmap_ops on version mismatch
From: Su Yue @ 2026-02-24 1:52 UTC (permalink / raw)
To: Yu Kuai; +Cc: song, linan122, xni, colyli, linux-raid, linux-kernel
In-Reply-To: <d8598163-f684-4a88-bde7-bef795a3a584@fnnas.com>
On Mon 23 Feb 2026 at 10:22, "Yu Kuai" <yukuai@fnnas.com> wrote:
> Hi,
>
> 在 2026/2/17 16:54, Su Yue 写道:
>> On Sat 14 Feb 2026 at 14:10, Yu Kuai <yukuai@fnnas.com> wrote:
>>
>>> If default bitmap version and on-disk version doesn't match,
>>> and mdadm
>>> is not the latest version to set bitmap_type, set bitmap_ops
>>> based on
>>> the disk version.
>>>
>> Why not just let old version mdadm fails since llbitmap is a
>> new
>> feature.
>
> The original use case is that we found llbitmap array fails to
> assemble in
> some corner cases, and with the respect I'm not quite familiar
> with mdadm
> code, so I think this patch is the best solution for now.
>
Would you please elaborate which corner cases that llbitmap array
fails to assemble
in? Do they happen in mdadm <= 4.5?
> On the other hand, this should also be helpful if we decide to
> make llbitmap
> the default option in the future.
>
But it's so far, right? llbitmap support is still on the way(mdadm
4.6 is not released).
I am not opposed to the patch. It just looks strange to me that
changing kernel code to
let old userspace work with *new* feature.
Maybe the mdadm maintainers have words in another angles?
--
Su
>
>>
>>> Signed-off-by: Yu Kuai <yukuai@fnnas.com>
>>> ---
>>> drivers/md/md.c | 103
>>> +++++++++++++++++++++++++++++++++++++++++++++++-
>>> 1 file changed, 102 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>>> index 59cd303548de..d2607ed5c2e9 100644
>>> --- a/drivers/md/md.c
>>> +++ b/drivers/md/md.c
>>> @@ -6447,15 +6447,116 @@ static void
>>> md_safemode_timeout(struct
>>> timer_list *t)
>>>
>>> static int start_dirty_degraded;
>>>
>>> +/*
>>> + * Read bitmap superblock and return the bitmap_id based on
>>> disk
>>> version.
>>> + * This is used as fallback when default bitmap version and
>>> on-disk
>>> version
>>> + * doesn't match, and mdadm is not the latest version to set
>>> bitmap_type.
>>> + */
>>> +static enum md_submodule_id md_bitmap_get_id_from_sb(struct
>>> mddev
>>> *mddev)
>>> +{
>>> + struct md_rdev *rdev;
>>> + struct page *sb_page;
>>> + bitmap_super_t *sb;
>>> + enum md_submodule_id id = ID_BITMAP_NONE;
>>> + sector_t sector;
>>> + u32 version;
>>> +
>>> + if (!mddev->bitmap_info.offset)
>>> + return ID_BITMAP_NONE;
>>> +
>>> + sb_page = alloc_page(GFP_KERNEL);
>>> + if (!sb_page)
>>> + return ID_BITMAP_NONE;
>>> +
>>>
>> Personally I don't like the way treating error as
>> ID_BITMAP_NONE.
>> When wrong things happen everything looks fine, no error code,
>> no
>> error message.
>
> Ok, sounds reasonable.
>
>>
>>> + sector = mddev->bitmap_info.offset;
>>> +
>>> + rdev_for_each(rdev, mddev) {
>>> + u32 iosize;
>>> +
>>> + if (!test_bit(In_sync, &rdev->flags) ||
>>> + test_bit(Faulty, &rdev->flags) ||
>>> + test_bit(Bitmap_sync, &rdev->flags))
>>> + continue;
>>> +
>>> + iosize = roundup(sizeof(bitmap_super_t),
>>> + bdev_logical_block_size(rdev->bdev));
>>> + if (sync_page_io(rdev, sector, iosize, sb_page,
>>> REQ_OP_READ,
>>> + true))
>>> + goto read_ok;
>>> + }
>>>
>> And here.
>>
>>> + goto out;
>>> +
>>> +read_ok:
>>> + sb = kmap_local_page(sb_page);
>>> + if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
>>> + goto out_unmap;
>>> +
>>> + version = le32_to_cpu(sb->version);
>>> + switch (version) {
>>> + case BITMAP_MAJOR_LO:
>>> + case BITMAP_MAJOR_HI:
>>> + case BITMAP_MAJOR_CLUSTERED:
>>>
>> For BITMAP_MAJOR_CLUSTERED, why not ID_CLUSTER ?
>
> Because there is no optional bitmap_ops for md-cluster, it's
> still
> the old bitmap, and llbitmap does not support md-cluster for
> now.
>
>>
>> --
>> Su
>>> + id = ID_BITMAP;
>>> + break;
>>> + case BITMAP_MAJOR_LOCKLESS:
>>> + id = ID_LLBITMAP;
>>> + break;
>>> + default:
>>> + pr_warn("md: %s: unknown bitmap version %u\n",
>>> + mdname(mddev), version);
>>> + break;
>>> + }
>>> +
>>> +out_unmap:
>>> + kunmap_local(sb);
>>> +out:
>>> + __free_page(sb_page);
>>> + return id;
>>> +}
>>> +
>>> static int md_bitmap_create(struct mddev *mddev)
>>> {
>>> + enum md_submodule_id orig_id = mddev->bitmap_id;
>>> + enum md_submodule_id sb_id;
>>> + int err;
>>> +
>>> if (mddev->bitmap_id == ID_BITMAP_NONE)
>>> return -EINVAL;
>>>
>>> if (!mddev_set_bitmap_ops(mddev))
>>> return -ENOENT;
>>>
>>> - return mddev->bitmap_ops->create(mddev);
>>> + err = mddev->bitmap_ops->create(mddev);
>>> + if (!err)
>>> + return 0;
>>>
>>> +
>>> + /*
>>> + * Create failed, if default bitmap version and on-disk
>>> version
>>> + * doesn't match, and mdadm is not the latest version to
>>> set
>>> + * bitmap_type, set bitmap_ops based on the disk version.
>>> + */
>>> + mddev_clear_bitmap_ops(mddev);
>>> +
>>> + sb_id = md_bitmap_get_id_from_sb(mddev);
>>> + if (sb_id == ID_BITMAP_NONE || sb_id == orig_id)
>>> + return err;
>>> +
>>> + pr_info("md: %s: bitmap version mismatch, switching from
>>> %d to
>>> %d\n",
>>> + mdname(mddev), orig_id, sb_id);
>>> +
>>> + mddev->bitmap_id = sb_id;
>>> + if (!mddev_set_bitmap_ops(mddev)) {
>>> + mddev->bitmap_id = orig_id;
>>> + return -ENOENT;
>>> + }
>>> +
>>> + err = mddev->bitmap_ops->create(mddev);
>>> + if (err) {
>>> + mddev_clear_bitmap_ops(mddev);
>>> + mddev->bitmap_id = orig_id;
>>> + }
>>> +
>>> + return err;
>>> }
>>>
>>> static void md_bitmap_destroy(struct mddev *mddev)
^ permalink raw reply
* [PATCH 16/62] md: Make mddev_suspend() easier to analyze
From: Bart Van Assche @ 2026-02-23 22:00 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Ingo Molnar, Will Deacon, Boqun Feng, Waiman Long, linux-kernel,
Marco Elver, Christoph Hellwig, Steven Rostedt, Nick Desaulniers,
Nathan Chancellor, Kees Cook, Jann Horn, Bart Van Assche,
Song Liu, Yu Kuai, linux-raid
In-Reply-To: <20260223220102.2158611-1-bart.vanassche@linux.dev>
From: Bart Van Assche <bvanassche@acm.org>
Prepare for enabling Clang's thread-safety analysis by moving an
if-statement. No functionality has been changed.
Cc: Song Liu <song@kernel.org>
Cc: Yu Kuai <yukuai@fnnas.com>
Cc: linux-raid@vger.kernel.org
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/md/md.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3ce6f9e9d38e..b0d260d03a7d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -475,12 +475,13 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
*/
lockdep_assert_not_held(&mddev->reconfig_mutex);
- if (interruptible)
+ if (interruptible) {
err = mutex_lock_interruptible(&mddev->suspend_mutex);
- else
+ if (err)
+ return err;
+ } else {
mutex_lock(&mddev->suspend_mutex);
- if (err)
- return err;
+ }
if (mddev->suspended) {
WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
^ permalink raw reply related
* Re: [PATCH 16/62] md: Make mddev_suspend() easier to analyze
From: Paul Menzel @ 2026-02-23 22:01 UTC (permalink / raw)
To: Bart Van Assche; +Cc: Peter Zijlstra, Song Liu, Yu Kuai, linux-raid
In-Reply-To: <20260223214950.2153735-17-bvanassche@acm.org>
Dear Bart,
Thank you for the patch.
Am 23.02.26 um 22:49 schrieb Bart Van Assche:
> Prepare for enabling Clang's thread-safety analysis by moving an
> if-statement. No functionality has been changed.
Why does the if-statement need to be moved? Could you explain it in the
commit message?
> Cc: Song Liu <song@kernel.org>
> Cc: Yu Kuai <yukuai@fnnas.com>
> Cc: linux-raid@vger.kernel.org
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> ---
> drivers/md/md.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 3ce6f9e9d38e..b0d260d03a7d 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -475,12 +475,13 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
> */
> lockdep_assert_not_held(&mddev->reconfig_mutex);
>
> - if (interruptible)
> + if (interruptible) {
> err = mutex_lock_interruptible(&mddev->suspend_mutex);
> - else
> + if (err)
> + return err;
> + } else {
> mutex_lock(&mddev->suspend_mutex);
> - if (err)
> - return err;
> + }
>
> if (mddev->suspended) {
> WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
>
Kind regards,
Paul
^ permalink raw reply
* [PATCH 16/62] md: Make mddev_suspend() easier to analyze
From: Bart Van Assche @ 2026-02-23 21:50 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Ingo Molnar, Will Deacon, Boqun Feng, Waiman Long, linux-kernel,
Marco Elver, Christoph Hellwig, Steven Rostedt, Nick Desaulniers,
Nathan Chancellor, Kees Cook, Jann Horn, Bart Van Assche,
Song Liu, Yu Kuai, linux-raid
In-Reply-To: <20260223215118.2154194-1-bvanassche@acm.org>
Prepare for enabling Clang's thread-safety analysis by moving an
if-statement. No functionality has been changed.
Cc: Song Liu <song@kernel.org>
Cc: Yu Kuai <yukuai@fnnas.com>
Cc: linux-raid@vger.kernel.org
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/md/md.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3ce6f9e9d38e..b0d260d03a7d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -475,12 +475,13 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
*/
lockdep_assert_not_held(&mddev->reconfig_mutex);
- if (interruptible)
+ if (interruptible) {
err = mutex_lock_interruptible(&mddev->suspend_mutex);
- else
+ if (err)
+ return err;
+ } else {
mutex_lock(&mddev->suspend_mutex);
- if (err)
- return err;
+ }
if (mddev->suspended) {
WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
^ permalink raw reply related
* [PATCH 16/62] md: Make mddev_suspend() easier to analyze
From: Bart Van Assche @ 2026-02-23 21:49 UTC (permalink / raw)
To: Peter Zijlstra; +Cc: Bart Van Assche, Song Liu, Yu Kuai, linux-raid
In-Reply-To: <20260223214950.2153735-1-bvanassche@acm.org>
Prepare for enabling Clang's thread-safety analysis by moving an
if-statement. No functionality has been changed.
Cc: Song Liu <song@kernel.org>
Cc: Yu Kuai <yukuai@fnnas.com>
Cc: linux-raid@vger.kernel.org
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/md/md.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3ce6f9e9d38e..b0d260d03a7d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -475,12 +475,13 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
*/
lockdep_assert_not_held(&mddev->reconfig_mutex);
- if (interruptible)
+ if (interruptible) {
err = mutex_lock_interruptible(&mddev->suspend_mutex);
- else
+ if (err)
+ return err;
+ } else {
mutex_lock(&mddev->suspend_mutex);
- if (err)
- return err;
+ }
if (mddev->suspended) {
WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
^ permalink raw reply related
* Re: [PATCH] md/raid5: set chunk_sectors to enable full stripe I/O splitting
From: Christoph Hellwig @ 2026-02-23 14:05 UTC (permalink / raw)
To: Yu Kuai; +Cc: hch, song, linux-raid, linux-kernel, linan122
In-Reply-To: <20260223035834.3132498-1-yukuai@fnnas.com>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH] md/raid5: set chunk_sectors to enable full stripe I/O splitting
From: Paul Menzel @ 2026-02-23 7:26 UTC (permalink / raw)
To: Yu Kuai; +Cc: hch, song, linux-raid, linux-kernel, linan122
In-Reply-To: <20260223035834.3132498-1-yukuai@fnnas.com>
Dear Kuai,
Thank you for your patch.
Am 23.02.26 um 04:58 schrieb Yu Kuai:
> Set chunk_sectors to the full stripe width (io_opt) so that the block
> layer splits I/O at full stripe boundaries. This ensures that large
> writes are aligned to full stripes, avoiding the read-modify-write
> overhead that occurs with partial stripe writes in RAID-5/6.
>
> When chunk_sectors is set, the block layer's bio splitting logic in
> get_max_io_size() uses blk_boundary_sectors_left() to limit I/O size
> to the boundary. This naturally aligns split bios to full stripe
> boundaries, enabling more efficient full stripe writes.
>
> Test results with 24-disk RAID5 (chunk_size=64k):
> dd if=/dev/zero of=/dev/md0 bs=10M oflag=direct
> Before: 461 MB/s
> After: 520 MB/s (+12.8%)
Sweet.
> Suggested-by: Christoph Hellwig <hch@infradead.org>
> Signed-off-by: Yu Kuai <yukuai@fnnas.com>
Once committed, should this be backported to the longterm and stable series?
> ---
> drivers/md/raid5.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 8854e024f311..810d936560d1 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -7783,6 +7783,7 @@ static int raid5_set_limits(struct mddev *mddev)
> lim.logical_block_size = mddev->logical_block_size;
> lim.io_min = mddev->chunk_sectors << 9;
> lim.io_opt = lim.io_min * (conf->raid_disks - conf->max_degraded);
> + lim.chunk_sectors = lim.io_opt >> 9;
> lim.features |= BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE;
> lim.discard_granularity = stripe;
> lim.max_write_zeroes_sectors = 0;
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Kind regards,
Paul
^ permalink raw reply
* [PATCH] md/raid5: set chunk_sectors to enable full stripe I/O splitting
From: Yu Kuai @ 2026-02-23 3:58 UTC (permalink / raw)
To: hch, song; +Cc: linux-raid, linux-kernel, yukuai, linan122
Set chunk_sectors to the full stripe width (io_opt) so that the block
layer splits I/O at full stripe boundaries. This ensures that large
writes are aligned to full stripes, avoiding the read-modify-write
overhead that occurs with partial stripe writes in RAID-5/6.
When chunk_sectors is set, the block layer's bio splitting logic in
get_max_io_size() uses blk_boundary_sectors_left() to limit I/O size
to the boundary. This naturally aligns split bios to full stripe
boundaries, enabling more efficient full stripe writes.
Test results with 24-disk RAID5 (chunk_size=64k):
dd if=/dev/zero of=/dev/md0 bs=10M oflag=direct
Before: 461 MB/s
After: 520 MB/s (+12.8%)
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
drivers/md/raid5.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 8854e024f311..810d936560d1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7783,6 +7783,7 @@ static int raid5_set_limits(struct mddev *mddev)
lim.logical_block_size = mddev->logical_block_size;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * (conf->raid_disks - conf->max_degraded);
+ lim.chunk_sectors = lim.io_opt >> 9;
lim.features |= BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE;
lim.discard_granularity = stripe;
lim.max_write_zeroes_sectors = 0;
--
2.51.0
^ permalink raw reply related
* [PATCH v2 5/5] md/md-llbitmap: optimize initial sync with write_zeroes_unmap support
From: Yu Kuai @ 2026-02-23 2:40 UTC (permalink / raw)
To: song; +Cc: linan122, xni, colyli, linux-raid, linux-kernel
In-Reply-To: <20260223024038.3084853-1-yukuai@fnnas.com>
For RAID-456 arrays with llbitmap, if all underlying disks support
write_zeroes with unmap, issue write_zeroes to zero all disk data
regions and initialize the bitmap to BitCleanUnwritten instead of
BitUnwritten.
This optimization skips the initial XOR parity building because:
1. write_zeroes with unmap guarantees zeroed reads after the operation
2. For RAID-456, when all data is zero, parity is automatically
consistent (0 XOR 0 XOR ... = 0)
3. BitCleanUnwritten indicates parity is valid but no user data
has been written
The implementation adds two helper functions:
- llbitmap_all_disks_support_wzeroes_unmap(): Checks if all active
disks support write_zeroes with unmap
- llbitmap_zero_all_disks(): Issues blkdev_issue_zeroout() to each
rdev's data region to zero all disks
The zeroing and bitmap state setting happens in llbitmap_init_state()
during bitmap initialization. If any disk fails to zero, we fall back
to BitUnwritten and normal lazy recovery.
This significantly reduces array initialization time for RAID-456
arrays built on modern NVMe SSDs or other devices that support
write_zeroes with unmap.
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
drivers/md/md-llbitmap.c | 62 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index 461050b2771b..48bc6a639edd 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -654,13 +654,73 @@ static int llbitmap_cache_pages(struct llbitmap *llbitmap)
return 0;
}
+/*
+ * Check if all underlying disks support write_zeroes with unmap.
+ */
+static bool llbitmap_all_disks_support_wzeroes_unmap(struct llbitmap *llbitmap)
+{
+ struct mddev *mddev = llbitmap->mddev;
+ struct md_rdev *rdev;
+
+ rdev_for_each(rdev, mddev) {
+ if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags))
+ continue;
+
+ if (bdev_write_zeroes_unmap_sectors(rdev->bdev) == 0)
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Issue write_zeroes to all underlying disks to zero their data regions.
+ * This ensures parity consistency for RAID-456 (0 XOR 0 = 0).
+ * Returns true if all disks were successfully zeroed.
+ */
+static bool llbitmap_zero_all_disks(struct llbitmap *llbitmap)
+{
+ struct mddev *mddev = llbitmap->mddev;
+ struct md_rdev *rdev;
+ sector_t dev_sectors = mddev->dev_sectors;
+ int ret;
+
+ rdev_for_each(rdev, mddev) {
+ if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags))
+ continue;
+
+ ret = blkdev_issue_zeroout(rdev->bdev,
+ rdev->data_offset,
+ dev_sectors,
+ GFP_KERNEL, 0);
+ if (ret) {
+ pr_warn("md/llbitmap: failed to zero disk %pg: %d\n",
+ rdev->bdev, ret);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void llbitmap_init_state(struct llbitmap *llbitmap)
{
+ struct mddev *mddev = llbitmap->mddev;
enum llbitmap_state state = BitUnwritten;
unsigned long i;
- if (test_and_clear_bit(BITMAP_CLEAN, &llbitmap->flags))
+ if (test_and_clear_bit(BITMAP_CLEAN, &llbitmap->flags)) {
state = BitClean;
+ } else if (raid_is_456(mddev) &&
+ llbitmap_all_disks_support_wzeroes_unmap(llbitmap)) {
+ /*
+ * All disks support write_zeroes with unmap. Zero all disks
+ * to ensure parity consistency, then set BitCleanUnwritten
+ * to skip initial sync.
+ */
+ if (llbitmap_zero_all_disks(llbitmap))
+ state = BitCleanUnwritten;
+ }
for (i = 0; i < llbitmap->chunks; i++)
llbitmap_write(llbitmap, state, i);
--
2.51.0
^ permalink raw reply related
* [PATCH v2 4/5] md/md-llbitmap: add CleanUnwritten state for RAID-5 proactive parity building
From: Yu Kuai @ 2026-02-23 2:40 UTC (permalink / raw)
To: song; +Cc: linan122, xni, colyli, linux-raid, linux-kernel
In-Reply-To: <20260223024038.3084853-1-yukuai@fnnas.com>
Add new states to the llbitmap state machine to support proactive XOR
parity building for RAID-5 arrays. This allows users to pre-build parity
data for unwritten regions before any user data is written.
New states added:
- BitNeedSyncUnwritten: Transitional state when proactive sync is triggered
via sysfs on Unwritten regions.
- BitSyncingUnwritten: Proactive sync in progress for unwritten region.
- BitCleanUnwritten: XOR parity has been pre-built, but no user data
written yet. When user writes to this region, it transitions to BitDirty.
New actions added:
- BitmapActionProactiveSync: Trigger for proactive XOR parity building.
- BitmapActionClearUnwritten: Convert CleanUnwritten/NeedSyncUnwritten/
SyncingUnwritten states back to Unwritten before recovery starts.
State flows:
- Current (lazy): Unwritten -> (write) -> NeedSync -> (sync) -> Dirty -> Clean
- New (proactive): Unwritten -> (sysfs) -> NeedSyncUnwritten -> (sync) -> CleanUnwritten
- On write to CleanUnwritten: CleanUnwritten -> (write) -> Dirty -> Clean
- On disk replacement: CleanUnwritten regions are converted to Unwritten
before recovery starts, so recovery only rebuilds regions with user data
A new sysfs interface is added at /sys/block/mdX/md/llbitmap/proactive_sync
(write-only) to trigger proactive sync. This only works for RAID-456 arrays.
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
drivers/md/md-llbitmap.c | 140 +++++++++++++++++++++++++++++++++++----
drivers/md/md.c | 6 +-
2 files changed, 132 insertions(+), 14 deletions(-)
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index 5f9e7004e3e3..461050b2771b 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -208,6 +208,20 @@ enum llbitmap_state {
BitNeedSync,
/* data is synchronizing */
BitSyncing,
+ /*
+ * Proactive sync requested for unwritten region (raid456 only).
+ * Triggered via sysfs when user wants to pre-build XOR parity
+ * for regions that have never been written.
+ */
+ BitNeedSyncUnwritten,
+ /* Proactive sync in progress for unwritten region */
+ BitSyncingUnwritten,
+ /*
+ * XOR parity has been pre-built for a region that has never had
+ * user data written. When user writes to this region, it transitions
+ * to BitDirty.
+ */
+ BitCleanUnwritten,
BitStateCount,
BitNone = 0xff,
};
@@ -232,6 +246,12 @@ enum llbitmap_action {
* BitNeedSync.
*/
BitmapActionStale,
+ /*
+ * Proactive sync trigger for raid456 - builds XOR parity for
+ * Unwritten regions without requiring user data write first.
+ */
+ BitmapActionProactiveSync,
+ BitmapActionClearUnwritten,
BitmapActionCount,
/* Init state is BitUnwritten */
BitmapActionInit,
@@ -304,6 +324,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
[BitmapActionDaemon] = BitNone,
[BitmapActionDiscard] = BitNone,
[BitmapActionStale] = BitNone,
+ [BitmapActionProactiveSync] = BitNeedSyncUnwritten,
+ [BitmapActionClearUnwritten] = BitNone,
},
[BitClean] = {
[BitmapActionStartwrite] = BitDirty,
@@ -314,6 +336,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
[BitmapActionDaemon] = BitNone,
[BitmapActionDiscard] = BitUnwritten,
[BitmapActionStale] = BitNeedSync,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitNone,
},
[BitDirty] = {
[BitmapActionStartwrite] = BitNone,
@@ -324,6 +348,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
[BitmapActionDaemon] = BitClean,
[BitmapActionDiscard] = BitUnwritten,
[BitmapActionStale] = BitNeedSync,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitNone,
},
[BitNeedSync] = {
[BitmapActionStartwrite] = BitNone,
@@ -334,6 +360,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
[BitmapActionDaemon] = BitNone,
[BitmapActionDiscard] = BitUnwritten,
[BitmapActionStale] = BitNone,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitNone,
},
[BitSyncing] = {
[BitmapActionStartwrite] = BitNone,
@@ -344,6 +372,44 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
[BitmapActionDaemon] = BitNone,
[BitmapActionDiscard] = BitUnwritten,
[BitmapActionStale] = BitNeedSync,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitNone,
+ },
+ [BitNeedSyncUnwritten] = {
+ [BitmapActionStartwrite] = BitNeedSync,
+ [BitmapActionStartsync] = BitSyncingUnwritten,
+ [BitmapActionEndsync] = BitNone,
+ [BitmapActionAbortsync] = BitUnwritten,
+ [BitmapActionReload] = BitUnwritten,
+ [BitmapActionDaemon] = BitNone,
+ [BitmapActionDiscard] = BitUnwritten,
+ [BitmapActionStale] = BitUnwritten,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitUnwritten,
+ },
+ [BitSyncingUnwritten] = {
+ [BitmapActionStartwrite] = BitSyncing,
+ [BitmapActionStartsync] = BitSyncingUnwritten,
+ [BitmapActionEndsync] = BitCleanUnwritten,
+ [BitmapActionAbortsync] = BitUnwritten,
+ [BitmapActionReload] = BitUnwritten,
+ [BitmapActionDaemon] = BitNone,
+ [BitmapActionDiscard] = BitUnwritten,
+ [BitmapActionStale] = BitUnwritten,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitUnwritten,
+ },
+ [BitCleanUnwritten] = {
+ [BitmapActionStartwrite] = BitDirty,
+ [BitmapActionStartsync] = BitNone,
+ [BitmapActionEndsync] = BitNone,
+ [BitmapActionAbortsync] = BitNone,
+ [BitmapActionReload] = BitNone,
+ [BitmapActionDaemon] = BitNone,
+ [BitmapActionDiscard] = BitUnwritten,
+ [BitmapActionStale] = BitUnwritten,
+ [BitmapActionProactiveSync] = BitNone,
+ [BitmapActionClearUnwritten] = BitUnwritten,
},
};
@@ -376,6 +442,7 @@ static void llbitmap_infect_dirty_bits(struct llbitmap *llbitmap,
pctl->state[pos] = level_456 ? BitNeedSync : BitDirty;
break;
case BitClean:
+ case BitCleanUnwritten:
pctl->state[pos] = BitDirty;
break;
}
@@ -383,7 +450,7 @@ static void llbitmap_infect_dirty_bits(struct llbitmap *llbitmap,
}
static void llbitmap_set_page_dirty(struct llbitmap *llbitmap, int idx,
- int offset)
+ int offset, bool infect)
{
struct llbitmap_page_ctl *pctl = llbitmap->pctl[idx];
unsigned int io_size = llbitmap->io_size;
@@ -398,7 +465,7 @@ static void llbitmap_set_page_dirty(struct llbitmap *llbitmap, int idx,
* resync all the dirty bits, hence skip infect new dirty bits to
* prevent resync unnecessary data.
*/
- if (llbitmap->mddev->degraded) {
+ if (llbitmap->mddev->degraded || !infect) {
set_bit(block, pctl->dirty);
return;
}
@@ -438,7 +505,9 @@ static void llbitmap_write(struct llbitmap *llbitmap, enum llbitmap_state state,
llbitmap->pctl[idx]->state[bit] = state;
if (state == BitDirty || state == BitNeedSync)
- llbitmap_set_page_dirty(llbitmap, idx, bit);
+ llbitmap_set_page_dirty(llbitmap, idx, bit, true);
+ else if (state == BitNeedSyncUnwritten)
+ llbitmap_set_page_dirty(llbitmap, idx, bit, false);
}
static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx)
@@ -627,11 +696,10 @@ static enum llbitmap_state llbitmap_state_machine(struct llbitmap *llbitmap,
goto write_bitmap;
}
- if (c == BitNeedSync)
+ if (c == BitNeedSync || c == BitNeedSyncUnwritten)
need_resync = !mddev->degraded;
state = state_machine[c][action];
-
write_bitmap:
if (unlikely(mddev->degraded)) {
/* For degraded array, mark new data as need sync. */
@@ -658,8 +726,7 @@ static enum llbitmap_state llbitmap_state_machine(struct llbitmap *llbitmap,
}
llbitmap_write(llbitmap, state, start);
-
- if (state == BitNeedSync)
+ if (state == BitNeedSync || state == BitNeedSyncUnwritten)
need_resync = !mddev->degraded;
else if (state == BitDirty &&
!timer_pending(&llbitmap->pending_timer))
@@ -1229,7 +1296,7 @@ static bool llbitmap_blocks_synced(struct mddev *mddev, sector_t offset)
unsigned long p = offset >> llbitmap->chunkshift;
enum llbitmap_state c = llbitmap_read(llbitmap, p);
- return c == BitClean || c == BitDirty;
+ return c == BitClean || c == BitDirty || c == BitCleanUnwritten;
}
static sector_t llbitmap_skip_sync_blocks(struct mddev *mddev, sector_t offset)
@@ -1243,6 +1310,10 @@ static sector_t llbitmap_skip_sync_blocks(struct mddev *mddev, sector_t offset)
if (c == BitUnwritten)
return blocks;
+ /* Skip CleanUnwritten - no user data, will be reset after recovery */
+ if (c == BitCleanUnwritten)
+ return blocks;
+
/* For degraded array, don't skip */
if (mddev->degraded)
return 0;
@@ -1261,14 +1332,25 @@ static bool llbitmap_start_sync(struct mddev *mddev, sector_t offset,
{
struct llbitmap *llbitmap = mddev->bitmap;
unsigned long p = offset >> llbitmap->chunkshift;
+ enum llbitmap_state state;
+
+ /*
+ * Before recovery starts, convert CleanUnwritten to Unwritten.
+ * This ensures the new disk won't have stale parity data.
+ */
+ if (offset == 0 && test_bit(MD_RECOVERY_RECOVER, &mddev->recovery) &&
+ !test_bit(MD_RECOVERY_LAZY_RECOVER, &mddev->recovery))
+ llbitmap_state_machine(llbitmap, 0, llbitmap->chunks - 1,
+ BitmapActionClearUnwritten);
+
/*
* Handle one bit at a time, this is much simpler. And it doesn't matter
* if md_do_sync() loop more times.
*/
*blocks = llbitmap->chunksize - (offset & (llbitmap->chunksize - 1));
- return llbitmap_state_machine(llbitmap, p, p,
- BitmapActionStartsync) == BitSyncing;
+ state = llbitmap_state_machine(llbitmap, p, p, BitmapActionStartsync);
+ return state == BitSyncing || state == BitSyncingUnwritten;
}
/* Something is wrong, sync_thread stop at @offset */
@@ -1474,9 +1556,15 @@ static ssize_t bits_show(struct mddev *mddev, char *page)
}
mutex_unlock(&mddev->bitmap_info.mutex);
- return sprintf(page, "unwritten %d\nclean %d\ndirty %d\nneed sync %d\nsyncing %d\n",
+ return sprintf(page,
+ "unwritten %d\nclean %d\ndirty %d\n"
+ "need sync %d\nsyncing %d\n"
+ "need sync unwritten %d\nsyncing unwritten %d\n"
+ "clean unwritten %d\n",
bits[BitUnwritten], bits[BitClean], bits[BitDirty],
- bits[BitNeedSync], bits[BitSyncing]);
+ bits[BitNeedSync], bits[BitSyncing],
+ bits[BitNeedSyncUnwritten], bits[BitSyncingUnwritten],
+ bits[BitCleanUnwritten]);
}
static struct md_sysfs_entry llbitmap_bits = __ATTR_RO(bits);
@@ -1549,11 +1637,39 @@ barrier_idle_store(struct mddev *mddev, const char *buf, size_t len)
static struct md_sysfs_entry llbitmap_barrier_idle = __ATTR_RW(barrier_idle);
+static ssize_t
+proactive_sync_store(struct mddev *mddev, const char *buf, size_t len)
+{
+ struct llbitmap *llbitmap;
+
+ /* Only for RAID-456 */
+ if (!raid_is_456(mddev))
+ return -EINVAL;
+
+ mutex_lock(&mddev->bitmap_info.mutex);
+ llbitmap = mddev->bitmap;
+ if (!llbitmap || !llbitmap->pctl) {
+ mutex_unlock(&mddev->bitmap_info.mutex);
+ return -ENODEV;
+ }
+
+ /* Trigger proactive sync on all Unwritten regions */
+ llbitmap_state_machine(llbitmap, 0, llbitmap->chunks - 1,
+ BitmapActionProactiveSync);
+
+ mutex_unlock(&mddev->bitmap_info.mutex);
+ return len;
+}
+
+static struct md_sysfs_entry llbitmap_proactive_sync =
+ __ATTR(proactive_sync, 0200, NULL, proactive_sync_store);
+
static struct attribute *md_llbitmap_attrs[] = {
&llbitmap_bits.attr,
&llbitmap_metadata.attr,
&llbitmap_daemon_sleep.attr,
&llbitmap_barrier_idle.attr,
+ &llbitmap_proactive_sync.attr,
NULL
};
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 245785ad0ffd..b6543d81ac96 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9878,8 +9878,10 @@ void md_do_sync(struct md_thread *thread)
* Give other IO more of a chance.
* The faster the devices, the less we wait.
*/
- wait_event(mddev->recovery_wait,
- !atomic_read(&mddev->recovery_active));
+ wait_event_timeout(
+ mddev->recovery_wait,
+ !atomic_read(&mddev->recovery_active),
+ HZ);
}
}
}
--
2.51.0
^ permalink raw reply related
* [PATCH v2 3/5] md: add fallback to correct bitmap_ops on version mismatch
From: Yu Kuai @ 2026-02-23 2:40 UTC (permalink / raw)
To: song; +Cc: linan122, xni, colyli, linux-raid, linux-kernel
In-Reply-To: <20260223024038.3084853-1-yukuai@fnnas.com>
If default bitmap version and on-disk version doesn't match, and mdadm
is not the latest version to set bitmap_type, set bitmap_ops based on
the disk version.
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
drivers/md/md.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 72a1c7267851..245785ad0ffd 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6447,15 +6447,124 @@ static void md_safemode_timeout(struct timer_list *t)
static int start_dirty_degraded;
+/*
+ * Read bitmap superblock and return the bitmap_id based on disk version.
+ * This is used as fallback when default bitmap version and on-disk version
+ * doesn't match, and mdadm is not the latest version to set bitmap_type.
+ */
+static enum md_submodule_id md_bitmap_get_id_from_sb(struct mddev *mddev)
+{
+ struct md_rdev *rdev;
+ struct page *sb_page;
+ bitmap_super_t *sb;
+ enum md_submodule_id id = ID_BITMAP_NONE;
+ sector_t sector;
+ u32 version;
+
+ if (!mddev->bitmap_info.offset)
+ return ID_BITMAP_NONE;
+
+ sb_page = alloc_page(GFP_KERNEL);
+ if (!sb_page) {
+ pr_warn("md: %s: failed to allocate memory for bitmap\n",
+ mdname(mddev));
+ return ID_BITMAP_NONE;
+ }
+
+ sector = mddev->bitmap_info.offset;
+
+ rdev_for_each(rdev, mddev) {
+ u32 iosize;
+
+ if (!test_bit(In_sync, &rdev->flags) ||
+ test_bit(Faulty, &rdev->flags) ||
+ test_bit(Bitmap_sync, &rdev->flags))
+ continue;
+
+ iosize = roundup(sizeof(bitmap_super_t),
+ bdev_logical_block_size(rdev->bdev));
+ if (sync_page_io(rdev, sector, iosize, sb_page, REQ_OP_READ,
+ true))
+ goto read_ok;
+ }
+ pr_warn("md: %s: failed to read bitmap from any device\n",
+ mdname(mddev));
+ goto out;
+
+read_ok:
+ sb = kmap_local_page(sb_page);
+ if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) {
+ pr_warn("md: %s: invalid bitmap magic 0x%x\n",
+ mdname(mddev), le32_to_cpu(sb->magic));
+ goto out_unmap;
+ }
+
+ version = le32_to_cpu(sb->version);
+ switch (version) {
+ case BITMAP_MAJOR_LO:
+ case BITMAP_MAJOR_HI:
+ case BITMAP_MAJOR_CLUSTERED:
+ id = ID_BITMAP;
+ break;
+ case BITMAP_MAJOR_LOCKLESS:
+ id = ID_LLBITMAP;
+ break;
+ default:
+ pr_warn("md: %s: unknown bitmap version %u\n",
+ mdname(mddev), version);
+ break;
+ }
+
+out_unmap:
+ kunmap_local(sb);
+out:
+ __free_page(sb_page);
+ return id;
+}
+
static int md_bitmap_create(struct mddev *mddev)
{
+ enum md_submodule_id orig_id = mddev->bitmap_id;
+ enum md_submodule_id sb_id;
+ int err;
+
if (mddev->bitmap_id == ID_BITMAP_NONE)
return -EINVAL;
if (!mddev_set_bitmap_ops(mddev))
return -ENOENT;
- return mddev->bitmap_ops->create(mddev);
+ err = mddev->bitmap_ops->create(mddev);
+ if (!err)
+ return 0;
+
+ /*
+ * Create failed, if default bitmap version and on-disk version
+ * doesn't match, and mdadm is not the latest version to set
+ * bitmap_type, set bitmap_ops based on the disk version.
+ */
+ mddev_clear_bitmap_ops(mddev);
+
+ sb_id = md_bitmap_get_id_from_sb(mddev);
+ if (sb_id == ID_BITMAP_NONE || sb_id == orig_id)
+ return err;
+
+ pr_info("md: %s: bitmap version mismatch, switching from %d to %d\n",
+ mdname(mddev), orig_id, sb_id);
+
+ mddev->bitmap_id = sb_id;
+ if (!mddev_set_bitmap_ops(mddev)) {
+ mddev->bitmap_id = orig_id;
+ return -ENOENT;
+ }
+
+ err = mddev->bitmap_ops->create(mddev);
+ if (err) {
+ mddev_clear_bitmap_ops(mddev);
+ mddev->bitmap_id = orig_id;
+ }
+
+ return err;
}
static void md_bitmap_destroy(struct mddev *mddev)
--
2.51.0
^ permalink raw reply related
* [PATCH v2 2/5] md/md-llbitmap: raise barrier before state machine transition
From: Yu Kuai @ 2026-02-23 2:40 UTC (permalink / raw)
To: song; +Cc: linan122, xni, colyli, linux-raid, linux-kernel
In-Reply-To: <20260223024038.3084853-1-yukuai@fnnas.com>
Move the barrier raise operation before calling llbitmap_state_machine()
in both llbitmap_start_write() and llbitmap_start_discard(). This
ensures the barrier is in place before any state transitions occur,
preventing potential race conditions where the state machine could
complete before the barrier is properly raised.
Cc: stable@vger.kernel.org
Fixes: 5ab829f1971d ("md/md-llbitmap: introduce new lockless bitmap")
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
drivers/md/md-llbitmap.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index 30d7e36b22c4..5f9e7004e3e3 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset,
int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT;
int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT;
- llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite);
-
while (page_start <= page_end) {
llbitmap_raise_barrier(llbitmap, page_start);
page_start++;
}
+
+ llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite);
}
static void llbitmap_end_write(struct mddev *mddev, sector_t offset,
@@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset,
int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT;
int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT;
- llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard);
-
while (page_start <= page_end) {
llbitmap_raise_barrier(llbitmap, page_start);
page_start++;
}
+
+ llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard);
}
static void llbitmap_end_discard(struct mddev *mddev, sector_t offset,
--
2.51.0
^ permalink raw reply related
* [PATCH v2 1/5] md/md-llbitmap: skip reading rdevs that are not in_sync
From: Yu Kuai @ 2026-02-23 2:40 UTC (permalink / raw)
To: song; +Cc: linan122, xni, colyli, linux-raid, linux-kernel
In-Reply-To: <20260223024038.3084853-1-yukuai@fnnas.com>
When reading bitmap pages from member disks, the code iterates through
all rdevs and attempts to read from the first available one. However,
it only checks for raid_disk assignment and Faulty flag, missing the
In_sync flag check.
This can cause bitmap data to be read from spare disks that are still
being rebuilt and don't have valid bitmap information yet. Reading
stale or uninitialized bitmap data from such disks can lead to
incorrect dirty bit tracking, potentially causing data corruption
during recovery or normal operation.
Add the In_sync flag check to ensure bitmap pages are only read from
fully synchronized member disks that have valid bitmap data.
Cc: stable@vger.kernel.org
Fixes: 5ab829f1971d ("md/md-llbitmap: introduce new lockless bitmap")
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
drivers/md/md-llbitmap.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index cd713a7dc270..30d7e36b22c4 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx)
rdev_for_each(rdev, mddev) {
sector_t sector;
- if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags))
+ if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) ||
+ !test_bit(In_sync, &rdev->flags))
continue;
sector = mddev->bitmap_info.offset +
--
2.51.0
^ permalink raw reply related
* [PATCH v2 0/5] md/md-llbitmap: fixes and proactive parity building support
From: Yu Kuai @ 2026-02-23 2:40 UTC (permalink / raw)
To: song; +Cc: linan122, xni, colyli, linux-raid, linux-kernel
Changes in v2:
- add error message in error path in patch 3;
This series contains fixes and enhancements for the md-llbitmap (lockless
bitmap) implementation.
Patches 1-2 are bug fixes:
- Patch 1 fixes bitmap data being read from spare disks that are not yet
in sync, which could lead to incorrect dirty bit tracking.
- Patch 2 fixes a race condition where the state machine could transition
before the barrier is properly raised.
Patch 3 improves compatibility with older mdadm versions by detecting
on-disk bitmap version and falling back to the correct bitmap_ops when
there's a version mismatch.
Patch 4 adds support for proactive XOR parity building in RAID-456 arrays.
This allows users to pre-build parity for unwritten regions via sysfs
before any user data is written, which can improve write performance for
workloads that will eventually use all storage. New states (CleanUnwritten,
NeedSyncUnwritten, SyncingUnwritten) are added to track these regions
separately from normal dirty/syncing states.
Patch 5 optimizes initial array sync for RAID-456 arrays on devices that
support write_zeroes with unmap. By zeroing all disks upfront, parity is
automatically consistent (0 XOR 0 = 0), allowing the bitmap to be
initialized to BitCleanUnwritten and skipping the initial sync entirely.
This significantly reduces array initialization time on modern NVMe SSDs.
Yu Kuai (5):
md/md-llbitmap: skip reading rdevs that are not in_sync
md/md-llbitmap: raise barrier before state machine transition
md: add fallback to correct bitmap_ops on version mismatch
md/md-llbitmap: add CleanUnwritten state for RAID-5 proactive parity
building
md/md-llbitmap: optimize initial sync with write_zeroes_unmap support
drivers/md/md-llbitmap.c | 213 +++++++++++++++++++++++++++++++++++----
drivers/md/md.c | 117 ++++++++++++++++++++-
2 files changed, 309 insertions(+), 21 deletions(-)
--
2.51.0
^ permalink raw reply
* Re: [PATCH 3/5] md: add fallback to correct bitmap_ops on version mismatch
From: Yu Kuai @ 2026-02-23 2:22 UTC (permalink / raw)
To: Su Yue; +Cc: song, linan122, xni, colyli, linux-raid, linux-kernel, yukuai
In-Reply-To: <h5rf7nsv.fsf@damenly.org>
Hi,
在 2026/2/17 16:54, Su Yue 写道:
> On Sat 14 Feb 2026 at 14:10, Yu Kuai <yukuai@fnnas.com> wrote:
>
>> If default bitmap version and on-disk version doesn't match, and mdadm
>> is not the latest version to set bitmap_type, set bitmap_ops based on
>> the disk version.
>>
> Why not just let old version mdadm fails since llbitmap is a new
> feature.
The original use case is that we found llbitmap array fails to assemble in
some corner cases, and with the respect I'm not quite familiar with mdadm
code, so I think this patch is the best solution for now.
On the other hand, this should also be helpful if we decide to make llbitmap
the default option in the future.
>
>> Signed-off-by: Yu Kuai <yukuai@fnnas.com>
>> ---
>> drivers/md/md.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 102 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>> index 59cd303548de..d2607ed5c2e9 100644
>> --- a/drivers/md/md.c
>> +++ b/drivers/md/md.c
>> @@ -6447,15 +6447,116 @@ static void md_safemode_timeout(struct
>> timer_list *t)
>>
>> static int start_dirty_degraded;
>>
>> +/*
>> + * Read bitmap superblock and return the bitmap_id based on disk
>> version.
>> + * This is used as fallback when default bitmap version and on-disk
>> version
>> + * doesn't match, and mdadm is not the latest version to set
>> bitmap_type.
>> + */
>> +static enum md_submodule_id md_bitmap_get_id_from_sb(struct mddev
>> *mddev)
>> +{
>> + struct md_rdev *rdev;
>> + struct page *sb_page;
>> + bitmap_super_t *sb;
>> + enum md_submodule_id id = ID_BITMAP_NONE;
>> + sector_t sector;
>> + u32 version;
>> +
>> + if (!mddev->bitmap_info.offset)
>> + return ID_BITMAP_NONE;
>> +
>> + sb_page = alloc_page(GFP_KERNEL);
>> + if (!sb_page)
>> + return ID_BITMAP_NONE;
>> +
>>
> Personally I don't like the way treating error as ID_BITMAP_NONE.
> When wrong things happen everything looks fine, no error code, no
> error message.
Ok, sounds reasonable.
>
>> + sector = mddev->bitmap_info.offset;
>> +
>> + rdev_for_each(rdev, mddev) {
>> + u32 iosize;
>> +
>> + if (!test_bit(In_sync, &rdev->flags) ||
>> + test_bit(Faulty, &rdev->flags) ||
>> + test_bit(Bitmap_sync, &rdev->flags))
>> + continue;
>> +
>> + iosize = roundup(sizeof(bitmap_super_t),
>> + bdev_logical_block_size(rdev->bdev));
>> + if (sync_page_io(rdev, sector, iosize, sb_page, REQ_OP_READ,
>> + true))
>> + goto read_ok;
>> + }
>>
> And here.
>
>> + goto out;
>> +
>> +read_ok:
>> + sb = kmap_local_page(sb_page);
>> + if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
>> + goto out_unmap;
>> +
>> + version = le32_to_cpu(sb->version);
>> + switch (version) {
>> + case BITMAP_MAJOR_LO:
>> + case BITMAP_MAJOR_HI:
>> + case BITMAP_MAJOR_CLUSTERED:
>>
> For BITMAP_MAJOR_CLUSTERED, why not ID_CLUSTER ?
Because there is no optional bitmap_ops for md-cluster, it's still
the old bitmap, and llbitmap does not support md-cluster for now.
>
> --
> Su
>> + id = ID_BITMAP;
>> + break;
>> + case BITMAP_MAJOR_LOCKLESS:
>> + id = ID_LLBITMAP;
>> + break;
>> + default:
>> + pr_warn("md: %s: unknown bitmap version %u\n",
>> + mdname(mddev), version);
>> + break;
>> + }
>> +
>> +out_unmap:
>> + kunmap_local(sb);
>> +out:
>> + __free_page(sb_page);
>> + return id;
>> +}
>> +
>> static int md_bitmap_create(struct mddev *mddev)
>> {
>> + enum md_submodule_id orig_id = mddev->bitmap_id;
>> + enum md_submodule_id sb_id;
>> + int err;
>> +
>> if (mddev->bitmap_id == ID_BITMAP_NONE)
>> return -EINVAL;
>>
>> if (!mddev_set_bitmap_ops(mddev))
>> return -ENOENT;
>>
>> - return mddev->bitmap_ops->create(mddev);
>> + err = mddev->bitmap_ops->create(mddev);
>> + if (!err)
>> + return 0;
>>
>> +
>> + /*
>> + * Create failed, if default bitmap version and on-disk version
>> + * doesn't match, and mdadm is not the latest version to set
>> + * bitmap_type, set bitmap_ops based on the disk version.
>> + */
>> + mddev_clear_bitmap_ops(mddev);
>> +
>> + sb_id = md_bitmap_get_id_from_sb(mddev);
>> + if (sb_id == ID_BITMAP_NONE || sb_id == orig_id)
>> + return err;
>> +
>> + pr_info("md: %s: bitmap version mismatch, switching from %d to
>> %d\n",
>> + mdname(mddev), orig_id, sb_id);
>> +
>> + mddev->bitmap_id = sb_id;
>> + if (!mddev_set_bitmap_ops(mddev)) {
>> + mddev->bitmap_id = orig_id;
>> + return -ENOENT;
>> + }
>> +
>> + err = mddev->bitmap_ops->create(mddev);
>> + if (err) {
>> + mddev_clear_bitmap_ops(mddev);
>> + mddev->bitmap_id = orig_id;
>> + }
>> +
>> + return err;
>> }
>>
>> static void md_bitmap_destroy(struct mddev *mddev)
--
Thansk,
Kuai
^ permalink raw reply
* Fw: Re: slab raid6-md125 start c000000d9371bf30 pointer offset 16 size 2544 ist_add corruption. prev->next should be next
From: jfiusdq @ 2026-02-18 13:44 UTC (permalink / raw)
To: linux-raid@vger.kernel.org
In-Reply-To: <hWTi4qnyyq1EBkwAD1UperpLdhLIpIPWhx2YNesZO9blCrGVIa24-c8eOQ0NK7my8KqyzN_NOiV7tRODZAR1fDSpDUyibmXubU74FdXZcKs=@proton.me>
[-- Attachment #1.1.1: Type: text/plain, Size: 28341 bytes --]
Hello,
I have been facing a troubling issue with weird silent data loss on latest linux stable on Fedora ;
I initially thought it could be arch specific but at the end it does not seem like it. Hence why I initially sent my report to linux-ppc mailing list.
I also opened an issue at RHEL's Bugzilla : https://bugzilla.redhat.com/show_bug.cgi?id=2438830
I am continuously monitoring the issue and trying to gather more diagnostic data, I have been unable to find the cause as of now.
If you have any idea what's causing this, also don't hesitate to ask me for more info if you need it. I am surprised that it seems not many people are affected by it, at least I could not find more reports online about this same issue, weirdly.
Thanks alot
------- Forwarded Message -------
From: jfiusdq <jfiusdq@proton.me>
Date: On Tuesday, February 10th, 2026 at 4:57 PM
Subject: Re: slab raid6-md125 start c000000d9371bf30 pointer offset 16 size 2544 ist_add corruption. prev->next should be next
To: linuxppc-dev@lists.ozlabs.org <linuxppc-dev@lists.ozlabs.org>
> I have removed my out of tree module out of precaution and it still happened again, this time un-tainted kernel:
>
> [24962.760298] sd 1:0:0:0: Power-on or device reset occurred[122456.581878] slab raid6-md125 start c0000006487c31b0 pointer offset 16 size 2544
> [122456.581972] list_add corruption. prev->next should be next (c00020005a376ce0), but was c0000006487c31c0. (prev=c0000006487c31c0).
> [122456.582068] ------------[ cut here ]------------
> [122456.582097] kernel BUG at lib/list_debug.c:32!
> [122456.582130] Oops: Exception in kernel mode, sig: 5 [#1]
> [122456.582185] LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA PowerNV
> [122456.582231] Modules linked in: vhost_net vhost vhost_iotlb tap tun nft_masq nft_reject_ipv4 act_csum cls_u32 sch_htb nf_nat_tftp nf_conntrack_tftp bridge stp llc kvm_hv kvm rfkill xt_conntrack nft_compat nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables dm_cache_smq dm_cache raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx sunrpc raid10 snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hda_core joydev snd_hwdep snd_seq snd_seq_device at24 onboard_usb_dev snd_pcm snd_timer atlantic tg3 snd ofpart ipmi_powernv macsec soundcore powernv_flash ipmi_devintf mtd ipmi_msghandler vmx_crypto opal_prd rtc_opal i2c_opal fuse dm_multipath loop nfnetlink zram lz4hc_compress lz4_compress xfs dm_thin_pool dm_persistent_data dm_bio_prison dm_crypt raid1 nvme nvme_core uas usb_storage nvme_keyring mpt3sas nvme_auth hkdf ast raid_class scsi_transport_sas i2c_algo_bit scsi_dh_rdac
> [122456.582467] scsi_dh_emc scsi_dh_alua i2c_dev aes_gcm_p10_crypto crypto_simd cryptd
> [122456.583119] CPU: 5 UID: 0 PID: 2697 Comm: dmcrypt_write/2 Not tainted 6.18.8-200.fc43.ppc64le #1 PREEMPT(voluntary)
> [122456.583216] Hardware name: T2P9D01 REV 1.00 POWER9 (raw) 0x4e1202 opal:skiboot-ecb1dc7 PowerNV
> [122456.583292] NIP: c000000000e098fc LR: c000000000e098f8 CTR: 0000000000000000
> [122456.583370] REGS: c00000003c9877a0 TRAP: 0700 Not tainted (6.18.8-200.fc43.ppc64le)
> [122456.583432] MSR: 900000000282b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 24004240 XER: 00000156
> [122456.583498] CFAR: c00000000034542c IRQMASK: 0
> GPR00: c000000000e098f8 c00000003c987a40 c0000000026ba900 0000000000000075
> GPR04: 00000000ffffbfff 0000000000000001 0000201ff71a0000 0000000000000001
> GPR08: 0000000000000027 0000000000000000 0000000000000000 c00000003c987890
> GPR12: c000201fff18ffa8 c000201fff7e8180 c000000000299c28 c000000005aba780
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
> GPR24: 0000000000000000 c00000003c987c70 c000200060539800 c000200618eddb30
> GPR28: 0000000000000000 c000201485cbe738 c00000003bd42800 c000201485cbe6f0
> [122456.583968] NIP [c000000000e098fc] __list_add_valid_or_report+0xdc/0x140
> [122456.584045] LR [c000000000e098f8] __list_add_valid_or_report+0xd8/0x140
> [122456.584093] Call Trace:
> [122456.584115] [c00000003c987a40] [c000000000e098f8] __list_add_valid_or_report+0xd8/0x140 (unreliable)
> [122456.584189] [c00000003c987ab0] [c008000026e90ad4] release_stripe_plug+0x9c/0x150 [raid456]
> [122456.584258] [c00000003c987b00] [c008000026e959f4] make_stripe_request+0x32c/0x560 [raid456]
> [122456.584333] [c00000003c987bd0] [c008000026e95df8] raid5_make_request+0x1d0/0x610 [raid456]
> [122456.584418] [c00000003c987d10] [c000000001369a04] md_handle_request+0x1c4/0x400
> [122456.584484] [c00000003c987da0] [c000000000d04010] __submit_bio+0x230/0x3d0
> [122456.584560] [c00000003c987e40] [c000000000d04244] __submit_bio_noacct+0x94/0x250
> [122456.584635] [c00000003c987eb0] [c00000000138743c] dm_submit_bio_remap+0x4c/0x120
> [122456.584698] [c00000003c987ef0] [c00800001dc226a8] dmcrypt_write+0x1a0/0x200 [dm_crypt]
> [122456.584765] [c00000003c987f90] [c000000000299da8] kthread+0x188/0x1a0
> [122456.584818] [c00000003c987fe0] [c00000000000ded8] start_kernel_thread+0x14/0x18
> [122456.584879] Code: f8c10060 f8010080 4b883b35 60000000 3c62ff82 38639388 e8c10060 e9210068 e8a60000 7d244b78 4b53baf5 60000000 <0fe00000> 7c0802a6 7c852378 7c641b78
> [122456.585015] ---[ end trace 0000000000000000 ]---
> [122457.162074] pstore: backend (nvram) writing error (-1)
>
> [122457.162141] note: dmcrypt_write/2[2697] exited with irqs disabled
> [122457.162214] ------------[ cut here ]------------
> [122457.162257] WARNING: CPU: 5 PID: 2697 at kernel/exit.c:903 do_exit+0x5c/0x5b0
> [122457.162314] Modules linked in: vhost_net vhost vhost_iotlb tap tun nft_masq nft_reject_ipv4 act_csum cls_u32 sch_htb nf_nat_tftp nf_conntrack_tftp bridge stp llc kvm_hv kvm rfkill xt_conntrack nft_compat nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables dm_cache_smq dm_cache raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx sunrpc raid10 snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hda_core joydev snd_hwdep snd_seq snd_seq_device at24 onboard_usb_dev snd_pcm snd_timer atlantic tg3 snd ofpart ipmi_powernv macsec soundcore powernv_flash ipmi_devintf mtd ipmi_msghandler vmx_crypto opal_prd rtc_opal i2c_opal fuse dm_multipath loop nfnetlink zram lz4hc_compress lz4_compress xfs dm_thin_pool dm_persistent_data dm_bio_prison dm_crypt raid1 nvme nvme_core uas usb_storage nvme_keyring mpt3sas nvme_auth hkdf ast raid_class scsi_transport_sas i2c_algo_bit scsi_dh_rdac
> [122457.162459] scsi_dh_emc scsi_dh_alua i2c_dev aes_gcm_p10_crypto crypto_simd cryptd
> [122457.163011] CPU: 5 UID: 0 PID: 2697 Comm: dmcrypt_write/2 Tainted: G D 6.18.8-200.fc43.ppc64le #1 PREEMPT(voluntary)
> [122457.163123] Tainted: [D]=DIE
> [122457.163171] Hardware name: T2P9D01 REV 1.00 POWER9 (raw) 0x4e1202 opal:skiboot-ecb1dc7 PowerNV
> [122457.163240] NIP: c00000000026035c LR: c000000000260950 CTR: 0000000000000000
> [122457.163322] REGS: c00000003c987330 TRAP: 0700 Tainted: G D (6.18.8-200.fc43.ppc64le)
> [122457.163406] MSR: 9000000002029033 <SF,HV,VEC,EE,ME,IR,DR,RI,LE> CR: 24004240 XER: 20040156
> [122457.163501] CFAR: c00000000026094c IRQMASK: 0
> GPR00: c000000000260950 c00000003c9875d0 c0000000026ba900 0000000000000005
> GPR04: 0000000000002710 0000000000000001 0000201ff71a0000 0000000000000001
> GPR08: 0000000000000005 0000000000000001 c00000003c987f18 0000000000004000
> GPR12: c000201fff18ffa8 c000201fff7e8180 0000000000000000 0000000000000000
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR24: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR28: 0000000000000005 0000000000000003 c000000003e3a900 c00000001be2a000
> [122457.163984] NIP [c00000000026035c] do_exit+0x5c/0x5b0
> [122457.164037] LR [c000000000260950] make_task_dead+0xa0/0x1d0
> [122457.164079] Call Trace:
> [122457.164126] [c00000003c9875d0] [c00000003c987600] 0xc00000003c987600 (unreliable)
> [122457.164216] [c00000003c987670] [c000000000260950] make_task_dead+0xa0/0x1d0
> [122457.164276] [c00000003c9876f0] [c00000000002a314] oops_end+0x164/0x1a0
> [122457.164336] [c00000003c987770] [c000000000009b2c] program_check_common_virt+0x3bc/0x3c0
> [122457.164399] ---- interrupt: 700 at __list_add_valid_or_report+0xdc/0x140
> [122457.164454] NIP: c000000000e098fc LR: c000000000e098f8 CTR: 0000000000000000
> [122457.164509] REGS: c00000003c9877a0 TRAP: 0700 Tainted: G D (6.18.8-200.fc43.ppc64le)
> [122457.164575] MSR: 900000000282b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 24004240 XER: 00000156
> [122457.164654] CFAR: c00000000034542c IRQMASK: 0
> GPR00: c000000000e098f8 c00000003c987a40 c0000000026ba900 0000000000000075
> GPR04: 00000000ffffbfff 0000000000000001 0000201ff71a0000 0000000000000001
> GPR08: 0000000000000027 0000000000000000 0000000000000000 c00000003c987890
> GPR12: c000201fff18ffa8 c000201fff7e8180 c000000000299c28 c000000005aba780
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
> GPR24: 0000000000000000 c00000003c987c70 c000200060539800 c000200618eddb30
> GPR28: 0000000000000000 c000201485cbe738 c00000003bd42800 c000201485cbe6f0
> [122457.165148] NIP [c000000000e098fc] __list_add_valid_or_report+0xdc/0x140
> [122457.165191] LR [c000000000e098f8] __list_add_valid_or_report+0xd8/0x140
> [122457.165233] ---- interrupt: 700
> [122457.165273] [c00000003c987ab0] [c008000026e90ad4] release_stripe_plug+0x9c/0x150 [raid456]
> [122457.165358] [c00000003c987b00] [c008000026e959f4] make_stripe_request+0x32c/0x560 [raid456]
> [122457.165405] [c00000003c987bd0] [c008000026e95df8] raid5_make_request+0x1d0/0x610 [raid456]
> [122457.165481] [c00000003c987d10] [c000000001369a04] md_handle_request+0x1c4/0x400
> [122457.165545] [c00000003c987da0] [c000000000d04010] __submit_bio+0x230/0x3d0
> [122457.165593] [c00000003c987e40] [c000000000d04244] __submit_bio_noacct+0x94/0x250
> [122457.165648] [c00000003c987eb0] [c00000000138743c] dm_submit_bio_remap+0x4c/0x120
> [122457.165744] [c00000003c987ef0] [c00800001dc226a8] dmcrypt_write+0x1a0/0x200 [dm_crypt]
> [122457.165832] [c00000003c987f90] [c000000000299da8] kthread+0x188/0x1a0
> [122457.165889] [c00000003c987fe0] [c00000000000ded8] start_kernel_thread+0x14/0x18
> [122457.165960] Code: 91610008 f8010010 f821ff61 e92d0c78 f9210078 39200000 892d0932 552907fe 0b090000 e95f0c68 312affff 7d295110 <0b090000> ebbf0b90 ebdf0b88 7fa3eb78
> [122457.166065] ---[ end trace 0000000000000000 ]---
> On Monday, February 9th, 2026 at 12:38 AM, jfiusdq <jfiusdq@proton.me> wrote:
>
> > Sorry for duplicate but it happened after a disk started failing during a check that was triggered on all my 3 RAID arrays and then after a good while this bug happened. That's basically it.
> >
> > [154043.105837] md: check of RAID array md125[154049.432225] md: check of RAID array md126
> > [154055.718196] md: check of RAID array md127
> > [163101.001572] sd 1:0:0:0: [sda] tag#8069 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163101.001655] sd 1:0:0:0: [sda] tag#8069 CDB: Read(10) 28 00 1b 28 d1 80 00 02 80 00
> > [163101.001691] I/O error, dev sda, sector 455659904 op 0x0:(READ) flags 0x80700 phys_seg 5 prio class 2
> > [163101.412714] sd 1:0:0:0: Power-on or device reset occurred
> > [163101.698759] sd 1:0:0:0: [sda] tag#7728 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163101.698813] sd 1:0:0:0: [sda] tag#7728 CDB: Read(10) 28 00 74 70 6d 00 00 00 80 00
> > [163101.698843] I/O error, dev sda, sector 1953524992 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 2
> > [163102.162693] sd 1:0:0:0: Power-on or device reset occurred
> > [163102.447648] sd 1:0:0:0: [sda] Unaligned partial completion (resid=866300, sector_sz=512)
> > [163102.447723] sd 1:0:0:0: [sda] tag#8049 CDB: Read(10) 28 00 5e 21 d4 00 00 08 00 00
> > [163102.447751] sd 1:0:0:0: [sda] tag#8049 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163102.447789] sd 1:0:0:0: [sda] tag#8049 CDB: Read(10) 28 00 5e 21 d4 00 00 08 00 00
> > [163102.447855] I/O error, dev sda, sector 1579275264 op 0x0:(READ) flags 0x80700 phys_seg 8 prio class 2
> > [163102.912783] sd 1:0:0:0: Power-on or device reset occurred
> > [163103.662867] sd 1:0:0:0: Power-on or device reset occurred
> > [163104.413036] sd 1:0:0:0: Power-on or device reset occurred
> > [163105.163044] sd 1:0:0:0: Power-on or device reset occurred
> > [163105.913609] sd 1:0:0:0: Power-on or device reset occurred
> > [163106.663213] sd 1:0:0:0: Power-on or device reset occurred
> > [163107.289773] sd 1:0:0:0: Power-on or device reset occurred
> > [163107.932812] sd 1:0:0:0: Power-on or device reset occurred
> > [163108.913957] sd 1:0:0:0: Power-on or device reset occurred
> > [163109.664106] sd 1:0:0:0: Power-on or device reset occurred
> > [163110.414281] sd 1:0:0:0: Power-on or device reset occurred
> > [163111.164312] sd 1:0:0:0: Power-on or device reset occurred
> > [163111.913814] sd 1:0:0:0: Power-on or device reset occurred
> > [163112.663904] sd 1:0:0:0: Power-on or device reset occurred
> > [163113.414627] sd 1:0:0:0: Power-on or device reset occurred
> > [163113.699639] sd 1:0:0:0: [sda] Unaligned partial completion (resid=205820, sector_sz=512)
> > [163113.699771] sd 1:0:0:0: [sda] tag#7615 CDB: Read(10) 28 00 01 4d 84 00 00 04 00 00
> > [163113.699976] sd 1:0:0:0: [sda] tag#7615 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163113.700198] sd 1:0:0:0: [sda] tag#7615 CDB: Read(10) 28 00 01 4d 84 00 00 04 00 00
> > [163113.700329] I/O error, dev sda, sector 21857280 op 0x0:(READ) flags 0x80700 phys_seg 4 prio class 2
> > [163114.164085] sd 1:0:0:0: Power-on or device reset occurred
> > [163114.914167] sd 1:0:0:0: Power-on or device reset occurred
> > [163115.664261] sd 1:0:0:0: Power-on or device reset occurred
> > [163115.959965] sd 1:0:0:0: [sda] tag#8044 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163115.959963] sd 1:0:0:0: [sda] Unaligned partial completion (resid=308220, sector_sz=512)
> > [163115.959996] sd 1:0:0:0: [sda] tag#8016 CDB: Read(10) 28 00 00 58 a0 00 00 04 00 00
> > [163115.960041] sd 1:0:0:0: [sda] tag#8044 CDB: Read(10) 28 00 1b 48 fc 00 00 04 00 00
> > [163115.960081] sd 1:0:0:0: [sda] tag#8016 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163115.960109] I/O error, dev sda, sector 457767936 op 0x0:(READ) flags 0x80700 phys_seg 8 prio class 2
> > [163115.960155] sd 1:0:0:0: [sda] tag#8016 CDB: Read(10) 28 00 00 58 a0 00 00 04 00 00
> > [163115.960402] I/O error, dev sda, sector 5808128 op 0x0:(READ) flags 0x80700 phys_seg 4 prio class 2
> > [163116.414438] sd 1:0:0:0: Power-on or device reset occurred
> > [163116.706739] sd 1:0:0:0: [sda] tag#8103 FAILED Result: hostbyte=DID_SOFT_ERROR driverbyte=DRIVER_OK cmd_age=0s
> > [163116.706804] sd 1:0:0:0: [sda] tag#8103 CDB: Read(10) 28 00 0d 86 3c 00 00 08 00 00
> > [163116.706853] I/O error, dev sda, sector 226900992 op 0x0:(READ) flags 0x80700 phys_seg 12 prio class 2
> > [163117.109789] sd 1:0:0:0: Power-on or device reset occurred
> > [163117.914577] sd 1:0:0:0: Power-on or device reset occurred
> > [163497.189569] md: md126: check done.
> > [163829.231426] md: md127: check done.
> > [185096.100388] md: md125: check done.
> >
> >
> > and just after that, just the kernel logs you saw in my previous mail, nothing in between.
> > On Monday, February 9th, 2026 at 12:19 AM, jfiusdq <jfiusdq@proton.me> wrote:
> >
> > > Hello,
> > >
> > >
> > > Today I was met with the following kernel log on IBM POWER9, abit worrying because of it concerning RAID6:
> > >
> > >
> > > [240888.555387] slab raid6-md125 start c000000d9371bf30 pointer offset 16 size 2544
> > > [240888.555464] list_add corruption. prev->next should be next (c00000002a3fc3e0), but was c000000d9371bf40. (prev=c000000d9371bf40).
> > > [240888.555582] ------------[ cut here ]------------
> > > [240888.555615] kernel BUG at lib/list_debug.c:32!
> > > [240888.555650] Oops: Exception in kernel mode, sig: 5 [#1]
> > > [240888.555703] LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA PowerNV
> > > [240888.555755] Modules linked in: vendor_reset(OE) vfio_pci vfio_pci_core vfio_iommu_spapr_tce vfio iommufd vhost_net vhost vhost_iotlb tap tun nft_masq nft_reject_ipv4 act_csum cls_u32 sch_htb nf_nat_tftp nf_conntrack_tftp bridge stp llc kvm_hv kvm rfkill xt_conntrack nft_compat nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables dm_cache_smq dm_cache raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx sunrpc raid10 snd_hda_intel at24 joydev snd_intel_dspcfg snd_hda_codec snd_hda_core onboard_usb_dev snd_hwdep snd_seq snd_seq_device snd_pcm ofpart tg3 powernv_flash snd_timer atlantic vmx_crypto ipmi_powernv snd ipmi_devintf mtd ipmi_msghandler macsec rtc_opal opal_prd soundcore i2c_opal fuse dm_multipath loop nfnetlink zram lz4hc_compress lz4_compress xfs dm_thin_pool dm_persistent_data dm_bio_prison dm_crypt raid1 nvme mpt3sas nvme_core uas usb_storage ast nvme_keyring
> > > [240888.555962] nvme_auth hkdf raid_class i2c_algo_bit scsi_transport_sas scsi_dh_rdac scsi_dh_emc scsi_dh_alua i2c_dev aes_gcm_p10_crypto crypto_simd cryptd
> > > [240888.556531] CPU: 33 UID: 0 PID: 2851 Comm: dmcrypt_write/2 Tainted: G OE 6.18.8-200.fc43.ppc64le #1 PREEMPT(voluntary)
> > > [240888.556608] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
> > > [240888.556650] Hardware name: T2P9D01 REV 1.00 POWER9 (raw) 0x4e1202 opal:skiboot-ecb1dc7 PowerNV
> > > [240888.556721] NIP: c000000000e098fc LR: c000000000e098f8 CTR: 0000000000000000
> > > [240888.556766] REGS: c0000000295e77a0 TRAP: 0700 Tainted: G OE (6.18.8-200.fc43.ppc64le)
> > > [240888.556822] MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24004280 XER: 00000000
> > > [240888.556904] CFAR: c00000000034542c IRQMASK: 0
> > > GPR00: c000000000e098f8 c0000000295e7a40 c0000000026ba900 0000000000000075
> > > GPR04: 00000000ffffbfff 0000000000000001 0000001ffc2d0000 0000000000000001
> > > GPR08: 0000000000000027 0000000000000000 0000000000000000 c0000000295e7890
> > > GPR12: c000201fff18ffa8 c000001ffffde600 c000000000299c28 c0002000113fdb40
> > > GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> > > GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
> > > GPR24: 0000000000000000 c0000000295e7c70 c00000002bbce800 c000001126d57830
> > > GPR28: 0000000000000000 c000201d2995b588 c00020005f464000 c000201d2995b540
> > > [240888.557339] NIP [c000000000e098fc] __list_add_valid_or_report+0xdc/0x140
> > > [240888.557405] LR [c000000000e098f8] __list_add_valid_or_report+0xd8/0x140
> > > [240888.557463] Call Trace:
> > > [240888.557484] [c0000000295e7a40] [c000000000e098f8] __list_add_valid_or_report+0xd8/0x140 (unreliable)
> > > [240888.557541] [c0000000295e7ab0] [c0080000238f0ad4] release_stripe_plug+0x9c/0x150 [raid456]
> > > [240888.557607] [c0000000295e7b00] [c0080000238f59f4] make_stripe_request+0x32c/0x560 [raid456]
> > > [240888.557678] [c0000000295e7bd0] [c0080000238f5df8] raid5_make_request+0x1d0/0x610 [raid456]
> > > [240888.557765] [c0000000295e7d10] [c000000001369a04] md_handle_request+0x1c4/0x400
> > > [240888.557850] [c0000000295e7da0] [c000000000d04010] __submit_bio+0x230/0x3d0
> > > [240888.557927] [c0000000295e7e40] [c000000000d04244] __submit_bio_noacct+0x94/0x250
> > > [240888.557998] [c0000000295e7eb0] [c00000000138743c] dm_submit_bio_remap+0x4c/0x120
> > > [240888.558070] [c0000000295e7ef0] [c00800001bce26a8] dmcrypt_write+0x1a0/0x200 [dm_crypt]
> > > [240888.558131] [c0000000295e7f90] [c000000000299da8] kthread+0x188/0x1a0
> > > [240888.558196] [c0000000295e7fe0] [c00000000000ded8] start_kernel_thread+0x14/0x18
> > > [240888.558257] Code: f8c10060 f8010080 4b883b35 60000000 3c62ff82 38639388 e8c10060 e9210068 e8a60000 7d244b78 4b53baf5 60000000 <0fe00000> 7c0802a6 7c852378 7c641b78
> > > [240888.558363] ---[ end trace 0000000000000000 ]---
> > > [240889.114586] pstore: backend (nvram) writing error (-1)
> > >
> > > [240889.114636] note: dmcrypt_write/2[2851] exited with irqs disabled
> > > [240889.114756] ------------[ cut here ]------------
> > > [240889.114785] WARNING: CPU: 33 PID: 2851 at kernel/exit.c:903 do_exit+0x5c/0x5b0
> > > [240889.114837] Modules linked in: vendor_reset(OE) vfio_pci vfio_pci_core vfio_iommu_spapr_tce vfio iommufd vhost_net vhost vhost_iotlb tap tun nft_masq nft_reject_ipv4 act_csum cls_u32 sch_htb nf_nat_tftp nf_conntrack_tftp bridge stp llc kvm_hv kvm rfkill xt_conntrack nft_compat nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables dm_cache_smq dm_cache raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx sunrpc raid10 snd_hda_intel at24 joydev snd_intel_dspcfg snd_hda_codec snd_hda_core onboard_usb_dev snd_hwdep snd_seq snd_seq_device snd_pcm ofpart tg3 powernv_flash snd_timer atlantic vmx_crypto ipmi_powernv snd ipmi_devintf mtd ipmi_msghandler macsec rtc_opal opal_prd soundcore i2c_opal fuse dm_multipath loop nfnetlink zram lz4hc_compress lz4_compress xfs dm_thin_pool dm_persistent_data dm_bio_prison dm_crypt raid1 nvme mpt3sas nvme_core uas usb_storage ast nvme_keyring
> > > [240889.114993] nvme_auth hkdf raid_class i2c_algo_bit scsi_transport_sas scsi_dh_rdac scsi_dh_emc scsi_dh_alua i2c_dev aes_gcm_p10_crypto crypto_simd cryptd
> > > [240889.115528] CPU: 33 UID: 0 PID: 2851 Comm: dmcrypt_write/2 Tainted: G D OE 6.18.8-200.fc43.ppc64le #1 PREEMPT(voluntary)
> > > [240889.115641] Tainted: [D]=DIE, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
> > > [240889.115678] Hardware name: T2P9D01 REV 1.00 POWER9 (raw) 0x4e1202 opal:skiboot-ecb1dc7 PowerNV
> > > [240889.115771] NIP: c00000000026035c LR: c000000000260950 CTR: 0000000000000000
> > > [240889.115828] REGS: c0000000295e7330 TRAP: 0700 Tainted: G D OE (6.18.8-200.fc43.ppc64le)
> > > [240889.115875] MSR: 9000000002029033 <SF,HV,VEC,EE,ME,IR,DR,RI,LE> CR: 24004280 XER: 20040000
> > > [240889.115936] CFAR: c00000000026094c IRQMASK: 0
> > > GPR00: c000000000260950 c0000000295e75d0 c0000000026ba900 0000000000000005
> > > GPR04: 0000000000002710 0000000000000001 0000001ffc2d0000 0000000000000001
> > > GPR08: 0000000000000005 0000000000000001 c0000000295e7f18 0000000000004000
> > > GPR12: c000201fff18ffa8 c000001ffffde600 0000000000000000 0000000000000000
> > > GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> > > GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> > > GPR24: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> > > GPR28: 0000000000000005 0000000000000003 c000000003e3a900 c00000004555e800
> > > [240889.116379] NIP [c00000000026035c] do_exit+0x5c/0x5b0
> > > [240889.116407] LR [c000000000260950] make_task_dead+0xa0/0x1d0
> > > [240889.116427] Call Trace:
> > > [240889.116473] [c0000000295e75d0] [c0000000295e7600] 0xc0000000295e7600 (unreliable)
> > > [240889.116549] [c0000000295e7670] [c000000000260950] make_task_dead+0xa0/0x1d0
> > > [240889.116621] [c0000000295e76f0] [c00000000002a314] oops_end+0x164/0x1a0
> > > [240889.116689] [c0000000295e7770] [c000000000009b2c] program_check_common_virt+0x3bc/0x3c0
> > > [240889.116749] ---- interrupt: 700 at __list_add_valid_or_report+0xdc/0x140
> > > [240889.116799] NIP: c000000000e098fc LR: c000000000e098f8 CTR: 0000000000000000
> > > [240889.116838] REGS: c0000000295e77a0 TRAP: 0700 Tainted: G D OE (6.18.8-200.fc43.ppc64le)
> > > [240889.116905] MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24004280 XER: 00000000
> > > [240889.116967] CFAR: c00000000034542c IRQMASK: 0
> > > GPR00: c000000000e098f8 c0000000295e7a40 c0000000026ba900 0000000000000075
> > > GPR04: 00000000ffffbfff 0000000000000001 0000001ffc2d0000 0000000000000001
> > > GPR08: 0000000000000027 0000000000000000 0000000000000000 c0000000295e7890
> > > GPR12: c000201fff18ffa8 c000001ffffde600 c000000000299c28 c0002000113fdb40
> > > GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> > > GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
> > > GPR24: 0000000000000000 c0000000295e7c70 c00000002bbce800 c000001126d57830
> > > GPR28: 0000000000000000 c000201d2995b588 c00020005f464000 c000201d2995b540
> > > [240889.117343] NIP [c000000000e098fc] __list_add_valid_or_report+0xdc/0x140
> > > [240889.117400] LR [c000000000e098f8] __list_add_valid_or_report+0xd8/0x140
> > > [240889.117454] ---- interrupt: 700
> > > [240889.117487] [c0000000295e7ab0] [c0080000238f0ad4] release_stripe_plug+0x9c/0x150 [raid456]
> > > [240889.117544] [c0000000295e7b00] [c0080000238f59f4] make_stripe_request+0x32c/0x560 [raid456]
> > > [240889.117605] [c0000000295e7bd0] [c0080000238f5df8] raid5_make_request+0x1d0/0x610 [raid456]
> > > [240889.117678] [c0000000295e7d10] [c000000001369a04] md_handle_request+0x1c4/0x400
> > > [240889.117738] [c0000000295e7da0] [c000000000d04010] __submit_bio+0x230/0x3d0
> > > [240889.117792] [c0000000295e7e40] [c000000000d04244] __submit_bio_noacct+0x94/0x250
> > > [240889.117859] [c0000000295e7eb0] [c00000000138743c] dm_submit_bio_remap+0x4c/0x120
> > > [240889.117956] [c0000000295e7ef0] [c00800001bce26a8] dmcrypt_write+0x1a0/0x200 [dm_crypt]
> > > [240889.118017] [c0000000295e7f90] [c000000000299da8] kthread+0x188/0x1a0
> > > [240889.118084] [c0000000295e7fe0] [c00000000000ded8] start_kernel_thread+0x14/0x18
> > > [240889.118131] Code: 91610008 f8010010 f821ff61 e92d0c78 f9210078 39200000 892d0932 552907fe 0b090000 e95f0c68 312affff 7d295110 <0b090000> ebbf0b90 ebdf0b88 7fa3eb78
> > > [240889.118320] ---[ end trace 0000000000000000 ]---
> > >
> > >
> > > If that's any useful to reveal a bug, about the tainting module, it's a port of https://github.com/gnif/vendor-reset to ppc to reset some older graphics cards, nothing that should affect what the log is talking about, furthermore its been here for quite a long time without any errors.
> > >
> > >
> > > Thanks
[-- Attachment #1.1.2.1: Type: text/html, Size: 39231 bytes --]
[-- Attachment #1.2: publickey - jfiusdq@proton.me - 0x344F580A.asc --]
[-- Type: application/pgp-keys, Size: 832 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 343 bytes --]
^ permalink raw reply
* Re: [f2fs-dev] [PATCH V3 0/6] block: ignore __blkdev_issue_discard() ret value
From: patchwork-bot+f2fs @ 2026-02-17 21:14 UTC (permalink / raw)
To: Chaitanya Kulkarni
Cc: axboe, agk, snitzer, mpatocka, song, yukuai, hch, sagi, kch,
jaegeuk, chao, cem, dm-devel, linux-raid, linux-kernel,
linux-nvme, linux-f2fs-devel, linux-block, bpf, linux-xfs
In-Reply-To: <20251124234806.75216-1-ckulkarnilinux@gmail.com>
Hello:
This series was applied to jaegeuk/f2fs.git (dev)
by Carlos Maiolino <cem@kernel.org>:
On Mon, 24 Nov 2025 15:48:00 -0800 you wrote:
> Hi,
>
> __blkdev_issue_discard() only returns value 0, that makes post call
> error checking code dead. This patch series revmoes this dead code at
> all the call sites and adjust the callers.
>
> Please note that it doesn't change the return type of the function from
> int to void in this series, it will be done once this series gets merged
> smoothly.
>
> [...]
Here is the summary with links:
- [f2fs-dev,V3,1/6] block: ignore discard return value
(no matching commit)
- [f2fs-dev,V3,2/6] md: ignore discard return value
https://git.kernel.org/jaegeuk/f2fs/c/699fcfb6cb80
- [f2fs-dev,V3,3/6] dm: ignore discard return value
(no matching commit)
- [f2fs-dev,V3,4/6] nvmet: ignore discard return value
https://git.kernel.org/jaegeuk/f2fs/c/38d12f15c477
- [f2fs-dev,V3,5/6] f2fs: ignore discard return value
(no matching commit)
- [f2fs-dev,V3,6/6] xfs: ignore discard return value
https://git.kernel.org/jaegeuk/f2fs/c/2145f447b79a
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ 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