Linux block layer
 help / color / mirror / Atom feed
* Re: [bug report] blktests rnbd/001 hang on s390x server
From: Haris Iqbal @ 2026-04-13  9:49 UTC (permalink / raw)
  To: Yi Zhang; +Cc: linux-block, jinpu.wang, Shinichiro Kawasaki,
	Zhijian Li (Fujitsu)
In-Reply-To: <CAJpMwyjAQhL9H_5Odz3zg12D-ja3VdsbZbwE2TxuLEsaP5KQbg@mail.gmail.com>

On Tue, Mar 24, 2026 at 11:10 AM Haris Iqbal <haris.iqbal@ionos.com> wrote:
>
> On Sat, Mar 21, 2026 at 2:00 PM Yi Zhang <yi.zhang@redhat.com> wrote:
> >
> > Hi
> >
> > I found this issue when I running blktests rnbd/ on s390x server,
> > please help check it and let me know if you need any info, thanks.
>
> Thanks for reporting.
> We'll take a look and come back.
>
> >
> > dmesg:
> > [   72.319120] rdma_rxe: loaded
> > [   72.358181] rtrs_server L2371: Loading module rtrs_server, proto
> > 2.0: (max_chunk_size: 131072 (pure IO 126976, headers 4096) ,
> > sess_queue_depth: 512, always_invalidate: 1)
> > [   72.380277] loop: module loaded
> > [   72.399060] run blktests rnbd/001 at 2026-03-21 08:42:02
> > [   72.408570] infiniband enc600_rxe: set active
> > [   72.408573] infiniband enc600_rxe: added enc600
> > [   72.422914] rnbd_client L607: Mapping device /dev/loop0 on session
> > blktest, (access_mode: rw, nr_poll_queues: 0)
> > [   72.488056] rnbd_client L1192: [session=blktest] mapped 2/2
> > default/read queues.
> > [   72.488199] rtrs_server L1058: <blktest>: Processing read request
> > failed, invalid message
> >
> > # uname -r
> > 7.0.0-0.rc4.260317g2d1373e4246d.37.fc45.s390x
> >
> > # ps aux | grep rnbd
> > root        1492  0.0  0.0   8276  4436 pts/0    S+   08:42   0:00
> > /bin/bash ./check rnbd/001
> > root        1521  0.0  0.0   8288  3292 pts/0    S+   08:42   0:00
> > /bin/bash ./check rnbd/001
> > root        1523  0.0  0.0   8424  3664 pts/0    D+   08:42   0:00
> > /bin/bash ./check rnbd/001
> >
> > # cat /proc/1523/stack
> > [<0>] send_usr_msg+0x120/0x170 [rnbd_client]
> > [<0>] send_msg_sess_info+0x1d2/0x210 [rnbd_client]
> > [<0>] find_and_get_or_create_sess+0x274/0x2f0 [rnbd_client]
> > [<0>] rnbd_clt_map_device+0xf6/0x7b0 [rnbd_client]
> > [<0>] rnbd_clt_map_device_store+0x228/0x320 [rnbd_client]
> > [<0>] kernfs_fop_write_iter+0x168/0x220
> > [<0>] vfs_write+0x282/0x450
> > [<0>] ksys_write+0x84/0x110
> > [<0>] __do_syscall+0x166/0x600
> > [<0>] system_call+0x6e/0x90
> >
> > --
> > Best Regards,
> >   Yi Zhang

Hi,

We have the following patch which fixes the crash for us. However, we
tested the changes in virtualized s390x VM, and observed a few hangs
initially, which later went away. We are not sure if it was because
the virtualization was slow or something else. Do you have s390x
hardware to test and confirm that the below change fixes the issue
cleanly without any other hangs/crashes?

From 85f8bb94b7357d50cd9daf5c5eb72a7c39cfdeba Mon Sep 17 00:00:00 2001
From: Grzegorz Prajsner <grzegorz.prajsner@ionos.com>
Date: Thu, 9 Apr 2026 13:29:59 +0200
Subject: [PATCH] RDMA/rtrs-srv: Fix processing messages for Big-Endian archs

Convert msg->sg_cnt from le16 to cpu endianness before processing
it. This fixes bug processing messages on Big-Endian architectures.

Signed-off-by: Grzegorz Prajsner <grzegorz.prajsner@ionos.com>
Signed-off-by: Md Haris Iqbal <haris.iqbal@ionos.com>
---
 drivers/infiniband/ulp/rtrs/rtrs-srv.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index 0140bfaed721..978daa69e096 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -1044,7 +1044,7 @@ static void process_read(struct rtrs_srv_con *con,
        struct rtrs_srv_ctx *ctx = srv->ctx;
        struct rtrs_srv_op *id;

-       size_t usr_len, data_len;
+       size_t usr_len, data_len, sg_cnt;
        void *data;
        int ret;

@@ -1054,7 +1054,8 @@ static void process_read(struct rtrs_srv_con *con,
                             rtrs_srv_state_str(srv_path->state));
                return;
        }
