Linux block layer
 help / color / mirror / Atom feed
* [PATCH] ublk: reject FETCH from non-userspace context
From: Ming Lei @ 2026-05-01  8:52 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: Caleb Sander Mateos, Uday Shankar, Ming Lei

__ublk_fetch() sets io->task to current, which is later checked
against io_uring_cmd_get_task() in ublk_uring_cmd_cancel_fn().
With REQ_F_FORCE_ASYNC, the FETCH uring_cmd can be issued from
task work, which can be run from io_uring's fallback workqueue,
causing a task mismatch and triggering the WARN in cancel_fn.

Reject FETCH if current is not a real userspace task, and it is
reasonable for failing it in case of io_uring fallback.

Fixes: 3421c7f68bba ("ublk: make sure io cmd handled in submitter task context")
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 drivers/block/ublk_drv.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 8e5f3738c203..57abc0e9681f 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -3251,12 +3251,19 @@ static int __ublk_fetch(struct io_uring_cmd *cmd, struct ublk_device *ub,
 
 	WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV);
 
-	ublk_fill_io_cmd(io, cmd);
-
-	if (ublk_dev_support_batch_io(ub))
+	if (ublk_dev_support_batch_io(ub)) {
 		WRITE_ONCE(io->task, NULL);
-	else
+	} else {
+		/*
+		 * FETCH must come from a real userspace task, not a
+		 * kworker is actually io_uring fallback workqueue.
+		 */
+		if (current->flags & (PF_KTHREAD | PF_WQ_WORKER))
+			return -EINVAL;
 		WRITE_ONCE(io->task, get_task_struct(current));
+	}
+
+	ublk_fill_io_cmd(io, cmd);
 
 	return 0;
 }
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v5 2/2] blk-mq: expose tag starvation counts via debugfs
From: kernel test robot @ 2026-05-01  4:24 UTC (permalink / raw)
  To: Aaron Tomlin, axboe, rostedt, mhiramat, mathieu.desnoyers
  Cc: oe-kbuild-all, bvanassche, johannes.thumshirn, kch, dlemoal,
	ritesh.list, loberman, neelx, sean, mproche, chjohnst,
	linux-block, linux-kernel, linux-trace-kernel
In-Reply-To: <20260427020142.358912-3-atomlin@atomlin.com>

Hi Aaron,

kernel test robot noticed the following build errors:

