The NVMe-oF target supports interrupt mode for the vfio-user, TCP, and RDMA transports. Interrupt mode allows reactors to sleep when idle and wake on network or device events, reducing CPU usage when the target is not under load.
For general SPDK interrupt mode design, see Interrupt Mode.
This section is for users who want to test or use interrupt mode with the nvmf_tgt application.
nvmf_tgt with the --interrupt-mode flag.-M for vfio-user.spdk_top or scripts/rpc.py framework_get_reactors).Start nvmf_tgt with interrupt mode enabled using the --interrupt-mode flag:
The flag enables interrupt mode during app initialization.
Configure NVMe-oF transports via RPC. TCP and RDMA do not require any interrupt-mode-specific transport options. vfio-user requires the -M flag:
For vfio-user, the -M (--disable-mappable-bar0) flag is required for interrupt mode.
acceptor_poll_rate in interrupt mode because it is fully event-driven.scripts/rpc.py framework_get_reactors or spdk_top to confirm reactors report idle when traffic stops.strace -e epoll_wait on the nvmf_tgt process should show sleeps when idle; for RDMA, ibv_req_notify_cq() counters should increase only when new completions arrive.test/nvmf/target/interrupt.sh demonstrates expected idle/busy transitions under load.ibv_req_notify_cq() succeeds; otherwise poll group creation will fail.disable_mappable_bar0 is set and interrupt fds are properly registered; check guest VM interrupt configuration.This section is for developers embedding the lib/nvmf library into their own applications.
Each NVMe-oF transport integrates with SPDK's event-driven framework differently:
disable_mappable_bar0 option for interrupt mode compatibility.nvmf_tcp_create() in lib/nvmf/tcp.c).nvmf_tcp_poll_group_create() in lib/nvmf/tcp.c).create_ib_device() in lib/nvmf/rdma.c).nvmf_rdma_create() in lib/nvmf/rdma.c).ibv_req_notify_cq() for completions (see nvmf_rdma_poller_create() in lib/nvmf/rdma.c).Developers embedding the NVMe-oF target should enable interrupt mode before initializing SPDK threading and then create transports normally.
spdk_interrupt_mode_enable() once before spdk_thread_lib_init_ext(). If using the event framework (spdk_app_start()), set opts->interrupt_mode = true instead — the framework calls spdk_interrupt_mode_enable() automatically.lib/nvmf/tcp.c, lib/nvmf/rdma.c, and lib/nvmf/vfio_user.c). vfio-user additionally requires the disable_mappable_bar0 transport option.spdk_nvmf_transport_opts_init() with the transport name to get correct per-transport defaults, and check its return value before using the options structure.spdk_nvmf_transport_create_async() has two failure paths: it can fail immediately via its return code, or later via the callback with transport == NULL.spdk_nvmf_tgt_add_transport() before assuming the transport is usable.spdk_nvmf_transport_create_async() must remain valid until all outstanding callbacks complete; keep it in app-owned or heap-allocated state rather than transient stack state.spdk_poller_register_interrupt() so they do not force the thread to stay in poll mode.