4
4
* SPDX-License-Identifier: GPL-2.0-or-later
5
5
*/
6
6
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
+
7
25
#include <uapi/linux/ptrace.h>
8
26
#include <linux/bpf_common.h>
9
27
#include <uapi/linux/bpf.h>
20
38
typedef struct {
21
39
u64 ts ;
22
40
u64 size ;
41
+ u32 direction ;
23
42
} iscsi_data_t ;
24
43
25
44
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 );
27
47
28
48
// @@ kprobe|iscsit_process_scsi_cmd|iscsi_target_start
29
49
int
30
50
iscsi_target_start (struct pt_regs * ctx , struct iscsi_conn * conn ,
31
51
struct iscsi_cmd * cmd , struct iscsi_scsi_req * hdr )
32
52
{
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 );
37
55
38
56
return (0 );
39
57
}
@@ -53,25 +71,48 @@ aggregate_data(iscsi_data_t *data, u64 ts, char *opstr)
53
71
return (0 );
54
72
}
55
73
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
58
77
int
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 )
60
101
{
61
102
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 ) ;
64
105
65
106
if (data == 0 ) {
66
107
return (0 ); // missed issue
67
108
}
68
109
69
- if (cmd -> data_direction == DMA_FROM_DEVICE ) {
110
+ if (data -> direction == DMA_FROM_DEVICE ) {
70
111
aggregate_data (data , ts , READ_STR );
71
- } else if (cmd -> data_direction & DMA_TO_DEVICE ) {
112
+ } else if (data -> direction == DMA_TO_DEVICE ) {
72
113
aggregate_data (data , ts , WRITE_STR );
73
114
}
74
- iscsi_base_data .delete (( u64 * ) & cmd );
115
+ iscsi_base_data .delete (& tid );
75
116
76
117
return (0 );
77
118
}
0 commit comments