[auto build test ERROR on axboe/for-next]
[also build test ERROR on trace/for-next riteshharjani/for-next linus/master v7.1-rc1 next-20260430]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Aaron-Tomlin/blk-mq-add-tracepoint-block_rq_tag_wait/20260428-013259
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git for-next
patch link:    https://lore.kernel.org/r/20260427020142.358912-3-atomlin%40atomlin.com
patch subject: [PATCH v5 2/2] blk-mq: expose tag starvation counts via debugfs
config: i386-allnoconfig-bpf (https://download.01.org/0day-ci/archive/20260501/202605010658.UrX2ImE9-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260501/202605010658.UrX2ImE9-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605010658.UrX2ImE9-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from ./include/trace/define_trace.h:132,
                    from ./include/trace/events/block.h:726,
                    from block/blk-core.c:45:
   ./include/trace/events/block.h: In function 'do_trace_event_raw_event_block_rq_tag_wait':
>> ./include/trace/events/block.h:255:71: error: expected ':' before ';' token
     255 |                 __entry->dev            = q->disk ? disk_devt(q->disk);
         |                                                                       ^
   ./include/trace/trace_events.h:427:11: note: in definition of macro '__DECLARE_EVENT_CLASS'
     427 |         { assign; }                                                     \
         |           ^~~~~~
   ./include/trace/trace_events.h:435:23: note: in expansion of macro 'PARAMS'
     435 |                       PARAMS(assign), PARAMS(print))                    \
         |                       ^~~~~~
   ./include/trace/trace_events.h:40:9: note: in expansion of macro 'DECLARE_EVENT_CLASS'
      40 |         DECLARE_EVENT_CLASS(name,                              \
         |         ^~~~~~~~~~~~~~~~~~~
   ./include/trace/trace_events.h:44:30: note: in expansion of macro 'PARAMS'
      44 |                              PARAMS(assign),                   \
         |                              ^~~~~~
   ./include/trace/events/block.h:241:1: note: in expansion of macro 'TRACE_EVENT'
     241 | TRACE_EVENT(block_rq_tag_wait,
         | ^~~~~~~~~~~
   ./include/trace/events/block.h:254:9: note: in expansion of macro 'TP_fast_assign'
     254 |         TP_fast_assign(
         |         ^~~~~~~~~~~~~~
   In file included from ./include/trace/define_trace.h:133:
   ./include/trace/events/block.h: In function 'do_perf_trace_block_rq_tag_wait':
>> ./include/trace/events/block.h:255:71: error: expected ':' before ';' token
     255 |                 __entry->dev            = q->disk ? disk_devt(q->disk);
         |                                                                       ^
   ./include/trace/perf.h:51:11: note: in definition of macro '__DECLARE_EVENT_CLASS'
      51 |         { assign; }                                                     \
         |           ^~~~~~
   ./include/trace/perf.h:67:23: note: in expansion of macro 'PARAMS'
      67 |                       PARAMS(assign), PARAMS(print))                    \
         |                       ^~~~~~
   ./include/trace/trace_events.h:40:9: note: in expansion of macro 'DECLARE_EVENT_CLASS'
      40 |         DECLARE_EVENT_CLASS(name,                              \
         |         ^~~~~~~~~~~~~~~~~~~
   ./include/trace/trace_events.h:44:30: note: in expansion of macro 'PARAMS'
      44 |                              PARAMS(assign),                   \
         |                              ^~~~~~
   ./include/trace/events/block.h:241:1: note: in expansion of macro 'TRACE_EVENT'
     241 | TRACE_EVENT(block_rq_tag_wait,
         | ^~~~~~~~~~~
   ./include/trace/events/block.h:254:9: note: in expansion of macro 'TP_fast_assign'
     254 |         TP_fast_assign(
         |         ^~~~~~~~~~~~~~


vim +255 ./include/trace/events/block.h

   242	
   243		TP_PROTO(struct request_queue *q, struct blk_mq_hw_ctx *hctx, bool is_sched_tag),
   244	
   245		TP_ARGS(q, hctx, is_sched_tag),
   246	
   247		TP_STRUCT__entry(
   248			__field( dev_t,		dev			)
   249			__field( u32,		hctx_id			)
   250			__field( u32,		nr_tags			)
   251			__field( bool,		is_sched_tag		)
   252		),
   253	
   254		TP_fast_assign(
 > 255			__entry->dev		= q->disk ? disk_devt(q->disk);
   256			__entry->hctx_id	= hctx->queue_num;
   257			__entry->is_sched_tag	= is_sched_tag;
   258	
   259			if (is_sched_tag)
   260				__entry->nr_tags = hctx->sched_tags->nr_tags;
   261			else
   262				__entry->nr_tags = hctx->tags->nr_tags;
   263		),
   264	
   265		TP_printk("%d,%d hctx=%u starved on %s tags (depth=%u)",
   266			  MAJOR(__entry->dev), MINOR(__entry->dev),
   267			  __entry->hctx_id,
   268			  __entry->is_sched_tag ? "scheduler" : "hardware",
   269			  __entry->nr_tags)
   270	);
   271	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [GIT PULL] Block fixes for 7.1-rc2
From: Jens Axboe @ 2026-05-01  1:49 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-block@vger.kernel.org

Hi Linus,

Set of fixes for block that should go into the 7.1 kernel release. This
is a bit larger than usual at -rc2 time, mostly because the nvme PR was
delayed last week, and hence it didn't make -rc1. This pull request
contains:

- MD pull request via Yu:
     - Fix a raid5 UAF on IO across the reshape position.
	- Avoid failing RAID1/RAID10 devices for invalid IO errors.
	- Fix RAID10 divide-by-zero when far_copies is zero.
	- Restore bitmap grow through sysfs.
	- Use mddev_is_dm() instead of open-coding gendisk checks.
	- Use ATTRIBUTE_GROUPS() for md default sysfs attributes.
	- Replace open-coded wait loops with wait_event helpers.

- NVMe pull request via Keith:
	- Target data transfer size configuation (Aurelien)
	- Enable P2P for RDMA (Shivaji Kant)
	- TCP target updates (Maurizio, Alistair, Chaitanya,
	  Shivam Kumar)
	- TCP host updates (Alistair, Chaitanya)
	- Authentication updates (Alistair, Daniel, Chris Leech)
	- Multipath fixes (John Garry)
	- New quirks (Alan Cui, Tao Jiang)
	- Apple driver fix (Fedor Pchelkin)
	- PCI admin doorbell update fix (Keith)

- Properly propagate CDROM read-only state to the block layer

Please pull!


The following changes since commit 254f49634ee16a731174d2ae34bc50bd5f45e731:

  Linux 7.1-rc1 (2026-04-26 14:19:00 -0700)

are available in the Git repository at:

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

for you to fetch changes up to 7e36e03d192a5547757bd8f9d9052a60f64e6d17:

  Merge tag 'md-7.1-20260428' of https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux into block-7.1 (2026-04-28 08:36:26 -0600)

----------------------------------------------------------------
block-7.1-20260430

----------------------------------------------------------------
Abd-Alrhman Masalkhi (5):
      md: replace wait loop with wait_event() in md_handle_request()
      md: use mddev_lock_nointr() in mddev_suspend_and_lock_nointr()
      md/raid1: replace wait loop with wait_event_idle() in raid1_write_request()
      md: use mddev_is_dm() instead of open-coding gendisk checks
      md: use ATTRIBUTE_GROUPS() for md default sysfs attributes

Alan Cui (1):
      nvme: add quirk NVME_QUIRK_IGNORE_DEV_SUBNQN for 144d:a808 (Samsung PM981/983/970 EVO Plus )

Alistair Francis (3):
      Revert "nvmet-tcp: Don't free SQ on authentication success"
      nvmet-tcp: Don't clear tls_key when freeing sq
      nvme-auth: Include SC_C in RVAL controller hash

Aurelien Aptel (1):
      nvmet: introduce new mdts configuration entry

Benjamin Marzinski (1):
      md/raid5: Fix UAF on IO across the reshape position

Chaitanya Kulkarni (3):
      nvmet-tcp: fix race between ICReq handling and queue teardown
      nvmet: avoid recursive nvmet-wq flush in nvmet_ctrl_free
      nvme-tcp: teardown circular locking fixes

Chris Leech (1):
      nvme-auth: Hash DH shared secret to create session key

Daan De Meyer (1):
      cdrom, scsi: sr: propagate read-only status to block layer via set_disk_ro()

Daniel Wagner (1):
      nvme: expose TLS mode

Fedor Pchelkin (1):
      nvme-apple: drop invalid put of admin queue reference count

Flavio Suligoi (1):
      nvme-core: fix parameter name in comment

Geliang Tang (1):
      nvme: add missing MODULE_ALIAS for fabrics transports

Jens Axboe (2):
      Merge tag 'nvme-7.1-2026-04-24' of git://git.infradead.org/nvme into block-7.1
      Merge tag 'md-7.1-20260428' of https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux into block-7.1

John Garry (2):
      nvme-multipath: drop head pointer check in nvme_mpath_clear_current_path()
      nvme-multipath: put module reference when delayed removal work is canceled

Junrui Luo (1):
      md/raid10: fix divide-by-zero in setup_geo() with zero far_copies

Keith Busch (3):
      nvme: skip trace completion for host path errors
      nvme-pci: fix missed admin queue sq doorbell write
      md/raid1,raid10: don't fail devices for invalid IO errors

Maurizio Lombardi (2):
      nvmet-tcp: propagate nvmet_tcp_build_pdu_iovec() errors to its callers
      nvmet-tcp: remove redundant calls to nvmet_tcp_fatal_error()

Shivaji Kant (1):
      nvme: enable PCI P2PDMA support for RDMA transport

Shivam Kumar (1):
      nvmet-tcp: check INIT_FAILED before nvmet_req_uninit in digest error path

Tao Jiang (1):
      nvme-pci: add quirk for Memblaze Pblaze5 (0x1c5f:0x0555)

Xiao Ni (1):
      MAINTAINERS: Add Xiao Ni as md/raid reviewer

Yu Kuai (3):
      md: factor bitmap creation away from sysfs handling
      md/md-bitmap: split bitmap sysfs groups
      md/md-bitmap: add a none backend for bitmap grow

 MAINTAINERS                            |   1 +
 drivers/cdrom/cdrom.c                  |  73 ++++++++-----
 drivers/md/md-bitmap.c                 | 131 +++++++++++++++++++++---
 drivers/md/md-bitmap.h                 |   2 +-
 drivers/md/md-llbitmap.c               |   7 +-
 drivers/md/md.c                        | 182 ++++++++++++++++++---------------
 drivers/md/md.h                        |   6 +-
 drivers/md/raid1-10.c                  |   7 +-
 drivers/md/raid1.c                     |  15 +--
 drivers/md/raid10.c                    |   2 +
 drivers/md/raid5.c                     |   7 +-
 drivers/nvme/common/auth.c             |  94 +++++++++++++----
 drivers/nvme/host/apple.c              |   6 +-
 drivers/nvme/host/auth.c               |  16 +--
 drivers/nvme/host/core.c               |  16 ++-
 drivers/nvme/host/fc.c                 |   1 +
 drivers/nvme/host/multipath.c          |   4 -
 drivers/nvme/host/pci.c                |   5 +
 drivers/nvme/host/rdma.c               |   9 ++
 drivers/nvme/host/sysfs.c              |  19 ++++
 drivers/nvme/host/tcp.c                |  29 ++++--
 drivers/nvme/target/admin-cmd.c        |   8 +-
 drivers/nvme/target/auth.c             |  21 ++--
 drivers/nvme/target/configfs.c         |  27 +++++
 drivers/nvme/target/core.c             |  10 +-
 drivers/nvme/target/fabrics-cmd-auth.c |   9 +-
 drivers/nvme/target/nvmet.h            |  13 +++
 drivers/nvme/target/tcp.c              | 117 +++++++++++----------
 drivers/nvme/target/zns.c              |   6 +-
 drivers/scsi/sr.c                      |  11 +-
 drivers/scsi/sr.h                      |   1 -
 include/linux/cdrom.h                  |   1 +
 include/linux/nvme-auth.h              |   6 +-
 33 files changed, 587 insertions(+), 275 deletions(-)

-- 
Jens Axboe


^ permalink raw reply

* Re: [PATCH v3 01/10] file: add callback for creating long-term dmabuf maps
From: Pavel Begunkov @ 2026-04-30 18:33 UTC (permalink / raw)
  To: Christian König, Jens Axboe, Keith Busch, Christoph Hellwig,
	Sagi Grimberg, Alexander Viro, Christian Brauner, Andrew Morton,
	Sumit Semwal, linux-block, linux-kernel, linux-nvme,
	linux-fsdevel, io-uring, linux-media, dri-devel, linaro-mm-sig
  Cc: Nitesh Shetty, Kanchan Joshi, Anuj Gupta, Tushar Gohad,
	William Power, Phil Cayton, Jason Gunthorpe
In-Reply-To: <f0dd8f89-835e-4331-b593-4405ec59f4fe@amd.com>

On 4/30/26 07:03, Christian König wrote:
> On 4/29/26 17:25, Pavel Begunkov wrote:
>> Introduce a new file callback that allows creating long-term dma
>> mapping. All necessary information together with a dmabuf will be passed
>> in the second argument of type struct io_dmabuf_token, which will be
>> defined in following patches.
> 
> Well first of all the naming is probably not the best. Maybe rather call that dma-buf attachment or context or mappping.

"Mapping" or "attachment" would be confusing as maps are created lazily
together with struct io_dmabuf_map. I can name it create_dmabuf_ctx(),
but I decided to use "token" not to collide with dmabuf terminology.
e.g. I wouldn't be surprised to see some dmabuf ctx in the dmabuf
implementation code. Maybe "*io_ctx" would be better.

> Then the patch should probably define the full interface and not just add the callback here and then the structure in a follow up patch.

I strongly prefer splitting patches so that they touch one tree at
a time whenever possible. tbh, I don't see much of a problem it being
not defined as it's just forwarded in first patches, but I can shuffle
it around in the series so that definitions come first.

-- 
Pavel Begunkov


^ permalink raw reply

* Re: [PATCH v3 07/10] nvme-pci: implement dma_token backed requests
From: Pavel Begunkov @ 2026-04-30 18:18 UTC (permalink / raw)
  To: Maurizio Lombardi, Jens Axboe, Keith Busch, Christoph Hellwig,
	Sagi Grimberg, Alexander Viro, Christian Brauner, Andrew Morton,
	Sumit Semwal, Christian König, linux-block, linux-kernel,
	linux-nvme, linux-fsdevel, io-uring, linux-media, dri-devel,
	linaro-mm-sig
  Cc: Nitesh Shetty, Kanchan Joshi, Anuj Gupta, Tushar Gohad,
	William Power, Phil Cayton, Jason Gunthorpe
In-Reply-To: <DI5RO76D5IWR.19K0ES58HUIVS@arkamax.eu>

On 4/29/26 17:07, Maurizio Lombardi wrote:
> On Wed Apr 29, 2026 at 5:25 PM CEST, Pavel Begunkov wrote:
>> Enable BIO_DMABUF_MAP backed requests. It creates a prp list for the
>> dmabuf when it's mapped, which is then used to initialise requests.
>>
>> Suggested-by: Keith Busch <kbusch@kernel.org>
>> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
>> ---
...>> +
>> +static int nvme_create_dmabuf_token(struct request_queue *q,
>> +				 struct io_dmabuf_token *token)
>> +{
>> +	struct nvme_dmabuf_token *data;
>> +	struct dma_buf_attachment *attach;
>> +	struct nvme_ns *ns = q->queuedata;
>> +	struct nvme_dev *dev = to_nvme_dev(ns->ctrl);
>> +	struct dma_buf *dmabuf = token->dmabuf;
>> +
>> +	data = kzalloc(sizeof(data), GFP_KERNEL);
>> +	if (!data)
>> +		return -ENOMEM;
> 
> Shouldn't this be kzalloc(sizeof(*data)...) ?

Good catch, I'll apply it all for next version

-- 
Pavel Begunkov


^ permalink raw reply

* Re: [PATCH] block: blk-mq: fix UAF in blk_mq_tagset_busy_iter
From: Bart Van Assche @ 2026-04-30 16:11 UTC (permalink / raw)
  To: l1za0.sec, axboe; +Cc: linux-block, linux-kernel
In-Reply-To: <20260430042821.29120-1-l1za0.sec@gmail.com>


On 4/29/26 9:28 PM, l1za0.sec@gmail.com wrote:
> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index d626d32f6e57..4357625a512d 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -4738,6 +4738,7 @@ static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
>   				       int new_nr_hw_queues)
>   {
>   	struct blk_mq_tags **new_tags;
> +	struct blk_mq_tags **old_tags;
>   	int i;
>   
>   	if (set->nr_hw_queues >= new_nr_hw_queues)
> @@ -4751,8 +4752,10 @@ static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
>   	if (set->tags)
>   		memcpy(new_tags, set->tags, set->nr_hw_queues *
>   		       sizeof(*set->tags));
> -	kfree(set->tags);
> +	old_tags = set->tags;
>   	set->tags = new_tags;
> +	synchronize_srcu(&set->tags_srcu);
> +	kfree(old_tags);
>   
>   	for (i = set->nr_hw_queues; i < new_nr_hw_queues; i++) {
>   		if (!__blk_mq_alloc_map_and_rqs(set, i)) {

The function blk_mq_realloc_tag_set_tags() no longer exists.

> base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449

That commit is too old. It's description is as follows: "Merge tag
'timers_urgent_for_v6.18_rc8' of git://git.kernel.org/pub/scm/linux/
kernel/git/tip/tip". Please develop block layer fixes against the
for-next branch of this kernel tree:
https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git/

Thanks,

Bart.

^ permalink raw reply

* Re: [PATCH v12 00/13] blk: honor isolcpus configuration
From: Jan Kiszka @ 2026-04-30 15:45 UTC (permalink / raw)
  To: Daniel Wagner, Florian Bezdeka
  Cc: Aaron Tomlin, 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, ming.lei,
	tom.leiming, steve, sean, chjohnst, neelx, mproche, nick.lange,
	marco.crivellari, linux-block, linux-kernel, virtualization,
	linux-nvme, linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
	MPT-FusionLinux.pdl
In-Reply-To: <8c074639-bb75-40be-a338-e80b93123477@flourine.local>

On 30.04.26 14:09, Daniel Wagner wrote:
> On Wed, Apr 29, 2026 at 11:01:33PM +0200, Florian Bezdeka wrote:
>>> Which use case are you actually aiming to support? While dynamic
>>> reconfiguration would be ideal, the amount of work to get there is
>>> significant. I won't be signing up for it.
>>
>> The use case at hand is a RT enabled platform where the concrete RT
>> workload is not known at boot time. RT applications are deployed "on-
>> the-fly", nowadays using the existing container runtimes with some
>> extended resource management on top.
>>
>> Applications can request certain resources like isolated CPU cores,
>> special IRQ affinities, PCI devices to pass through, ...,  so that the
>> resource management on the system can take care of proper system
>> configuration.
> 
> 
> This is where I really question this use case. Currently, it takes quite
> a lot of time to tune a system to work properly for RT workloads.
> Between memory channel interference, GPU interference, and shared
> transports everywhere, you end up with a fixed split: a set of CPUs
> suitable for RT work and a set for housekeeping. This partitioning
> generally does not change during runtime, even if the way you utilize
> those two sets remains dynamic.
> 
> Furthermore, reconfiguring a system while running an active RT workload
> is asking for trouble. I wouldn't be surprised if doing so triggered a
> wide range of unpredictable side effects.

No questions that the devils are waiting in the details (and some
already showed up). It is a process of resolving issues and opening up
use cases from "boring", restricting boot-time settings to more and more
flexible reconfigurations. But if you do not hold up that goal and keep
it in mind or even act accordingly on changes, you will never reached.
Also RT would not be in mainline today without such a vision.

Jan

-- 
Siemens AG, Foundational Technologies
Linux Expert Center

^ permalink raw reply

* Re: [RFC PATCH v2 0/4] mm/zsmalloc: reduce zs_free() latency on swap release path
From: Wenchao Hao @ 2026-04-30 15:15 UTC (permalink / raw)
  To: Kairui Song
  Cc: Yosry Ahmed, Andrew Morton, Chengming Zhou, Jens Axboe,
	Johannes Weiner, Minchan Kim, Nhat Pham, Sergey Senozhatsky,
	linux-block, linux-kernel, linux-mm, Barry Song, Xueyuan Chen,
	Wenchao Hao
In-Reply-To: <CAMgjq7BTM1HKWwSTxkm7br+L2MDy7=OxEvF+yDRJfFfr24TiVA@mail.gmail.com>

On Thu, Apr 30, 2026 at 4:00 PM Kairui Song <ryncsn@gmail.com> wrote:
>
> On Thu, Apr 30, 2026 at 3:43 PM Wenchao Hao <haowenchao22@gmail.com> wrote:
> > The data I shared earlier was class_idx-in-obj only — no
> > deferred freeing at all.
> >
> > > I couldn't immediately tell by looking at this vs. the cover letter.  I wonder
> > > what portion of the improvement comes from the deferred freeing?
> >
> > On top of that, we added deferred freeing in the zsmalloc
> > layer (per-cpu page-pool based buffer swap + WQ_UNBOUND
> > drain worker). With both class_idx + deferred:
> >
> > Test 1: concurrent munmap (256MB/process, RPi 4B):
> >
> >   mode      Base       Deferred    Speedup
> >   single    56.2ms     17.2ms      3.27x
> >   multi 3p  153.2ms    51.5ms      2.97x
> >
> > Test 2: single process munmap (various sizes):
> >
> >   size      Base       Deferred    Speedup
> >   64MB      15.0ms     4.3ms       3.47x
> >   128MB     28.7ms     8.5ms       3.37x
> >   192MB     43.2ms     13.0ms      3.32x
> >   256MB     57.0ms     17.3ms      3.30x
> >   512MB     114.4ms    38.5ms      2.97x
>

Hi Kairui,

> One concern here is that the total amount of work is
> unchanged. But when under pressure these workers could
> be a larger burden.

The total CPU work is actually slightly reduced — the
batch drain eliminates pool->lock entirely, and holds
class->lock across consecutive same-class handles rather
than acquiring/releasing per handle. So the deferred
path does less lock work than synchronous per-handle
zs_free. I'm also exploring further reductions, such as
merging zram flags operations in the notify path (as you
suggested earlier) and reducing lock overhead. Suggestions
are welcome.

The key win is not reducing work but unblocking anon
folio freeing. Each folio free returns a full page
immediately, whereas zs_free may need many handle frees
before a zspage becomes empty (multiple compressed
objects share the same zspage). By not blocking folio
freeing with expensive zs_free, we improve the rate at
which usable memory returns to the system.

With parallelism (munmap + worker on different CPUs),
the process exits faster and memory is returned sooner.
For example, what used to take ~1s on one CPU can now
complete in ~400ms across two CPUs. Under memory
pressure, spending a bit more CPU to release memory
faster is a reasonable tradeoff.

> Is it possible for you to measure that part too?

Sure. Could you describe the specific scenario you're
concerned about — CPU contention, memory pressure, or
scheduling latency? I'm happy to design and run a test
around it.

Thanks,
Wenchao

^ permalink raw reply

* Re: [PATCH 1/2] block: pass a minsize argument to bio_iov_iter_bounce
From: Christoph Hellwig @ 2026-04-30 14:53 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Christoph Hellwig, Jens Axboe, Christian Brauner, Darrick J. Wong,
	linux-block, linux-xfs, linux-fsdevel
In-Reply-To: <afNZi5HRDWtK9Wdx@casper.infradead.org>

On Thu, Apr 30, 2026 at 02:30:51PM +0100, Matthew Wilcox wrote:
> Seems a bit inefficient.  How about something like this:

Works maybe a bit more efficiently, but also is more code and harder
to read.  So unless it actualy makes a difference in a relevant way,
why bother?


^ permalink raw reply

* Re: [PATCH v4] block: bio-integrity: Fix null-ptr-deref in bio_integrity_map_user()
From: Shin'ichiro Kawasaki @ 2026-04-30 13:35 UTC (permalink / raw)
  To: Sungwoo Kim
  Cc: Jens Axboe, Keith Busch, Chao Shi, Weidong Zhu, Dave Tian,
	linux-block, linux-kernel
In-Reply-To: <20260427040926.987166-3-iam@sung-woo.kim>

On Apr 27, 2026 / 00:09, Sungwoo Kim wrote:
> pin_user_pages_fast() can partially succeed and return the number of
> pages that were actually pinned. However, the bio_integrity_map_user()
> does not handle this partial pinning. This leads to a general protection
> fault since bvec_from_pages() dereferences an unpinned page address,
> which is 0.
> 
> To fix this, add a check to verify that all requested memory is pinned.
> If partial pinning occurs, unpin the memory and return -EFAULT.
> 
> Reproducer in blktest: https://github.com/linux-blktests/blktests/pull/244

The blktests Pull Request modifies the test case nvme/064 to write with 80KiB
size metadata. With this change, I confirmed that the Oops below was recreated
on my test system using the kernel v7.1-rc1.

> 
> Kernel Oops:
> 
> Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
> KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
> CPU: 0 UID: 0 PID: 1061 Comm: nvme-passthroug Not tainted 7.0.0-11783-g90957f9314e8-dirty #16 PREEMPT(lazy)
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
> RIP: 0010:bio_integrity_map_user.cold+0x1b0/0x9d6
> 
> Fixes: 492c5d455969 ("block: bio-integrity: directly map user buffers")
> Acked-by: Chao Shi <cshi008@fiu.edu>
> Acked-by: Weidong Zhu <weizhu@fiu.edu>
> Acked-by: Dave Tian <daveti@purdue.edu>
> Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
> ---
> V3: https://lore.kernel.org/linux-block/20260420020327.1667156-3-iam@sung-woo.kim/
> 
> V3->V4
> - Addressed a sashiko's comments [1], if it makes sense.
> - V3 wrongly assumed that iov_iter_extract_pages() always pins user
>   memory.
> - V3 insufficiently handled the return value range.
> 
> [1] https://sashiko.dev/#/patchset/20260420020327.1667156-3-iam%40sung-woo.kim

I applied this v4 patch to v7.1-rc1 kernel. With this, I confirmed that the
Oops goes away. Looks good from testing point of view.

Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>

^ permalink raw reply

* Re: [PATCH 1/2] block: pass a minsize argument to bio_iov_iter_bounce
From: Matthew Wilcox @ 2026-04-30 13:30 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jens Axboe, Christian Brauner, Darrick J. Wong, linux-block,
	linux-xfs, linux-fsdevel
In-Reply-To: <20260430132019.312405-2-hch@lst.de>

On Thu, Apr 30, 2026 at 03:20:04PM +0200, Christoph Hellwig wrote:
> -static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size)
> +static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
> +		size_t minsize)
>  {
>  	struct folio *folio;
>  
> -	while (*size > PAGE_SIZE) {
> +	while (*size > minsize) {
>  		folio = folio_alloc(gfp | __GFP_NORETRY, get_order(*size));
>  		if (folio)
>  			return folio;

Seems a bit inefficient.  How about something like this:

static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size, size_t minsize)
{
        unsigned int order = get_order(*size);
        unsigned int minorder = get_order(minsize);
        struct folio *folio;

        while (order > minorder) {
                folio = folio_alloc(gfp | __GFP_NORETRY, order);
                if (folio)
                        return folio;
                order--;
                *size = 1UL << order;
        }

        return folio_alloc(gfp, order);
}


^ permalink raw reply

* [PATCH 1/2] block: pass a minsize argument to bio_iov_iter_bounce
From: Christoph Hellwig @ 2026-04-30 13:20 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, Darrick J. Wong, linux-block, linux-xfs,
	linux-fsdevel
In-Reply-To: <20260430132019.312405-1-hch@lst.de>

When bouncing for block size > PAGE_SIZE file systems, the bio needs to
be big enough to fit an entire block.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c          | 23 +++++++++++++----------
 fs/iomap/direct-io.c |  2 +-
 include/linux/bio.h  |  3 ++-
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index b8972dba68a0..f3e5d8bea08c 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1279,11 +1279,12 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
 	return bio_iov_iter_align_down(bio, iter, len_align_mask);
 }
 
-static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size)
+static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
+		size_t minsize)
 {
 	struct folio *folio;
 
-	while (*size > PAGE_SIZE) {
+	while (*size > minsize) {
 		folio = folio_alloc(gfp | __GFP_NORETRY, get_order(*size));
 		if (folio)
 			return folio;
@@ -1307,7 +1308,7 @@ static void bio_free_folios(struct bio *bio)
 }
 
 static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
-		size_t maxlen)
+		size_t maxlen, size_t minsize)
 {
 	size_t total_len = min(maxlen, iov_iter_count(iter));
 
@@ -1322,13 +1323,13 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
 		size_t this_len = min(total_len, SZ_1M);
 		struct folio *folio;
 
-		if (this_len > PAGE_SIZE * 2)
+		if (this_len > minsize * 2)
 			this_len = rounddown_pow_of_two(this_len);
 
 		if (bio->bi_iter.bi_size > BIO_MAX_SIZE - this_len)
 			break;
 
-		folio = folio_alloc_greedy(GFP_KERNEL, &this_len);
+		folio = folio_alloc_greedy(GFP_KERNEL, &this_len, minsize);
 		if (!folio)
 			break;
 		bio_add_folio_nofail(bio, folio, this_len, 0);
@@ -1348,12 +1349,12 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
 }
 
 static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
-		size_t maxlen)
+		size_t maxlen, size_t minsize)
 {
 	size_t len = min3(iov_iter_count(iter), maxlen, SZ_1M);
 	struct folio *folio;
 
-	folio = folio_alloc_greedy(GFP_KERNEL, &len);
+	folio = folio_alloc_greedy(GFP_KERNEL, &len, minsize);
 	if (!folio)
 		return -ENOMEM;
 
@@ -1390,6 +1391,7 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
  * @bio:	bio to send
  * @iter:	iter to read from / write into
  * @maxlen:	maximum size to bounce
+ * @minsize:	minimum folio allocation size
  *
  * Helper for direct I/O implementations that need to bounce buffer because
  * we need to checksum the data or perform other operations that require
@@ -1397,11 +1399,12 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
  * copies the data into it.  Needs to be paired with bio_iov_iter_unbounce()
  * called on completion.
  */
-int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen)
+int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen,
+			size_t minsize)
 {
 	if (op_is_write(bio_op(bio)))
-		return bio_iov_iter_bounce_write(bio, iter, maxlen);
-	return bio_iov_iter_bounce_read(bio, iter, maxlen);
+		return bio_iov_iter_bounce_write(bio, iter, maxlen, minsize);
+	return bio_iov_iter_bounce_read(bio, iter, maxlen, minsize);
 }
 
 static void bvec_unpin(struct bio_vec *bv, bool mark_dirty)
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index b0a6549b3848..b36ee619cdcd 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -355,7 +355,7 @@ static ssize_t iomap_dio_bio_iter_one(struct iomap_iter *iter,
 
 	if (dio->flags & IOMAP_DIO_BOUNCE)
 		ret = bio_iov_iter_bounce(bio, dio->submit.iter,
-				iomap_max_bio_size(&iter->iomap));
+				iomap_max_bio_size(&iter->iomap), alignment);
 	else
 		ret = bio_iov_iter_get_pages(bio, dio->submit.iter,
 					     alignment - 1);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 97d747320b35..dc17780d6c1e 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -475,7 +475,8 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty);
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 
-int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen);
+int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen,
+		size_t minsize);
 void bio_iov_iter_unbounce(struct bio *bio, bool is_error, bool mark_dirty);
 
 extern void bio_copy_data_iter(struct bio *dst, struct bvec_iter *dst_iter,
-- 
2.53.0


^ permalink raw reply related

* [PATCH 2/2] block: align down bounces bios
From: Christoph Hellwig @ 2026-04-30 13:20 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, Darrick J. Wong, linux-block, linux-xfs,
	linux-fsdevel
In-Reply-To: <20260430132019.312405-1-hch@lst.de>

Just like for the extract user pages path, we need to align down the
size to the supported boundary.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index f3e5d8bea08c..5f10900b3f42 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1345,7 +1345,7 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
 
 	if (!bio->bi_iter.bi_size)
 		return -ENOMEM;
-	return 0;
+	return bio_iov_iter_align_down(bio, iter, minsize - 1);
 }
 
 static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