-       if (msg->sg_cnt != 1 && msg->sg_cnt != 0) {
+       sg_cnt = le16_to_cpu(msg->sg_cnt);
+       if (sg_cnt != 1 && sg_cnt != 0) {
                rtrs_err_rl(s,
                            "Processing read request failed, invalid
message\n");
                return;
-- 
2.43.0

> >

^ permalink raw reply related

* [PATCH] iov_iter: use kmemdup_array for dup_iter to harden against overflow
From: Wang Haoran @ 2026-04-13  6:06 UTC (permalink / raw)
  To: viro, akpm; +Cc: linux-block, linux-fsdevel, linux-kernel, Wang Haoran

While auditing the Linux 7.0-rc2 kernel, I identified a potential security
vulnerability in the iov_iter framework's memory allocation logic.

The dup_iter() function, which is exported via EXPORT_SYMBOL, currently
uses kmemdup() with a raw multiplication to allocate the duplicate iovec array:

new->iov = kmemdup(from->iov, nr_segs * sizeof(struct iovec), gfp);

The hazard here is that dup_iter() relies on a primitive multiplication without
any integrated overflow check. Since nr_segs is often derived from user-space
input, this line is vulnerable to integer overflow (on 32-bit systems or
via type narrowing), potentially leading to a small allocation followed by a
large out-of-bounds memory copy. Furthermore, it allows for unbounded memory
allocations, as the function lacks intrinsic knowledge of safe limits.

On the 7.0-rc2 branch, several high-impact callchains still rely on this
exported function:

drivers/usb/gadget/function/f_fs.c:
The ffs_epfile_read_iter() path demonstrates why relying on dup_iter() is
dangerous: it performs allocation based on user input before verifying driver
state. This confirms that dup_iter() must be hardened internally as it cannot
assume pre-validated input.

drivers/usb/gadget/legacy/inode.c:
The ep_read_iter() path illustrates how dup_iter()’s lack of boundary awareness
compounds resource risks. When combined with other allocations, it creates
a multiplier effect for kernel memory pressure.

This patch replaces kmemdup() with kmemdup_array(), which utilizes
check_mul_overflow() to ensure the allocation size is calculated safely,
hardening dup_iter() against malicious or malformed inputs from its callers

Signed-off-by: Wang Haoran <haoranwangsec@gmail.com>
---
 lib/iov_iter.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 0a63c7fba..63aa8b6e3 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1224,13 +1224,13 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
 {
 	*new = *old;
 	if (iov_iter_is_bvec(new))
-		return new->bvec = kmemdup(new->bvec,
-				    new->nr_segs * sizeof(struct bio_vec),
+		return new->bvec = kmemdup_array(new->bvec,
+				    new->nr_segs, sizeof(struct bio_vec),
 				    flags);
 	else if (iov_iter_is_kvec(new) || iter_is_iovec(new))
 		/* iovec and kvec have identical layout */
-		return new->__iov = kmemdup(new->__iov,
-				   new->nr_segs * sizeof(struct iovec),
+		return new->__iov = kmemdup_array(new->__iov,
+				   new->nr_segs, sizeof(struct iovec),
 				   flags);
 	return NULL;
 }
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v3 02/12] block/bdev: Annotate the blk_holder_ops callback invocations
From: Marco Elver @ 2026-04-13  6:00 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Jens Axboe, linux-block, Damien Le Moal,
	Nathan Chancellor
In-Reply-To: <08078df0-d3e6-4860-b22b-937035d45857@acm.org>

On Sat, 11 Apr 2026 at 01:44, Bart Van Assche <bvanassche@acm.org> wrote:
>
> On 4/10/26 3:43 PM, Marco Elver wrote:
> > Can you retry? Thanks!
>
> Thanks, this works much better! However, I think there is still an issue
> with this new version: no compiler warning is emitted if one function
> pointer is assigned to another function pointer and the lock context
> annotations of the two pointers differ.

For now, that's intended - focus is on getting rid of false positives.
Doing what you suggest above would require abusing the attributes to
effectively become type qualifiers; that's generally questionable,
because that's not what attributes are meant to do (and reworking TSA
to provide real type-qualifiers is an intrusion into the type system
that's also a hard sell). So for now, I'll try to do the simpler
change, and later may look into adding -Wthread-safety specific
warnings that points out such mismatches.

^ permalink raw reply

* Re: [PATCH v10 13/13] docs: add io_queue flag to isolcpus
From: Aaron Tomlin @ 2026-04-12 22:50 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: <adpD8M8cNu3IZzEL@fedora>

[-- Attachment #1: Type: text/plain, Size: 7212 bytes --]

On Sat, Apr 11, 2026 at 08:52:00PM +0800, Ming Lei wrote:
> > The critical issue lies at the invocation of group_cpus_evenly(). Without
> > this patchset, the core logic lacks the necessary constraints to respect
> > CPU isolation. It is entirely possible, and indeed happens in practice, for
> > an isolated CPU to be assigned to a CPU mask group.
> 
> It is one bug report? No, because it doesn't show any trouble from user
> viewpoint.

Hi Ming,

The lack of a formal bug report does not negate the fact that the current
behaviour silently breaks the fundamental contract of CPU isolation from
the administrator's perspective.

To illustrate the user-visible impact, the following demonstrates the
difference between relying on isolcpus=managed_irq and isolcpus=io_queue
under 7.0.0-rc3-00065-gd80965e205a5, which includes this series.

The Broadcom MPI3 Storage Controller driver allocates a full complement of
48 operational queue pairs. Consequently, a number of MSI-X vectors are
generated and mapped directly onto the isolated cores thereby breaching
isolation.

    # uname -r
    7.0.0-rc3-00065-gd80965e205a5

    # tr ' ' '\n' < /proc/cmdline | grep isolcpus=
    isolcpus=managed_irq,domain,2-47

    # cat /sys/devices/system/cpu/isolated
    2-47

    # dmesg | grep -A 6 'MSI-X vectors supported:'
    [   2.981705] mpi3mr0: MSI-X vectors supported: 128, no of cores: 48,
    [   2.981705] mpi3mr0: MSI-X vectors requested: 49 poll_queues 0
    [   3.001915] mpi3mr0: trying to create 48 operational queue pairs
    [   3.011214] mpi3mr0: allocating operational queues through segmented queues 
    [   3.101903] mpi3mr0: successfully created 48 operational queue pairs(default/polled) queue = (2/0)
    [   3.111468] mpi3mr0: controller initialization completed successfully

    # awk '/mpi3mr0/ { print $1" "$NF }' /proc/interrupts
    78: mpi3mr0-msix0
    79: mpi3mr0-msix1
    80: mpi3mr0-msix2
    81: mpi3mr0-msix3
    82: mpi3mr0-msix4
    83: mpi3mr0-msix5
    84: mpi3mr0-msix6
    85: mpi3mr0-msix7
    86: mpi3mr0-msix8
    87: mpi3mr0-msix9
    88: mpi3mr0-msix10
    89: mpi3mr0-msix11
    90: mpi3mr0-msix12
    ...
    122: mpi3mr0-msix44
    123: mpi3mr0-msix45
    124: mpi3mr0-msix46
    125: mpi3mr0-msix47
    126: mpi3mr0-msix48

    # grep -H '' /proc/irq/{119,120,121,122}/{effective,smp}_affinity_list
    /proc/irq/119/effective_affinity_list:42
    /proc/irq/119/smp_affinity_list:42
    /proc/irq/120/effective_affinity_list:43
    /proc/irq/120/smp_affinity_list:43
    /proc/irq/121/effective_affinity_list:44
    /proc/irq/121/smp_affinity_list:44
    /proc/irq/122/effective_affinity_list:45
    /proc/irq/122/smp_affinity_list:45


Now with isolcpus=io_queue,2-47 the allocation is structurally restricted
at the source. The driver creates only two operational queues, confining
all resulting interrupts exclusively to housekeeping CPUs (0 and 1):

    # uname -r
    7.0.0-rc3-00065-gd80965e205a5

    # tr ' ' '\n' < /proc/cmdline | grep isolcpus=
    isolcpus=io_queue,domain,2-47

    # cat /sys/devices/system/cpu/isolated
    2-47

    # dmesg | grep -A 6 'MSI-X vectors supported:'
    [   3.284850] mpi3mr0: MSI-X vectors supported: 128, no of cores: 48,
    [   3.284851] mpi3mr0: MSI-X vectors requested: 49 poll_queues 0
    [   3.305492] mpi3mr0: allocated vectors (3) are less than configured (49)
    [   3.316528] mpi3mr0: trying to create 2 operational queue pairs
    [   3.328013] mpi3mr0: allocating operational queues through segmented queues
    [   3.340697] mpi3mr0: successfully created 2 operational queue pairs(default/polled) queue = (2/0)
    [   3.350664] mpi3mr0: controller initialization completed successfully

    # awk '/mpi3mr0/ { print $1" "$NF }' /proc/interrupts
    79: mpi3mr0-msix0
    80: mpi3mr0-msix1
    81: mpi3mr0-msix2

    # grep -H '' /proc/irq/{79,80,81}/{effective,smp}_affinity_list
    /proc/irq/79/effective_affinity_list:1
    /proc/irq/79/smp_affinity_list:1
    /proc/irq/80/effective_affinity_list:1
    /proc/irq/80/smp_affinity_list:1
    /proc/irq/81/effective_affinity_list:0
    /proc/irq/81/smp_affinity_list:0

> Sebastian explains/shows how "isolcpus=managed_irq" works perfectly in the
> following link:
> 
> https://lore.kernel.org/all/20260401110232.ET5RxZfl@linutronix.de/
> 
> You have reviewed it...
> 
> What matters is that IO won't interrupt isolated CPU.

The isolcpus=managed_irq acts as a "best effort" avoidance algorithm rather
than a strict, unbreakable constraint. This is indicated in the proposed
changes to Documentation/core-api/irq/managed_irq.rst [1].

[1]: https://lore.kernel.org/all/20260401110232.ET5RxZfl@linutronix.de/

The following is an excerpt of irq_do_set_affinity().

 - File: kernel/irq/manage.c

 232 int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 233 {
 234         struct cpumask *tmp_mask = this_cpu_ptr(&__tmp_mask);
  :
 262         if (irqd_affinity_is_managed(data) &&
 263             housekeeping_enabled(HK_TYPE_MANAGED_IRQ)) {
 264                 const struct cpumask *hk_mask;
 265 
 266                 hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
 267 
 268                 cpumask_and(tmp_mask, mask, hk_mask);
 269                 if (!cpumask_intersects(tmp_mask, cpu_online_mask))
 270                         prog_mask = mask;
 271                 else
 272                         prog_mask = tmp_mask;
 273         } else {
 274                 prog_mask = mask;
 275         }

    1.  If the requested mask consists only of isolated CPUs (e.g., 2-47),
        it will have zero intersection with the hk_mask (which contains
        only the housekeeping CPUs). Consequently, the resulting tmp_mask
        becomes completely empty.

    2.  Because the tmp_mask is empty, it cannot intersect with the
        cpu_online_mask.

    3.  The kernel triggers this fallback path. It abandons the empty,
        filtered tmp_mask and reverts back to the originally requested
        mask, which only contains isolated CPUs. Consequently, the
        interrupt is routed directly to an isolated CPU, proving that
        managed_irq cannot guarantee isolation. 

> > The newer implementation of irq_create_affinity_masks() introduced by this
> > series resolves this. It considers the new CPU mask added to the IRQ
> > affinity descriptor. When group_mask_cpus_evenly() is called, this mask is
> > evaluated [1], guaranteeing that isolated CPUs are entirely excluded from
> > the mask groups.
> > 
> > [1]: https://lore.kernel.org/lkml/20260401222312.772334-8-atomlin@atomlin.com/
> 
> Not at all.
> 
> isolated CPU is still included in each group's cpu mask, please see patch
> 9:

You are entirely correct. The actual structural exclusion preventing the
interrupts from landing on those cores occurs subsequently via
irq_spread_hk_filter() in irq_create_affinity_masks() as per patch 12 [2].

[2]: https://lore.kernel.org/lkml/20260401222312.772334-13-atomlin@atomlin.com/


Kind regards,
-- 
Aaron Tomlin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH 2/4] tools: ynl-gen-c: optionally emit structs and helpers
From: Jakub Kicinski @ 2026-04-12 19:55 UTC (permalink / raw)
  To: Christoph Böhmwalder
  Cc: Jens Axboe, drbd-dev, linux-kernel, Lars Ellenberg,
	Philipp Reisner, linux-block, Donald Hunter, Eric Dumazet, netdev
In-Reply-To: <20260407173356.873887-3-christoph.boehmwalder@linbit.com>

On Tue,  7 Apr 2026 19:33:54 +0200 Christoph Böhmwalder wrote:
> The new flags in the genetlink-legacy spec that are required for
> existing consumers to keep working are:
> 
>   "default": a literal value or C define that sets the default value
>   for an attribute, consumed by set_defaults().
> 
>   "required": if true, from_attrs() returns an error when this
>   attribute is missing from the request message.
> 
>   "nla-policy-type": can be used to override the NLA type used in
>   policy arrays. This is needed when the semantic type differs from
>   the wire type for backward compatibility: genl_magic maps s32 fields
>   to NLA_U32/nla_get_u32, and existing userspace might depend on this
>   encoding. The immediate motivation is DRBD, whose genl spec
>   definition predates the addition of signed types in genl. However,
>   this is a generic issue that potentially affects multiple families:
>   for example, nftables has NFTA_HOOK_PRIORITY as s32 in the spec but
>   NLA_U32 in the actual kernel policy.

The series doesn't apply for me (neither to Linus's tree nor 
to networking trees), so I didn't experiment with this code.

Are the new code gen additions purely for the kernel?
Can we just commit the code they output and leave the YNL itself be?
Every single legacy family has some weird quirks the point of YNL
is to get rid of them, not support them all..

^ permalink raw reply

* Re: [PATCH 06/20] drbd: add RDMA transport implementation
From: Leon Romanovsky @ 2026-04-12 16:36 UTC (permalink / raw)
  To: Christoph Hellwig, Jens Axboe, drbd-dev, linux-kernel,
	Lars Ellenberg, Philipp Reisner, linux-block, Joel Colledge,
	linux-rdma, Jason Gunthorpe
In-Reply-To: <adZCPanS7iZlcPE9@localhost.localdomain>

On Wed, Apr 08, 2026 at 02:01:43PM +0200, Christoph Böhmwalder wrote:
> On Tue, Apr 07, 2026 at 10:42:55PM -0700, Christoph Hellwig wrote:
> > You really need to add the RDMA mailing list before adding new RDMA
> > code.  I'll try to review the bits I still remember, but you also
> > need a maintainer ACK.
> 
> Thanks for the hint and your detailed feedback. I'll address all that
> in v2 (plus some other similar fixes).

Thanks Christoph for adding us.
I fast-forward read the patch and immediately spotted two things:
1. Please don't call directly to HW drivers.
+	err = device->ops.query_device(device, &dev_attr, &uhw);
+	if (err) {
+		tr_err(transport, "ib_query_device: %d\n", err);
+		return err;
+	}

2. Add any missing API to RDMA subsystem, don't leave it to the users:
+	} else if (reduced) {
+		/* ib_create_qp() may return -ENOMEM if max_send_wr or max_recv_wr are
+		   too big. Unfortunately there is no way to find the working maxima.
+		   http://www.rdmamojo.com/2012/12/21/ibv_create_qp/
+		   Suggests "Trial end error" to find the maximal number. */
+
+		tr_warn(transport, "Needed to adjust buffer sizes for HCA\n");
+		tr_warn(transport, "rcvbuf = %d sndbuf = %d \n",
+			path->flow[DATA_STREAM].rx_descs_max * DRBD_SOCKET_BUFFER_SIZE,
+			path->flow[DATA_STREAM].tx_descs_max * DRBD_SOCKET_BUFFER_SIZE);
+		tr_warn(transport, "It is recommended to apply this change to the configuration\n");
+	}
+

Thanks


> 
> Thanks,
> Christoph

^ permalink raw reply

* Re: [RFC PATCH] zram: support asynchronous GC for lazy slot freeing
From: Kairui Song @ 2026-04-12 11:48 UTC (permalink / raw)
  To: Barry Song (Xiaomi)
  Cc: minchan, senozhatsky, akpm, linux-mm, axboe, linux-block,
	linux-kernel, kasong, chrisl, justinjiang, liulei.rjpt,
	Xueyuan Chen
In-Reply-To: <20260412060450.15813-1-baohua@kernel.org>

On Sun, Apr 12, 2026 at 02:04:50PM +0800, Barry Song (Xiaomi) wrote:
> Swap freeing can be expensive when unmapping a VMA containing
> many swap entries. This has been reported to significantly
> delay memory reclamation during Android’s low-memory killing,
> especially when multiple processes are terminated to free
> memory, with slot_free() accounting for more than 80% of
> the total cost of freeing swap entries.
> 
> Two earlier attempts by Lei and Zhiguo added a new thread in the mm core
> to asynchronously collect and free swap entries [1][2], but the
> design itself is fairly complex.
> 
> When anon folios and swap entries are mixed within a
> process, reclaiming anon folios from killed processes
> helps return memory to the system as quickly as possible,
> so that newly launched applications can satisfy their
> memory demands. It is not ideal for swap freeing to block
> anon folio freeing. On the other hand, swap freeing can
> still return memory to the system, although at a slower
> rate due to memory compression.
> 
> Therefore, in zram, we introduce a GC worker to allow anon
> folio freeing and slot_free to run in parallel, since
> slot_free is performed asynchronously, maximizing the rate at
> which memory is returned to the system.
> 
> Xueyuan’s test on RK3588 shows that unmapping a 256MB swap-filled
> VMA becomes 3.4× faster when pinning tasks to CPU2, reducing the
> execution time from 63,102,982 ns to 18,570,726 ns.
> 
> A positive side effect is that async GC also slightly improves
> do_swap_page() performance, as it no longer has to wait for
> slot_free() to complete.
> 
> Xueyuan’s test shows that swapping in 256MB of data (each page
> filled with repeating patterns such as “1024 one”, “1024 two”,
> “1024 three”, and “1024 four”) reduces execution time from
> 1,358,133,886 ns to 1,104,315,986 ns, achieving a 1.22× speedup.
> 
> [1] https://lore.kernel.org/all/20240805153639.1057-1-justinjiang@vivo.com/
> [2] https://lore.kernel.org/all/20250909065349.574894-1-liulei.rjpt@vivo.com/
> 
> Tested-by: Xueyuan Chen <xueyuan.chen21@gmail.com>
> Signed-off-by: Barry Song (Xiaomi) <baohua@kernel.org>

Hi Barry

This looks an interesting idea to me.

> ---
>  drivers/block/zram/zram_drv.c | 56 ++++++++++++++++++++++++++++++++++-
>  drivers/block/zram/zram_drv.h |  3 ++
>  2 files changed, 58 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
> index c2afd1c34f4a..f5c07eb997a8 100644
> --- a/drivers/block/zram/zram_drv.c
> +++ b/drivers/block/zram/zram_drv.c
> @@ -1958,6 +1958,23 @@ static ssize_t debug_stat_show(struct device *dev,
>  	return ret;
>  }
>  
> +static void gc_slots_free(struct zram *zram)
> +{
> +	size_t num_pages = zram->disksize >> PAGE_SHIFT;
> +	unsigned long index;
> +
> +	index = find_next_bit(zram->gc_map, num_pages, 0);
> +	while (index < num_pages) {
> +		if (slot_trylock(zram, index)) {
> +			if (test_bit(index, zram->gc_map))
> +				slot_free(zram, index);
> +			slot_unlock(zram, index);
> +			cond_resched();
> +		}
> +		index = find_next_bit(zram->gc_map, num_pages, index + 1);
> +	}
> +}
> +

The ideas looks interesting but the implementation looks not that
optimal to me. find_next_bit does a O(n) looks up for every gc call
looks really expensive if the pending slot is at tail.

Perhaps a percpu stack can be used, something like the folio batch?

> -	slot_free(zram, index);
> +	if (!try_slot_lazy_free(zram, index))
> +		slot_free(zram, index);

What is making this slot_free so costly? zs_free?

>  	slot_unlock(zram, index);
>  }
>  
> diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
> index 08d1774c15db..1f3ffd79fcb1 100644
> --- a/drivers/block/zram/zram_drv.h
> +++ b/drivers/block/zram/zram_drv.h
> @@ -88,6 +88,7 @@ struct zram_stats {
>  	atomic64_t pages_stored;	/* no. of pages currently stored */
>  	atomic_long_t max_used_pages;	/* no. of maximum pages stored */
>  	atomic64_t miss_free;		/* no. of missed free */
> +	atomic64_t gc_slots;		/* no. of queued for lazy free by gc */

Maybe we want to track the size of content being delayed instead
of slots number? I saw there is a 30000 hard limit for that.

Perhaps it will make more sense if we have a "buffer size"
(e.g. 64M), seems more intuitive to me. e.g. the ZRAM module can occupy
at most 64M of memory, so the delayed free won't cause a significant
global pressure.

Also I think this patch is batching the memory free operations, so the
workqueue or design can also be further optimized for batching, for
example if the zs_free is the expensive part then maybe we shall just
clear the handler for the freeing slot and leave the handler in a
percpu stack, then batch free these handlers. zsmalloc might make
use some batch optimization based on that too, something like
kmem_cache_free_bulk but for zsmalloc?

if zs_free is not all the expensive part, I took a look at slot_free
maybe a lot of read / write of slot data can be merged.

This patch currently doesn't reduce the total amount of work, but
if above idea works, a lot of redundant operations might be be dropped,
result in better performance in every case.

Just my two cents and ideas, not sure if I got everything correct.
Looking forward for more disscussion on this :)

^ permalink raw reply

* [RFC PATCH] zram: support asynchronous GC for lazy slot freeing
From: Barry Song (Xiaomi) @ 2026-04-12  6:04 UTC (permalink / raw)
  To: minchan, senozhatsky, akpm, linux-mm
  Cc: axboe, linux-block, linux-kernel, kasong, chrisl, justinjiang,
	liulei.rjpt, Barry Song (Xiaomi), Xueyuan Chen

Swap freeing can be expensive when unmapping a VMA containing
many swap entries. This has been reported to significantly
delay memory reclamation during Android’s low-memory killing,
especially when multiple processes are terminated to free
memory, with slot_free() accounting for more than 80% of
the total cost of freeing swap entries.

Two earlier attempts by Lei and Zhiguo added a new thread in the mm core
to asynchronously collect and free swap entries [1][2], but the
design itself is fairly complex.

When anon folios and swap entries are mixed within a
process, reclaiming anon folios from killed processes
helps return memory to the system as quickly as possible,
so that newly launched applications can satisfy their
memory demands. It is not ideal for swap freeing to block
anon folio freeing. On the other hand, swap freeing can
still return memory to the system, although at a slower
rate due to memory compression.

Therefore, in zram, we introduce a GC worker to allow anon
folio freeing and slot_free to run in parallel, since
slot_free is performed asynchronously, maximizing the rate at
which memory is returned to the system.

Xueyuan’s test on RK3588 shows that unmapping a 256MB swap-filled
VMA becomes 3.4× faster when pinning tasks to CPU2, reducing the
execution time from 63,102,982 ns to 18,570,726 ns.

A positive side effect is that async GC also slightly improves
do_swap_page() performance, as it no longer has to wait for
slot_free() to complete.

Xueyuan’s test shows that swapping in 256MB of data (each page
filled with repeating patterns such as “1024 one”, “1024 two”,
“1024 three”, and “1024 four”) reduces execution time from
1,358,133,886 ns to 1,104,315,986 ns, achieving a 1.22× speedup.

[1] https://lore.kernel.org/all/20240805153639.1057-1-justinjiang@vivo.com/
[2] https://lore.kernel.org/all/20250909065349.574894-1-liulei.rjpt@vivo.com/

Tested-by: Xueyuan Chen <xueyuan.chen21@gmail.com>
Signed-off-by: Barry Song (Xiaomi) <baohua@kernel.org>
---
 drivers/block/zram/zram_drv.c | 56 ++++++++++++++++++++++++++++++++++-
 drivers/block/zram/zram_drv.h |  3 ++
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index c2afd1c34f4a..f5c07eb997a8 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1958,6 +1958,23 @@ static ssize_t debug_stat_show(struct device *dev,
 	return ret;
 }
 
+static void gc_slots_free(struct zram *zram)
+{
+	size_t num_pages = zram->disksize >> PAGE_SHIFT;
+	unsigned long index;
+
+	index = find_next_bit(zram->gc_map, num_pages, 0);
+	while (index < num_pages) {
+		if (slot_trylock(zram, index)) {
+			if (test_bit(index, zram->gc_map))
+				slot_free(zram, index);
+			slot_unlock(zram, index);
+			cond_resched();
+		}
+		index = find_next_bit(zram->gc_map, num_pages, index + 1);
+	}
+}
+
 static void zram_meta_free(struct zram *zram, u64 disksize)
 {
 	size_t num_pages = disksize >> PAGE_SHIFT;
@@ -1966,6 +1983,9 @@ static void zram_meta_free(struct zram *zram, u64 disksize)
 	if (!zram->table)
 		return;
 
+	flush_work(&zram->gc_work);
+	gc_slots_free(zram);
+
 	/* Free all pages that are still in this zram device */
 	for (index = 0; index < num_pages; index++)
 		slot_free(zram, index);
@@ -1973,6 +1993,14 @@ static void zram_meta_free(struct zram *zram, u64 disksize)
 	zs_destroy_pool(zram->mem_pool);
 	vfree(zram->table);
 	zram->table = NULL;
+	bitmap_free(zram->gc_map);
+}
+
+static void zram_gc_work(struct work_struct *work)
+{
+	struct zram *zram = container_of(work, struct zram, gc_work);
+
+	gc_slots_free(zram);
 }
 
 static bool zram_meta_alloc(struct zram *zram, u64 disksize)
@@ -1991,12 +2019,22 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
 		return false;
 	}
 
+	zram->gc_map = bitmap_zalloc(num_pages, GFP_KERNEL);
+	if (!zram->gc_map) {
+		zs_destroy_pool(zram->mem_pool);
+		vfree(zram->table);
+		zram->table = NULL;
+		return false;
+	}
+
 	if (!huge_class_size)
 		huge_class_size = zs_huge_class_size(zram->mem_pool);
 
 	for (index = 0; index < num_pages; index++)
 		slot_lock_init(zram, index);
 
+	INIT_WORK(&zram->gc_work, zram_gc_work);
+
 	return true;
 }
 
