summaryrefslogtreecommitdiffstats
path: root/src/spdk/doc/nvmf_tracing.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/doc/nvmf_tracing.md')
-rw-r--r--src/spdk/doc/nvmf_tracing.md179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/spdk/doc/nvmf_tracing.md b/src/spdk/doc/nvmf_tracing.md
new file mode 100644
index 00000000..4a7b9afb
--- /dev/null
+++ b/src/spdk/doc/nvmf_tracing.md
@@ -0,0 +1,179 @@
+# NVMe-oF Target Tracepoints {#nvmf_tgt_tracepoints}
+
+# Introduction {#tracepoints_intro}
+
+SPDK has a tracing framework for capturing low-level event information at runtime.
+Tracepoints provide a high-performance tracing mechanism that is accessible at runtime.
+They are implemented as a circular buffer in shared memory that is accessible from other
+processes. The NVMe-oF target is instrumented with tracepoints to enable analysis of
+both performance and application crashes. (Note: the SPDK tracing framework should still
+be considered experimental. Work to formalize and document the framework is in progress.)
+
+# Enabling Tracepoints {#enable_tracepoints}
+
+Tracepoints are placed in groups. They are enabled and disabled as a group. To enable
+the instrumentation of all the tracepoints group in an SPDK target application, start the
+target with -e parameter set to 0xFFFF:
+
+~~~
+app/nvmf_tgt/nvmf_tgt -e 0xFFFF
+~~~
+
+To enable the instrumentation of just the NVMe-oF RDMA tracepoints in an SPDK target
+application, start the target with the -e parameter set to 0x10:
+
+~~~
+app/nvmf_tgt/nvmf_tgt -e 0x10
+~~~
+
+When the target starts, a message is logged with the information you need to view
+the tracepoints in a human-readable format using the spdk_trace application. The target
+will also log information about the shared memory file.
+
+~~~{.sh}
+app.c: 527:spdk_app_setup_trace: *NOTICE*: Tracepoint Group Mask 0xFFFF specified.
+app.c: 531:spdk_app_setup_trace: *NOTICE*: Use 'spdk_trace -s nvmf -p 24147' to capture a snapshot of events at runtime.
+app.c: 533:spdk_app_setup_trace: *NOTICE*: Or copy /dev/shm/nvmf_trace.pid24147 for offline analysis/debug.
+~~~
+
+Note that when tracepoints are enabled, the shared memory files are not deleted when the application
+exits. This ensures the file can be used for analysis after the application exits. On Linux, the
+shared memory files are in /dev/shm, and can be deleted manually to free shm space if needed. A system
+reboot will also free all of the /dev/shm files.
+
+# Capturing a snapshot of events {#capture_tracepoints}
+
+Send I/Os to the SPDK target application to generate events. The following is
+an example usage of perf to send I/Os to the NVMe-oF target over an RDMA network
+interface for 10 minutes.
+
+~~~
+./perf -q 128 -s 4096 -w randread -t 600 -r 'trtype:RDMA adrfam:IPv4 traddr:192.168.100.2 trsvcid:4420'
+~~~
+
+The spdk_trace program can be found in the app/trace directory. To analyze the tracepoints on the same
+system running the NVMe-oF target, simply execute the command line shown in the log:
+
+~~~{.sh}
+app/trace/spdk_trace -s nvmf -p 24147
+~~~
+
+To analyze the tracepoints on a different system, first prepare the tracepoint file for transfer. The
+tracepoint file can be large, but usually compresses very well. This step can also be used to prepare
+a tracepoint file to attach to a GitHub issue for debugging NVMe-oF application crashes.
+
+~~~{.sh}
+bzip2 -c /dev/shm/nvmf_trace.pid24147 > /tmp/trace.bz2
+~~~
+
+After transferring the /tmp/trace.bz2 tracepoint file to a different system:
+
+~~~{.sh}
+bunzip2 /tmp/trace.bz2
+app/trace/spdk_trace -f /tmp/trace
+~~~
+
+The following is sample trace capture showing the cumulative time that each
+I/O spends at each RDMA state. All the trace captures with the same id are for
+the same I/O.
+
+~~~
+28: 6026.658 ( 12656064) RDMA_REQ_NEED_BUFFER id: r3622 time: 0.019
+28: 6026.694 ( 12656140) RDMA_REQ_RDY_TO_EXECUTE id: r3622 time: 0.055
+28: 6026.820 ( 12656406) RDMA_REQ_EXECUTING id: r3622 time: 0.182
+28: 6026.992 ( 12656766) RDMA_REQ_EXECUTED id: r3477 time: 228.510
+28: 6027.010 ( 12656804) RDMA_REQ_TX_PENDING_C_TO_H id: r3477 time: 228.528
+28: 6027.022 ( 12656828) RDMA_REQ_RDY_TO_COMPLETE id: r3477 time: 228.539
+28: 6027.115 ( 12657024) RDMA_REQ_COMPLETING id: r3477 time: 228.633
+28: 6027.471 ( 12657770) RDMA_REQ_COMPLETED id: r3518 time: 171.577
+28: 6028.027 ( 12658940) RDMA_REQ_NEW id: r3623
+28: 6028.057 ( 12659002) RDMA_REQ_NEED_BUFFER id: r3623 time: 0.030
+28: 6028.095 ( 12659082) RDMA_REQ_RDY_TO_EXECUTE id: r3623 time: 0.068
+28: 6028.216 ( 12659336) RDMA_REQ_EXECUTING id: r3623 time: 0.189
+28: 6028.408 ( 12659740) RDMA_REQ_EXECUTED id: r3505 time: 190.509
+28: 6028.441 ( 12659808) RDMA_REQ_TX_PENDING_C_TO_H id: r3505 time: 190.542
+28: 6028.452 ( 12659832) RDMA_REQ_RDY_TO_COMPLETE id: r3505 time: 190.553
+28: 6028.536 ( 12660008) RDMA_REQ_COMPLETING id: r3505 time: 190.637
+28: 6028.854 ( 12660676) RDMA_REQ_COMPLETED id: r3465 time: 247.000
+28: 6029.433 ( 12661892) RDMA_REQ_NEW id: r3624
+28: 6029.452 ( 12661932) RDMA_REQ_NEED_BUFFER id: r3624 time: 0.019
+28: 6029.482 ( 12661996) RDMA_REQ_RDY_TO_EXECUTE id: r3624 time: 0.050
+28: 6029.591 ( 12662224) RDMA_REQ_EXECUTING id: r3624 time: 0.158
+28: 6029.782 ( 12662624) RDMA_REQ_EXECUTED id: r3564 time: 96.937
+28: 6029.798 ( 12662658) RDMA_REQ_TX_PENDING_C_TO_H id: r3564 time: 96.953
+28: 6029.812 ( 12662688) RDMA_REQ_RDY_TO_COMPLETE id: r3564 time: 96.967
+28: 6029.899 ( 12662870) RDMA_REQ_COMPLETING id: r3564 time: 97.054
+28: 6030.262 ( 12663634) RDMA_REQ_COMPLETED id: r3477 time: 231.780
+28: 6030.786 ( 12664734) RDMA_REQ_NEW id: r3625
+28: 6030.804 ( 12664772) RDMA_REQ_NEED_BUFFER id: r3625 time: 0.018
+28: 6030.841 ( 12664848) RDMA_REQ_RDY_TO_EXECUTE id: r3625 time: 0.054
+28: 6030.963 ( 12665104) RDMA_REQ_EXECUTING id: r3625 time: 0.176
+28: 6031.139 ( 12665474) RDMA_REQ_EXECUTED id: r3552 time: 114.906
+28: 6031.196 ( 12665594) RDMA_REQ_TX_PENDING_C_TO_H id: r3552 time: 114.963
+28: 6031.210 ( 12665624) RDMA_REQ_RDY_TO_COMPLETE id: r3552 time: 114.977
+28: 6031.293 ( 12665798) RDMA_REQ_COMPLETING id: r3552 time: 115.060
+28: 6031.633 ( 12666512) RDMA_REQ_COMPLETED id: r3505 time: 193.734
+28: 6032.230 ( 12667766) RDMA_REQ_NEW id: r3626
+28: 6032.248 ( 12667804) RDMA_REQ_NEED_BUFFER id: r3626 time: 0.018
+28: 6032.288 ( 12667888) RDMA_REQ_RDY_TO_EXECUTE id: r3626 time: 0.058
+28: 6032.396 ( 12668114) RDMA_REQ_EXECUTING id: r3626 time: 0.166
+28: 6032.593 ( 12668528) RDMA_REQ_EXECUTED id: r3570 time: 90.443
+28: 6032.611 ( 12668564) RDMA_REQ_TX_PENDING_C_TO_H id: r3570 time: 90.460
+28: 6032.623 ( 12668590) RDMA_REQ_RDY_TO_COMPLETE id: r3570 time: 90.473
+28: 6032.707 ( 12668766) RDMA_REQ_COMPLETING id: r3570 time: 90.557
+28: 6033.056 ( 12669500) RDMA_REQ_COMPLETED id: r3564 time: 100.211
+~~~
+
+# Adding New Tracepoints {#add_tracepoints}
+
+SPDK applications and libraries provide several trace points. You can add new
+tracepoints to the existing trace groups. For example, to add a new tracepoints
+to the SPDK RDMA library (lib/nvmf/rdma.c) trace group TRACE_GROUP_NVMF_RDMA,
+define the tracepoints and assigning them a unique ID using the SPDK_TPOINT_ID macro:
+
+~~~
+#define TRACE_GROUP_NVMF_RDMA 0x4
+#define TRACE_RDMA_REQUEST_STATE_NEW SPDK_TPOINT_ID(TRACE_GROUP_NVMF_RDMA, 0x0)
+...
+#define NEW_TRACE_POINT_NAME SPDK_TPOINT_ID(TRACE_GROUP_NVMF_RDMA, UNIQUE_ID)
+~~~
+
+You also need to register the new trace points in the SPDK_TRACE_REGISTER_FN macro call
+within the application/library using the spdk_trace_register_description function
+as shown below:
+
+~~~
+SPDK_TRACE_REGISTER_FN(nvmf_trace)
+{
+ spdk_trace_register_object(OBJECT_NVMF_RDMA_IO, 'r');
+ spdk_trace_register_description("RDMA_REQ_NEW", "",
+ TRACE_RDMA_REQUEST_STATE_NEW,
+ OWNER_NONE, OBJECT_NVMF_RDMA_IO, 1, 1, "cmid: ");
+ ...
+ spdk_trace_register_description("NEW_RDMA_REQ_NAME", "",
+ NEW_TRACE_POINT_NAME,
+ OWNER_NONE, OBJECT_NVMF_RDMA_IO, 0, 1, "cmid: ");
+}
+~~~
+
+Finally, use the spdk_trace_record function at the appropriate point in the
+application/library to record the current trace state for the new trace points.
+The following example shows the usage of the spdk_trace_record function to
+record the current trace state of several tracepoints.
+
+~~~
+ case RDMA_REQUEST_STATE_NEW:
+ spdk_trace_record(TRACE_RDMA_REQUEST_STATE_NEW, 0, 0, (uintptr_t)rdma_req, (uintptr_t)rqpair->cm_id);
+ ...
+ break;
+ case RDMA_REQUEST_STATE_NEED_BUFFER:
+ spdk_trace_record(TRACE_RDMA_REQUEST_STATE_NEED_BUFFER, 0, 0, (uintptr_t)rdma_req, (uintptr_t)rqpair->cm_id);
+ ...
+ break;
+ case RDMA_REQUEST_STATE_TRANSFER_PENDING_HOST_TO_CONTROLLER:
+ spdk_trace_record(TRACE_RDMA_REQUEST_STATE_TRANSFER_PENDING_HOST_TO_CONTROLLER, 0, 0,
+ (uintptr_t)rdma_req, (uintptr_t)rqpair->cm_id);
+ ...
+~~~
+
+All the tracing functions are documented in the [Tracepoint library documentation](https://www.spdk.io/doc/trace_8h.html)