@@ -1383,7 +1383,7 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
 	bvec_set_folio(&bio->bi_io_vec[0], folio, bio->bi_iter.bi_size, 0);
 	if (iov_iter_extract_will_pin(iter))
 		bio_set_flag(bio, BIO_PAGE_PINNED);
-	return 0;
+	return bio_iov_iter_align_down(bio, iter, minsize - 1);
 }
 
 /**
-- 
2.53.0


^ permalink raw reply related

* fix block layer bounce buffering for block size > PAGE_SIZE
From: Christoph Hellwig @ 2026-04-30 13:20 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, Darrick J. Wong, linux-block, linux-xfs,
	linux-fsdevel

Hi all,

this series has two fixes that make the new block layer bounce
buffering code work for the block size > PAGE_SIZE case.

Diffstat:
 block/bio.c          |   27 +++++++++++++++------------
 fs/iomap/direct-io.c |    2 +-
 include/linux/bio.h  |    3 ++-
 3 files changed, 18 insertions(+), 14 deletions(-)

^ permalink raw reply

* Re: [PATCH 1/9] dt-bindings: mmc: Document support for nvmem-layout
From: Loic Poulain @ 2026-04-30 13:13 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
	Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
	Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, linux-mmc, devicetree, linux-kernel, linux-arm-msm,
	linux-block, linux-wireless, ath10k, linux-bluetooth, netdev,
	daniel
In-Reply-To: <20260430-bird-of-sheer-ampleness-744e7f@quoll>

Hi Krzysztof,

On Thu, Apr 30, 2026 at 11:59 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Tue, Apr 28, 2026 at 04:23:06PM +0200, Loic Poulain wrote:
>
> > +                    compatible = "fixed-layout";
> > +
> > +                    #address-cells = <1>;
> > +                    #size-cells = <1>;
> > +
> > +                    mac-addr@4400 {
> > +                        reg = <0x4400 0x6>;
>
> This looks incomplete. Why isn't this mac-base type of entry? And how do
> you address it from NVMEM consumer?

This indeed falls under the fixed-cell/mac-base type, thanks for
pointing that out.
NVMEM consumers reference these entries using the nvmem-cells
property, via the corresponding label/phandle.

>
> > +                    };
> > +
> > +                    bd-addr@5400 {
> > +                        reg = <0x5400 0x6>;
> > +                    };
> > +                };
> > +            };
> >          };
> >      };
> >
> >
> > --
> > 2.34.1
> >

^ permalink raw reply

* Re: [PATCH] blk-mq: recover from stale cached request in blk_mq_submit_bio
From: Christoph Hellwig @ 2026-04-30 13:09 UTC (permalink / raw)
  To: Keith Busch; +Cc: axboe, hch, linux-block, Keith Busch
In-Reply-To: <20260424184551.1540062-1-kbusch@meta.com>

On Fri, Apr 24, 2026 at 11:45:51AM -0700, Keith Busch wrote:
> -static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug,
> +static bool blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug,
>  		struct bio *bio)
>  {
> -	if (rq_list_pop(&plug->cached_rqs) != rq)
> -		WARN_ON_ONCE(1);
> -
>  	/*
> -	 * If any qos ->throttle() end up blocking, we will have flushed the
> -	 * plug and hence killed the cached_rq list as well. Pop this entry
> -	 * before we throttle.
> +	 * We will have flushed the plug and hence killed the cached_rq list as
> +	 * well if anything had blocked. Pop this entry before we throttle if
> +	 * the entry is still valid.
>  	 */
> +	if (rq_list_pop(&plug->cached_rqs) != rq)
> +		return false;
> +
>  	rq_qos_throttle(rq->q, bio);
>  
>  	blk_mq_rq_time_init(rq, blk_time_get_ns());
>  	rq->cmd_flags = bio->bi_opf;
>  	INIT_LIST_HEAD(&rq->queuelist);
> +	return true;
>  }
>  
>  static bool bio_unaligned(const struct bio *bio, struct request_queue *q)
> @@ -3211,8 +3212,13 @@ void blk_mq_submit_bio(struct bio *bio)
>  
>  new_request:
>  	if (rq) {
> -		blk_mq_use_cached_rq(rq, plug, bio);
> -	} else {
> +		if (!blk_mq_use_cached_rq(rq, plug, bio)) {
> +			rq = NULL;
> +			if (unlikely(bio_queue_enter(bio)))
> +				return;
> +		}

This means we now did the checks earlier in the function without
q_usage_counter protection, which looks wrong.  I think we have
to redo all of that here.

^ permalink raw reply

* Re: [PATCH v12 00/13] blk: honor isolcpus configuration
From: Daniel Wagner @ 2026-04-30 12:09 UTC (permalink / raw)
  To: Florian Bezdeka
  Cc: Aaron Tomlin, 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, ming.lei,
	tom.leiming, steve, sean, chjohnst, neelx, mproche, nick.lange,
	marco.crivellari, linux-block, linux-kernel, virtualization,
	linux-nvme, linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
	MPT-FusionLinux.pdl, Jan Kiszka
In-Reply-To: <85415539137c61cdec145ac0ee299dbea7cdd2a1.camel@siemens.com>

On Wed, Apr 29, 2026 at 11:01:33PM +0200, Florian Bezdeka wrote:
> > Which use case are you actually aiming to support? While dynamic
> > reconfiguration would be ideal, the amount of work to get there is
> > significant. I won't be signing up for it.
> 
> The use case at hand is a RT enabled platform where the concrete RT
> workload is not known at boot time. RT applications are deployed "on-
> the-fly", nowadays using the existing container runtimes with some
> extended resource management on top.
> 
> Applications can request certain resources like isolated CPU cores,
> special IRQ affinities, PCI devices to pass through, ...,  so that the
> resource management on the system can take care of proper system
> configuration.


This is where I really question this use case. Currently, it takes quite
a lot of time to tune a system to work properly for RT workloads.
Between memory channel interference, GPU interference, and shared
transports everywhere, you end up with a fixed split: a set of CPUs
suitable for RT work and a set for housekeeping. This partitioning
generally does not change during runtime, even if the way you utilize
those two sets remains dynamic.

Furthermore, reconfiguring a system while running an active RT workload
is asking for trouble. I wouldn't be surprised if doing so triggered a
wide range of unpredictable side effects.

^ permalink raw reply

* [PATCH blktests v3] nvme/068: add a test for multipath delayed removal
From: John Garry @ 2026-04-30  8:46 UTC (permalink / raw)
  To: shinichiro.kawasaki, linux-block
  Cc: linux-nvme, nilay, dwagner, John Garry, Chaitanya Kulkarni

For NVMe multipath, the delayed removal feature allows the multipath
gendisk to remain present when all available paths are gone. The purpose of
this feature is to ensure that we keep the gendisk for intermittent path
failures.

The delayed removal works on a timer - when all paths are gone, a timer is
kicked off; once the timer expires and no paths have returned, the gendisk
is removed.

When all paths are gone and the gendisk is still present, all reads and
writes to the disk are queued. If a path returns before the timer
expiration, the timer canceled and the queued IO is submitted;
otherwise they fail when the timer expires.

This testcase covers two scenarios in separate parts:
a. test that IOs submitted after all paths are removed (and do not return)
   fail
b. test that IOs submitted between all paths removed and a path
   returning succeed

During the period of the timer being active, it must be ensured that the
nvme-core module is not removed. Otherwise the driver may not be present
to handle the timeout expiry. The kernel ensures this by taking a
reference to the module. Ideally, we would try to remove the module during
this test to prove that this is not possible (and the kernel behaves as
expected), but that module will probably not be removable anyway due to
many references. To test this feature, check that the refcount of the
nvme-core module is incremented when the delayed timer is active.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---

@Chaitanya, @Nilay, Please check changes since RB tag granted

Differences to v2:
- Stop using sleeps so often (Daniel)
- Add RB tag from Nilay (Thanks!)

Differences to v1:
- Add RB tag from Chaitanya (Thanks!)
- Address shellcheck issues (Shinichiro)
- Drop Quick=1 (Shinichiro)
- Reference kernel commit (Nilay)
- Tidy setting refcnt (Nilay)

Note that a fix for a refcnt issue has been merged into nvme-7.1 queue

diff --git a/common/nvme b/common/nvme
index 565de59..3dc9e2c 100644
--- a/common/nvme
+++ b/common/nvme
@@ -268,6 +268,38 @@ _nvme_disconnect_ctrl() {
 	nvme disconnect --device "${ctrl}"
 }
 
+_nvme_disconnect_ctrl_sync() {
+	local ctrl="$1"
+	local subsysnqn="$2"
+
+	_nvme_disconnect_ctrl "${ctrl}"
+
+	for ((i = 0; i < 10; i++)); do
+		_nvme_ctrl_ready "${ctrl}" "${subsysnqn}"
+		if [[ $? -eq 1 ]]; then
+			break
+		fi
+		sleep .1
+	done
+}
+
+_nvme_wait_subsys_removed() {
+	local subsysnqn="$def_subsysnqn"
+
+	for subsyspath in /sys/class/nvme-subsystem/*; do
+		_subsysnqn=$(cat "${subsyspath}/subsysnqn" 2> /dev/null)
+		if [ "$subsysnqn" == "$_subsysnqn" ]; then
+			for ((i = 0; i < 10; i++)); do
+				if [ ! -d "$subsyspath" ]; then
+					break
+				fi
+				sleep .1
+			done
+			break
+		fi
+	done
+}
+
 _nvme_connect_subsys() {
 	local subsysnqn="$def_subsysnqn"
 	local hostnqn="$def_hostnqn"
diff --git a/common/rc b/common/rc
index d2c1d74..f73c22f 100644
--- a/common/rc
+++ b/common/rc
@@ -117,6 +117,16 @@ _module_not_in_use() {
 	fi
 }
 
+_module_use_count() {
+	local refcnt
+	if [ -f "/sys/module/$1/refcnt" ]; then
+		refcnt="$(cat /sys/module/"$1"/refcnt)"
+		echo "$refcnt"
+		return
+	fi
+	echo ""
+}
+
 _have_module_param() {
 	 _have_driver "$1" || return
 
diff --git a/tests/nvme/068 b/tests/nvme/068
new file mode 100755
index 0000000..41e799b
--- /dev/null
+++ b/tests/nvme/068
@@ -0,0 +1,113 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-3.0+
+# Copyright (C) 2026 John Garry
+#
+# Test NVMe multipath delayed removal works as expected. This feature was
+# introduced in commit 62188639ec16 ("nvme-multipath: introduce delayed removal
+# of the multipath head node")
+
+. tests/nvme/rc
+. common/xfs
+
+DESCRIPTION="NVMe multipath delayed removal test"
+
+requires() {
+	_nvme_requires
+	_have_loop
+	_have_module_param_value nvme_core multipath Y
+	_require_nvme_trtype_is_fabrics
+}
+
+set_conditions() {
+	_set_nvme_trtype "$@"
+}
+
+_delayed_nvme_reconnect_ctrl() {
+	sleep 1
+	_nvme_connect_subsys
+}
+
+test() {
+	echo "Running ${TEST_NAME}"
+
+	_setup_nvmet
+
+	local nvmedev
+	local ns
+	local bytes_written
+	local refcnt_orig
+	local refcnt
+	_nvmet_target_setup
+
+	_nvme_connect_subsys
+
+	# Part a: Prove that writes fail when no path returns. Any reads or
+	#	  writes are queued during the delayed removal period. If no
+	#	  paths return before the timer expires, then those IOs should
+	#	  fail.
+	#	  During the delayed removal period, ensure that the module
+	#	  refcnt is incremented, to prove that we cannot remove the
+	#	  driver during this period.
+	nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
+	ns=$(_find_nvme_ns "${def_subsys_uuid}")
+	refcnt_orig=$(_module_use_count nvme_core)
+	echo 5 > "/sys/block/${ns}/delayed_removal_secs"
+	_nvme_disconnect_ctrl_sync "${nvmedev}" "${def_subsysnqn}"
+	ns=$(_find_nvme_ns "${def_subsys_uuid}")
+	if [[ "${ns}" = "" ]]; then
+		echo "could not find ns after disconnect"
+	fi
+	refcnt=$(_module_use_count nvme_core)
+	if [ "$refcnt" != "" ] && [ "$refcnt" -le "$refcnt_orig" ]; then
+		echo "module refcount did not increase"
+	fi
+	bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns" 4096)
+	if [ "$bytes_written" == 4096 ]; then
+		echo "wrote successfully after disconnect"
+	fi
+	_nvme_wait_subsys_removed
+	ns=$(_find_nvme_ns "${def_subsys_uuid}")
+	if [[ ! "${ns}" = "" ]]; then
+		echo "found ns after delayed removal"
+	fi
+	refcnt=$(_module_use_count nvme_core)
+	if [ "$refcnt" != "" ] && [ "$refcnt" -ne "$refcnt_orig" ]; then
+		echo "module refcount not as original"
+	fi
+
+	# Part b: Ensure writes for an intermittent disconnect are successful.
+	#	  During an intermittent disconnect, any reads or writes
+	#	  queued should succeed after a path returns.
+	#	  Also ensure module refcount behaviour is as expected, as
+	#	  above.
+	_nvme_connect_subsys
+	nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
+	ns=$(_find_nvme_ns "${def_subsys_uuid}")
+	refcnt_orig=$(_module_use_count nvme_core)
+	echo 5 > "/sys/block/${ns}/delayed_removal_secs"
+	_nvme_disconnect_ctrl_sync "${nvmedev}" "${def_subsysnqn}"
+	ns=$(_find_nvme_ns "${def_subsys_uuid}")
+	if [[ "${ns}" = "" ]]; then
+		echo "could not find ns after disconnect"
+	fi
+	_delayed_nvme_reconnect_ctrl "${nvmedev}" &
+	bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns" 4096)
+	if [ "$bytes_written" != 4096 ]; then
+		echo "could not write successfully with reconnect"
+	fi
+	if ! _nvmf_wait_for_state "${def_subsysnqn}" "live" ; then
+		echo "subsystem did not return"
+	fi
+	refcnt=$(_module_use_count nvme_core)
+	if [ "$refcnt" != "" ] && [ "$refcnt" -ne "$refcnt_orig" ]; then
+		echo "module refcount not as original"
+	fi
+
+	# Final tidy-up
+	echo 0 > "/sys/block/${ns}/delayed_removal_secs"
+	nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
+	_nvme_disconnect_ctrl "${nvmedev}"
+	_nvmet_target_cleanup
+
+	echo "Test complete"
+}
diff --git a/tests/nvme/068.out b/tests/nvme/068.out
new file mode 100644
index 0000000..b913d19
--- /dev/null
+++ b/tests/nvme/068.out
@@ -0,0 +1,3 @@
+Running nvme/068
+pwrite: Input/output error
+Test complete
-- 
2.43.5


^ permalink raw reply related

* Re: [PATCH 1/9] dt-bindings: mmc: Document support for nvmem-layout
From: Krzysztof Kozlowski @ 2026-04-30  9:59 UTC (permalink / raw)
  To: Loic Poulain
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
	Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
	Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, linux-mmc, devicetree, linux-kernel, linux-arm-msm,
	linux-block, linux-wireless, ath10k, linux-bluetooth, netdev,
	daniel
In-Reply-To: <20260428-block-as-nvmem-v1-1-6ad23e75190a@oss.qualcomm.com>

On Tue, Apr 28, 2026 at 04:23:06PM +0200, Loic Poulain wrote:

> +                    compatible = "fixed-layout";
> +
> +                    #address-cells = <1>;
> +                    #size-cells = <1>;
> +
> +                    mac-addr@4400 {
> +                        reg = <0x4400 0x6>;

This looks incomplete. Why isn't this mac-base type of entry? And how do
you address it from NVMEM consumer?

> +                    };
> +
> +                    bd-addr@5400 {
> +                        reg = <0x5400 0x6>;
> +                    };
> +                };
> +            };
>          };
>      };
>  
> 
> -- 
> 2.34.1
> 

^ permalink raw reply

* [PATCH v3 3/3] dm: add documentation for dm-inlinecrypt target
From: Linlin Zhang @ 2026-04-30  9:52 UTC (permalink / raw)
  To: linux-block, ebiggers, mpatocka, gmazyland, bmarzins
  Cc: linux-kernel, adrianvovk, dm-devel, quic_mdalam, israelr, hch,
	axboe
In-Reply-To: <20260430095244.3352446-1-linlin.zhang@oss.qualcomm.com>

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>
---
 .../device-mapper/dm-inlinecrypt.rst          | 123 ++++++++++++++++++
 1 file changed, 123 insertions(+)
 create mode 100644 Documentation/admin-guide/device-mapper/dm-inlinecrypt.rst

diff --git a/Documentation/admin-guide/device-mapper/dm-inlinecrypt.rst b/Documentation/admin-guide/device-mapper/dm-inlinecrypt.rst
new file mode 100644
index 000000000000..c71e600efb76
--- /dev/null
+++ b/Documentation/admin-guide/device-mapper/dm-inlinecrypt.rst
@@ -0,0 +1,123 @@
+========
+dm-inlinecrypt
+========
+
+Device-Mapper's "inlinecrypt" target provides transparent encryption of block devices
+using the inline encryption hardware.
+
+For a more detailed description of inline encryption, see:
+https://docs.kernel.org/block/inline-encryption.html
+
+Parameters::
+
+	      <cipher> <key> <iv_offset> <device path> \
+	      <offset> [<#opt_params> <opt_params>]
+
+<cipher>
+    Encryption cipher type.
+
+    The cipher specifications format is::
+
+       cipher
+
+    Examples::
+
+       aes-xts-plain64
+
+    The cipher type corresponds to the encryption modes supported by
+    inline crypto in the block layer. Currently, only
+    BLK_ENCRYPTION_MODE_AES_256_XTS (i.e. aes-xts-plain64) is supported.
+
+<key>
+    Key used for encryption. It is encoded either as a hexadecimal number
+    or it can be passed as <key_string> prefixed with single colon
+    character (':') for keys residing in kernel keyring service.
+    You can only use key sizes that are valid for the selected cipher.
+    Note that the size in bytes of a valid key must be in bellow range.
+
+        [BLK_CRYPTO_KEY_TYPE_RAW, BLK_CRYPTO_KEY_TYPE_HW_WRAPPED]
+
+<key_string>
+    The kernel keyring key is identified by string in following format:
+    <key_size>:<key_type>:<key_description>.
+
+<key_size>
+    The encryption key size in bytes. The kernel key payload size must match
+    the value passed in <key_size>.
+
+<key_type>
+    Either 'logon', or 'trusted' kernel key type.
+
+<key_description>
+    The kernel keyring key description inlinecrypt target should look for
+    when loading key of <key_type>.
+
+<iv_offset>
+    The IV offset is a sector count that is added to the sector number
+    before creating the IV.
+
+<device path>
+    This is the device that is going to be used as backend and contains the
+    encrypted data.  You can specify it as a path like /dev/xxx or a device
+    number <major>:<minor>.
+
+<offset>
+    Starting sector within the device where the encrypted data begins.
+
+<#opt_params>
+    Number of optional parameters. If there are no optional parameters,
+    the optional parameters section can be skipped or #opt_params can be zero.
+    Otherwise #opt_params is the number of following arguments.
+
+    Example of optional parameters section:
+        allow_discards sector_size:4096 iv_large_sectors
+
+allow_discards
+    Block discard requests (a.k.a. TRIM) are passed through the inlinecrypt
+    device. The default is to ignore discard requests.
+
+    WARNING: Assess the specific security risks carefully before enabling this
+    option.  For example, allowing discards on encrypted devices may lead to
+    the leak of information about the ciphertext device (filesystem type,
+    used space etc.) if the discarded blocks can be located easily on the
+    device later.
+
+sector_size:<bytes>
+    Use <bytes> as the encryption unit instead of 512 bytes sectors.
+    This option can be in range 512 - 4096 bytes and must be power of two.
+    Virtual device will announce this size as a minimal IO and logical sector.
+
+iv_large_sectors
+    Use <sector_size>-based sector numbers for IV generation instead of
+    512-byte sectors.
+
+    For dm-inlinecrypt, this flag must be specified when <sector_size>
+    is larger than 512 bytes. The legacy 512-byte-based IV behavior is
+    not supported.
+
+    When specified, if <sector_size> is 4096 bytes, plain64 IV for the
+    second sector will be 1, and <iv_offset> must be a multiple of
+    <sector_size> (in 512-byte units).
+
+Example scripts
+===============
+Currently, dm-inlinecrypt devices must be set up directly using dmsetup.
+There is no userspace support yet to integrate dm-inlinecrypt with LUKS
+or cryptsetup. In particular, cryptsetup currently only supports
+dm-crypt, and cannot be used to create dm-inlinecrypt mappings.
+
+The following examples demonstrate how to create dm-inlinecrypt devices
+using dmsetup
+
+::
+
+	#!/bin/sh
+	# Create a inlinecrypt device using dmsetup
+	dmsetup create inlinecrypt1 --table "0 `blockdev --getsz $1` inlinecrypt aes-xts-plain64 babebabebabebabebabebabebabebabebabebabebabebabebabebabebabebabe 0 $1 0"
+
+::
+
+	#!/bin/sh
+	# Create a inlinecrypt device using dmsetup when encryption key is stored in keyring service
+	dmsetup create inlinecrypt2 --table "0 `blockdev --getsz $1` inlinecrypt aes-xts-plain64 :64:logon:fde:dminlinecrypt_test_key 0 $1 0"
+
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 2/3] dm-inlinecrypt: add target for inline block device encryption
From: Linlin Zhang @ 2026-04-30  9:52 UTC (permalink / raw)
  To: linux-block, ebiggers, mpatocka, gmazyland, bmarzins
  Cc: linux-kernel, adrianvovk, dm-devel, quic_mdalam, israelr, hch,
	axboe
In-Reply-To: <20260430095244.3352446-1-linlin.zhang@oss.qualcomm.com>

From: Eric Biggers <ebiggers@google.com>

Add a new device-mapper target "dm-inlinecrypt" that is similar to
dm-crypt but uses the blk-crypto API instead of the regular crypto API.
This allows it to take advantage of inline encryption hardware such as
that commonly built into UFS host controllers.

The table syntax matches dm-crypt's, but for now only a stripped-down
set of parameters is supported.  For example, for now AES-256-XTS is the
only supported cipher.

dm-inlinecrypt is based on Android's dm-default-key with the
controversial passthrough support removed.  Note that due to the removal
of passthrough support, use of dm-inlinecrypt in combination with
fscrypt causes double encryption of file contents (similar to dm-crypt +
fscrypt), with the fscrypt layer not being able to use the inline
encryption hardware.  This makes dm-inlinecrypt unusable on systems such
as Android that use fscrypt and where a more optimized approach is
needed.  It is however suitable as a replacement for dm-crypt.

dm-inlinecrypt supports both keyring key and hex key, the former avoids
the key to be exposed in dm-table message. Similar to dm-default-key in
Android, it will fallabck to the software block crypto once the inline
crypto hardware cannot support the expected cipher.

Test:
dmsetup create inlinecrypt_logon --table "0 `blockdev --getsz $1` \
inlinecrypt aes-xts-plain64 :64:logon:fde:dminlinecrypt_test_key 0 $1 0"

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Linlin Zhang <linlin.zhang@oss.qualcomm.com>
---
 drivers/md/Kconfig          |  11 +
 drivers/md/Makefile         |   1 +
 drivers/md/dm-inlinecrypt.c | 596 ++++++++++++++++++++++++++++++++++++
 3 files changed, 608 insertions(+)
 create mode 100644 drivers/md/dm-inlinecrypt.c

diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index c58a9a8ea54e..260c9c5e51bd 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -313,6 +313,17 @@ config DM_CRYPT
 
 	  If unsure, say N.
 
+config DM_INLINECRYPT
+	tristate "Inline encryption target support"
+	depends on BLK_DEV_DM
+	depends on (KEYS || KEYS=n)
+	depends on BLK_INLINE_ENCRYPTION
+	help
+	  This device-mapper target is similar to dm-crypt, but it uses the
+	  blk-crypto API instead of the regular crypto API. This allows it to
+	  take advantage of inline encryption hardware such as that commonly
+	  built into UFS host controllers.
+
 config DM_SNAPSHOT
        tristate "Snapshot target"
        depends on BLK_DEV_DM
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index c338cc6fbe2e..517d1f7d8288 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_DM_UNSTRIPED)	+= dm-unstripe.o
 obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
 obj-$(CONFIG_DM_BIO_PRISON)	+= dm-bio-prison.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
+obj-$(CONFIG_DM_INLINECRYPT)	+= dm-inlinecrypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_DUST)		+= dm-dust.o
 obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
diff --git a/drivers/md/dm-inlinecrypt.c b/drivers/md/dm-inlinecrypt.c
new file mode 100644
index 000000000000..6f804f5a4be6
--- /dev/null
+++ b/drivers/md/dm-inlinecrypt.c
@@ -0,0 +1,596 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2024 Google LLC
+ */
+
+#include <linux/blk-crypto.h>
+#include <linux/ctype.h>
+#include <linux/device-mapper.h>
+#include <linux/hex.h>
+#include <linux/module.h>
+#include <keys/user-type.h>
+
+#define DM_MSG_PREFIX	"inlinecrypt"
+
+static const struct dm_inlinecrypt_cipher {
+	const char *name;
+	enum blk_crypto_mode_num mode_num;
+} dm_inlinecrypt_ciphers[] = {
+	{
+		.name = "aes-xts-plain64",
+		.mode_num = BLK_ENCRYPTION_MODE_AES_256_XTS,
+	},
+};
+
+/**
+ * struct inlinecrypt_ctx - private data of an inlinecrypt target
+ * @dev: the underlying device
+ * @start: starting sector of the range of @dev which this target actually maps.
+ *	   For this purpose a "sector" is 512 bytes.
+ * @cipher_string: the name of the encryption algorithm being used
+ * @iv_offset: starting offset for IVs.  IVs are generated as if the target were
+ *	       preceded by @iv_offset 512-byte sectors.
+ * @sector_size: crypto sector size in bytes (usually 4096)
+ * @sector_bits: log2(sector_size)
+ * @key: the encryption key to use
+ * @max_dun: the maximum DUN that may be used (computed from other params)
+ */
+struct inlinecrypt_ctx {
+	struct dm_dev *dev;
+	sector_t start;
+	const char *cipher_string;
+	unsigned int key_size;
+	u64 iv_offset;
+	unsigned int sector_size;
+	unsigned int sector_bits;
+	struct blk_crypto_key key;
+	u64 max_dun;
+};
+
+static const struct dm_inlinecrypt_cipher *
+lookup_cipher(const char *cipher_string)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dm_inlinecrypt_ciphers); i++) {
+		if (strcmp(cipher_string, dm_inlinecrypt_ciphers[i].name) == 0)
+			return &dm_inlinecrypt_ciphers[i];
+	}
+	return NULL;
+}
+
+static void inlinecrypt_dtr(struct dm_target *ti)
+{
+	struct inlinecrypt_ctx *ctx = ti->private;
+
+	if (ctx->dev) {
+		if (ctx->key.size)
+			blk_crypto_evict_key(ctx->dev->bdev, &ctx->key);
+		dm_put_device(ti, ctx->dev);
+	}
+	kfree_sensitive(ctx->cipher_string);
+	kfree_sensitive(ctx);
+}
+
+#ifdef CONFIG_KEYS
+
+static bool contains_whitespace(const char *str)
+{
+	while (*str)
+		if (isspace(*str++))
+			return true;
+	return false;
+}
+
+static int set_key_user(struct key *key, char *bin_key,
+			const unsigned int bin_key_size)
+{
+	const struct user_key_payload *ukp;
+
+	ukp = user_key_payload_locked(key);
+	if (!ukp)
+		return -EKEYREVOKED;
+
+	if (bin_key_size != ukp->datalen)
+		return -EINVAL;
+
+	memcpy(bin_key, ukp->data, bin_key_size);
+
+	return 0;
+}
+
+static int inlinecrypt_get_keyring_key(const char *key_string, u8 *bin_key,
+					const unsigned int bin_key_size)
+{
+	char *key_desc;
+	int ret;
+	struct key_type *type;
+	struct key *key;
+	int (*set_key)(struct key *key, char *bin_key,
+				   const unsigned int bin_key_size);
+
+	/*
+	 * Reject key_string with whitespace. dm core currently lacks code for
+	 * proper whitespace escaping in arguments on DM_TABLE_STATUS path.
+	 */
+	if (contains_whitespace(key_string)) {
+		DMERR("whitespace chars not allowed in key string");
+		return -EINVAL;
+	}
+
+	/* look for next ':' separating key_type from key_description */
+	key_desc = strchr(key_string, ':');
+	if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
+		return -EINVAL;
+
+	if (!strncmp(key_string, "logon:", key_desc - key_string + 1)) {
+		type = &key_type_logon;
+		set_key = set_key_user;
+	} else {
+		return -EINVAL;
+	}
+
+	key = request_key(type, key_desc + 1, NULL);
+	if (IS_ERR(key))
+		return PTR_ERR(key);
+
+	down_read(&key->sem);
+
+	ret = set_key(key, (char *)bin_key, bin_key_size);
+
+	up_read(&key->sem);
+	key_put(key);
+
+	return ret;
+}
+
+static int get_key_size(char **key_string)
+{
+	char *colon, dummy;
+	int ret;
+
+	if (*key_string[0] != ':') {
+		ret = strlen(*key_string);
+
+		if (ret > 2 * BLK_CRYPTO_MAX_ANY_KEY_SIZE
+			|| ret  % 2
+			|| !ret) {
+			DMERR("Invalid keysize");
+			return -EINVAL;
+		}
+		return ret >> 1;
+	}
+
+	/* look for next ':' in key string */
+	colon = strpbrk(*key_string + 1, ":");
+	if (!colon)
+		return -EINVAL;
+
+	if (sscanf(*key_string + 1, "%u%c", &ret, &dummy) != 2 || dummy != ':')
+		return -EINVAL;
+
+	/* remaining key string should be :<logon|user>:<key_desc> */
+	*key_string = colon;
+
+	return ret;
+}
+
+#else
+
+static int inlinecrypt_get_keyring_key(const char *key_string, u8 *bin_key,
+					const unsigned int bin_key_size)
+{
+	return -EINVAL;
+}
+
+static int get_key_size(char **key_string)
+{
+	int key_hex_size = strlen(*key_string);
+
+	if (*key_string[0] == ':')
+		return -EINVAL;
+
+	if (key_hex_size > 2 * BLK_CRYPTO_MAX_ANY_KEY_SIZE
+		|| key_hex_size  % 2
+		|| !key_hex_size) {
+		DMERR("Invalid keysize");
+		return -EINVAL;
+	}
+
+	return key_hex_size >> 1;
+}
+
+#endif /* CONFIG_KEYS */
+
+static int inlinecrypt_get_key(const char *key_string,
+				u8 key[BLK_CRYPTO_MAX_ANY_KEY_SIZE],
+				const unsigned int key_size)
+{
+	int ret = 0;
+
+	if (key_size > BLK_CRYPTO_MAX_ANY_KEY_SIZE) {
+		DMERR("Invalid keysize");
+		return -EINVAL;
+	}
+
+	/* ':' means the key is in kernel keyring, short-circuit normal key processing */
+	if (key_string[0] == ':') {
+		/* key string should be :<logon|user>:<key_desc> */
+		ret = inlinecrypt_get_keyring_key(key_string + 1, key, key_size);
+		goto out;
+	}
+
+	if (hex2bin(key, key_string, key_size) != 0)
+		ret = -EINVAL;
+
+out:
+	return ret;
+}
+
+static int inlinecrypt_ctr_optional(struct dm_target *ti,
+				    unsigned int argc, char **argv)
+{
+	struct inlinecrypt_ctx *ctx = ti->private;
+	struct dm_arg_set as;
+	static const struct dm_arg _args[] = {
+		{0, 3, "Invalid number of feature args"},
+	};
+	unsigned int opt_params;
+	const char *opt_string;
+	bool iv_large_sectors = false;
+	char dummy;
+	int err;
+
+	as.argc = argc;
+	as.argv = argv;
+
+	err = dm_read_arg_group(_args, &as, &opt_params, &ti->error);
+	if (err)
+		return err;
+
+	while (opt_params--) {
+		opt_string = dm_shift_arg(&as);
+		if (!opt_string) {
+			ti->error = "Not enough feature arguments";
+			return -EINVAL;
+		}
+		if (!strcmp(opt_string, "allow_discards")) {
+			ti->num_discard_bios = 1;
+		} else if (sscanf(opt_string, "sector_size:%u%c",
+				  &ctx->sector_size, &dummy) == 1) {
+			if (ctx->sector_size < SECTOR_SIZE ||
+			    ctx->sector_size > 4096 ||
+			    !is_power_of_2(ctx->sector_size)) {
+				ti->error = "Invalid sector_size";
+				return -EINVAL;
+			}
+		} else if (!strcmp(opt_string, "iv_large_sectors")) {
+			iv_large_sectors = true;
+		} else {
+			ti->error = "Invalid feature arguments";
+			return -EINVAL;
+		}
+	}
+
+	/* dm-inlinecrypt doesn't implement iv_large_sectors=false. */
+	if (ctx->sector_size != SECTOR_SIZE && !iv_large_sectors) {
+		ti->error = "iv_large_sectors must be specified";
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Construct an inlinecrypt mapping:
+ * <cipher> [<key>|:<key_size>:<logon>:<key_description>] <iv_offset> <dev_path> <start>
+ *
+ * This syntax matches dm-crypt's, but the set of supported functionality has
+ * been stripped down.
+ */
+static int inlinecrypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	struct inlinecrypt_ctx *ctx;
+	const struct dm_inlinecrypt_cipher *cipher;
+	u8 raw_key[BLK_CRYPTO_MAX_ANY_KEY_SIZE];
+	unsigned int dun_bytes;
+	unsigned long long tmpll;
+	char dummy;
+	int err;
+
+	if (argc < 5) {
+		ti->error = "Not enough arguments";
+		return -EINVAL;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		ti->error = "Out of memory";
+		return -ENOMEM;
+	}
+	ti->private = ctx;
+
+	/* <cipher> */
+	ctx->cipher_string = kstrdup(argv[0], GFP_KERNEL);
+	if (!ctx->cipher_string) {
+		ti->error = "Out of memory";
+		err = -ENOMEM;
+		goto bad;
+	}
+	cipher = lookup_cipher(ctx->cipher_string);
+	if (!cipher) {
+		ti->error = "Unsupported cipher";
+		err = -EINVAL;
+		goto bad;
+	}
+
+	/* <key> */
+	ctx->key_size = get_key_size(&argv[1]);
+	if (ctx->key_size < 0) {
+		ti->error = "Cannot parse key size";
+		return -EINVAL;
+	}
+	err = inlinecrypt_get_key(argv[1], raw_key, ctx->key_size);
+	if (err) {
+		ti->error = "Malformed key string";
+		goto bad;
+	}
+
+	/* <iv_offset> */
+	if (sscanf(argv[2], "%llu%c", &ctx->iv_offset, &dummy) != 1) {
+		ti->error = "Invalid iv_offset sector";
+		err = -EINVAL;
+		goto bad;
+	}
+
+	/* <dev_path> */
+	err = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
+			    &ctx->dev);
+	if (err) {
+		ti->error = "Device lookup failed";
+		goto bad;
+	}
+
+	/* <start> */
+	if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1 ||
+	    tmpll != (sector_t)tmpll) {
+		ti->error = "Invalid start sector";
+		err = -EINVAL;
+		goto bad;
+	}
+	ctx->start = tmpll;
+
+	/* optional arguments */
+	ctx->sector_size = SECTOR_SIZE;
+	if (argc > 5) {
+		err = inlinecrypt_ctr_optional(ti, argc - 5, &argv[5]);
+		if (err)
+			goto bad;
+	}
+	ctx->sector_bits = ilog2(ctx->sector_size);
+	if (ti->len & ((ctx->sector_size >> SECTOR_SHIFT) - 1)) {
+		ti->error = "Device size is not a multiple of sector_size";
+		err = -EINVAL;
+		goto bad;
+	}
+	if (ctx->iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1)) {
+		ti->error = "Wrong alignment of iv_offset sector";
+		err = -EINVAL;
+	}
+
+	ctx->max_dun = (ctx->iv_offset + ti->len - 1) >>
+		       (ctx->sector_bits - SECTOR_SHIFT);
+	dun_bytes = DIV_ROUND_UP(fls64(ctx->max_dun), 8);
+
+	err = blk_crypto_init_key(&ctx->key, raw_key, ctx->key_size,
+				  BLK_CRYPTO_KEY_TYPE_RAW,
+				  cipher->mode_num, dun_bytes,
+				  ctx->sector_size);
+	if (err) {
+		ti->error = "Error initializing blk-crypto key";
+		goto bad;
+	}
+
+	err = blk_crypto_start_using_key(ctx->dev->bdev, &ctx->key);
+	if (err) {
+		ti->error = "Error starting to use blk-crypto";
+		goto bad;
+	}
+
+	ti->num_flush_bios = 1;
+
+	err = 0;
+	goto out;
+
+bad:
+	inlinecrypt_dtr(ti);
+out:
+	memzero_explicit(raw_key, sizeof(raw_key));
+	return err;
+}
+
+static int inlinecrypt_map(struct dm_target *ti, struct bio *bio)
+{
+	const struct inlinecrypt_ctx *ctx = ti->private;
+	sector_t sector_in_target;
+	u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE] = {};
+
+	bio_set_dev(bio, ctx->dev->bdev);
+
+	/*
+	 * If the bio is a device-level request which doesn't target a specific
+	 * sector, there's nothing more to do.
+	 */
+	if (bio_sectors(bio) == 0)
+		return DM_MAPIO_REMAPPED;
+
+	/*
+	 * The bio should never have an encryption context already, since
+	 * dm-inlinecrypt doesn't pass through any inline encryption
+	 * capabilities to the layer above it.
+	 */
+	if (WARN_ON_ONCE(bio_has_crypt_ctx(bio)))
+		return DM_MAPIO_KILL;
+
+	/* Map the bio's sector to the underlying device. (512-byte sectors) */
+	sector_in_target = dm_target_offset(ti, bio->bi_iter.bi_sector);
+	bio->bi_iter.bi_sector = ctx->start + sector_in_target;
+	/*
+	 * If the bio doesn't have any data (e.g. if it's a DISCARD request),
+	 * there's nothing more to do.
+	 */
+	if (!bio_has_data(bio))
+		return DM_MAPIO_REMAPPED;
+
+	/* Calculate the DUN and enforce data-unit (crypto sector) alignment. */
+	dun[0] = ctx->iv_offset + sector_in_target; /* 512-byte sectors */
+	if (dun[0] & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
+		return DM_MAPIO_KILL;
+	dun[0] >>= ctx->sector_bits - SECTOR_SHIFT; /* crypto sectors */
+
+	/*
+	 * This check isn't necessary as we should have calculated max_dun
+	 * correctly, but be safe.
+	 */
+	if (WARN_ON_ONCE(dun[0] > ctx->max_dun))
+		return DM_MAPIO_KILL;
+
+	bio_crypt_set_ctx(bio, &ctx->key, dun, GFP_NOIO);
+
+	/*
+	 * Since we've added an encryption context to the bio and
+	 * blk-crypto-fallback may be needed to process it, it's necessary to
+	 * use the fallback-aware bio submission code rather than
+	 * unconditionally returning DM_MAPIO_REMAPPED.
+	 *
+	 * To get the correct accounting for a dm target in the case where
+	 * __blk_crypto_submit_bio() doesn't take ownership of the bio (returns
+	 * true), call __blk_crypto_submit_bio() directly and return
+	 * DM_MAPIO_REMAPPED in that case, rather than relying on
+	 * blk_crypto_submit_bio() which calls submit_bio() in that case.
+	 *
+	 * TODO: blk-crypto fallback write slow-path currently double-accounts
+	 * IO in vmstat, as encrypted bios are submitted via submit_bio().
+	 * This does not affect data correctness. Consider fixing this if
+	 * a cleaner accounting model for derived bios is introduced.
+	 */
+	if (__blk_crypto_submit_bio(bio))
+		return DM_MAPIO_REMAPPED;
+	return DM_MAPIO_SUBMITTED;
+}
+
+static void inlinecrypt_status(struct dm_target *ti, status_type_t type,
+			       unsigned int status_flags, char *result,
+			       unsigned int maxlen)
+{
+	const struct inlinecrypt_ctx *ctx = ti->private;
+	unsigned int sz = 0;
+	int num_feature_args = 0;
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+	case STATUSTYPE_IMA:
+		result[0] = '\0';
+		break;
+
+	case STATUSTYPE_TABLE:
+		/*
+		 * Warning: like dm-crypt, dm-inlinecrypt includes the key in
+		 * the returned table.  Userspace is responsible for redacting
+		 * the key when needed.
+		 */
+		DMEMIT("%s %*phN %llu %s %llu", ctx->cipher_string,
+		       ctx->key.size, ctx->key.bytes, ctx->iv_offset,
+		       ctx->dev->name, ctx->start);
+		num_feature_args += !!ti->num_discard_bios;
+		if (ctx->sector_size != SECTOR_SIZE)
+			num_feature_args += 2;
+		if (num_feature_args != 0) {
+			DMEMIT(" %d", num_feature_args);
+			if (ti->num_discard_bios)
+				DMEMIT(" allow_discards");
+			if (ctx->sector_size != SECTOR_SIZE) {
+				DMEMIT(" sector_size:%u", ctx->sector_size);
+				DMEMIT(" iv_large_sectors");
+			}
+		}
+		break;
+	}
+}
+
+static int inlinecrypt_prepare_ioctl(struct dm_target *ti,
+				     struct block_device **bdev, unsigned int cmd,
+				     unsigned long arg, bool *forward)
+{
+	const struct inlinecrypt_ctx *ctx = ti->private;
+	const struct dm_dev *dev = ctx->dev;
+
+	*bdev = dev->bdev;
+
+	/* Only pass ioctls through if the device sizes match exactly. */
+	return ctx->start != 0 || ti->len != bdev_nr_sectors(dev->bdev);
+}
+
+static int inlinecrypt_iterate_devices(struct dm_target *ti,
+				       iterate_devices_callout_fn fn,
+				       void *data)
+{
+	const struct inlinecrypt_ctx *ctx = ti->private;
+
+	return fn(ti, ctx->dev, ctx->start, ti->len, data);
+}
+
+#ifdef CONFIG_BLK_DEV_ZONED
+static int inlinecrypt_report_zones(struct dm_target *ti,
+				    struct dm_report_zones_args *args,
+				    unsigned int nr_zones)
+{
+	const struct inlinecrypt_ctx *ctx = ti->private;
+
+	return dm_report_zones(ctx->dev->bdev, ctx->start,
+			ctx->start + dm_target_offset(ti, args->next_sector),
+			args, nr_zones);
+}
+#else
+#define inlinecrypt_report_zones NULL
+#endif
+
+static void inlinecrypt_io_hints(struct dm_target *ti,
+				 struct queue_limits *limits)
+{
+	const struct inlinecrypt_ctx *ctx = ti->private;
+	const unsigned int sector_size = ctx->sector_size;
+
+	limits->logical_block_size =
+		max_t(unsigned int, limits->logical_block_size, sector_size);
+	limits->physical_block_size =
+		max_t(unsigned int, limits->physical_block_size, sector_size);
+	limits->io_min = max_t(unsigned int, limits->io_min, sector_size);
+	limits->dma_alignment = limits->logical_block_size - 1;
+}
+
+static struct target_type inlinecrypt_target = {
+	.name			= "inlinecrypt",
+	.version		= {1, 0, 0},
+	/*
+	 * Do not set DM_TARGET_PASSES_CRYPTO, since dm-inlinecrypt consumes the
+	 * crypto capability itself.
+	 */
+	.features		= DM_TARGET_ZONED_HM,
+	.module			= THIS_MODULE,
+	.ctr			= inlinecrypt_ctr,
+	.dtr			= inlinecrypt_dtr,
+	.map			= inlinecrypt_map,
+	.status			= inlinecrypt_status,
+	.prepare_ioctl		= inlinecrypt_prepare_ioctl,
+	.iterate_devices	= inlinecrypt_iterate_devices,
+	.report_zones		= inlinecrypt_report_zones,
+	.io_hints		= inlinecrypt_io_hints,
+};
+
+module_dm(inlinecrypt);
+
+MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
+MODULE_AUTHOR("Linlin Zhang <linlin.zhang@oss.qualcomm.com>");
+MODULE_DESCRIPTION(DM_NAME " target for inline encryption");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 1/3] block: export blk-crypto symbols required by dm-inlinecrypt
From: Linlin Zhang @ 2026-04-30  9:52 UTC (permalink / raw)
  To: linux-block, ebiggers, mpatocka, gmazyland, bmarzins
  Cc: linux-kernel, adrianvovk, dm-devel, quic_mdalam, israelr, hch,
	axboe