@@ -2008,6 +2046,8 @@ static void slot_free(struct zram *zram, u32 index)
 	zram->table[index].attr.ac_time = 0;
 #endif
 
+	if (test_and_clear_bit(index, zram->gc_map))
+		atomic64_dec(&zram->stats.gc_slots);
 	clear_slot_flag(zram, index, ZRAM_IDLE);
 	clear_slot_flag(zram, index, ZRAM_INCOMPRESSIBLE);
 	clear_slot_flag(zram, index, ZRAM_PP_SLOT);
@@ -2781,6 +2821,19 @@ static void zram_submit_bio(struct bio *bio)
 	}
 }
 
+static bool try_slot_lazy_free(struct zram *zram, unsigned long index)
+{
+	/* too many lazy-free slots, perform direct free */
+	if (atomic64_read(&zram->stats.gc_slots) > 30000)
+		return false;
+	if (test_and_set_bit(index, zram->gc_map))
+		return false;
+	/* accumulated lazy-free slots, wake up GC worker */
+	if (atomic64_inc_return(&zram->stats.gc_slots) > 200)
+		queue_work(system_dfl_wq, &zram->gc_work);
+	return true;
+}
+
 static void zram_slot_free_notify(struct block_device *bdev,
 				unsigned long index)
 {
@@ -2794,7 +2847,8 @@ static void zram_slot_free_notify(struct block_device *bdev,
 		return;
 	}
 
-	slot_free(zram, index);
+	if (!try_slot_lazy_free(zram, index))
+		slot_free(zram, index);
 	slot_unlock(zram, index);
 }
 
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 08d1774c15db..1f3ffd79fcb1 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -88,6 +88,7 @@ struct zram_stats {
 	atomic64_t pages_stored;	/* no. of pages currently stored */
 	atomic_long_t max_used_pages;	/* no. of maximum pages stored */
 	atomic64_t miss_free;		/* no. of missed free */
+	atomic64_t gc_slots;		/* no. of queued for lazy free by gc */
 #ifdef	CONFIG_ZRAM_WRITEBACK
 	atomic64_t bd_count;		/* no. of pages in backing device */
 	atomic64_t bd_reads;		/* no. of reads from backing device */
@@ -142,5 +143,7 @@ struct zram {
 #ifdef CONFIG_ZRAM_MEMORY_TRACKING
 	struct dentry *debugfs_dir;
 #endif
+	unsigned long *gc_map;
+	struct work_struct gc_work;
 };
 #endif
-- 
2.39.3 (Apple Git-146)


^ permalink raw reply related

* [GIT PULL] Block changes for the 7.1 merge window
From: Jens Axboe @ 2026-04-11 23:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-block@vger.kernel.org

Hi Linus,

Same as the io_uring one, coming a bit early due to already stated
reasons. These are the changes queued up for the 7.1 merge window in the
block subsystem:

- Add shared memory zero-copy I/O support for ublk, bypassing per-I/O
  copies between kernel and userspace by matching registered buffer
  PFNs at I/O time. Includes selftests.

- Refactor bio integrity to support filesystem initiated integrity
  operations and arbitrary buffer alignment.

- Clean up bio allocation, splitting bio_alloc_bioset() into clear
  fast and slow paths. Add bio_await() and bio_submit_or_kill()
  helpers, unify synchronous bi_end_io callbacks.

- Fix zone write plug refcount handling and plug removal races. Add
  support for serializing zone writes at QD=1 for rotational zoned
  devices, yielding significant throughput improvements.

- Add SED-OPAL ioctls for Single User Mode management and a
  STACK_RESET command.

- Add io_uring passthrough (uring_cmd) support to the BSG layer.

- Replace pp_buf in partition scanning with struct seq_buf.

- zloop improvements and cleanups.

- drbd genl cleanup, switching to pre_doit/post_doit.

- NVMe pull request via Keith:
     - Fabrics authentication updates
     - Enhanced block queue limits support
     - Workqueue usage updates
     - A new write zeroes device quirk
     - Tagset cleanup fix for loop device

- MD pull requests via Yu Kuai:
     - Fix raid5 soft lockup in retry_aligned_read()
     - Fix raid10 deadlock with check operation and nowait requests
     - Fix raid1 overlapping writes on writemostly disks
     - Fix sysfs deadlock on array_state=clear
     - Proactive RAID-5 parity building with llbitmap, with
       write_zeroes_unmap optimization for initial sync
     - Fix llbitmap barrier ordering, rdev skipping, and bitmap_ops
       version mismatch fallback
     - Fix bcache use-after-free and uninitialized closure
     - Validate raid5 journal metadata payload size
     - Various cleanups

- Various other fixes, improvements, and cleanups

The following changes since commit 1f318b96cc84d7c2ab792fcc0bfd42a7ca890681:

  Linux 7.0-rc3 (2026-03-08 16:56:54 -0700)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git tags/for-7.1/block-20260411

for you to fetch changes up to 36446de0c30c62b9d89502fd36c4904996d86ecd:

  ublk: fix tautological comparison warning in ublk_ctrl_reg_buf (2026-04-10 07:02:37 -0600)

----------------------------------------------------------------
for-7.1/block-20260411

----------------------------------------------------------------
Abd-Alrhman Masalkhi (1):
      md: remove unused static md_wq workqueue

Alistair Francis (6):
      nvmet-tcp: Don't error if TLS is enabed on a reset
      nvmet-tcp: Don't free SQ on authentication success
      nvme: Expose the tls_configured sysfs for secure concat connections
      nvme: Allow reauth from sysfs
      nvme: Add the DHCHAP maximum HD IDs
      nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C

Bart Van Assche (1):
      drbd: Balance RCU calls in drbd_adm_dump_devices()

Bill Wendling (1):
      block: annotate struct request_queue with __counted_by_ptr

Caleb Sander Mateos (10):
      ublk: report BLK_SPLIT_INTERVAL_CAPABLE
      nvme: add preferred I/O size fields to struct nvme_id_ns_nvm
      nvme: fold nvme_config_discard() into nvme_update_disk_info()
      nvme: update nvme_id_ns OPTPERF constants
      nvme: always issue I/O Command Set specific Identify Namespace
      nvme: add from0based() helper
      nvme: set discard_granularity from NPDG/NPDA
      nvmet: use NVME_NS_FEAT_OPTPERF_SHIFT
      nvmet: report NPDGL and NPDAL
      block: remove unused BVEC_ITER_ALL_INIT

Chaitanya Kulkarni (2):
      block: move bio queue-transition flag fixups into blk_steal_bios()
      block: clear BIO_QOS flags in blk_steal_bios()

Chen Cheng (4):
      md: suppress spurious superblock update error message for dm-raid
      md/raid5: remove stale md_raid5_kick_device() declaration
      md/raid5: move handle_stripe() comment to correct location
      md: remove unused mddev argument from export_rdev

Chia-Ming Chang (1):
      md/raid5: fix soft lockup in retry_aligned_read()

Christoph Böhmwalder (2):
      drbd: use genl pre_doit/post_doit
      drbd: remove DRBD_GENLA_F_MANDATORY flag handling

Christoph Hellwig (19):
      block: factor out a bio_integrity_action helper
      block: factor out a bio_integrity_setup_default helper
      block: add a bdev_has_integrity_csum helper
      block: prepare generation / verification helpers for fs usage
      block: make max_integrity_io_size public
      block: add fs_bio_integrity helpers
      block: pass a maxlen argument to bio_iov_iter_bounce
      block: mark bvec_{alloc,free} static
      block: split bio_alloc_bioset more clearly into a fast and slowpath
      block: remove bvec_free
      zloop: refactor zloop_rw
      zloop: forget write cache on force removal
      blk-crypto: fix name of the bio completion callback
      xfs: fix number of GC bvecs
      block: unify the synchronous bi_end_io callbacks
      block: factor out a bio_await helper
      block: add a bio_submit_or_kill helper
      xfs: use bio_await in xfs_zone_gc_reset_sync
      block: refactor blkdev_zone_mgmt_ioctl

Daan De Meyer (1):
      loop: fix partition scan race between udev and loop_reread_partitions()

Damien Le Moal (10):
      block: fix zone write plug removal
      block: fix zone write plugs refcount handling in disk_zone_wplug_schedule_bio_work()
      block: rename and simplify disk_get_and_lock_zone_wplug()
      block: remove disk_zone_is_full()
      block: rename struct gendisk zone_wplugs_lock field
      block: allow submitting all zone writes from a single context
      block: default to QD=1 writes for blk-mq rotational zoned devices
      Documentation: ABI: stable: document the zoned_qd1_writes attribute
      block: remove bdev_nonrot()
      zloop: add max_open_zones option

Dan Carpenter (1):
      scsi: bsg: fix buffer overflow in scsi_bsg_uring_cmd()

David Carlier (1):
      drbd: use get_random_u64() where appropriate

Eric Biggers (21):
      nvme-auth: add NVME_AUTH_MAX_DIGEST_SIZE constant
      nvme-auth: common: constify static data
      nvme-auth: use proper argument types
      nvme-auth: common: add KUnit tests for TLS key derivation
      nvme-auth: rename nvme_auth_generate_key() to nvme_auth_parse_key()
      nvme-auth: common: explicitly verify psk_len == hash_len
      nvme-auth: common: add HMAC helper functions
      nvme-auth: common: use crypto library in nvme_auth_transform_key()
      nvme-auth: common: use crypto library in nvme_auth_augmented_challenge()
      nvme-auth: common: use crypto library in nvme_auth_generate_psk()
      nvme-auth: common: use crypto library in nvme_auth_generate_digest()
      nvme-auth: common: use crypto library in nvme_auth_derive_tls_psk()
      nvme-auth: host: use crypto library in nvme_auth_dhchap_setup_host_response()
      nvme-auth: host: use crypto library in nvme_auth_dhchap_setup_ctrl_response()
      nvme-auth: host: remove allocation of crypto_shash
      nvme-auth: target: remove obsolete crypto_has_shash() checks
      nvme-auth: target: use crypto library in nvmet_auth_host_hash()
      nvme-auth: target: use crypto library in nvmet_auth_ctrl_hash()
      nvme-auth: common: remove nvme_auth_digest_name()
      nvme-auth: common: remove selections of no-longer used crypto modules
      crypto: remove HKDF library

FengWei Shih (1):
      md/raid5: skip 2-failure compute when other disk is R5_LOCKED

Gregory Price (1):
      md/raid0: use kvzalloc/kvfree for strip_zone and devlist allocations

Jackie Liu (2):
      block: fix zones_cond memory leak on zone revalidation error paths
      blk-cgroup: fix disk reference leak in blkcg_maybe_throttle_current()

Jens Axboe (4):
      Merge branch 'for-7.1/block-integrity' into for-7.1/block
      Merge tag 'md-7.1-20260323' of git://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux into for-7.1/block
      Merge tag 'nvme-7.1-2026-03-27' of git://git.infradead.org/nvme into for-7.1/block
      Merge tag 'md-7.1-20260407' of git://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux into for-7.1/block

Jialin Wang (1):
      blk-iocost: fix busy_level reset when no IOs complete

John Garry (1):
      block: Correct comments on bio_alloc_clone() and bio_init_clone()

Josh Hunt (1):
      md/raid10: fix deadlock with check operation and nowait requests

Junrui Luo (1):
      md/raid5: validate payload size before accessing journal metadata

Kees Cook (1):
      block: partitions: Replace pp_buf with struct seq_buf

Keith Busch (1):
      blk-integrity: support arbitrary buffer alignment

Marco Crivellari (3):
      nvmet: replace use of system_wq with system_percpu_wq
      nvmet-fc: add WQ_PERCPU to alloc_workqueue users
      nvme: add WQ_PERCPU to alloc_workqueue users

Milan Broz (1):
      sed-opal: Add STACK_RESET command

Ming Lei (21):
      blk-cgroup: wait for blkcg cleanup before initializing new disk
      ublk: move cold paths out of __ublk_batch_dispatch() for icache efficiency
      bio: fix kmemleak false positives from percpu bio alloc cache
      ublk: add UBLK_U_CMD_REG_BUF/UNREG_BUF control commands
      ublk: add PFN-based buffer matching in I/O path
      ublk: enable UBLK_F_SHMEM_ZC feature flag
      ublk: eliminate permanent pages[] array from struct ublk_buf
      selftests/ublk: add shared memory zero-copy support in kublk
      selftests/ublk: add UBLK_F_SHMEM_ZC support for loop target
      selftests/ublk: add shared memory zero-copy test
      selftests/ublk: add hugetlbfs shmem_zc test for loop target
      selftests/ublk: add filesystem fio verify test for shmem_zc
      selftests/ublk: add read-only buffer registration test
      ublk: widen ublk_shmem_buf_reg.len to __u64 for 4GB buffer support
      ublk: verify all pages in multi-page bvec fall within registered range
      ublk: simplify PFN range loop in __ublk_ctrl_reg_buf
      ublk: replace xarray with IDA for shmem buffer index allocation
      ublk: allow buffer registration before device is started
      Documentation: ublk: address review comments for SHMEM_ZC docs
      MAINTAINERS: update ublk driver maintainer email
      ublk: fix tautological comparison warning in ublk_ctrl_reg_buf

Mingzhe Zou (2):
      bcache: fix cached_dev.sb_bio use-after-free and crash
      bcache: fix uninitialized closure object

Nilay Shroff (1):
      nvme-loop: do not cancel I/O and admin tagset during ctrl reset/shutdown

Ondrej Kozina (9):
      sed-opal: add UID of Locking Table.
      sed-opal: add RangeStartRangeLengthPolicy parameter.
      sed-opal: add Admin1PIN parameter.
      sed-opal: add IOC_OPAL_REACTIVATE_LSP.
      sed-opal: refactor (split) IOC_OPAL_LR_SETUP internals.
      sed-opal: add IOC_OPAL_LR_SET_START_LEN ioctl.
      sed-opal: add IOC_OPAL_ENABLE_DISABLE_LR.
      sed-opal: increase column attribute type size to 64 bits.
      sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.

Qu Wenruo (1):
      block: reject zero length in bio_add_page()

Robert Beckett (2):
      nvme: respect NVME_QUIRK_DISABLE_WRITE_ZEROES when wzsl is set
      nvme-pci: add NVME_QUIRK_DISABLE_WRITE_ZEROES for Kingston OM3SGP4

Thomas Weißschuh (4):
      block: make queue_sysfs_entry instances const
      block: ia-ranges: make blk_ia_range_sysfs_entry instances const
      blk-crypto: make blk_crypto_attr instances const
      blk-mq: make blk_mq_hw_ctx_sysfs_entry instances const

Thorsten Blum (1):
      block: use sysfs_emit in sysfs show functions

Uday Shankar (2):
      ublk: reset per-IO canceled flag on each fetch
      selftests: ublk: test that teardown after incomplete recovery completes

Vasily Gorbik (1):
      block: fix bio_alloc_bioset slowpath GFP handling

Xiao Ni (2):
      md/raid1: fix the comparing region of interval tree
      md/raid1: serialize overlap io for writemostly disk

Yang Xiuwei (3):
      bsg: add bsg_uring_cmd uapi structure
      bsg: add io_uring command support to generic layer
      scsi: bsg: add io_uring passthrough handler

Yu Kuai (8):
      md/raid5: set chunk_sectors to enable full stripe I/O splitting
      md/md-llbitmap: skip reading rdevs that are not in_sync
      md/md-llbitmap: raise barrier before state machine transition
      md: fix array_state=clear sysfs deadlock
      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
      md: wake raid456 reshape waiters before suspend

Yuto Ohnuki (1):
      blk-wbt: remove WARN_ON_ONCE from wbt_init_enable_default()

 Documentation/ABI/stable/sysfs-block              |  15 +
 Documentation/ABI/testing/sysfs-nvme              |  13 +
 Documentation/admin-guide/blockdev/zoned_loop.rst |  10 +-
 Documentation/block/inline-encryption.rst         |   2 +-
 Documentation/block/ublk.rst                      | 119 ++++
 MAINTAINERS                                       |   2 +-
 block/Makefile                                    |   2 +-
 block/bio-integrity-auto.c                        |  80 +--
 block/bio-integrity-fs.c                          |  81 +++
 block/bio-integrity.c                             |  64 ++
 block/bio.c                                       | 326 ++++-----
 block/blk-cgroup.c                                |  16 +
 block/blk-crypto-sysfs.c                          |  40 +-
 block/blk-ia-ranges.c                             |   6 +-
 block/blk-iocost.c                                |  23 +-
 block/blk-lib.c                                   |  16 +-
 block/blk-mq-debugfs.c                            |   1 +
 block/blk-mq-sysfs.c                              |  10 +-
 block/blk-mq.c                                    |  25 +-
 block/blk-settings.c                              |  25 +-
 block/blk-sysfs.c                                 |  89 ++-
 block/blk-wbt.c                                   |   5 +-
 block/blk-zoned.c                                 | 469 ++++++++-----
 block/blk.h                                       |  13 +-
 block/bsg-lib.c                                   |   2 +-
 block/bsg.c                                       |  33 +-
 block/disk-events.c                               |   3 +-
 block/ioctl.c                                     |  11 +-
 block/opal_proto.h                                |  24 +
 block/partitions/acorn.c                          |  32 +-
 block/partitions/aix.c                            |  21 +-
 block/partitions/amiga.c                          |  35 +-
 block/partitions/atari.c                          |  12 +-
 block/partitions/check.h                          |   8 +-
 block/partitions/cmdline.c                        |   6 +-
 block/partitions/core.c                           |  31 +-
 block/partitions/efi.c                            |   2 +-
 block/partitions/ibm.c                            |  27 +-
 block/partitions/karma.c                          |   2 +-
 block/partitions/ldm.c                            |   4 +-
 block/partitions/mac.c                            |   4 +-
 block/partitions/msdos.c                          |  67 +-
 block/partitions/of.c                             |   6 +-
 block/partitions/osf.c                            |   2 +-
 block/partitions/sgi.c                            |   2 +-
 block/partitions/sun.c                            |   2 +-
 block/partitions/sysv68.c                         |   9 +-
 block/partitions/ultrix.c                         |   2 +-
 block/sed-opal.c                                  | 434 +++++++++++-
 block/t10-pi.c                                    | 818 ++++++++++++----------
 crypto/Kconfig                                    |   6 -
 crypto/Makefile                                   |   1 -
 crypto/hkdf.c                                     | 573 ---------------
 drivers/block/drbd/Makefile                       |   1 -
 drivers/block/drbd/drbd_main.c                    |   4 +-
 drivers/block/drbd/drbd_nl.c                      | 602 +++++++++-------
 drivers/block/drbd/drbd_nla.c                     |  56 --
 drivers/block/drbd/drbd_nla.h                     |   9 -
 drivers/block/ublk_drv.c                          | 477 +++++++++++--
 drivers/block/zloop.c                             | 511 ++++++++++----
 drivers/md/bcache/super.c                         |   8 +
 drivers/md/md-llbitmap.c                          | 213 +++++-
 drivers/md/md.c                                   | 171 ++++-
 drivers/md/md.h                                   |   5 +-
 drivers/md/raid0.c                                |  18 +-
 drivers/md/raid1.c                                |  53 +-
 drivers/md/raid10.c                               |   6 +-
 drivers/md/raid5-cache.c                          |  48 +-
 drivers/md/raid5.c                                |  39 +-
 drivers/md/raid5.h                                |   1 -
 drivers/nvdimm/btt.c                              |   6 +-
 drivers/nvme/common/.kunitconfig                  |   6 +
 drivers/nvme/common/Kconfig                       |  14 +-
 drivers/nvme/common/Makefile                      |   2 +
 drivers/nvme/common/auth.c                        | 587 +++++++---------
 drivers/nvme/common/tests/auth_kunit.c            | 175 +++++
 drivers/nvme/host/auth.c                          | 187 ++---
 drivers/nvme/host/core.c                          |  89 ++-
 drivers/nvme/host/multipath.c                     |  15 +-
 drivers/nvme/host/nvme.h                          |   6 +
 drivers/nvme/host/pci.c                           |   2 +
 drivers/nvme/host/sysfs.c                         |  50 +-
 drivers/nvme/target/admin-cmd.c                   |   4 +-
 drivers/nvme/target/auth.c                        | 202 ++----
 drivers/nvme/target/configfs.c                    |   3 -
 drivers/nvme/target/core.c                        |   7 +-
 drivers/nvme/target/fabrics-cmd-auth.c            |  18 +-
 drivers/nvme/target/fc.c                          |   6 +-
 drivers/nvme/target/io-cmd-bdev.c                 |  19 +-
 drivers/nvme/target/loop.c                        |   2 -
 drivers/nvme/target/nvmet.h                       |   8 +-
 drivers/nvme/target/tcp.c                         |   2 +-
 drivers/scsi/scsi_bsg.c                           | 176 ++++-
 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 +-
 fs/iomap/direct-io.c                              |   2 +-
 fs/xfs/xfs_zone_gc.c                              |  38 +-
 include/crypto/hkdf.h                             |  20 -
 include/linux/bio-integrity.h                     |  12 +-
 include/linux/bio.h                               |   7 +-
 include/linux/blk-integrity.h                     |  29 +-
 include/linux/blkdev.h                            |  49 +-
 include/linux/bsg.h                               |   6 +-
 include/linux/bvec.h                              |   9 -
 include/linux/drbd_genl.h                         | 208 +++---
 include/linux/genl_magic_func.h                   |   7 +-
 include/linux/genl_magic_struct.h                 |  15 +-
 include/linux/nvme-auth.h                         |  41 +-
 include/linux/nvme.h                              |  24 +-
 include/linux/sed-opal.h                          |   5 +
 include/uapi/linux/bsg.h                          |  75 ++
 include/uapi/linux/sed-opal.h                     |  30 +
 include/uapi/linux/ublk_cmd.h                     |  80 +++
 mm/swapfile.c                                     |   2 +-
 tools/testing/selftests/ublk/Makefile             |   6 +
 tools/testing/selftests/ublk/fault_inject.c       |  52 +-
 tools/testing/selftests/ublk/file_backed.c        |  38 +
 tools/testing/selftests/ublk/kublk.c              | 354 +++++++++-
 tools/testing/selftests/ublk/kublk.h              |  18 +
 tools/testing/selftests/ublk/test_common.sh       |  15 +-
 tools/testing/selftests/ublk/test_generic_17.sh   |  35 +
 tools/testing/selftests/ublk/test_shmemzc_01.sh   |  72 ++
 tools/testing/selftests/ublk/test_shmemzc_02.sh   |  68 ++
 tools/testing/selftests/ublk/test_shmemzc_03.sh   |  69 ++
 tools/testing/selftests/ublk/test_shmemzc_04.sh   |  72 ++
 128 files changed, 5709 insertions(+), 3200 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-nvme
 create mode 100644 block/bio-integrity-fs.c
 delete mode 100644 crypto/hkdf.c
 delete mode 100644 drivers/block/drbd/drbd_nla.c
 delete mode 100644 drivers/block/drbd/drbd_nla.h
 create mode 100644 drivers/nvme/common/.kunitconfig
 create mode 100644 drivers/nvme/common/tests/auth_kunit.c
 delete mode 100644 include/crypto/hkdf.h
 create mode 100755 tools/testing/selftests/ublk/test_generic_17.sh
 create mode 100755 tools/testing/selftests/ublk/test_shmemzc_01.sh
 create mode 100755 tools/testing/selftests/ublk/test_shmemzc_02.sh
 create mode 100755 tools/testing/selftests/ublk/test_shmemzc_03.sh
 create mode 100755 tools/testing/selftests/ublk/test_shmemzc_04.sh

-- 
Jens Axboe


^ permalink raw reply

* Re: Re: [RFC PATCH 0/2] rust: block: add a borrowed blk-mq timeout callback
From: Miguel Ojeda @ 2026-04-11 22:47 UTC (permalink / raw)
  To: wenzhaoliao
  Cc: Greg KH, Andreas Hindborg, Jens Axboe, Miguel Ojeda, linux-block,
	rust-for-linux, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	linux-kernel
In-Reply-To: <ABUAdgD1KKnjiCpcrxWXD4pE.3.1775914622691.Hmail.2023000929@ruc.edu.cn>

On Sat, Apr 11, 2026 at 3:37 PM wenzhaoliao <wenzhaoliao@ruc.edu.cn> wrote:
>
> Learning from you that module options are considered 1990's technology and do not fit the modern kernel model is a great lesson for us. If we misunderstood the maintainer's intention, or if pursuing this outdated mechanism goes against modern kernel design principles, we sincerely apologize for the noise and for any burden this has caused.
>
> We are perfectly happy to drop this patch if this functionality is no longer desired in the modern kernel. We really just want to help improve the kernel, and we will try our best to sync with the maintainers to pick up tasks that are more aligned with current kernel standards (like sysfs/configfs) next time.

It appears you are replying to Andreas' message, not Greg's :)

