44 * SPDX-License-Identifier: GPL-2.0-or-later
55 */
66
7+ /*
8+ * This tracer provides latency and througphput data for the iscsi target
9+ * read and writes. The latency is measured from entering
10+ * iscsit_process_scsi_cmd() to exiting iscsit_target_response(). The
11+ * thread that enters iscsi_process_scsi_cmd() will put an entry on the
12+ * request task queue. This entry will be removed from the queue and
13+ * processed by another thread which calls iscsi_target_response.
14+ * The tracing is performed by three probe functions.
15+ * 1. iscsi_target_start - This function saves a timestamp of the entry
16+ * into iscsit_process_scsi_cmd() hashed by a pointer to the iscssi_cmd.
17+ * 2. iscsi_target_response - This function serves the purpose of moving
18+ * the timestamp saved by iscsi_target_start to a thread id based hash.
19+ * Also the size and direction are stored in the hash since kretprobes
20+ * do not have access to parameters.
21+ * 3. iscsi_target_end - This function retrieves the hashed base data by
22+ * thread id and performs the data aggregation.
23+ */
24+
725#include <uapi/linux/ptrace.h>
826#include <linux/bpf_common.h>
927#include <uapi/linux/bpf.h>
2038typedef struct {
2139 u64 ts ;
2240 u64 size ;
41+ u32 direction ;
2342} iscsi_data_t ;
2443
2544
26- BPF_HASH (iscsi_base_data , u64 , iscsi_data_t );
45+ BPF_HASH (iscsi_start_ts , u64 , u64 );
46+ BPF_HASH (iscsi_base_data , u32 , iscsi_data_t );
2747
2848// @@ kprobe|iscsit_process_scsi_cmd|iscsi_target_start
2949int
3050iscsi_target_start (struct pt_regs * ctx , struct iscsi_conn * conn ,
3151 struct iscsi_cmd * cmd , struct iscsi_scsi_req * hdr )
3252{
33- iscsi_data_t data = {};
34- data .ts = bpf_ktime_get_ns ();
35- data .size = hdr -> data_length ;
36- iscsi_base_data .update ((u64 * ) & cmd , & data );
53+ u64 ts = bpf_ktime_get_ns ();
54+ iscsi_start_ts .update ((u64 * ) & cmd , & ts );
3755
3856 return (0 );
3957}
@@ -53,25 +71,48 @@ aggregate_data(iscsi_data_t *data, u64 ts, char *opstr)
5371 return (0 );
5472}
5573
56- // @@ kprobe|iscsit_build_rsp_pdu|iscsi_target_end
57- // @@ kprobe|iscsit_build_datain_pdu|iscsi_target_end
74+
75+
76+ // @@ kprobe|iscsit_response_queue|iscsi_target_response
5877int
59- iscsi_target_end (struct pt_regs * ctx , struct iscsi_cmd * cmd )
78+ iscsi_target_response (struct pt_regs * ctx , struct iscsi_conn * conn , struct iscsi_cmd * cmd , int state )
79+ {
80+ u32 tid = bpf_get_current_pid_tgid ();
81+ iscsi_data_t data = {};
82+
83+ u64 * tsp = iscsi_start_ts .lookup ((u64 * ) & cmd );
84+ if (tsp == 0 ) {
85+ return (0 ); // missed issue
86+ }
87+
88+ data .ts = * tsp ;
89+ data .size = cmd -> se_cmd .data_length ;
90+ data .direction = cmd -> data_direction ;
91+
92+ iscsi_base_data .update (& tid , & data );
93+ iscsi_start_ts .delete ((u64 * ) & cmd );
94+
95+ return (0 );
96+ }
97+
98+ // @@ kretprobe|iscsit_response_queue|iscsi_target_end
99+ int
100+ iscsi_target_end (struct pt_regs * ctx )
60101{
61102 u64 ts = bpf_ktime_get_ns ();
62- iscsi_data_t * data = iscsi_base_data . lookup (( u64 * ) & cmd );
63- u64 delta ;
103+ u32 tid = bpf_get_current_pid_tgid ( );
104+ iscsi_data_t * data = iscsi_base_data . lookup ( & tid ) ;
64105
65106 if (data == 0 ) {
66107 return (0 ); // missed issue
67108 }
68109
69- if (cmd -> data_direction == DMA_FROM_DEVICE ) {
110+ if (data -> direction == DMA_FROM_DEVICE ) {
70111 aggregate_data (data , ts , READ_STR );
71- } else if (cmd -> data_direction & DMA_TO_DEVICE ) {
112+ } else if (data -> direction == DMA_TO_DEVICE ) {
72113 aggregate_data (data , ts , WRITE_STR );
73114 }
74- iscsi_base_data .delete (( u64 * ) & cmd );
115+ iscsi_base_data .delete (& tid );
75116
76117 return (0 );
77118}
0 commit comments