In-Reply-To: <20260430095244.3352446-1-linlin.zhang@oss.qualcomm.com>

From: Eric Biggers <ebiggers@google.com>

bio_crypt_set_ctx(), blk_crypto_init_key(), and
blk_crypto_start_using_key() are needed to use inline encryption; see
Documentation/block/inline-encryption.rst.  Export them so that
dm-inlinecrypt can use them.  The only reason these weren't exported
before was that inline encryption was previously used only by fs/crypto/
which is built-in code.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 block/blk-crypto.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/block/blk-crypto.c b/block/blk-crypto.c
index 856d3c5b1fa0..40a99a859748 100644
--- a/block/blk-crypto.c
+++ b/block/blk-crypto.c
@@ -116,6 +116,7 @@ void bio_crypt_set_ctx(struct bio *bio, const struct blk_crypto_key *key,
 
 	bio->bi_crypt_context = bc;
 }
+EXPORT_SYMBOL_GPL(bio_crypt_set_ctx);
 
 void __bio_crypt_free_ctx(struct bio *bio)
 {
@@ -349,6 +350,7 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(blk_crypto_init_key);
 
 bool blk_crypto_config_supported_natively(struct block_device *bdev,
 					  const struct blk_crypto_config *cfg)
@@ -399,6 +401,7 @@ int blk_crypto_start_using_key(struct block_device *bdev,
 	}
 	return blk_crypto_fallback_start_using_mode(key->crypto_cfg.crypto_mode);
 }