It is true that kernel module parameters are not something that one
should generally be used when there are better alternatives, but rnull
is a bit of a special case, i.e. null block is used for benchmarking,
and Andreas may want to have parity with the C one for comparison
purposes.

But since your commit message didn't really say for what this was
meant for, then Greg rightly pointed it out :)

In any case, I wanted to thank you for reading and following the AI
and tooling kernel policies I mentioned to you in Zulip! It may also
be good to disclose the research side, at least just a link to that
Zulip thread could be good.

Thanks!

Cheers,
Miguel

^ permalink raw reply

* Re:Re: [RFC PATCH 0/2] rust: block: add a borrowed blk-mq timeout callback
From: wenzhaoliao @ 2026-04-11 13:37 UTC (permalink / raw)
  To: Andreas Hindborg
  Cc: Jens Axboe, Miguel Ojeda, linux-block, rust-for-linux, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, linux-kernel
In-Reply-To: <87ldetx01d.fsf@kernel.org>


Hi Greg,


Thank you so much for taking the time to review this patch and for your valuable guidance.


To be completely honest, we do not have a specific driver use case for this feature at the moment. Our overarching goal is simply to learn the kernel development process and find ways to genuinely contribute to the Rust-for-Linux project. 


Recently, we submitted a patch that unfortunately duplicated existing work. In that thread, Andreas Hindborg kindly pointed us to a new task with this exact suggestion:


