[PATCH 1/5] nvme-tcp: initialize pf_cache_lock when allocating the controller

Saravanan D saravanand at crusoe.ai
Sat Oct 17 14:37:15 PDT 2026


On Wed, Oct 14, 2026 at 09:46:39AM +0200, Daniel Wagner wrote:
> Since commit 61b0ed3be81b ("nvme-tcp: parallelize I/O queue allocation
> and startup") the I/O tag set is allocated before the I/O queues.
> blk_mq_alloc_tag_set calls nvme_tcp_init_request for every request,
> which takes pf_cache_lock of the request's queue, but nvme_tcp_alloc_queue
> initializes that mutex only later.  With CONFIG_DEBUG_MUTEXES the first
> connect triggers DEBUG_LOCKS_WARN_ON(lock->magic != lock) in
> __mutex_lock and lock debugging is disabled.

I hit the same warning on nvme-7.4, and also a second path to it, a
reconnect that grows the queue count. Every teardown frees the I/O
queues, and nvme_tcp_free_queue() destroys their pf_cache_lock. When
a reconnect raises the queue count, blk_mq_update_nr_hw_queues()
initializes the requests of the added hardware contexts, and with them
takes pf_cache_lock of their queues, before nvme_tcp_setup_io_queues()
allocates those queues.

  shrink, 4 -> 3 queues
    nvme_tcp_free_queue(4)        mutex_destroy(q4 pf_cache_lock)
  grow, 3 -> 4 queues
    blk_mq_update_nr_hw_queues()
      nvme_tcp_init_request()     mutex_lock(q4 pf_cache_lock)  <- WARN
    nvme_tcp_setup_io_queues()
      nvme_tcp_alloc_queue(4)     mutex_init(q4 pf_cache_lock)

  WARNING: kernel/locking/mutex.c:625 at __mutex_lock+0x434/0x117c
  Call trace:
   __mutex_lock+0x434/0x117c (P)
   mutex_lock_nested+0x24/0x30
   nvme_tcp_init_request+0xb0/0x260
   blk_mq_alloc_map_and_rqs+0x388/0x670
   blk_mq_update_nr_hw_queues+0xb30/0x1058
   nvme_tcp_setup_ctrl+0xa9c/0xda4
   nvme_tcp_reconnect_ctrl_work+0x70/0x2d8
   process_one_work+0x7a0/0x1b5c

Dropping the mutex_destroy() from nvme_tcp_free_queue(), as this patch
does, fixes that path too. It may be worth mentioning this fact in the
changelog.

Tested against nvmet-tcp over loopback with lockdep, KASAN and
DEBUG_KOBJECT_RELEASE, covering connect, reset loops under I/O,
shrinking and growing the queue count through attr_qid_max, and
reconnects while the port is removed.

Tested-by: Saravanan D <saravanand at crusoe.ai>

Thanks,
Saravanan D.



More information about the Linux-nvme mailing list