+EXPORT_SYMBOL_GPL(blk_crypto_start_using_key);
 
 /**
  * blk_crypto_evict_key() - Evict a blk_crypto_key from a block_device
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 0/3] dm-inlinecrypt: add target for inline block device encryption
From: Linlin Zhang @ 2026-04-30  9:52 UTC (permalink / raw)
  To: linux-block, ebiggers, mpatocka, gmazyland, bmarzins
  Cc: linux-kernel, adrianvovk, dm-devel, quic_mdalam, israelr, hch,
	axboe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 1671 bytes --]

This patch series is based on Eric’s work posted at:
https://lore.kernel.org/all/ecbb7ea8-11f6-30c1-ad77-bd984c52ca33@quicinc.com/

Eric’s patches introduce a new dm target, dm-inlinecrypt, to support inline
block-device encryption. The implementation builds on the work previously done
in Android’s dm-default-key, but intentionally drops passthrough support,
as that functionality does not appear likely to be accepted upstream in the
near future. With this limitation, dm-inlinecrypt is positioned as a
practical replacement for dm-crypt, rather than a general passthrough
mechanism.

On top of Eric’s series, keyring key support is added in dm-inlinecrypt. Thus,
both keyring key and hex key are feasible for dm-inlinecrypt. In addition,
dm-inlinecrypt.rst is added as the user-guide of dm-inlinecrypt.

V2:
https://lore.kernel.org/all/20260410134031.2880675-1-linlin.zhang@oss.qualcomm.com/

V1:
https://lore.kernel.org/all/20260304121729.1532469-1-linlin.zhang@oss.qualcomm.com/

Eric Biggers (2):
  block: export blk-crypto symbols required by dm-inlinecrypt
  dm-inlinecrypt: add target for inline block device encryption

Linlin Zhang (1):
  dm: add documentation for dm-inlinecrypt target

 .../device-mapper/dm-inlinecrypt.rst          | 123 ++++
 block/blk-crypto.c                            |   3 +
 drivers/md/Kconfig                            |  11 +
 drivers/md/Makefile                           |   1 +
 drivers/md/dm-inlinecrypt.c                   | 596 ++++++++++++++++++
 5 files changed, 734 insertions(+)
 create mode 100644 Documentation/admin-guide/device-mapper/dm-inlinecrypt.rst
 create mode 100644 drivers/md/dm-inlinecrypt.c

-- 
2.34.1


^ permalink raw reply

* Re: [PATCH 2/9] arm64: dts: qcom: arduino-imola: Describe boot1 NVMEM layout
From: Krzysztof Kozlowski @ 2026-04-30  9:43 UTC (permalink / raw)
  To: Loic Poulain
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
	Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
	Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, linux-mmc, devicetree, linux-kernel, linux-arm-msm,
	linux-block, linux-wireless, ath10k, linux-bluetooth, netdev,
	daniel
In-Reply-To: <20260428-block-as-nvmem-v1-2-6ad23e75190a@oss.qualcomm.com>

On Tue, Apr 28, 2026 at 04:23:07PM +0200, Loic Poulain wrote:
> On Arduino Uno-Q, the eMMC boot1 partition is factory provisioned
> with device-specific information such as the WiFi MAC address
> and the Bluetooth BD address. This partition can serve as an
> alternative to additional non-volatile memory, such as a
> dedicated EEPROM.
> 
> The eMMC boot partitions are typically good candidates, as they
> are realively small, read-only by default (and can be enforced
> as hardware read-only), and are not affected by board reflashing
> procedures, which generally target the eMMC user or GP partitions.
> 
> Describe the corresponding nvmem-layout for the WiFi and
> Bluetooth addresses.
> 
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> ---
>  arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts
> index bf088fa9807f040f0c8f405f9111b01790b09377..dc85cf94f71cac8666cab30ccf37cc2d2f8fd941 100644
> --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts
> +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts
> @@ -409,7 +409,31 @@ &sdhc_1 {
>  	no-sdio;
>  	no-sd;
>  
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
>  	status = "okay";
> +
> +	card@0 {
> +		compatible = "mmc-card";
> +		reg = <0>;

> +
> +		partitions-boot1 {
> +			nvmem-layout {

This should not be a separate patch. You add the layout AND you use it.

> +				compatible = "fixed-layout";
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +
> +				wifi_mac_addr: mac-addr@4400 {
> +					reg = <0x4400 0x6>;
> +				};
> +
> +				bd_addr: bd-addr@5400 {
> +					reg = <0x5400 0x6>;
> +				};
> +			};
> +		};
> +	};
>  };
>  
>  &spi5 {
> 
> -- 
> 2.34.1
> 

^ permalink raw reply

* Re: [PATCH v2 2/3] dm-inlinecrypt: add target for inline block device encryption
From: Linlin Zhang @ 2026-04-30  9:21 UTC (permalink / raw)
  To: Benjamin Marzinski
  Cc: linux-block, ebiggers, mpatocka, gmazyland, linux-kernel,
	adrianvovk, dm-devel, quic_mdalam, israelr, hch, axboe
In-Reply-To: <afIqszyKboCEmHDa@redhat.com>



On 4/29/2026 11:58 PM, Benjamin Marzinski wrote:
> On Wed, Apr 29, 2026 at 11:25:04AM -0400, Benjamin Marzinski wrote:
>> On Wed, Apr 29, 2026 at 08:34:00PM +0800, Linlin Zhang wrote:
> [...]
>>>
>>> Thanks for the suggestions.
>>>
>>> Adding a bool need_acct parameter to __blk_crypto_submit_bio() would require
>>> updating all existing callers, which feels rather intrusive given that the
>>> accounting issue only affects the blk‑crypto fallback write slow‑path. I’m a
>>> bit concerned that this would broaden the scope of the change more than
>>> necessary for the problem at hand.
>>
>> I get your concern, and I'd like a second opinion on how much we should
>> care about this, but it doesn't look like there are many other callers
>> that would be effected here. The only existing caller of
>> __blk_crypto_submit_bio() is blk_crypto_submit_bio(), which would just
>> call it with "need_acct=true". Looking at the code path below
>> __blk_crypto_submit_bio() that would need to change for submitting the
>> bios:
>>
>> __blk_crypto_submit_bio() is the only caller of
>> blk_crypto_fallback_bio_prep()
>>
>> blk_crypto_fallback_bio_prep() is the only caller of
>> blk_crypto_fallback_encrypt_bio().
>>
>> blk_crypto_fallback_encrypt_bio() is the only caller of
>> __blk_crypto_fallback_encrypt_bio(), which is the function that would
>> need to choose between submit_bio() and submit_bio_noacct().
>>
>> Doing this would change the crypto API (by necessity, since we're adding
>> a new argument to __blk_crypto_submit_bio() for stacking devices to
>> use), and it is adds a extra argument to a number of functions, just to
>> handle this corner case. But it is still a relatively contained change.
> 
> Having discussed this a bit, I'm fine with leaving this as a TODO for
> now. If anyone wants to chime in with an opinion on how acceptable it
> would be to add a new bio flag for skipping accounting, that would be
> great.

Thanks, Ben.

I’d appreciate it if someone else could chime in on these two approaches.

> 
> -Ben 
> 


^ 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