"If you really want to use your tokens to improve the kernel, I would suggest adding boolean parameter support to the Rust module parameter parser code."
(https://lore.kernel.org/rust-for-linux/20260216-rnull-v6-19-rc5-send-v1-0-de9a7af4b469@kernel.org/)


We took this as a good "first issue" to familiarize ourselves with the Rust subsystem, and that is the sole reason we implemented it. 


Learning from you that module options are considered 1990's technology and do not fit the modern kernel model is a great lesson for us. If we misunderstood the maintainer's intention, or if pursuing this outdated mechanism goes against modern kernel design principles, we sincerely apologize for the noise and for any burden this has caused.


We are perfectly happy to drop this patch if this functionality is no longer desired in the modern kernel. We really just want to help improve the kernel, and we will try our best to sync with the maintainers to pick up tasks that are more aligned with current kernel standards (like sysfs/configfs) next time.


Best regards,
Wenzhao







发件人:Andreas Hindborg <a.hindborg@kernel.org>
发送日期:2026-04-11 18:29:34
收件人:Wenzhao Liao <wenzhaoliao@ruc.edu.cn>,Jens Axboe <axboe@kernel.dk>,Miguel Ojeda <ojeda@kernel.org>,linux-block@vger.kernel.org,rust-for-linux@vger.kernel.org
抄送人:Boqun Feng <boqun@kernel.org>,Gary Guo <gary@garyguo.net>,"Björn Roy Baron" <bjorn3_gh@protonmail.com>,Benno Lossin <lossin@kernel.org>,Alice Ryhl <aliceryhl@google.com>,Trevor Gross <tmgross@umich.edu>,Danilo Krummrich <dakr@kernel.org>,linux-kernel@vger.kernel.org
主题:Re: [RFC PATCH 0/2] rust: block: add a borrowed blk-mq timeout callback>Hi Wenzhao,
>
>"Wenzhao Liao" <wenzhaoliao@ruc.edu.cn> writes:
>
>> This small RFC series fills a missing blk-mq callback in the Rust block
>> layer. Today, Rust block drivers cannot participate in request timeout
>> handling because the Rust blk-mq vtable hardcodes `timeout: None`.
>
>I already pointed you to [1] multiple times. Please make sure to read
>that patch series. The functionality you are submitting is already
>covered by that series.
>
>If you really want to use your tokens to improve the kernel, I would
>suggest adding boolean parameter support to the Rust module parameter
>parser code.
>
>Be sure to credit your LLM according to [2]. And please do instruct your
>agents to find related discussion on the mailing list, so we avoid
>solving the same problem over and over.
>
>Best regards,
>Andreas Hindborg
>
>
>[1] https://lore.kernel.org/rust-for-linux/20260216-rnull-v6-19-rc5-send-v1-0-de9a7af4b469@kernel.org/
>[2] https://docs.kernel.org/process/coding-assistants.html
>
>

^ permalink raw reply

* Re: [PATCH v10 13/13] docs: add io_queue flag to isolcpus
From: Ming Lei @ 2026-04-11 12:52 UTC (permalink / raw)
  To: Aaron Tomlin
  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: <dzpxscrhibmi5okkozf5jfull4dcajgpctldvdyfcjgmpeetk5@tkeyqouyabzy>

On Fri, Apr 10, 2026 at 03:31:22PM -0400, Aaron Tomlin wrote:
> On Fri, Apr 10, 2026 at 10:44:15AM +0800, Ming Lei wrote:
> > For unmanaged interrupts, user can set irq affinity on housekeeping cpus
> > from /proc or kernel command line.
> > 
> > Why is unmanaged interrupts involved with this patchset?
> 
> Thank you for your continued engagement and for ultimately supporting the
> progression of this series.
> 
> To clarify the handling of unmanaged interrupts, while it is entirely true
> that an administrator could attempt to manually configure "irqaffinity=" or
> via procfs after the fact, this series actively address unmanaged interrupts.
> 
> > > CPUs, thereby breaking isolation. By applying the constraint via io_queue
> > > at the block layer, we restrict the hardware queue count and map the
> > > isolated CPUs to the housekeeping queues, ensuring isolation is maintained
> > > regardless of whether the driver uses managed interrupts.
> > > 
> > > Does the above help?
> > 
> > As I mentioned, managed irq already covers it:
> > 
> > - typically application submits IO from housekeeping CPUs, which is mapped
> >   to one hardware, which effective interrupt affinity excludes isolated
> >   CPUs if possible.
> > 
> > I'd suggest to share some real problems you found instead of something
> > imaginary.
> 
> If we trace how mpi3mr sets up its ISRs, it relies heavily on the core
> grouping logic:
> 
> mpi3mr_setup_isr
> {
>   unsigned int irq_flags = PCI_IRQ_MSIX
> 
>   struct irq_affinity desc = { .pre_vectors =  1, .post_vectors = 1, }
> 
>   pci_alloc_irq_vectors_affinity(mrioc->pdev, min_vec,
>                                  max_vectors, irq_flags, &desc)
>   {
>     if (flags & PCI_IRQ_MSIX) {
>       // affd != NULL
>       __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, affd, flags)
>       {
> 
>         for (;;) {
> 
>           msix_capability_init(dev, entries, nvec, affd)
>           {
>             msix_setup_interrupts(dev, entries, nvec, affd)
>             {
>               // affd
>               irq_create_affinity_masks(nvec, 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)
>                   if (!result) {
>                     kfree(masks)
>                     return NULL
>                   }
> 
>                   for (int j = 0; j < nr_masks; j++)
>                     cpumask_copy(&masks[curvec + j].mask, &result[j])
>                   kfree(result);
> 
>                   curvec += nr_masks
>                   usedvecs += nr_masks
>                 }
>               }
>             }
>           }
>         }
>       }
>     }
>   }
> }
> 
> The critical issue lies at the invocation of group_cpus_evenly(). Without
> this patchset, the core logic lacks the necessary constraints to respect
> CPU isolation. It is entirely possible, and indeed happens in practice, for
> an isolated CPU to be assigned to a CPU mask group.

