* Re: [RFC PATCH] zram: support asynchronous GC for lazy slot freeing
From: Sergey Senozhatsky @ 2026-04-16 7:41 UTC (permalink / raw)
To: Xueyuan Chen
Cc: ryncsn, baohua, minchan, senozhatsky, akpm, linux-mm, axboe,
linux-block, linux-kernel, kasong, chrisl, justinjiang,
liulei.rjpt
In-Reply-To: <20260414054930.225853-1-xueyuan.chen21@gmail.com>
On (26/04/14 13:49), Xueyuan Chen wrote:
> On Sun, Apr 12, 2026 at 07:48:48PM +0800, Kairui Song wrote:
> [...]
> >What is making this slot_free so costly? zs_free?
>
> Yes, I've captured some perf data on RK3588 cpu2:
>
> - 3.79% 0.42% zram [zram] [k] slot_free
> - 89.04% slot_free
> - 65.40% zs_free
> + 77.29% free_zspage
> + 21.75% kmem_cache_free
> 0.68% __kern_my_cpu_offset
> + 13.19% _raw_spin_unlock
> + 4.86% _raw_read_unlock
> 4.75% obj_free
> + 4.72% _raw_read_lock
> 3.64% fix_fullness_group
> + 2.02% _raw_spin_lock
> + 1.31% kmem_cache_free
>
> It's clear that zs_free is the primary hotspot, accounting for ~65.40%
> of the total slot_free cycles. Beyond that, have some read and spin lock
> in slot_free.
Just a random thought, if zs_free() is costly then it likely also affects
zswap, which makes me wonder if doing something on the zsmalloc side is a
"batter" way forward.
^ permalink raw reply
* Re: [RFC PATCH] zram: support asynchronous GC for lazy slot freeing
From: Barry Song @ 2026-04-16 8:09 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Xueyuan Chen, ryncsn, minchan, akpm, linux-mm, axboe, linux-block,
linux-kernel, kasong, chrisl, justinjiang, liulei.rjpt
In-Reply-To: <aeCRnAhfg3fNi6Ey@google.com>
On Thu, Apr 16, 2026 at 3:41 PM Sergey Senozhatsky
<senozhatsky@chromium.org> wrote:
>
> On (26/04/14 13:49), Xueyuan Chen wrote:
> > On Sun, Apr 12, 2026 at 07:48:48PM +0800, Kairui Song wrote:
> > [...]
> > >What is making this slot_free so costly? zs_free?
> >
> > Yes, I've captured some perf data on RK3588 cpu2:
> >
> > - 3.79% 0.42% zram [zram] [k] slot_free
> > - 89.04% slot_free
> > - 65.40% zs_free
> > + 77.29% free_zspage
> > + 21.75% kmem_cache_free
> > 0.68% __kern_my_cpu_offset
> > + 13.19% _raw_spin_unlock
> > + 4.86% _raw_read_unlock
> > 4.75% obj_free
> > + 4.72% _raw_read_lock
> > 3.64% fix_fullness_group
> > + 2.02% _raw_spin_lock
> > + 1.31% kmem_cache_free
> >
> > It's clear that zs_free is the primary hotspot, accounting for ~65.40%
> > of the total slot_free cycles. Beyond that, have some read and spin lock
> > in slot_free.
>
> Just a random thought, if zs_free() is costly then it likely also affects
> zswap, which makes me wonder if doing something on the zsmalloc side is a
> "batter" way forward.
Xueyuan's perf shows that 65.4% of slot_free is spent in
zs_free, so there is still around 35% elsewhere. However, this
might be a measurement issue. If we confirm the number is >=90%
or so, moving GC into zsmalloc seems like a better option. My
real use case is zram rather than zswap in the Android industry,
but this would benefit both zswap and zram.
Meanwhile, I would also like to try whether combining many bit
operations, such as clear_slot_flag(), can further help.
Thanks
Barry
^ permalink raw reply
* Re: [REGRESSION][BISECTED] Spurious raid1 device failure triggered by qemu direct IO on 6.18+
From: Tomáš Trnka @ 2026-04-16 10:13 UTC (permalink / raw)
To: Keith Busch; +Cc: Jens Axboe, linux-kernel, regressions, linux-block
In-Reply-To: <ad-0LIubzaT8M2_O@kbusch-mbp>
The proposed patch fixes the issue for me and doesn't cause any visible issues
(in normal operation, I didn't test actual device failure). Thanks a lot for
such a speedy fix, looking forward for the final version to test as well.
> ---
> diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c
> index c33099925f230..cf1c25f290f36 100644
> --- a/drivers/md/raid1-10.c
> +++ b/drivers/md/raid1-10.c
> @@ -293,8 +293,16 @@ static inline bool raid1_should_read_first(struct mddev
> *mddev, * bio with REQ_RAHEAD or REQ_NOWAIT can fail at anytime, before
> such IO is * submitted to the underlying disks, hence don't record
> badblocks or retry * in this case.
> + *
> + * BLK_STS_INVAL means the request itself is malformed (e.g. unaligned
> + * buffers that violate DMA constraints). Retrying on another mirror will
> + * fail the same way, and counting it against the device is wrong.
> */
> static inline bool raid1_should_handle_error(struct bio *bio)
> {
> - return !(bio->bi_opf & (REQ_RAHEAD | REQ_NOWAIT));
> + if (bio->bi_opf & (REQ_RAHEAD | REQ_NOWAIT))
> + return false;
> + if (bio->bi_status == BLK_STS_INVAL)
> + return false;
> + return true;
> }
> --
^ permalink raw reply
* Re: [PATCH blktests] nvme/068: add a test for multipath delayed removal
From: Nilay Shroff @ 2026-04-16 11:18 UTC (permalink / raw)
To: John Garry, shinichiro.kawasaki, linux-block; +Cc: linux-nvme
In-Reply-To: <20260415104111.1439459-1-john.g.garry@oracle.com>
> diff --git a/tests/nvme/068 b/tests/nvme/068
> new file mode 100644
> index 0000000..e06fd6b
> --- /dev/null
> +++ b/tests/nvme/068
> @@ -0,0 +1,118 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-3.0+
> +# Copyright (C) 2026 John Garry
> +#
> +# Test NVMe multipath delayed removal works as expected
> +
Should we also reference the commit 62188639ec16 ("nvme-multipath:
introduce delayed removal of the multipath head node") which introduced
this feature in the kernel?
> +. tests/nvme/rc
> +. common/xfs
> +
> +DESCRIPTION="NVMe multipath delayed removal test"
> +QUICK=1
> +
> +requires() {
> + _nvme_requires
> + _have_loop
> + _have_module_param_value nvme_core multipath Y
> + _require_nvme_trtype_is_fabrics
> +}
> +
> +set_conditions() {
> + _set_nvme_trtype "$@"
> +}
> +
> +_delayed_nvme_reconnect_ctrl() {
> + sleep 5
> + _nvme_connect_subsys
> +}
> +
> +test() {
> + echo "Running ${TEST_NAME}"
> +
> + _setup_nvmet
> +
> + local nvmedev
> + local ns
> + local bytes_written
> + local refcnt_orig
> + local refcnt
> + _nvmet_target_setup
> +
> + _nvme_connect_subsys
> +
> + # Part a: Prove that writes fail when no path returns. Any reads or
> + # writes are queued during the delayed removal period. If no
> + # paths return before the timer expires, then those IOs should
> + # fail.
> + # During the delayed removal period, ensure that the module
> + # refcnt is incremented, to prove that we cannot remove the
> + # driver during this period.
> + nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
> + refcnt=$(_module_use_count nvme_core)
Should the refcount be stored in $refcnt_orig instead of $refcnt?
> + echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
> + refcnt_orig=$(_module_use_count nvme_core)
We may not need to again store refcnt here if we store it
before enabling delayed_removal_sec above.
Other than above trivial comments, this looks good to me.
Thanks,
--Nilay
^ permalink raw reply
* [PATCH blktests] throtl/{002,003,007}, zbd/014: use _get_page_size to get PAGE_SIZE
From: Shin'ichiro Kawasaki @ 2026-04-16 11:42 UTC (permalink / raw)
To: linux-block; +Cc: Yi Zhang, Shin'ichiro Kawasaki
From: Yi Zhang <yi.zhang@redhat.com>
Commit 8eca9fa369ee ("common/rc, scsi/011, zbd/010: introduce
_page_size_equals() helper") introduced the helper bash function
_get_page_size(). Replace "getconf PAGE_SIZE" with the helper to cut
dependency to the getconf tool.
Link: https://github.com/linux-blktests/blktests/pull/243
Signed-off-by: Yi Zhang <yi.zhang@redhat.com>
[Shin'ichiro: removed getconf command check in zbd/014]
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
---
tests/throtl/002 | 2 +-
tests/throtl/003 | 2 +-
tests/throtl/007 | 2 +-
tests/zbd/014 | 3 +--
4 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/tests/throtl/002 b/tests/throtl/002
index 08e685f..275c900 100755
--- a/tests/throtl/002
+++ b/tests/throtl/002
@@ -21,7 +21,7 @@ test() {
local io_size_kb block_size
local iops=256
- page_size=$(getconf PAGE_SIZE)
+ page_size=$(_get_page_size)
if ! _set_up_throtl --sector_size "${page_size}"; then
return 1;
diff --git a/tests/throtl/003 b/tests/throtl/003
index 700e9e6..b45123a 100755
--- a/tests/throtl/003
+++ b/tests/throtl/003
@@ -18,7 +18,7 @@ test() {
echo "Running ${TEST_NAME}"
local page_size
- page_size=$(getconf PAGE_SIZE)
+ page_size=$(_get_page_size)
if ! _set_up_throtl --sector_size "${page_size}"; then
return 1;
diff --git a/tests/throtl/007 b/tests/throtl/007
index 97dece6..4292feb 100755
--- a/tests/throtl/007
+++ b/tests/throtl/007
@@ -19,7 +19,7 @@ test() {
echo "Running ${TEST_NAME}"
local page_size
- page_size=$(getconf PAGE_SIZE)
+ page_size=$(_get_page_size)
if ! _set_up_throtl --sector_size "${page_size}"; then
return 1;
diff --git a/tests/zbd/014 b/tests/zbd/014
index 35ecc85..18e6fd9 100755
--- a/tests/zbd/014
+++ b/tests/zbd/014
@@ -23,7 +23,6 @@ requires() {
_have_driver f2fs
_have_driver null_blk
_have_program fscrypt
- _have_program getconf
_have_program mkfs.f2fs
for o in BLK_INLINE_ENCRYPTION_FALLBACK FS_ENCRYPTION_INLINE_CRYPT; do
if ! _check_kernel_option "$o"; then
@@ -112,7 +111,7 @@ run_test() {
local bio_max_vecs=256
local page_size
- page_size=$(getconf PAGE_SIZE)
+ page_size=$(_get_page_size)
# In bytes.
local max_inl_encr_bio_size=$((bio_max_vecs * page_size))
--
2.49.0
^ permalink raw reply related
* Re: [PATCH blktests 1/1] common/scsi_debug: use _patient_rmmod() to unload scsi_debug
From: Shinichiro Kawasaki @ 2026-04-16 11:44 UTC (permalink / raw)
To: Bart Van Assche; +Cc: linux-block@vger.kernel.org, Yi Zhang
In-Reply-To: <9a297b35-639c-417f-bf22-a20742a9adcd@acm.org>
On Apr 10, 2026 / 09:34, Bart Van Assche wrote:
> On 4/9/26 10:30 PM, Shin'ichiro Kawasaki wrote:
> > - modprobe -qr scsi_debug >&/dev/null
> > + _patient_rmmod scsi_debug >&/dev/null
>
> The output of none of the other _patient_rmmod calls is redirected to
> /dev/null. I propose to leave out the output redirection because of
> consistency.
Thanks, I completely agree with it. I folded in the suggested change and
applied the patch.
^ permalink raw reply
* Re: [PATCH blktests] nvme/068: add a test for multipath delayed removal
From: John Garry @ 2026-04-16 11:45 UTC (permalink / raw)
To: Nilay Shroff, shinichiro.kawasaki, linux-block; +Cc: linux-nvme
In-Reply-To: <c1e9d3b5-c236-4e5c-8cf2-90df5e32005b@linux.ibm.com>
On 16/04/2026 12:18, Nilay Shroff wrote:
>
>> diff --git a/tests/nvme/068 b/tests/nvme/068
>> new file mode 100644
>> index 0000000..e06fd6b
>> --- /dev/null
>> +++ b/tests/nvme/068
>> @@ -0,0 +1,118 @@
>> +#!/bin/bash
>> +# SPDX-License-Identifier: GPL-3.0+
>> +# Copyright (C) 2026 John Garry
>> +#
>> +# Test NVMe multipath delayed removal works as expected
>> +
> Should we also reference the commit 62188639ec16 ("nvme-multipath:
> introduce delayed removal of the multipath head node") which introduced
> this feature in the kernel?
>
Sure, if you think that it is useful.
We could also introduce at some point the _fixed_by_kernel_commit (like
xfstests), but I am not sure if it has value for blktests
>> +. tests/nvme/rc
>> +. common/xfs
>> +
>> +DESCRIPTION="NVMe multipath delayed removal test"
>> +QUICK=1
>> +
>> +requires() {
>> + _nvme_requires
>> + _have_loop
>> + _have_module_param_value nvme_core multipath Y
>> + _require_nvme_trtype_is_fabrics
>> +}
>> +
>> +set_conditions() {
>> + _set_nvme_trtype "$@"
>> +}
>> +
>> +_delayed_nvme_reconnect_ctrl() {
>> + sleep 5
>> + _nvme_connect_subsys
>> +}
>> +
>> +test() {
>> + echo "Running ${TEST_NAME}"
>> +
>> + _setup_nvmet
>> +
>> + local nvmedev
>> + local ns
>> + local bytes_written
>> + local refcnt_orig
>> + local refcnt
>> + _nvmet_target_setup
>> +
>> + _nvme_connect_subsys
>> +
>> + # Part a: Prove that writes fail when no path returns. Any reads or
>> + # writes are queued during the delayed removal period. If no
>> + # paths return before the timer expires, then those IOs should
>> + # fail.
>> + # During the delayed removal period, ensure that the module
>> + # refcnt is incremented, to prove that we cannot remove the
>> + # driver during this period.
>> + nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
>> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
>> + refcnt=$(_module_use_count nvme_core)
>
> Should the refcount be stored in $refcnt_orig instead of $refcnt?
Yeah, that's a small bug, as I needlessly store it twice:
+ refcnt=$(_module_use_count nvme_core)
+ echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
+ refcnt_orig=$(_module_use_count nvme_core)
>
>> + echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
>> + refcnt_orig=$(_module_use_count nvme_core)
>
> We may not need to again store refcnt here if we store it
> before enabling delayed_removal_sec above.
>
> Other than above trivial comments, this looks good to me.
>
Cheers,
John
^ permalink raw reply
* Re: [PATCH 55/61] interconnect: Prefer IS_ERR_OR_NULL over manual NULL check
From: Krzysztof Kozlowski @ 2026-04-16 12:24 UTC (permalink / raw)
To: Philipp Hahn, amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel,
dri-devel, gfs2, intel-gfx, intel-wired-lan, iommu, kvm,
linux-arm-kernel, linux-block, linux-bluetooth, linux-btrfs,
linux-cifs, linux-clk, linux-erofs, linux-ext4, linux-fsdevel,
linux-gpio, linux-hyperv, linux-input, linux-kernel, linux-leds,
linux-media, linux-mips, linux-mm, linux-modules, linux-mtd,
linux-nfs, linux-omap, linux-phy, linux-pm, linux-rockchip,
linux-s390, linux-scsi, linux-sctp, linux-security-module,
linux-sh, linux-sound, linux-stm32, linux-trace-kernel, linux-usb,
linux-wireless, netdev, ntfs3, samba-technical, sched-ext,
target-devel, tipc-discussion, v9fs
Cc: Georgi Djakov
In-Reply-To: <20260310-b4-is_err_or_null-v1-55-bd63b656022d@avm.de>
On 10/03/2026 12:49, Philipp Hahn wrote:
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
>
> Semantich change: Previously the code only printed the warning on error,
> but not when the pointer was NULL. Now the warning is printed in both
> cases!
NAK, read the code
>
> Change found with coccinelle.
>
> To: Georgi Djakov <djakov@kernel.org>
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
> ---
> drivers/interconnect/core.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
> index 8569b78a18517b33abeafac091978b25cbc1acc7..22e92b30f73853d5bd2e05b4f52cb5aa22556468 100644
> --- a/drivers/interconnect/core.c
> +++ b/drivers/interconnect/core.c
> @@ -790,7 +790,7 @@ void icc_put(struct icc_path *path)
> size_t i;
> int ret;
>
> - if (!path || WARN_ON(IS_ERR(path)))
> + if (WARN_ON(IS_ERR_OR_NULL(path)))
IS_ERR_OR_NULL is simply discouraged, but beside of code preference, you
just added bug here. This is clearly not equivalent and you emit warn on
perfectly valid case!
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 01/61] Coccinelle: Prefer IS_ERR_OR_NULL over manual NULL check
From: Krzysztof Kozlowski @ 2026-04-16 12:30 UTC (permalink / raw)
To: Philipp Hahn, amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel,
dri-devel, gfs2, intel-gfx, intel-wired-lan, iommu, kvm,
linux-arm-kernel, linux-block, linux-bluetooth, linux-btrfs,
linux-cifs, linux-clk, linux-erofs, linux-ext4, linux-fsdevel,
linux-gpio, linux-hyperv, linux-input, linux-kernel, linux-leds,
linux-media, linux-mips, linux-mm, linux-modules, linux-mtd,
linux-nfs, linux-omap, linux-phy, linux-pm, linux-rockchip,
linux-s390, linux-scsi, linux-sctp, linux-security-module,
linux-sh, linux-sound, linux-stm32, linux-trace-kernel, linux-usb,
linux-wireless, netdev, ntfs3, samba-technical, sched-ext,
target-devel, tipc-discussion, v9fs
Cc: Julia Lawall, Nicolas Palix
In-Reply-To: <20260310-b4-is_err_or_null-v1-1-bd63b656022d@avm.de>
On 10/03/2026 12:48, Philipp Hahn wrote:
> Find and convert uses of IS_ERR() plus NULL check to IS_ERR_OR_NULL().
>
> There are several cases where `!ptr && WARN_ON[_ONCE](IS_ERR(ptr))` is
> used:
> - arch/x86/kernel/callthunks.c:215 WARN_ON_ONCE
> - drivers/clk/clk.c:4561 WARN_ON_ONCE
> - drivers/interconnect/core.c:793 WARN_ON
> - drivers/reset/core.c:718 WARN_ON
> The change is not 100% semantical equivalent as the warning will now
> also happen when the pointer is NULL.
>
> To: Julia Lawall <Julia.Lawall@inria.fr>
> To: Nicolas Palix <nicolas.palix@imag.fr>
> Cc: cocci@inria.fr
> Cc: linux-kernel@vger.kernel.org
>
> ---
> drivers/clocksource/mips-gic-timer.c:283 looks suspicious: ret != clk,
> but Daniel Lezcano verified it as cottect.
>
> There are some cases where the checks are part of a larger expression:
> - mm/kmemleak.c:1095
> - mm/kmemleak.c:1155
> - mm/kmemleak.c:1173
> - mm/kmemleak.c:1290
> - mm/kmemleak.c:1328
> - mm/kmemleak.c:1241
> - mm/kmemleak.c:1310
> - mm/kmemleak.c:1258
> - net/netlink/af_netlink.c:2670
> Thanks to Julia Lawall for the help to also handle them.
>
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
> ---
> scripts/coccinelle/api/is_err_or_null.cocci | 125 ++++++++++++++++++++++++++++
> 1 file changed, 125 insertions(+)
>
Neither this, nor try from 2011, nor any future try should be accepted,
because it creates impression IS_ERR_OR_NULL is somehow okay. No, it is
not okay, it is a discouraged pattern leading to less readable and
maintainable code. We should not have therefore any tools suggesting
usage of IS_ERR_OR_NULL, because people will be converting poor code
into that, instead of fixing that poor code.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH blktests] nvme/068: add a test for multipath delayed removal
From: Shinichiro Kawasaki @ 2026-04-16 12:50 UTC (permalink / raw)
To: John Garry
Cc: linux-block@vger.kernel.org, linux-nvme@lists.infradead.org,
nilay@linux.ibm.com
In-Reply-To: <20260415104111.1439459-1-john.g.garry@oracle.com>
On Apr 15, 2026 / 10:41, John Garry wrote:
> For NVMe multipath, the delayed removal feature allows the multipath
> gendisk to remain present when all available paths are gone. The purpose of
> this feature is to ensure that we keep the gendisk for intermittent path
> failures.
>
> The delayed removal works on a timer - when all paths are gone, a timer is
> kicked off; once the timer expires and no paths have returned, the gendisk
> is removed.
>
> When all paths are gone and the gendisk is still present, all reads and
> writes to the disk are queued. If a path returns before the timer
> expiration, the timer canceled and the queued IO is submitted;
> otherwise they fail when the timer expires.
>
> This testcase covers two scenarios in separate parts:
> a. test that IOs submitted after all paths are removed (and do not return)
> fail
> b. test that IOs submitted between all paths removed and a path
> returning succeed
>
> During the period of the timer being active, it must be ensured that the
> nvme-core module is not removed. Otherwise the driver may not be present
> to handle the timeout expiry. The kernel ensures this by taking a
> reference to the module. Ideally, we would try to remove the module during
> this test to prove that this is not possible (and the kernel behaves as
> expected), but that module will probably not be removable anyway due to
> many references. To test this feature, check that the refcount of the
> nvme-core module is incremented when the delayed timer is active.
>
> Signed-off-by: John Garry <john.g.garry@oracle.com>
John, thanks for the patch. When I ran the new test case in my test environment,
it failed. The reported refcount mismatch looks happening in the Part b.
nvme/068 (tr=loop) (NVMe multipath delayed removal test) [failed]
runtime 38.579s ... 38.770s
--- tests/nvme/068.out 2026-04-16 20:50:21.228000000 +0900
+++ /home/shin/Blktests/blktests/results/nodev_tr_loop/nvme/068.out.bad 2026-04-16 21:30:36.215000000 +0900
@@ -1,3 +1,4 @@
Running nvme/068
pwrite: Input/output error
+module refcount not as original
Test complete
I have no idea why it fails. Do you have any guess about the failure cause?
Also, please find my review comments in line.
>
> diff --git a/common/rc b/common/rc
> index 5350057..6eae0e2 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -117,6 +117,16 @@ _module_not_in_use() {
> fi
> }
>
> +_module_use_count() {
> + local refcnt
> + if [ -f "/sys/module/$1/refcnt" ]; then
> + refcnt="$(cat /sys/module/"$1"/refcnt)"
> + echo $refcnt
To suppress Shellcheck warning, please add quotation marks: "$refcnt".
> + return
> + fi
> + echo ""
> +}
> +
> _have_module_param() {
> _have_driver "$1" || return
>
> diff --git a/tests/nvme/068 b/tests/nvme/068
> new file mode 100644
File mode 755 is recommended for consistency.
> index 0000000..e06fd6b
> --- /dev/null
> +++ b/tests/nvme/068
> @@ -0,0 +1,118 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-3.0+
> +# Copyright (C) 2026 John Garry
> +#
> +# Test NVMe multipath delayed removal works as expected
> +
> +. tests/nvme/rc
> +. common/xfs
> +
> +DESCRIPTION="NVMe multipath delayed removal test"
> +QUICK=1
It is guided to set QUICK=1 for the test cases which completes
"in ~30 seconds or less". In my environment, this test case took 38
seconds, so I'm not so sure if this test case is quick. How long
does it take in your environment?
> +
> +requires() {
> + _nvme_requires
> + _have_loop
> + _have_module_param_value nvme_core multipath Y
> + _require_nvme_trtype_is_fabrics
> +}
> +
> +set_conditions() {
> + _set_nvme_trtype "$@"
> +}
> +
> +_delayed_nvme_reconnect_ctrl() {
> + sleep 5
> + _nvme_connect_subsys
> +}
> +
> +test() {
> + echo "Running ${TEST_NAME}"
> +
> + _setup_nvmet
> +
> + local nvmedev
> + local ns
> + local bytes_written
> + local refcnt_orig
> + local refcnt
> + _nvmet_target_setup
> +
> + _nvme_connect_subsys
> +
> + # Part a: Prove that writes fail when no path returns. Any reads or
> + # writes are queued during the delayed removal period. If no
> + # paths return before the timer expires, then those IOs should
> + # fail.
> + # During the delayed removal period, ensure that the module
> + # refcnt is incremented, to prove that we cannot remove the
> + # driver during this period.
> + nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
> + refcnt=$(_module_use_count nvme_core)
> + echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
Shellcheck complains about the line above. I think it can be modified as below:
echo 10 > "/sys/block/${ns}/delayed_removal_secs"
> + refcnt_orig=$(_module_use_count nvme_core)
> + _nvme_disconnect_ctrl "${nvmedev}"
> + sleep 1
> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
> + if [[ "${ns}" = "" ]]; then
> + echo "could not find ns after disconnect"
> + fi
> + refcnt=$(_module_use_count nvme_core)
> + if [ "$refcnt" != "" ] && [ "$refcnt" -le "$refcnt_orig" ]; then
> + echo "module refcount did not increase"
> + fi
> + bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns" 4096)
> + if [ "$bytes_written" == 4096 ]; then
> + echo "wrote successfully after disconnect"
> + fi
> + sleep 10
> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
> + if [[ !"${ns}" = "" ]]; then
Shellcheck warns the line above. I guess it can be as follows:
if [[ "${ns}" != "" ]]; then
> + echo "found ns after delayed removal"
> + fi
> + refcnt=$(_module_use_count nvme_core)
> + if [ "$refcnt" != "" ] && [ "$refcnt" -ne "$refcnt_orig" ]; then
> + echo "module refcount not as original"
> + fi
> +
> + # Part b: Ensure writes for an intermittent disconnect are successful.
> + # During an intermittent disconnect, any reads or writes
> + # queued should succeed after a path returns.
> + # Also ensure module refcount behaviour is as expected, as
> + # above.
> + _nvme_connect_subsys
> +
> + nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
> + refcnt_orig=$(_module_use_count nvme_core)
> + echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
Again, the line above can be modified as follows for Shellcheck.
echo 10 > "/sys/block/${ns}/delayed_removal_secs"
^ permalink raw reply
* Re: [PATCH blktests] nvme/068: add a test for multipath delayed removal
From: John Garry @ 2026-04-16 13:03 UTC (permalink / raw)
To: Shinichiro Kawasaki
Cc: linux-block@vger.kernel.org, linux-nvme@lists.infradead.org,
nilay@linux.ibm.com
In-Reply-To: <aeDYE1BfumNvutvS@shinmob>
On 16/04/2026 13:50, Shinichiro Kawasaki wrote:
> On Apr 15, 2026 / 10:41, John Garry wrote:
>> For NVMe multipath, the delayed removal feature allows the multipath
>> gendisk to remain present when all available paths are gone. The purpose of
>> this feature is to ensure that we keep the gendisk for intermittent path
>> failures.
>>
>> The delayed removal works on a timer - when all paths are gone, a timer is
>> kicked off; once the timer expires and no paths have returned, the gendisk
>> is removed.
>>
>> When all paths are gone and the gendisk is still present, all reads and
>> writes to the disk are queued. If a path returns before the timer
>> expiration, the timer canceled and the queued IO is submitted;
>> otherwise they fail when the timer expires.
>>
>> This testcase covers two scenarios in separate parts:
>> a. test that IOs submitted after all paths are removed (and do not return)
>> fail
>> b. test that IOs submitted between all paths removed and a path
>> returning succeed
>>
>> During the period of the timer being active, it must be ensured that the
>> nvme-core module is not removed. Otherwise the driver may not be present
>> to handle the timeout expiry. The kernel ensures this by taking a
>> reference to the module. Ideally, we would try to remove the module during
>> this test to prove that this is not possible (and the kernel behaves as
>> expected), but that module will probably not be removable anyway due to
>> many references. To test this feature, check that the refcount of the
>> nvme-core module is incremented when the delayed timer is active.
>>
>> Signed-off-by: John Garry <john.g.garry@oracle.com>
>
> John, thanks for the patch. When I ran the new test case in my test environment,
> it failed. The reported refcount mismatch looks happening in the Part b.
>
> nvme/068 (tr=loop) (NVMe multipath delayed removal test) [failed]
> runtime 38.579s ... 38.770s
> --- tests/nvme/068.out 2026-04-16 20:50:21.228000000 +0900
> +++ /home/shin/Blktests/blktests/results/nodev_tr_loop/nvme/068.out.bad 2026-04-16 21:30:36.215000000 +0900
> @@ -1,3 +1,4 @@
> Running nvme/068
> pwrite: Input/output error
> +module refcount not as original
> Test complete
>
> I have no idea why it fails. Do you have any guess about the failure cause?
I posted a fix for this here:
https://lore.kernel.org/linux-nvme/20260416051459.GA14802@lst.de/T/#m17eb549aba102198009a37621cb45775841639d9
I should have mentioned this when posting this patch.
About this specific part of the test (checking module refcnt), I was
wondering if we should be testing kernel internals like this. But, since
it found a problem, I suppose that makes it ok :)
>
> Also, please find my review comments in line.
ok
>
>>
>> diff --git a/common/rc b/common/rc
>> index 5350057..6eae0e2 100644
>> --- a/common/rc
>> +++ b/common/rc
>> @@ -117,6 +117,16 @@ _module_not_in_use() {
>> fi
>> }
>>
>> +_module_use_count() {
>> + local refcnt
>> + if [ -f "/sys/module/$1/refcnt" ]; then
>> + refcnt="$(cat /sys/module/"$1"/refcnt)"
>> + echo $refcnt
>
> To suppress Shellcheck warning, please add quotation marks: "$refcnt".
ok
>
>> + return
>> + fi
>> + echo ""
>> +}
>> +
>> _have_module_param() {
>> _have_driver "$1" || return
>>
>> diff --git a/tests/nvme/068 b/tests/nvme/068
>> new file mode 100644
>
> File mode 755 is recommended for consistency.
>
ok
>> index 0000000..e06fd6b
>> --- /dev/null
>> +++ b/tests/nvme/068
>> @@ -0,0 +1,118 @@
>> +#!/bin/bash
>> +# SPDX-License-Identifier: GPL-3.0+
>> +# Copyright (C) 2026 John Garry
>> +#
>> +# Test NVMe multipath delayed removal works as expected
>> +
>> +. tests/nvme/rc
>> +. common/xfs
>> +
>> +DESCRIPTION="NVMe multipath delayed removal test"
>> +QUICK=1
>
> It is guided to set QUICK=1 for the test cases which completes
> "in ~30 seconds or less". In my environment, this test case took 38
> seconds, so I'm not so sure if this test case is quick. How long
> does it take in your environment?
I think that I will drop this, as the test time run should be > 30 with
the delays, below
>
>> +
>> +requires() {
>> + _nvme_requires
>> + _have_loop
>> + _have_module_param_value nvme_core multipath Y
>> + _require_nvme_trtype_is_fabrics
>> +}
>> +
>> +set_conditions() {
>> + _set_nvme_trtype "$@"
>> +}
>> +
>> +_delayed_nvme_reconnect_ctrl() {
>> + sleep 5
>> + _nvme_connect_subsys
>> +}
>> +
>> +test() {
>> + echo "Running ${TEST_NAME}"
>> +
>> + _setup_nvmet
>> +
>> + local nvmedev
>> + local ns
>> + local bytes_written
>> + local refcnt_orig
>> + local refcnt
>> + _nvmet_target_setup
>> +
>> + _nvme_connect_subsys
>> +
>> + # Part a: Prove that writes fail when no path returns. Any reads or
>> + # writes are queued during the delayed removal period. If no
>> + # paths return before the timer expires, then those IOs should
>> + # fail.
>> + # During the delayed removal period, ensure that the module
>> + # refcnt is incremented, to prove that we cannot remove the
>> + # driver during this period.
>> + nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
>> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
>> + refcnt=$(_module_use_count nvme_core)
>> + echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
>
> Shellcheck complains about the line above. I think it can be modified as below:
>
> echo 10 > "/sys/block/${ns}/delayed_removal_secs"
ok, I'll check that
>
>> + refcnt_orig=$(_module_use_count nvme_core)
>> + _nvme_disconnect_ctrl "${nvmedev}"
>> + sleep 1
>> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
>> + if [[ "${ns}" = "" ]]; then
>> + echo "could not find ns after disconnect"
>> + fi
>> + refcnt=$(_module_use_count nvme_core)
>> + if [ "$refcnt" != "" ] && [ "$refcnt" -le "$refcnt_orig" ]; then
>> + echo "module refcount did not increase"
>> + fi
>> + bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns" 4096)
>> + if [ "$bytes_written" == 4096 ]; then
>> + echo "wrote successfully after disconnect"
>> + fi
>> + sleep 10
>> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
>> + if [[ !"${ns}" = "" ]]; then
>
> Shellcheck warns the line above. I guess it can be as follows:
>
> if [[ "${ns}" != "" ]]; then
ok, I'll check that
>
>> + echo "found ns after delayed removal"
>> + fi
>> + refcnt=$(_module_use_count nvme_core)
>> + if [ "$refcnt" != "" ] && [ "$refcnt" -ne "$refcnt_orig" ]; then
>> + echo "module refcount not as original"
>> + fi
>> +
>> + # Part b: Ensure writes for an intermittent disconnect are successful.
>> + # During an intermittent disconnect, any reads or writes
>> + # queued should succeed after a path returns.
>> + # Also ensure module refcount behaviour is as expected, as
>> + # above.
>> + _nvme_connect_subsys
>> +
>> + nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
>> + ns=$(_find_nvme_ns "${def_subsys_uuid}")
>> + refcnt_orig=$(_module_use_count nvme_core)
>> + echo 10 > "/sys/block/"$ns"/delayed_removal_secs"
>
> Again, the line above can be modified as follows for Shellcheck.
>
sure
> echo 10 > "/sys/block/${ns}/delayed_removal_secs"
Thanks,
John
^ permalink raw reply
* Re: [PATCH] zram: add accounting for incompressible pages
From: chenqiwu @ 2026-04-16 13:20 UTC (permalink / raw)
To: Sergey Senozhatsky; +Cc: axboe, linux-block, qiwu.chen
In-Reply-To: <aeCKbSou1_JZw9UK@google.com>
On Thu, Apr 16, 2026 at 04:07:59PM +0900, Sergey Senozhatsky wrote:
> On (26/04/15 18:43), qiwu.chen wrote:
> > 1. Rename write_incompressible_page to write_huge_page since huge page
> > could be recompressed with secondary algorithms.
>
> Please no. "huge_page" is the most confusing term that zram uses.
>
So what is differece between ZRAM_HUGE and ZRAM_INCOMPRESSIBLE?
In my opinion, the slot is marked as ZRAM_HUGE if primary algorithm
cannot compress the page. the slot is marked as ZRAM_INCOMPRESSIBLE
if scondary algorithms failed to recompress the page in a way that
condary algorithms failed to recompress the page.
The huge page could be recompressed with secondary algorithms with
a certain probability, so it should not be defined as incompressible page.
> > 2. Similar to huge page, add incompressible_pages accounting for current
> > incompressible pages, and incompressible_pages_since accounting for
> > incompressible pages since zram set up. The accounting value can be showed
> > by mm_stat.
>
> What for?
Add accounting for ZRAM_INCOMPRESSIBLE pages showed by mm_stat, so we can get
how many pages is incompressiable in current system.
^ permalink raw reply
* Re: [PATCH v10 13/13] docs: add io_queue flag to isolcpus
From: Aaron Tomlin @ 2026-04-16 13:40 UTC (permalink / raw)
To: Ming Lei
Cc: Ming Lei, axboe, kbusch, hch, sagi, mst, aacraid, James.Bottomley,
martin.petersen, liyihang9, kashyap.desai, sumit.saxena,
shivasharan.srikanteshwara, chandrakanth.patil, sathya.prakash,
sreekanth.reddy, suganath-prabu.subramani, ranjan.kumar,
jinpu.wang, tglx, mingo, peterz, juri.lelli, vincent.guittot,
akpm, maz, ruanjinjie, bigeasy, yphbchou0911, wagi, frederic,
longman, chenridong, hare, kch, steve, sean, chjohnst, neelx,
mproche, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <aeAx2g-nJQO2yyS4@fedora>
[-- Attachment #1: Type: text/plain, Size: 261 bytes --]
On Thu, Apr 16, 2026 at 08:48:26AM +0800, Ming Lei wrote:
> However, as I mentioned, I don't object this patchset, but you have to
> fix all wrong comment & document & bug found in review first.
Hi Ming,
Understood.
Kind regards,
--
Aaron Tomlin
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v6 00/43] btrfs: add fscrypt support
From: Neal Gompa @ 2026-04-16 14:34 UTC (permalink / raw)
To: Daniel Vacek
Cc: Eric Biggers, Chris Mason, Josef Bacik, Theodore Y. Ts'o,
Jaegeuk Kim, Jens Axboe, David Sterba, linux-block, linux-fscrypt,
linux-btrfs, linux-kernel
In-Reply-To: <CAPjX3Fep5ZYLuSUY+zhewtcBqW84a+qYfLcc-20soDfMjvkecA@mail.gmail.com>
On Wed, Apr 15, 2026 at 6:21 AM Daniel Vacek <neelx@suse.com> wrote:
>
> On Wed, 15 Apr 2026 at 07:30, Neal Gompa <neal@gompa.dev> wrote:
> > On Sat, Feb 28, 2026 at 2:57 AM Daniel Vacek <neelx@suse.com> wrote:
> > > On Fri, 27 Feb 2026 at 23:26, Neal Gompa <ngompa13@gmail.com> wrote:
> > > > On Fri, Feb 27, 2026 at 10:55 AM Daniel Vacek <neelx@suse.com> wrote:
> > > > > On Sat, 21 Feb 2026 at 21:56, Eric Biggers <ebiggers@kernel.org> wrote:
> > > > > > On Fri, Feb 06, 2026 at 07:22:32PM +0100, Daniel Vacek wrote:
> > > > > > > Hello,
> > > > > > >
> > > > > > > These are the remaining parts from former series [1] from Omar, Sweet Tea
> > > > > > > and Josef. Some bits of it were split into the separate set [2] before.
> > > > > > >
> > > > > > > Notably, at this stage encryption is not supported with RAID5/6 setup
> > > > > > > and send is also isabled for now.
> > > > > >
> > > > > > Where does this series apply to? There's no base-commit or git tree,
> > > > > > and it doesn't apply to mainline or btrfs/for-next.
> > > > >
> > > > > Hi Eric,
> > > > >
> > > > > My apologies, I did not explicitly mention the base. I'll do it next time.
> > > > > This was based on for-next @20260127 (commit 80dbfe6512d9c).
> > > > > Since then, some changes occurred that will require additional
> > > > > touches. No wonder it does not apply anymore.
> > > > >
> > > >
> > > > When you make your next revision, can you also provide a tag or branch
> > > > that I can use to grab the patches for testing? It would be easier for
> > > > me than trying to yoink them down from the emails with how many of
> > > > them there are...
> > >
> > > Sure
> > >
> >
> > Ping to ask about the refreshed patch set. With 7.0 out the door, it'd
> > be nice to have an updated set with feedback addressed...
>
> Hi Neal,
>
> I wanted to post a new iteration last week but I hit some new issues
> that I'm trying to address now.
> The WIP is here if you want to have a peek:
>
> https://github.com/dvacek/linux-btrfs/tree/fscrypt
>
> Note, I'll be force-updating it later so don't take even the v7 tag
> for granted at this point.
>
Cool. I've got some travel and stuff going on, so I'll probably only
get to take another crack at this in a couple of weeks. Do you think
by then you'll have a finalized v7?
--
真実はいつも一つ!/ Always, there's only one truth!
^ permalink raw reply
* Re: [PATCH 1/2] sg: don't use GFP_ATOMIC in sg_start_req
From: Bart Van Assche @ 2026-04-16 15:05 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Doug Gilbert, Martin K. Petersen
Cc: Shin'ichiro Kawasaki, linux-block, linux-scsi
In-Reply-To: <20260415060813.807659-2-hch@lst.de>
On 4/14/26 11:08 PM, Christoph Hellwig wrote:
> sg_start_req is called from normal user context and can sleep when
> waiting for memory. Switch it to use GFP_KERNEL, which fixes allocation
> failures seend with the bio_alloc rework.
seend -> seen
Anyway:
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
^ permalink raw reply
* Re: [PATCH 2/2] block: only restrict bio allocation gfp mask asked to block
From: Bart Van Assche @ 2026-04-16 15:07 UTC (permalink / raw)
To: Christoph Hellwig, Jens Axboe, Doug Gilbert, Martin K. Petersen
Cc: Shin'ichiro Kawasaki, linux-block, linux-scsi
In-Reply-To: <20260415060813.807659-3-hch@lst.de>
On 4/14/26 11:08 PM, Christoph Hellwig wrote:
> If the caller is asking for a non-blocking allocation, we should not
> further restrict the gfp mask, which just increases the likelihood
> of failures.
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
^ permalink raw reply
* Re: [PATCH] nvmet-tcp: Ensure old keys are freed before replacing new ones
From: Chris Leech @ 2026-04-16 15:27 UTC (permalink / raw)
To: Hannes Reinecke
Cc: alistair23, hch, sagi, kch, kbusch, linux-nvme, linux-kernel,
yi.zhang, mlombard, linux-block, shinichiro.kawasaki,
Alistair Francis
In-Reply-To: <959f800d-b92e-406e-a174-680fb09c884e@suse.de>
On Thu, Apr 16, 2026 at 08:16:14AM +0200, Hannes Reinecke wrote:
> On 4/16/26 01:02, alistair23@gmail.com wrote:
> > From: Alistair Francis <alistair.francis@wdc.com>
> >
> > Previously after the host sends a REPLACETLSPSK we freed the TLS keys as
> > part of calling nvmet_auth_sq_free() on success. A recent change ensured
> > we don't free the keys, allowing REPLACETLSPSK to work.
> >
> > But that fix results in a kernel memory leak when running
> >
> > ```
> > nvme_trtype=loop ./check nvme/041 nvme/042 nvme/043 nvme/044 nvme/045 nvme/051 nvme/052
> > echo scan > /sys/kernel/debug/kmemleak
> > cat /sys/kernel/debug/kmemleak
> > ```
> >
> > We can't free the keys on a successful DHCHAP operation, otherwise the
> > next REPLACETLSPSK will fail, so instead let's free them before we
> > replace them as part of nvmet_auth_challenge().
> >
> > This ensures that REPLACETLSPSK works, while also avoiding any memory
> > leaks.
> >
> > Fixes: 2e6eb6b277f59 ("nvmet-tcp: Don't free SQ on authentication success")
> > Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
> > ---
> > drivers/nvme/target/fabrics-cmd-auth.c | 7 +++++++
> > 1 file changed, 7 insertions(+)
> >
> > diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c
> > index b9ab80c7a6941..58185184478a4 100644
> > --- a/drivers/nvme/target/fabrics-cmd-auth.c
> > +++ b/drivers/nvme/target/fabrics-cmd-auth.c
> > @@ -412,6 +412,13 @@ static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
> > int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
> > int data_size = sizeof(*d) + hash_len;
> > + /*
> > + * If replacing the keys then we have previous successful keys
> > + * that might be leaked, so we need to free them here.
> > + */
> > + if (req->sq->dhchap_c1)
> > + nvmet_auth_sq_free(req->sq);
> > +
> > if (ctrl->dh_tfm)
> > data_size += ctrl->dh_keysize;
> > if (al < data_size) {
> I am not sure.
> The authentication variables should be freed as soon as the authentication
> completes; the session key is ephemeral and
> should not be stored longer than necessary and will _never_
> be used again once authentication completes.
> The TLS key, OTOH, is used throughout the session and needs
> to be present while the session is active
> As such, both sets have vastly different lifetimes, and
> I would argue that this
>
> void nvmet_auth_sq_free(struct nvmet_sq *sq)
> {
> cancel_delayed_work(&sq->auth_expired_work);
> #ifdef CONFIG_NVME_TARGET_TCP_TLS
> sq->tls_key = NULL;
> #endif
> kfree(sq->dhchap_c1);
> sq->dhchap_c1 = NULL;
>
> is actually wrong as we should not modify 'tls_key' here.
I agree with Hannes, and was just about to respond with the same
feedback. I think the freeing of the auth temporaries needs to be
returned to fix the memleak, and the real problem is the setting of
tls_key to NULL. That doesn't seem like the right lifetime for tls_key,
and it looks to be a reference count leak as well.
Is the presence of sq->tls_key the best check to see if the socket is
currently in a kTLS mode? (it might be, I'm not as up on the target
code)
- Chris
^ permalink raw reply
* Re: [PATCH v2] t10-pi: reduce ref tag code duplication
From: Caleb Sander Mateos @ 2026-04-16 15:38 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Jens Axboe, linux-block, linux-kernel, Anuj Gupta
In-Reply-To: <aeBxOVmQ2bLli78f@infradead.org>
On Wed, Apr 15, 2026 at 10:18 PM Christoph Hellwig <hch@infradead.org> wrote:
>
> On Wed, Apr 15, 2026 at 03:08:47PM -0600, Caleb Sander Mateos wrote:
> > #ifndef _LINUX_T10_PI_H
> > #define _LINUX_T10_PI_H
> >
> > #include <linux/types.h>
> > #include <linux/blk-mq.h>
> > +#include <linux/wordpart.h>
>
> We must have already gotten this implicitly given that the code
> already uses lower_48_bits.
lower_48_bits() is defined (and only used) in this header. Yes,
wordpart.h is already transitively included by the other headers, but
I think it's good practice for each file to explicitly include the
headers defining all the items it uses. It reduces the risk that
refactoring the other header files in the future will result in a
compilation error here by dropping the transitive include.
Thanks,
Caleb
^ permalink raw reply
* [PATCH v11 00/13] blk: honor isolcpus configuration
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
Hi,
I have decided to drive this series forward on behalf of Daniel Wagner, the
original author. This iteration addresses the outstanding architectural and
concurrency concerns raised during the previous review cycle, and the series
has been rebased on v7.0-rc5-509-g545475aebc2a.
Building upon prior iterations, this series introduces critical
architectural refinements to the mapping and affinity spreading algorithms
to guarantee thread safety and resilience against concurrent CPU-hotplug
operations. Previously, the block layer relied on a shared global static
mask (i.e., blk_hk_online_mask), which proved vulnerable to race conditions
during rapid hotplug events. This vulnerability was recently highlighted by
the kernel test robot, which encountered a NULL pointer dereference during
rcutorture (cpuhotplug) stress testing due to concurrent mask modification.
To resolve this, the architecture has been fundamentally hardened. The
global static state has been eradicated. Instead, the IRQ affinity core now
employs a newly introduced irq_spread_hk_filter(), which safely intersects
the natively calculated affinity mask with the HK_TYPE_IO_QUEUE mask.
Crucially, this is achieved using a local, hotplug-safe snapshot via
data_race(cpu_online_mask). This approach circumvents the hotplug lock
deadlocks previously identified by Thomas Gleixner, while explicitly
avoiding CONFIG_CPUMASK_OFFSTACK stack bloat hazards on high-core-count
systems. A robust fallback mechanism guarantees that should an interrupt
vector be assigned exclusively to isolated cores, it is safely re-routed to
the system's online housekeeping CPUs.
Following rigorous testing of multiple queue maps (such as NVMe poll
queues) alongside isolated CPUs, the tenth iteration resolved a critical
page fault regression. The multi-queue mapping logic has been corrected to
strictly maintain absolute hardware queue indices, ensuring faultless queue
initialisation and preventing out-of-bounds memory access.
Furthermore, following feedback from Ming Lei, the administrative
documentation for isolcpus=io_queue has undergone a comprehensive overhaul
to reflect this architectural reality. Previous iterations lacked the
required technical precision regarding subsystem impact. The expanded
kernel-parameters.txt now explicitly details that this parameter applies
strictly to managed IRQs. It thoroughly documents how the block layer
intercepts multiqueue allocation to match the housekeeping mask, actively
preventing MSI-X vector exhaustion on massive topologies and forcing queue
sharing. Most importantly, it cements the structural guarantee: while an
application on an isolated CPU may freely submit I/O, the hardware
completion interrupt is strictly and safely offloaded to a housekeeping
core.
Please let me know your thoughts.
Aaron Tomlin (1):
genirq/affinity: Restrict managed IRQ affinity to housekeeping CPUs
Daniel Wagner (12):
scsi: aacraid: use block layer helpers to calculate num of queues
lib/group_cpus: remove dead !SMP code
lib/group_cpus: Add group_mask_cpus_evenly()
genirq/affinity: Add cpumask to struct irq_affinity
blk-mq: add blk_mq_{online|possible}_queue_affinity
nvme-pci: use block layer helpers to constrain queue affinity
scsi: Use block layer helpers to constrain queue affinity
virtio: blk/scsi: use block layer helpers to constrain queue affinity
isolation: Introduce io_queue isolcpus type
blk-mq: use hk cpus only when isolcpus=io_queue is enabled
blk-mq: prevent offlining hk CPUs with associated online isolated CPUs
docs: add io_queue flag to isolcpus
.../admin-guide/kernel-parameters.txt | 30 ++-
block/blk-mq-cpumap.c | 192 ++++++++++++++++--
block/blk-mq.c | 42 ++++
drivers/block/virtio_blk.c | 4 +-
drivers/nvme/host/pci.c | 1 +
drivers/scsi/aacraid/comminit.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 +
drivers/scsi/megaraid/megaraid_sas_base.c | 5 +-
drivers/scsi/mpi3mr/mpi3mr_fw.c | 6 +-
drivers/scsi/mpt3sas/mpt3sas_base.c | 5 +-
drivers/scsi/pm8001/pm8001_init.c | 1 +
drivers/scsi/virtio_scsi.c | 5 +-
include/linux/blk-mq.h | 2 +
include/linux/group_cpus.h | 3 +
include/linux/interrupt.h | 16 +-
include/linux/sched/isolation.h | 1 +
kernel/irq/affinity.c | 38 +++-
kernel/sched/isolation.c | 7 +
lib/group_cpus.c | 65 ++++--
19 files changed, 379 insertions(+), 48 deletions(-)
base-commit: 3cd8b194bf3428dfa53120fee47e827a7c495815
--
2.51.0
^ permalink raw reply
* [PATCH v11 01/13] scsi: aacraid: use block layer helpers to calculate num of queues
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <20260416192942.1243421-1-atomlin@atomlin.com>
From: Daniel Wagner <wagi@kernel.org>
The calculation of the upper limit for queues does not depend solely on
the number of online CPUs; for example, the isolcpus kernel
command-line option must also be considered.
To account for this, the block layer provides a helper function to
retrieve the maximum number of queues. Use it to set an appropriate
upper queue number limit.
Fixes: 94970cfb5f10 ("scsi: use block layer helpers to calculate num of queues")
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
drivers/scsi/aacraid/comminit.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 9bd3f5b868bc..ec165b57182d 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -469,8 +469,7 @@ void aac_define_int_mode(struct aac_dev *dev)
}
/* Don't bother allocating more MSI-X vectors than cpus */
- msi_count = min(dev->max_msix,
- (unsigned int)num_online_cpus());
+ msi_count = blk_mq_num_online_queues(dev->max_msix);
dev->max_msix = msi_count;
--
2.51.0
^ permalink raw reply related
* [PATCH v11 02/13] lib/group_cpus: remove dead !SMP code
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <20260416192942.1243421-1-atomlin@atomlin.com>
From: Daniel Wagner <wagi@kernel.org>
The support for the !SMP configuration has been removed from the core by
commit cac5cefbade9 ("sched/smp: Make SMP unconditional").
While one can technically still compile a uniprocessor kernel, the core
scheduler now mandates SMP unconditionally, rendering this particular
!SMP fallback handling redundant. Therefore, remove the #ifdef CONFIG_SMP
guards and the fallback logic.
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
[atomlin: Updated commit message to clarify !SMP removal context]
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
lib/group_cpus.c | 20 --------------------
1 file changed, 20 deletions(-)
diff --git a/lib/group_cpus.c b/lib/group_cpus.c
index e6e18d7a49bb..b8d54398f88a 100644
--- a/lib/group_cpus.c
+++ b/lib/group_cpus.c
@@ -9,8 +9,6 @@
#include <linux/sort.h>
#include <linux/group_cpus.h>
-#ifdef CONFIG_SMP
-
static void grp_spread_init_one(struct cpumask *irqmsk, struct cpumask *nmsk,
unsigned int cpus_per_grp)
{
@@ -564,22 +562,4 @@ struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks)
*nummasks = min(nr_present + nr_others, numgrps);
return masks;
}
-#else /* CONFIG_SMP */
-struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks)
-{
- struct cpumask *masks;
-
- if (numgrps == 0)
- return NULL;
-
- masks = kzalloc_objs(*masks, numgrps);
- if (!masks)
- return NULL;
-
- /* assign all CPUs(cpu 0) to the 1st group only */
- cpumask_copy(&masks[0], cpu_possible_mask);
- *nummasks = 1;
- return masks;
-}
-#endif /* CONFIG_SMP */
EXPORT_SYMBOL_GPL(group_cpus_evenly);
--
2.51.0
^ permalink raw reply related
* [PATCH v11 03/13] lib/group_cpus: Add group_mask_cpus_evenly()
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <20260416192942.1243421-1-atomlin@atomlin.com>
From: Daniel Wagner <wagi@kernel.org>
group_mask_cpu_evenly() allows the caller to pass in a CPU mask that
should be evenly distributed. This new function is a more generic
version of the existing group_cpus_evenly(), which always distributes
all present CPUs into groups.
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
include/linux/group_cpus.h | 3 ++
lib/group_cpus.c | 59 ++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/include/linux/group_cpus.h b/include/linux/group_cpus.h
index 9d4e5ab6c314..defab4123a82 100644
--- a/include/linux/group_cpus.h
+++ b/include/linux/group_cpus.h
@@ -10,5 +10,8 @@
#include <linux/cpu.h>
struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks);
+struct cpumask *group_mask_cpus_evenly(unsigned int numgrps,
+ const struct cpumask *mask,
+ unsigned int *nummasks);
#endif
diff --git a/lib/group_cpus.c b/lib/group_cpus.c
index b8d54398f88a..d3e9a20250ff 100644
--- a/lib/group_cpus.c
+++ b/lib/group_cpus.c
@@ -8,6 +8,7 @@
#include <linux/cpu.h>
#include <linux/sort.h>
#include <linux/group_cpus.h>
+#include <linux/sched/isolation.h>
static void grp_spread_init_one(struct cpumask *irqmsk, struct cpumask *nmsk,
unsigned int cpus_per_grp)
@@ -563,3 +564,61 @@ struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks)
return masks;
}
EXPORT_SYMBOL_GPL(group_cpus_evenly);
+
+/**
+ * group_mask_cpus_evenly - Group all CPUs evenly per NUMA/CPU locality
+ * @numgrps: number of cpumasks to create
+ * @mask: CPUs to consider for the grouping
+ * @nummasks: number of initialized cpusmasks
+ *
+ * Return: cpumask array if successful, NULL otherwise. Only the CPUs
+ * marked in the mask will be considered for the grouping. And each
+ * element includes CPUs assigned to this group. nummasks contains the
+ * number of initialized masks which can be less than numgrps. cpu_mask
+ *
+ * Try to put close CPUs from viewpoint of CPU and NUMA locality into
+ * same group, and run two-stage grouping:
+ * 1) allocate present CPUs on these groups evenly first
+ * 2) allocate other possible CPUs on these groups evenly
+ *
+ * We guarantee in the resulted grouping that all CPUs are covered, and
+ * no same CPU is assigned to multiple groups
+ */
+struct cpumask *group_mask_cpus_evenly(unsigned int numgrps,
+ const struct cpumask *mask,
+ unsigned int *nummasks)
+{
+ cpumask_var_t *node_to_cpumask;
+ cpumask_var_t nmsk;
+ int ret = -ENOMEM;
+ struct cpumask *masks = NULL;
+
+ if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
+ return NULL;
+
+ node_to_cpumask = alloc_node_to_cpumask();
+ if (!node_to_cpumask)
+ goto fail_nmsk;
+
+ masks = kcalloc(numgrps, sizeof(*masks), GFP_KERNEL);
+ if (!masks)
+ goto fail_node_to_cpumask;
+
+ build_node_to_cpumask(node_to_cpumask);
+
+ ret = __group_cpus_evenly(0, numgrps, node_to_cpumask, mask, nmsk,
+ masks);
+
+fail_node_to_cpumask:
+ free_node_to_cpumask(node_to_cpumask);
+
+fail_nmsk:
+ free_cpumask_var(nmsk);
+ if (ret < 0) {
+ kfree(masks);
+ return NULL;
+ }
+ *nummasks = ret;
+ return masks;
+}
+EXPORT_SYMBOL_GPL(group_mask_cpus_evenly);
--
2.51.0
^ permalink raw reply related
* [PATCH v11 04/13] genirq/affinity: Add cpumask to struct irq_affinity
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <20260416192942.1243421-1-atomlin@atomlin.com>
From: Daniel Wagner <wagi@kernel.org>
Pass a cpumask to irq_create_affinity_masks as an additional constraint
to consider when creating the affinity masks. This allows the caller to
exclude specific CPUs, e.g., isolated CPUs (see the 'isolcpus' kernel
command-line parameter).
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
include/linux/interrupt.h | 16 ++++++++++------
kernel/irq/affinity.c | 12 ++++++++++--
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 6cd26ffb0505..afd5a2c75b43 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -287,18 +287,22 @@ struct irq_affinity_notify {
* @nr_sets: The number of interrupt sets for which affinity
* spreading is required
* @set_size: Array holding the size of each interrupt set
+ * @mask: cpumask that constrains which CPUs to consider when
+ * calculating the number and size of the interrupt sets
* @calc_sets: Callback for calculating the number and size
* of interrupt sets
* @priv: Private data for usage by @calc_sets, usually a
* pointer to driver/device specific data.
*/
struct irq_affinity {
- unsigned int pre_vectors;
- unsigned int post_vectors;
- unsigned int nr_sets;
- unsigned int set_size[IRQ_AFFINITY_MAX_SETS];
- void (*calc_sets)(struct irq_affinity *, unsigned int nvecs);
- void *priv;
+ unsigned int pre_vectors;
+ unsigned int post_vectors;
+ unsigned int nr_sets;
+ unsigned int set_size[IRQ_AFFINITY_MAX_SETS];
+ const struct cpumask *mask;
+ void (*calc_sets)(struct irq_affinity *,
+ unsigned int nvecs);
+ void *priv;
};
/**
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index 78f2418a8925..e0cf70a99339 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -70,7 +70,13 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
*/
for (i = 0, usedvecs = 0; i < affd->nr_sets; i++) {
unsigned int nr_masks, this_vecs = affd->set_size[i];
- struct cpumask *result = group_cpus_evenly(this_vecs, &nr_masks);
+ struct cpumask *result;
+
+ if (affd->mask)
+ result = group_mask_cpus_evenly(this_vecs, affd->mask,
+ &nr_masks);
+ else
+ result = group_cpus_evenly(this_vecs, &nr_masks);
if (!result) {
kfree(masks);
@@ -115,7 +121,9 @@ unsigned int irq_calc_affinity_vectors(unsigned int minvec, unsigned int maxvec,
if (resv > minvec)
return 0;
- if (affd->calc_sets)
+ if (affd->mask)
+ set_vecs = cpumask_weight(affd->mask);
+ else if (affd->calc_sets)
set_vecs = maxvec - resv;
else
set_vecs = cpumask_weight(cpu_possible_mask);
--
2.51.0
^ permalink raw reply related
* [PATCH v11 05/13] blk-mq: add blk_mq_{online|possible}_queue_affinity
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <20260416192942.1243421-1-atomlin@atomlin.com>
From: Daniel Wagner <wagi@kernel.org>
Introduce blk_mq_{online|possible}_queue_affinity, which returns the
queue-to-CPU mapping constraints defined by the block layer. This allows
other subsystems (e.g., IRQ affinity setup) to respect block layer
requirements.
It is necessary to provide versions for both the online and possible CPU
masks because some drivers want to spread their I/O queues only across
online CPUs, while others prefer to use all possible CPUs. And the mask
used needs to match with the number of queues requested
(see blk_num_{online|possible}_queues).
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
block/blk-mq-cpumap.c | 24 ++++++++++++++++++++++++
include/linux/blk-mq.h | 2 ++
2 files changed, 26 insertions(+)
diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c
index 705da074ad6c..8244ecf87835 100644
--- a/block/blk-mq-cpumap.c
+++ b/block/blk-mq-cpumap.c
@@ -26,6 +26,30 @@ static unsigned int blk_mq_num_queues(const struct cpumask *mask,
return min_not_zero(num, max_queues);
}
+/**
+ * blk_mq_possible_queue_affinity - Return block layer queue affinity
+ *
+ * Returns an affinity mask that represents the queue-to-CPU mapping
+ * requested by the block layer based on possible CPUs.
+ */
+const struct cpumask *blk_mq_possible_queue_affinity(void)
+{
+ return cpu_possible_mask;
+}
+EXPORT_SYMBOL_GPL(blk_mq_possible_queue_affinity);
+
+/**
+ * blk_mq_online_queue_affinity - Return block layer queue affinity
+ *
+ * Returns an affinity mask that represents the queue-to-CPU mapping
+ * requested by the block layer based on online CPUs.
+ */
+const struct cpumask *blk_mq_online_queue_affinity(void)
+{
+ return cpu_online_mask;
+}
+EXPORT_SYMBOL_GPL(blk_mq_online_queue_affinity);
+
/**
* blk_mq_num_possible_queues - Calc nr of queues for multiqueue devices
* @max_queues: The maximum number of queues the hardware/driver
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 18a2388ba581..ebc45557aee8 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -969,6 +969,8 @@ int blk_mq_freeze_queue_wait_timeout(struct request_queue *q,
void blk_mq_unfreeze_queue_non_owner(struct request_queue *q);
void blk_freeze_queue_start_non_owner(struct request_queue *q);
+const struct cpumask *blk_mq_possible_queue_affinity(void);
+const struct cpumask *blk_mq_online_queue_affinity(void);
unsigned int blk_mq_num_possible_queues(unsigned int max_queues);
unsigned int blk_mq_num_online_queues(unsigned int max_queues);
void blk_mq_map_queues(struct blk_mq_queue_map *qmap);
--
2.51.0
^ permalink raw reply related
* [PATCH v11 06/13] nvme-pci: use block layer helpers to constrain queue affinity
From: Aaron Tomlin @ 2026-04-16 19:29 UTC (permalink / raw)
To: axboe, kbusch, hch, sagi, mst
Cc: atomlin, aacraid, James.Bottomley, martin.petersen, liyihang9,
kashyap.desai, sumit.saxena, shivasharan.srikanteshwara,
chandrakanth.patil, sathya.prakash, sreekanth.reddy,
suganath-prabu.subramani, ranjan.kumar, jinpu.wang, tglx, mingo,
peterz, juri.lelli, vincent.guittot, akpm, maz, ruanjinjie,
bigeasy, yphbchou0911, wagi, frederic, longman, chenridong, hare,
kch, ming.lei, tom.leiming, steve, sean, chjohnst, neelx, mproche,
nick.lange, linux-block, linux-kernel, virtualization, linux-nvme,
linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
MPT-FusionLinux.pdl
In-Reply-To: <20260416192942.1243421-1-atomlin@atomlin.com>
From: Daniel Wagner <wagi@kernel.org>
Ensure that IRQ affinity setup also respects the queue-to-CPU mapping
constraints provided by the block layer. This allows the NVMe driver
to avoid assigning interrupts to CPUs that the block layer has excluded
(e.g., isolated CPUs).
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
drivers/nvme/host/pci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index db5fc9bf6627..daa041d15d3c 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2862,6 +2862,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
.pre_vectors = 1,
.calc_sets = nvme_calc_irq_sets,
.priv = dev,
+ .mask = blk_mq_possible_queue_affinity(),
};
unsigned int irq_queues, poll_queues;
unsigned int flags = PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY;
--
2.51.0
^ permalink raw reply related
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