Skip to main content

No SSD

Design note

This page traces the NoSSD implementation through the source. For launch lines, guest commands, limits and verification, use the NoSSD guide in the FEMU Manual.

femu_mode=2 exposes an NVMe read/write device backed by host DRAM without a flash translation or NAND timing model. Use it to study the guest/emulator I/O path and as a baseline for the cost added by other modes.

Download nossd.conf. hiops_inline=on is the default; eligible requests bypass the FTL-ring round trip. A mixed controller still routes each namespace according to its actual mode.

For an explicit controller-service model, use nossd-link.conf, which adds 4000 MB/s link bandwidth, 1000 ns propagation, and 500 ns firmware service. These settings disable the pure inline shortcut. They are illustrative values, not a hardware calibration.

Completion routing​

Inline completion requires all of the following: the controller's base mode is NoSSD, hiops_inline=on, the request belongs to a NoSSD namespace, both link properties are zero, and fw_cpu_ns=0. Setting hiops_inline=on alone therefore does not establish which path a request takes.

ConfigurationCompletion path
NoSSD controller and namespace, inline enabled, no link or firmware costsPost the completion in the submission-queue sweep; batch its interrupt at sweep end
Same device with inline disabled or an added service costEnqueue the request; the completion handler applies configured costs and waits for its deadline
NoSSD namespace on a controller whose base mode is not NoSSDUse the ring path, even though the namespace has no NAND model
Another mode's namespace on a NoSSD controllerDispatch according to that namespace; it cannot take the NoSSD inline shortcut

The ring path does not by itself imply a separate FTL worker. When use_ftl_thread is false, nvme_process_cq_cpl() drains to_ftl directly. When a controller needs the worker, the completion handler drains to_poller after worker processing. Keep controller mode and per-namespace mode in the experiment record, especially for mixed controllers.

The inline sweep also stops before consuming another submission when its active completion queue is full. This preserves unread completion entries; queue depth and guest completion consumption still matter without NAND delay.

Isolate the cost you are measuring​

Compare three cases with the same workload and thread placement: the default inline path, hiops_inline=off with all service costs zero, and the link/firmware recipe above. The second case exposes ring and completion-scheduling overhead; the third adds modeled service costs as well. A direct comparison between the first and third changes both mechanisms.

For a 4 KiB request, the example link takes 4096 × 1000 / 4000 = 1024 ns. With idle timelines, propagation and firmware service bring the modeled deadline increment to 1024 + 1000 + 500 = 2524 ns. This is not a prediction of guest-observed latency. See the queued example for how later requests wait on shared resources.

queues, multipoller_enabled, and poller_ratio affect available queue and poller concurrency. The source includes run-nossd-hiops.sh and a hiops/ workflow for host checks, VM launch, preparation, pinning, and measurement. Inspect host-specific paths and affinity settings before using them.

Verify read/write correctness first, then report guest vCPUs, emulator thread placement, queue count, queue depth, I/O size, and the inline/link settings. NoSSD results contain software, DMA, and host scheduling costs; they are not an estimate of zero-latency physical SSD throughput.

Implementation sources​

Reviewed against FEMU 39a55eeb637b. The examples describe this revision; see validation coverage.