It is one bug report? No, because it doesn't show any trouble from user
viewpoint.

Sebastian explains/shows how "isolcpus=managed_irq" works perfectly in the
following link:

https://lore.kernel.org/all/20260401110232.ET5RxZfl@linutronix.de/

You have reviewed it...

What matters is that IO won't interrupt isolated CPU.

> 
> The newer implementation of irq_create_affinity_masks() introduced by this
> series resolves this. It considers the new CPU mask added to the IRQ
> affinity descriptor. When group_mask_cpus_evenly() is called, this mask is
> evaluated [1], guaranteeing that isolated CPUs are entirely excluded from
> the mask groups.
> 
> [1]: https://lore.kernel.org/lkml/20260401222312.772334-8-atomlin@atomlin.com/

Not at all.

isolated CPU is still included in each group's cpu mask, please see patch
9:

https://lore.kernel.org/linux-block/20260401222312.772334-1-atomlin@atomlin.com/T/#m59df0689ef144f5361535ce59c9ed5923d6e21d5



Thanks, 
Ming

^ permalink raw reply

* Re: [RFC PATCH 0/2] rust: block: safely abstract the blk-mq poll callback
From: Andreas Hindborg @ 2026-04-11 10:33 UTC (permalink / raw)
  To: Wenzhao Liao, Jens Axboe, Miguel Ojeda, linux-block,
	rust-for-linux
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel
In-Reply-To: <20260410191544.2203201-1-wenzhaoliao@ruc.edu.cn>

"Wenzhao Liao" <wenzhaoliao@ruc.edu.cn> writes:

> Rust blk-mq drivers currently cannot implement the `blk_mq_ops->poll`
> callback: the Rust vtable hardcodes `poll: None`, and there is no safe
> way for a driver to receive the borrowed hardware queue context or the
> optional completion batch pointer that blk-mq passes to C drivers.

Again, this is covered by the series at [1]. Please instruct your AI agent
to read that thread before submitting more patches.

Best regards,
Andreas Hindborg


[1] https://lore.kernel.org/rust-for-linux/20260216-rnull-v6-19-rc5-send-v1-0-de9a7af4b469@kernel.org/


^ permalink raw reply

* Re: [RFC PATCH 0/2] rust: block: add a borrowed blk-mq timeout callback
From: Andreas Hindborg @ 2026-04-11 10:29 UTC (permalink / raw)
  To: Wenzhao Liao, Jens Axboe, Miguel Ojeda, linux-block,
	rust-for-linux
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel
In-Reply-To: <20260410164704.1986859-1-wenzhaoliao@ruc.edu.cn>

Hi Wenzhao,

"Wenzhao Liao" <wenzhaoliao@ruc.edu.cn> writes:

> This small RFC series fills a missing blk-mq callback in the Rust block
> layer. Today, Rust block drivers cannot participate in request timeout
> handling because the Rust blk-mq vtable hardcodes `timeout: None`.

I already pointed you to [1] multiple times. Please make sure to read
that patch series. The functionality you are submitting is already
covered by that series.

If you really want to use your tokens to improve the kernel, I would
suggest adding boolean parameter support to the Rust module parameter
parser code.

Be sure to credit your LLM according to [2]. And please do instruct your
agents to find related discussion on the mailing list, so we avoid
solving the same problem over and over.

Best regards,
Andreas Hindborg


[1] https://lore.kernel.org/rust-for-linux/20260216-rnull-v6-19-rc5-send-v1-0-de9a7af4b469@kernel.org/
[2] https://docs.kernel.org/process/coding-assistants.html


^ permalink raw reply

* Re: [PATCH 8/8] RFC: use a TASK_FIFO kthread for read completion support
From: Gao Xiang @ 2026-04-10 23:53 UTC (permalink / raw)
  To: Dave Chinner, Christoph Hellwig
  Cc: Tal Zussman, Jens Axboe, Matthew Wilcox (Oracle),
	Christian Brauner, Darrick J. Wong, Carlos Maiolino, Al Viro,
	Jan Kara, Bart Van Assche, linux-block, linux-kernel, linux-xfs,
	linux-fsdevel, linux-mm, Sandeep Dhavale
In-Reply-To: <7f0d072b-97a7-405f-bff5-d3819de2e3dd@linux.alibaba.com>



On 2026/4/11 07:44, Gao Xiang wrote:
> 
> 
> On 2026/4/11 06:11, Dave Chinner wrote:
>> On Thu, Apr 09, 2026 at 06:02:21PM +0200, Christoph Hellwig wrote:
>>> Commit 3fffb589b9a6 ("erofs: add per-cpu threads for decompression as an
>>> option") explains why workqueue aren't great for low-latency completion
>>> handling.  Switch to a per-cpu kthread to handle it instead.  This code
>>> is based on the erofs code in the above commit, but further simplified
>>> by directly using a kthread instead of a kthread_work.
>>>
>>> Signed-off-by: Christoph Hellwig <hch@lst.de>
>>
>> Can we please not go back to the (bad) old days of individual
>> subsystems needing their own set of per-cpu kernel tasks just
>> sitting around idle most of of the time?  The whole point of the
>> workqueue infrastructure was to get rid of this widely repeated
>> anti-pattern.
>>
>> If there's a latency problem with workqueue scheduling, then we
>> should be fixing that problem rather than working around it in every
>> subsystem that thinkgs it has a workqueue scheduling latency
>> issue...
> 
> It has been "fixed" but never actually get fixed:
> https://lore.kernel.org/r/CAB=BE-QaNBn1cVK6c7LM2cLpH_Ck_9SYw-YDYEnNrtwfoyu81Q@mail.gmail.com
> 
> and workqueues don't have any plan to introduce RT threads;
> 
> If Sandeep has more time, I hope he could have more time to
> test since I don't work on Android anymore: In principle,
> I still think RT thread is needed somewhere for such usage
> since lowest latencies is needed.
> 
> Compared to the scheduling latency issues, interested users
> don't care "individual subsystems needing their own set of
> per-cpu kernel tasks just sitting around idle most of of
> the time". If end users care it more, they can just turn
> it off by Kconfig.
> 
> If you think it's unclean to block subsystems, I'm fine to
> leave it as-is.  I'm not sure how it impacts to others:
> either some subsystems implement RT threads (workqueue or
> block), or leave it as-is; Otherwise there is always such

^ Implement dedicated queues somewhere using
sched_set_fifo_low() for such latency-sensitive work.

> latency issues and unacceptable for end users.
> 
> Thanks,
> Gao Xiang
> 
> 
>>
>> -Dave.
>>
> 


^ permalink raw reply

* Re: [PATCH 8/8] RFC: use a TASK_FIFO kthread for read completion support
From: Gao Xiang @ 2026-04-10 23:44 UTC (permalink / raw)
  To: Dave Chinner, Christoph Hellwig
  Cc: Tal Zussman, Jens Axboe, Matthew Wilcox (Oracle),
	Christian Brauner, Darrick J. Wong, Carlos Maiolino, Al Viro,
	Jan Kara, Bart Van Assche, linux-block, linux-kernel, linux-xfs,
	linux-fsdevel, linux-mm, Sandeep Dhavale
In-Reply-To: <adl1iqhldFvJwSw-@dread>



On 2026/4/11 06:11, Dave Chinner wrote:
> On Thu, Apr 09, 2026 at 06:02:21PM +0200, Christoph Hellwig wrote:
>> Commit 3fffb589b9a6 ("erofs: add per-cpu threads for decompression as an
>> option") explains why workqueue aren't great for low-latency completion
>> handling.  Switch to a per-cpu kthread to handle it instead.  This code
>> is based on the erofs code in the above commit, but further simplified
>> by directly using a kthread instead of a kthread_work.
>>
>> Signed-off-by: Christoph Hellwig <hch@lst.de>
> 
> Can we please not go back to the (bad) old days of individual
> subsystems needing their own set of per-cpu kernel tasks just
> sitting around idle most of of the time?  The whole point of the
> workqueue infrastructure was to get rid of this widely repeated
> anti-pattern.
> 
> If there's a latency problem with workqueue scheduling, then we
> should be fixing that problem rather than working around it in every
> subsystem that thinkgs it has a workqueue scheduling latency
> issue...

It has been "fixed" but never actually get fixed:
https://lore.kernel.org/r/CAB=BE-QaNBn1cVK6c7LM2cLpH_Ck_9SYw-YDYEnNrtwfoyu81Q@mail.gmail.com

and workqueues don't have any plan to introduce RT threads;

If Sandeep has more time, I hope he could have more time to
test since I don't work on Android anymore: In principle,
I still think RT thread is needed somewhere for such usage
since lowest latencies is needed.

Compared to the scheduling latency issues, interested users
don't care "individual subsystems needing their own set of
per-cpu kernel tasks just sitting around idle most of of
the time". If end users care it more, they can just turn
it off by Kconfig.

If you think it's unclean to block subsystems, I'm fine to
leave it as-is.  I'm not sure how it impacts to others:
either some subsystems implement RT threads (workqueue or
block), or leave it as-is; Otherwise there is always such
latency issues and unacceptable for end users.

Thanks,
Gao Xiang


> 
> -Dave.
> 


^ permalink raw reply

* Re: [PATCH v3 02/12] block/bdev: Annotate the blk_holder_ops callback invocations
From: Bart Van Assche @ 2026-04-10 23:44 UTC (permalink / raw)
  To: Marco Elver
  Cc: Christoph Hellwig, Jens Axboe, linux-block, Damien Le Moal,
	Nathan Chancellor
In-Reply-To: <CANpmjNPJPz7qruFw8S=4qoF32snPW-RYrd_BZK6skR_y86CUZg@mail.gmail.com>

On 4/10/26 3:43 PM, Marco Elver wrote:
> Can you retry? Thanks!

Thanks, this works much better! However, I think there is still an issue
with this new version: no compiler warning is emitted if one function
pointer is assigned to another function pointer and the lock context
annotations of the two pointers differ.

Bart.

^ permalink raw reply

* Re: [PATCH v3 02/12] block/bdev: Annotate the blk_holder_ops callback invocations
From: Marco Elver @ 2026-04-10 22:43 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Jens Axboe, linux-block, Damien Le Moal,
	Nathan Chancellor
In-Reply-To: <2e09806a-d5fe-4581-8024-906be7dca4de@acm.org>

On Fri, 10 Apr 2026 at 19:17, Bart Van Assche <bvanassche@acm.org> wrote:
> On 4/9/26 6:27 AM, Marco Elver wrote:
> > On Thu, 9 Apr 2026 at 08:42, Christoph Hellwig <hch@lst.de> wrote:
> >> On Thu, Apr 02, 2026 at 11:39:34AM -0700, Bart Van Assche wrote:
> >>> The four callback functions in blk_holder_ops all release the
> >>> bd_holder_lock. Add __release() annotations where appropriate to prepare
> >>> for enabling thread-safety analysis. Explicit __release() annotations have
> >>> been added since Clang does not support adding a __releases() annotation
> >>> to a function pointer.
> >>
> >> I have to say I still hate this with passion.  If we can't propagate
> >> the lock context over function pointers it isn't ready for prime time
> >> unfortunately, as much as I'm looking forward to it.
> >
> > Let's see if we can land this: https://github.com/llvm/llvm-project/pull/191187
> >
> > I think we'll be bumping min Clang version to 23 for context analysis,
> > so hopefully it'll be included in Clang 23 and should solve the
> > function pointer false positives.
>
> That LLVM patch does not seem sufficient to address Christoph's concern.
> If I apply that LLVM patch on my local LLVM tree, and if I apply the
> following patch to the Linux kernel source tree:
[...]
> ./include/linux/blkdev.h:1763:15: error: use of undeclared identifier 'bdev'
>   1763 |                 __releases(&bdev->bd_holder_lock);
>        |                             ^~~~

I just pushed a fix:  https://github.com/llvm/llvm-project/pull/191187

Can you retry? Thanks!

^ permalink raw reply

* Re: [PATCH 8/8] RFC: use a TASK_FIFO kthread for read completion support
From: Dave Chinner @ 2026-04-10 22:11 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Tal Zussman, Jens Axboe, Matthew Wilcox (Oracle),
	Christian Brauner, Darrick J. Wong, Carlos Maiolino, Al Viro,
	Jan Kara, Bart Van Assche, Gao Xiang, linux-block, linux-kernel,
	linux-xfs, linux-fsdevel, linux-mm
In-Reply-To: <20260409160243.1008358-9-hch@lst.de>

On Thu, Apr 09, 2026 at 06:02:21PM +0200, Christoph Hellwig wrote:
> Commit 3fffb589b9a6 ("erofs: add per-cpu threads for decompression as an
> option") explains why workqueue aren't great for low-latency completion
> handling.  Switch to a per-cpu kthread to handle it instead.  This code
> is based on the erofs code in the above commit, but further simplified
> by directly using a kthread instead of a kthread_work.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Can we please not go back to the (bad) old days of individual
subsystems needing their own set of per-cpu kernel tasks just
sitting around idle most of of the time?  The whole point of the
workqueue infrastructure was to get rid of this widely repeated
anti-pattern.

If there's a latency problem with workqueue scheduling, then we
should be fixing that problem rather than working around it in every
subsystem that thinkgs it has a workqueue scheduling latency
issue...

-Dave.

-- 
Dave Chinner
dgc@kernel.org

^ permalink raw reply

* Re: [PATCH v10 13/13] docs: add io_queue flag to isolcpus
From: Aaron Tomlin @ 2026-04-10 19:31 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: <adhj_w11cpMfeEgN@fedora>

[-- Attachment #1: Type: text/plain, Size: 4347 bytes --]

On Fri, Apr 10, 2026 at 10:44:15AM +0800, Ming Lei wrote:
> For unmanaged interrupts, user can set irq affinity on housekeeping cpus
> from /proc or kernel command line.
> 
> Why is unmanaged interrupts involved with this patchset?

Thank you for your continued engagement and for ultimately supporting the
progression of this series.

To clarify the handling of unmanaged interrupts, while it is entirely true
that an administrator could attempt to manually configure "irqaffinity=" or
via procfs after the fact, this series actively address unmanaged interrupts.

> > CPUs, thereby breaking isolation. By applying the constraint via io_queue
> > at the block layer, we restrict the hardware queue count and map the
> > isolated CPUs to the housekeeping queues, ensuring isolation is maintained
> > regardless of whether the driver uses managed interrupts.
> > 
> > Does the above help?
> 
> As I mentioned, managed irq already covers it:
> 
> - typically application submits IO from housekeeping CPUs, which is mapped
>   to one hardware, which effective interrupt affinity excludes isolated
>   CPUs if possible.
> 
> I'd suggest to share some real problems you found instead of something
> imaginary.

If we trace how mpi3mr sets up its ISRs, it relies heavily on the core
grouping logic:

mpi3mr_setup_isr
{
  unsigned int irq_flags = PCI_IRQ_MSIX

  struct irq_affinity desc = { .pre_vectors =  1, .post_vectors = 1, }

  pci_alloc_irq_vectors_affinity(mrioc->pdev, min_vec,
                                 max_vectors, irq_flags, &desc)
  {
    if (flags & PCI_IRQ_MSIX) {
      // affd != NULL
      __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, affd, flags)
      {

        for (;;) {

          msix_capability_init(dev, entries, nvec, affd)
          {
            msix_setup_interrupts(dev, entries, nvec, affd)
            {
              // affd
              irq_create_affinity_masks(nvec, 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)
                  if (!result) {
                    kfree(masks)
                    return NULL
                  }

                  for (int j = 0; j < nr_masks; j++)
                    cpumask_copy(&masks[curvec + j].mask, &result[j])
                  kfree(result);

                  curvec += nr_masks
                  usedvecs += nr_masks
                }
              }
            }
          }
        }
      }
    }
  }
}

The critical issue lies at the invocation of group_cpus_evenly(). Without
this patchset, the core logic lacks the necessary constraints to respect
CPU isolation. It is entirely possible, and indeed happens in practice, for
an isolated CPU to be assigned to a CPU mask group.

The newer implementation of irq_create_affinity_masks() introduced by this
series resolves this. It considers the new CPU mask added to the IRQ
affinity descriptor. When group_mask_cpus_evenly() is called, this mask is
evaluated [1], guaranteeing that isolated CPUs are entirely excluded from
the mask groups.

[1]: https://lore.kernel.org/lkml/20260401222312.772334-8-atomlin@atomlin.com/

> > > > > IMO, only two differences from this viewpoint:
> > > > >
> > > > > 1) `io_queue` may reduce nr_hw_queues
> > > > >
> > > > > 2) when application submits IO from isolated CPUs, `io_queue` can complete
> > > > > IO from housekeeping CPUs.
> > > >
> > > > Acknowledged.
> > > 
> > > Are there other major differences besides the two mentioned above?
> > 
> > I believe the above is sufficient. Please let me know your thoughts.
> 
> Both two are small improvement, not bug fixes. However the user has to pay
> the cost of potential failing of offlining CPU. Not mention the little 
> complicated change: `19 files changed, 378 insertions(+), 48 deletions(-)`
> 
> But I won't object if you can update the commit log/kernel command line
> doc and fix the issue found in review.

