/
mpathIssueTrace.c
383 lines (346 loc) · 14 KB
/
mpathIssueTrace.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
/*
Струкура dm-multipath устройства, с мажнорным и минорным номеромм устройств
dm-multipath усройство dm-7 имеет можнорный номер 253, минорный 7 (253:7)
R2D2_ssd_pool0_res3 (000000000000000000000000000000000) dm-7
size=512G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
`-+- policy='service-time 0' prio=50 status=active
|- 14:0:0:4 sdh 8:112 active ready running
|- 16:0:0:4 sdr 65:16 active ready running
|- 17:0:0:4 sdab 65:176 active ready running
`- 18:0:0:4 sdal 66:80 active ready running
*/
/*
Формат структуры данных трейспоинта block_rq_issue
name: block_rq_issue
ID: 1051
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:dev_t dev; offset:8; size:4; signed:0;
field:sector_t sector; offset:16; size:8; signed:0;
field:unsigned int nr_sector; offset:24; size:4; signed:0;
field:unsigned int bytes; offset:28; size:4; signed:0;
field:char rwbs[8]; offset:32; size:8; signed:1;
field:char comm[16]; offset:40; size:16; signed:1;
field:__data_loc char[] cmd; offset:56; size:4; signed:1;
*/
/* Описание структуры аргумента для трейспоинтов block_rq_issue и block_rq_complete */
struct block_rq_args {
u64 __unused__;
u32 dev;
u64 sector;
u32 nr_sectors;
uint bytes;
char rwbs[8];
char comm[16];
char __data_loc[4];
};
/*
Формат структуры данных трейспоинта block_rq_remap
name: block_rq_remap
ID: 1039
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:dev_t dev; offset:8; size:4; signed:0;
field:sector_t sector; offset:16; size:8; signed:0;
field:unsigned int nr_sector; offset:24; size:4; signed:0;
field:dev_t old_dev; offset:28; size:4; signed:0;
field:sector_t old_sector; offset:32; size:8; signed:0;
field:unsigned int nr_bios; offset:40; size:4; signed:0;
field:char rwbs[8]; offset:44; size:8; signed:1;
*/
/* Описание структуры аргумента для трейспоинта block_rq_remap */
struct block_rq_remap_args {
u64 __unused__;
u32 dev;
u64 sector;
u32 nr_sectors;
u32 old_dev;
u64 old_sector;
uint nr_bios;
char rwbs[8];
};
/*
Структура описывающая операций ввода-вывода зерегистрировванных на блочных устройствах
Времеменная метка
Размер в байтах
*/
struct ioInfo {
u64 ts;
uint bytes;
};
/*
Хеш-таблица для регистрации событий на dm-multipath устройстве,
ключом является номер сектора
*/
BPF_HASH(dm7_253_7, u64, struct ioInfo, 10240); // dm-7 (253:7)
/*
Хеш-таблицы для регистрации событий ввода-вывода на нижележащих
блочных устройствах
*/
BPF_HASH(sdh_8_112, u64, struct ioInfo, 10240); // sdh (8:112)
BPF_HASH(sdr_65_16, u64, struct ioInfo, 10240); // sdr (65:16)
BPF_HASH(sdab_65_176, u64, struct ioInfo, 10240); // sdab (65:176)
BPF_HASH(sdal_66_80, u64, struct ioInfo, 10240); // sdal (66:80)
/*
Структура описывающая операции ввода-вывода подвергающиеся перенаправлению
Времеменная метка
Размер в байтах
Устройство на которое произошло переназначение
Сектор
*/
struct ioInfoRemap {
u64 ts;
uint bytes;
u32 dev;
u64 sector;
};
/*
Хеш-таблица для регистрации событий перенаправления, ключ - сектор
*/
BPF_HASH(dm7_253_7_remap, u64, struct ioInfoRemap, 10240);
/*
Фкнкция обработки события перенаправления
*/
int traceRemap (struct block_rq_remap_args *args) {
/*
Игнорируем все события не являющиеся операцией записи
*/
if (args->rwbs[0] != 'W') return 0;
/*
Подготавливаем и заполняем структуру описывающую перанаправленный запрос
*/
struct ioInfoRemap io;
__builtin_memset(&io, 0, sizeof(io));
io.ts = bpf_ktime_get_ns();
io.bytes=args->nr_sectors*512;
io.dev=args->dev;
io.sector=args->sector;
/*
Раскрываем мажорный и минорный номера устройства
*/
int majorNum = args->old_dev >> 20;
int minorNum = ((int) ((args->old_dev) & ((1U << 20) - 1)));
/*
Сохраняем сектор старого устройства для последующего использования
в качестве ключа для сохранения в хеш-таблице
*/
u64 sector=args->old_sector;
/*
Сохранение в заполененой структуры описывющей перенаправленную операцию
в хеш-таблицы соответвующей нашему dm-multipath устройству
*/
switch (majorNum) {
case 253:
switch (minorNum) {
// Блочное устройств dm-7 (253:7)
case 7:
dm7_253_7_remap.update(§or, &io);
break;
default:
break;
}
default:
break;
}
return 0;
}
/*
Функция обработки события отправки запсроса
*/
int traceIssue (struct block_rq_args *args) {
/*
Игнорируем все операции не явлющиеся записью
*/
if (args->rwbs[0] != 'W') return 0;
/*
Подготавливаем структуру и заполняем её значениями текущего времени
и размера блока
*/
struct ioInfo io;
__builtin_memset(&io, 0, sizeof(io));
io.ts = bpf_ktime_get_ns();
io.bytes = args->bytes;
/*
Сохраняем в перемнной значение секотра для последующего использования
в качестве индекса
*/
u64 sector=args->sector;
/*
Раскрываем мажорный и минорный номера устройства
*/
int majorNum = args->dev >> 20;
int minorNum = ((int) ((args->dev) & ((1U << 20) - 1)));
/*
Основываясь на мажорном и минорном номерах устройств сохраняем в
хеш-таблице информацию о времени начала операции и размере блока
на интересующих нас блочных устройствах
*/
switch (majorNum) {
case 253:
switch (minorNum) {
case 7:
dm7_253_7.update(§or, &io); // dm-7 253:7
break;
default:
break;
}
case 8:
switch (minorNum) {
case 112:
sdh_8_112.update(§or, &io); // sdh 8:112
break;
default:
break;
}
case 65:
switch (minorNum) {
case 16:
sdr_65_16.update(§or, &io); // sdr 65:16
break;
case 176:
sdab_65_176.update(§or, &io); // sdab 65:176
break;
default:
break;
}
case 66:
switch (minorNum) {
case 80:
sdal_66_80.update(§or, &io); // sdal 66:80
break;
default:
break;
}
default:
break;
}
return 0;
}
/*
Функция обработки события заершения запроса.
*/
int traceComplete (struct block_rq_args *args) {
/*
Игнорируем все операции не явлющиеся записью
*/
if (args->rwbs[0] != 'W') return 0;
u64 delta;
struct ioInfo *io;
struct ioInfo *io_inner;
struct ioInfoRemap *io_remap;
/*
Сохраняем в перемнной значение секотра для последующего использования
в качестве индекса поиска по таблицам устройств
*/
u64 sector=args->sector;
/*
Раскрываем мажорный и минорный номера устройств
*/
int majorNum = args->dev >> 20;
int minorNum = ((int) ((args->dev) & ((1U << 20) - 1)));
switch (majorNum) {
case 253:
switch (minorNum) {
/*
Вычисляем время выполнения для операции на устростве верхнего уровня,
в данном случае dm-mpath dm-7 (253:7)
*/
case 7:
io = dm7_253_7.lookup(§or);
if (io == 0) { return 0; }
/*
Вычисляем время выполнения операции, если оно ниже порогового значения
удаляем из таблиц записи соответсвуюшие сектору и завершаем обработку
*/
delta = (bpf_ktime_get_ns() - io->ts)/1000/1000;
if (delta < 1000) {
dm7_253_7.delete(§or);
dm7_253_7_remap.delete(§or);
sdh_8_112.delete(§or);
sdr_65_16.delete(§or);
sdab_65_176.delete(§or);
sdal_66_80.delete(§or);
return 0;
}
/*
В противном случае печатаем интересующую нас информацию, вычисляем
время от отпарвки события до операции remap, а затем производим поиск
в таблицах нижележащих устройств операции соответствующей сектору и
вычисляем время выполнения на данном устройстве. После вычисления и
распечатки интересующей информации записи в таблице удаляются
*/
bpf_trace_printk ("Sector: %llx size: %d lat: %d", sector, io->bytes, delta);
bpf_trace_printk ("Dev: %d:%d Op: %s",majorNum, minorNum, args->rwbs);
bpf_trace_printk ("Issue timestamp on %d:%d : %lld ",majorNum, minorNum, io->ts);
/*
Поиск в таблице dm7_253_7_remap структуры содержащей информацию о времени
события перенаправления для текущего сектора
*/
io_remap = dm7_253_7_remap.lookup(§or);
if (io_remap != 0) {
delta = (bpf_ktime_get_ns() - io_remap->ts)/1000/1000;
int majorNumRemap = io_remap->dev >> 20;
int minorNumRemap = ((int) ((io_remap->dev) & ((1U << 20) - 1)));
bpf_trace_printk ("Remap sector: %llx, size: %d, lat %d", io_remap->sector, io_remap->bytes, delta);
bpf_trace_printk ("Remap dev: %d:%d ts:", majorNumRemap, minorNumRemap, io_remap->ts);
/*
Удаление записи после обработки события
*/
dm7_253_7_remap.delete(§or);
} else { bpf_trace_printk ("Remap event not found"); }
/*
Поиск в таблицам нижележащих устройств записи содержащей информацию о
времени события отравки запроса для текущего сектора
*/
io_inner = sdh_8_112.lookup(§or);
if (io_inner != 0) {
delta = (bpf_ktime_get_ns() - io_inner->ts)/1000/1000;
bpf_trace_printk ("Maj: 8 Min: 112 lat: %d", delta);
/*
Удаление записей соответствущих текущему сектору в таблицах текущего устройства
и устройства верхнего уровня
*/
dm7_253_7.delete(§or);
sdh_8_112.delete(§or);
return 0;
}
io_inner = sdr_65_16.lookup(§or);
if (io_inner != 0) {
delta = (bpf_ktime_get_ns() - io_inner->ts)/1000/1000;
bpf_trace_printk ("Maj: 65 Min: 16 lat: %d", delta);
dm7_253_7.delete(§or);
sdr_65_16.delete(§or);
return 0;
}
io_inner = sdab_65_176.lookup(§or);
if (io_inner != 0) {
delta = (bpf_ktime_get_ns() - io_inner->ts)/1000/1000;
bpf_trace_printk ("Maj: 65 Min: 176 lat: %d", delta);
dm7_253_7.delete(§or);
sdab_65_176.delete(§or);
return 0;
}
io_inner = sdal_66_80.lookup(§or);
if (io_inner != 0) {
delta = (bpf_ktime_get_ns() - io_inner->ts)/1000/1000;
bpf_trace_printk ("Maj: 66 Min: 80 lat: %d", delta);
dm7_253_7.delete(§or);
sdal_66_80.delete(§or);
return 0;
}
bpf_trace_printk ("Inner event not found");
break;
default:
break;
}
default:
break;
}
return 0;
}