Thank you again for your rigorous review, patience, and invaluable
guidance.


Kind regards,
-- 
Aaron Tomlin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [RFC PATCH 2/2] block: rnull: wire up poll queues dummy callback
From: Wenzhao Liao @ 2026-04-10 19:15 UTC (permalink / raw)
  To: Andreas Hindborg, Jens Axboe, Miguel Ojeda, linux-block,
	rust-for-linux
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel
In-Reply-To: <20260410191544.2203201-2-wenzhaoliao@ruc.edu.cn>

Implement the new Operations::poll callback for rnull and return a
zero-completion PollResult.

This keeps rnull's current behavior unchanged while validating that the
borrowed poll abstraction wires cleanly into a Rust blk-mq driver.

Signed-off-by: Wenzhao Liao <wenzhaoliao@ruc.edu.cn>
---
 drivers/block/rnull/rnull.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index 0ca8715febe8..a5db14fcac34 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -97,4 +97,12 @@ fn complete(rq: ARef<mq::Request<Self>>) {
             // point, and so `end_ok` cannot fail.
             .expect("Fatal error - expected to be able to end request");
     }
+
+    fn poll(
+        _queue_data: &QueueData,
+        _hctx: &mq::HwCtx,
+        _iob: Option<&mq::IoCompBatch>,
+    ) -> mq::PollResult {
+        mq::PollResult::none()
+    }
 }
-- 
2.34.1


^ permalink raw reply related

* [RFC PATCH 1/2] rust: block: mq: safely abstract the poll callback
From: Wenzhao Liao @ 2026-04-10 19:15 UTC (permalink / raw)
  To: Andreas Hindborg, Jens Axboe, Miguel Ojeda, linux-block,
	rust-for-linux
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel
In-Reply-To: <20260410191544.2203201-1-wenzhaoliao@ruc.edu.cn>

Add a minimal poll abstraction for Rust blk-mq drivers.

Model the hardware queue context as a shared HwCtx borrow and map the
optional io_comp_batch pointer to Option<&IoCompBatch>. This keeps the
callback on borrowed data owned by blk-mq and avoids exposing raw
pointers in driver implementations.

Use a typed PollResult to represent either a completion count or a
request to stop polling, and wire the callback into the blk-mq vtable
behind HAS_POLL so existing drivers keep poll: None.

Signed-off-by: Wenzhao Liao <wenzhaoliao@ruc.edu.cn>
---
 rust/kernel/block/mq.rs            |   2 +-
 rust/kernel/block/mq/operations.rs | 143 +++++++++++++++++++++++++++--
 2 files changed, 138 insertions(+), 7 deletions(-)

diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs
index 1fd0d54dd549..a66e27401571 100644
--- a/rust/kernel/block/mq.rs
+++ b/rust/kernel/block/mq.rs
@@ -98,6 +98,6 @@
 mod request;
 mod tag_set;
 
-pub use operations::Operations;
+pub use operations::{HwCtx, IoCompBatch, Operations, PollResult};
 pub use request::Request;
 pub use tag_set::TagSet;
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 8ad46129a52c..31e1d61f107d 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -10,12 +10,120 @@
     error::{from_result, Result},
     prelude::*,
     sync::{aref::ARef, Refcount},
-    types::ForeignOwnable,
+    types::{ForeignOwnable, Opaque},
 };
 use core::marker::PhantomData;
 
 type ForeignBorrowed<'a, T> = <T as ForeignOwnable>::Borrowed<'a>;
 
+/// A borrowed blk-mq hardware queue context.
+///
+/// # Invariants
+///
+/// [`HwCtx`] is a transparent wrapper around a live `bindings::blk_mq_hw_ctx`.
+#[repr(transparent)]
+pub struct HwCtx(Opaque<bindings::blk_mq_hw_ctx>);
+
+impl HwCtx {
+    /// Creates a reference to an [`HwCtx`] from a valid raw pointer.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `ptr` points to a live
+    /// `bindings::blk_mq_hw_ctx` for the duration of `'a`.
+    ///
+    /// The caller must also ensure that the returned reference is the only
+    /// Rust view used to access the underlying hardware context for the
+    /// duration of `'a`.
+    pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::blk_mq_hw_ctx) -> &'a Self {
+        // SAFETY: `Self` is a transparent wrapper around `bindings::blk_mq_hw_ctx`.
+        unsafe { &*ptr.cast() }
+    }
+
+    /// Returns a raw pointer to the underlying `struct blk_mq_hw_ctx`.
+    pub fn as_ptr(&self) -> *mut bindings::blk_mq_hw_ctx {
+        self as *const Self as *mut bindings::blk_mq_hw_ctx
+    }
+
+    /// Returns the index of this hardware queue.
+    pub fn queue_num(&self) -> u32 {
+        // SAFETY: By the type invariant, `self` wraps a live hardware context.
+        unsafe { (*self.as_ptr()).queue_num }
+    }
+}
+
+/// A borrowed blk-mq completion batching context.
+///
+/// # Invariants
+///
+/// [`IoCompBatch`] is a transparent wrapper around a live
+/// `bindings::io_comp_batch`.
+#[repr(transparent)]
+pub struct IoCompBatch(Opaque<bindings::io_comp_batch>);
+
+impl IoCompBatch {
+    /// Creates an optional reference to an [`IoCompBatch`] from a raw pointer.
+    ///
+    /// # Safety
+    ///
+    /// If `ptr` is non-null, the caller must ensure that it points to a live
+    /// `bindings::io_comp_batch` for the duration of `'a`.
+    ///
+    /// The caller must also ensure that the returned reference is the only
+    /// Rust view used to access the underlying completion batch for the
+    /// duration of `'a`.
+    pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::io_comp_batch) -> Option<&'a Self> {
+        if ptr.is_null() {
+            None
+        } else {
+            // SAFETY: `Self` is a transparent wrapper around `bindings::io_comp_batch`.
+            Some(unsafe { &*ptr.cast() })
+        }
+    }
+
+    /// Returns a raw pointer to the underlying `struct io_comp_batch`.
+    pub fn as_ptr(&self) -> *mut bindings::io_comp_batch {
+        self as *const Self as *mut bindings::io_comp_batch
+    }
+}
+
+/// Result returned from blk-mq poll callbacks.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum PollResult {
+    /// The driver completed the given number of requests.
+    Completed(u32),
+
+    /// The driver cannot make progress and blk-mq should stop polling.
+    Stop,
+}
+
+impl PollResult {
+    /// Returns a result indicating that no requests were completed.
+    pub const fn none() -> Self {
+        Self::Completed(0)
+    }
+
+    /// Returns a result indicating that `completed` requests were completed.
+    pub const fn completed(completed: u32) -> Self {
+        Self::Completed(completed)
+    }
+
+    /// Returns a result indicating that blk-mq should stop polling for now.
+    pub const fn stop() -> Self {
+        Self::Stop
+    }
+
+    fn as_raw(self) -> crate::ffi::c_int {
+        match self {
+            Self::Completed(completed) => {
+                debug_assert!(completed <= crate::ffi::c_int::MAX as u32);
+                completed as crate::ffi::c_int
+            }
+            Self::Stop => -1,
+        }
+    }
+}
+
 /// Implement this trait to interface blk-mq as block devices.
 ///
 /// To implement a block device driver, implement this trait as described in the
@@ -48,7 +156,11 @@ fn queue_rq(
 
     /// Called by the kernel to poll the device for completed requests. Only
     /// used for poll queues.
-    fn poll() -> bool {
+    fn poll(
+        _queue_data: ForeignBorrowed<'_, Self::QueueData>,
+        _hctx: &HwCtx,
+        _iob: Option<&IoCompBatch>,
+    ) -> PollResult {
         build_error!(crate::error::VTABLE_DEFAULT_ERROR)
     }
 }
@@ -168,12 +280,31 @@ impl<T: Operations> OperationsVTable<T> {
     ///
     /// # Safety
     ///
-    /// This function may only be called by blk-mq C infrastructure.
+    /// This function may only be called by blk-mq C infrastructure. The caller
+    /// must ensure that `hctx` is valid. If non-null, `iob` must point to a
+    /// live completion batch for the duration of this callback.
     unsafe extern "C" fn poll_callback(
-        _hctx: *mut bindings::blk_mq_hw_ctx,
-        _iob: *mut bindings::io_comp_batch,
+        hctx: *mut bindings::blk_mq_hw_ctx,
+        iob: *mut bindings::io_comp_batch,
     ) -> crate::ffi::c_int {
-        T::poll().into()
+        // SAFETY: `hctx` is valid as required by this function.
+        let hctx = unsafe { HwCtx::from_raw(hctx) };
+
+        // SAFETY: `hctx` is live as required by this function, so the request
+        // queue and its `queuedata` are also live for the duration of this
+        // callback.
+        let queue_data = unsafe { (*(*hctx.as_ptr()).queue).queuedata };
+
+        // SAFETY: `queue.queuedata` was created by `GenDiskBuilder::build`
+        // with a call to `ForeignOwnable::into_foreign` to create
+        // `queuedata`. `ForeignOwnable::from_foreign` is only called when the
+        // tagset is dropped, which happens after we are dropped.
+        let queue_data = unsafe { T::QueueData::borrow(queue_data) };
+
+        // SAFETY: If non-null, `iob` is valid as required by this function.
+        let iob = unsafe { IoCompBatch::from_raw(iob) };
+
+        T::poll(queue_data, hctx, iob).as_raw()
     }
 
     /// This function is called by the C kernel. A pointer to this function is
-- 
2.34.1


^ permalink raw reply related

* [RFC PATCH 0/2] rust: block: safely abstract the blk-mq poll callback
From: Wenzhao Liao @ 2026-04-10 19:15 UTC (permalink / raw)
  To: Andreas Hindborg, Jens Axboe, Miguel Ojeda, linux-block,
	rust-for-linux
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich, linux-kernel

Rust blk-mq drivers currently cannot implement the `blk_mq_ops->poll`
callback: the Rust vtable hardcodes `poll: None`, and there is no safe
way for a driver to receive the borrowed hardware queue context or the
optional completion batch pointer that blk-mq passes to C drivers.

This small RFC series fills that abstraction gap and wires the new API
into `rnull` as a minimal in-tree user.

The core design choice is to keep the callback on borrowed blk-mq-owned
state instead of exposing raw pointers or synthesizing ownership in
Rust:

  fn poll(
      queue_data: ForeignBorrowed<'_, Self::QueueData>,
      hctx: &HwCtx,
      iob: Option<&IoCompBatch>,
  ) -> PollResult

`HwCtx` is a transparent borrowed wrapper over `struct blk_mq_hw_ctx`,
and `Option<&IoCompBatch>` models the nullable `struct io_comp_batch *`
argument directly. This keeps the Rust side aligned with the C lifetime
model of the callback, while still avoiding raw pointer handling in
drivers.

The return value is represented as a typed `PollResult` instead of a
bare `int`. The enum preserves blk-mq's semantics while making the Rust
side more self-descriptive:

- `PollResult::Completed(u32)` maps to a non-negative completion count.
- `PollResult::Stop` maps to the negative "stop polling" return.

The vtable wiring remains backward compatible: the callback is only
installed when `#[vtable]` reports `HAS_POLL`, so existing Rust blk-mq
drivers still get `poll: None` by default.

Patch 1 introduces the abstraction and hooks it into the blk-mq vtable.
Patch 2 implements a dummy `poll()` method in `rnull` returning
`PollResult::none()` as the minimal reference user.

Runtime validation summary
--------------------------

In addition to compiling the series in an out-of-tree build, the wiring
was validated at runtime in QEMU.

To exercise the Rust poll callback, I used a small out-of-tree helper
module as a test harness. The helper temporarily enabled a poll-capable
queue shape for an `rnull` device, submitted a `REQ_POLLED` bio, and
attached a kprobe directly to the queue's `mq_ops->poll` function
pointer. In the guest, the helper observed the Rust dummy poll callback
being invoked (`hits = 1`) and the polled bio completed successfully,
without deadlocks, crashes, or memory safety issues.

That helper is only test infrastructure and is not part of this RFC
series; it was used solely to provide a minimal "the VTABLE wiring
works" runtime proof for the new abstraction.

Any feedback on the design of the PollResult enum and the borrowing
strategy from hctx would be much appreciated.

Wenzhao Liao (2):
  rust: block: mq: safely abstract the poll callback
  block: rnull: wire up poll queues dummy callback

 drivers/block/rnull/rnull.rs       |   8 ++
 rust/kernel/block/mq.rs            |   2 +-
 rust/kernel/block/mq/operations.rs | 143 +++++++++++++++++++++++++++--
 3 files changed, 146 insertions(+), 7 deletions(-)

-- 
2.34.1

^ permalink raw reply

* Re: [PATCH v3 02/12] block/bdev: Annotate the blk_holder_ops callback invocations
From: Bart Van Assche @ 2026-04-10 17:17 UTC (permalink / raw)
  To: Marco Elver, Christoph Hellwig
  Cc: Jens Axboe, linux-block, Damien Le Moal, Nathan Chancellor
In-Reply-To: <CANpmjNMUv5n2VrWGPBOzGg7-r6gf3hH6ZoJYtRsrntY8+_=fQg@mail.gmail.com>

On 4/9/26 6:27 AM, Marco Elver wrote:
> On Thu, 9 Apr 2026 at 08:42, Christoph Hellwig <hch@lst.de> wrote:
>> On Thu, Apr 02, 2026 at 11:39:34AM -0700, Bart Van Assche wrote:
>>> The four callback functions in blk_holder_ops all release the
>>> bd_holder_lock. Add __release() annotations where appropriate to prepare
>>> for enabling thread-safety analysis. Explicit __release() annotations have
>>> been added since Clang does not support adding a __releases() annotation
>>> to a function pointer.
>>
>> I have to say I still hate this with passion.  If we can't propagate
>> the lock context over function pointers it isn't ready for prime time
>> unfortunately, as much as I'm looking forward to it.
> 
> Let's see if we can land this: https://github.com/llvm/llvm-project/pull/191187
> 
> I think we'll be bumping min Clang version to 23 for context analysis,
> so hopefully it'll be included in Clang 23 and should solve the
> function pointer false positives.

That LLVM patch does not seem sufficient to address Christoph's concern.
If I apply that LLVM patch on my local LLVM tree, and if I apply the
following patch to the Linux kernel source tree:

diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index e354b771a8ad..81b8064b4612 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1741,22 +1741,26 @@ void blkdev_show(struct seq_file *seqf, off_t 
offset);
  #endif

  struct blk_holder_ops {
-       void (*mark_dead)(struct block_device *bdev, bool surprise);
+       void (*mark_dead)(struct block_device *bdev, bool surprise)
+               __releases(&bdev->bd_holder_lock);

         /*
          * Sync the file system mounted on the block device.
          */
-       void (*sync)(struct block_device *bdev);
+       void (*sync)(struct block_device *bdev)
+               __releases(&bdev->bd_holder_lock);

         /*
          * Freeze the file system mounted on the block device.
          */
-       int (*freeze)(struct block_device *bdev);
+       int (*freeze)(struct block_device *bdev)
+               __releases(&bdev->bd_holder_lock);

         /*
          * Thaw the file system mounted on the block device.
          */
-       int (*thaw)(struct block_device *bdev);
+       int (*thaw)(struct block_device *bdev)
+               __releases(&bdev->bd_holder_lock);
  };

  /*

then the following errors appear while building the Linux kernel tree
with Clang:

In file included from block/blk-core.c:18:
./include/linux/blkdev.h:1745:15: error: use of undeclared identifier 'bdev'
  1745 |                 __releases(&bdev->bd_holder_lock);
       |                             ^~~~
./include/linux/blkdev.h:1751:15: error: use of undeclared identifier 'bdev'
  1751 |                 __releases(&bdev->bd_holder_lock);
       |                             ^~~~
./include/linux/blkdev.h:1757:15: error: use of undeclared identifier 'bdev'
  1757 |                 __releases(&bdev->bd_holder_lock);
       |                             ^~~~
./include/linux/blkdev.h:1763:15: error: use of undeclared identifier 'bdev'
  1763 |                 __releases(&bdev->bd_holder_lock);
       |                             ^~~~


Thanks,

Bart.

^ permalink raw reply related

* Re: [PATCH v2 3/3] dm: add documentation for dm-inlinecrypt target
From: Milan Broz @ 2026-04-10 17:07 UTC (permalink / raw)
  To: Linlin Zhang, linux-block, ebiggers, mpatocka
  Cc: linux-kernel, adrianvovk, dm-devel, quic_mdalam, israelr, hch,
	axboe
In-Reply-To: <20260410134031.2880675-4-linlin.zhang@oss.qualcomm.com>

On 4/10/26 3:40 PM, Linlin Zhang wrote:
> This adds the admin-guide documentation for dm-inlinecrypt.
> 
> dm-inlinecrypt.rst is the guide to using dm-inlinecrypt.
> 
> Signed-off-by: Linlin Zhang <linlin.zhang@oss.qualcomm.com>
> ---

...

> +
> +<cipher>
> +    Encryption cipher type.
> +
> +    The cipher specifications format is::
> +
> +       cipher
> +
> +    Examples::
> +
> +       aes-xts-plain64
> +
> +    The cipher type is correspond one-to-one with encryption modes. For

... with encryption modes supported for inline crypto in block layer?

In your patch only BLK_ENCRYPTION_MODE_AES_256_XTS.

> +    instance, the corresponding crypto mode of aes-xts-plain64 is
> +    BLK_ENCRYPTION_MODE_AES_256_XTS.

...

> +iv_large_sectors
> +   IV generators will use sector number counted in <sector_size> units
> +   instead of default 512 bytes sectors.
> +
> +   For example, if <sector_size> is 4096 bytes, plain64 IV for the second
> +   sector will be 8 (without flag) and 1 if iv_large_sectors is present.
> +   The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
> +   if this flag is specified.

Is it true? I see this comment in the code:

/* dm-inlinecrypt doesn't implement iv_large_sectors=false. */

...

> +Example scripts
> +===============
> +LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
> +encryption with dm-inlinecrypt using the 'cryptsetup' utility, see
> +https://gitlab.com/cryptsetup/cryptsetup

Cryptsetup has no support for inlinecrypt and it is question if it should have.
It would require additional options and maybe LUKS2 metadata flag to make it persistent.

How did you test it? Please remove this cryptsetup example.
It can be added later when userspace get this functionality.

...> +
> +	#!/bin/sh
> +	# Create a inlinecrypt device using cryptsetup and LUKS header with default cipher
> +	cryptsetup luksFormat $1
> +	cryptsetup luksOpen $1 inlinecrypt1

ditto. This example will use dm-crypt, not dm-inlinecrypt.

Milan


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox