diff options
Diffstat (limited to 'drivers/block/drbd/drbd_tracing.c')
-rw-r--r-- | drivers/block/drbd/drbd_tracing.c | 752 |
1 files changed, 0 insertions, 752 deletions
diff --git a/drivers/block/drbd/drbd_tracing.c b/drivers/block/drbd/drbd_tracing.c deleted file mode 100644 index d18d4f7b4bef..000000000000 --- a/drivers/block/drbd/drbd_tracing.c +++ /dev/null | |||
@@ -1,752 +0,0 @@ | |||
1 | /* | ||
2 | drbd_tracing.c | ||
3 | |||
4 | This file is part of DRBD by Philipp Reisner and Lars Ellenberg. | ||
5 | |||
6 | Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. | ||
7 | Copyright (C) 2003-2008, Philipp Reisner <philipp.reisner@linbit.com>. | ||
8 | Copyright (C) 2003-2008, Lars Ellenberg <lars.ellenberg@linbit.com>. | ||
9 | |||
10 | drbd is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2, or (at your option) | ||
13 | any later version. | ||
14 | |||
15 | drbd is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with drbd; see the file COPYING. If not, write to | ||
22 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | |||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/drbd.h> | ||
28 | #include <linux/ctype.h> | ||
29 | #include "drbd_int.h" | ||
30 | #include "drbd_tracing.h" | ||
31 | #include <linux/drbd_tag_magic.h> | ||
32 | |||
33 | MODULE_LICENSE("GPL"); | ||
34 | MODULE_AUTHOR("Philipp Reisner, Lars Ellenberg"); | ||
35 | MODULE_DESCRIPTION("DRBD tracepoint probes"); | ||
36 | MODULE_PARM_DESC(trace_mask, "Bitmap of events to trace see drbd_tracing.c"); | ||
37 | MODULE_PARM_DESC(trace_level, "Current tracing level (changeable in /sys)"); | ||
38 | MODULE_PARM_DESC(trace_devs, "Bitmap of devices to trace (changeable in /sys)"); | ||
39 | |||
40 | unsigned int trace_mask = 0; /* Bitmap of events to trace */ | ||
41 | int trace_level; /* Current trace level */ | ||
42 | int trace_devs; /* Bitmap of devices to trace */ | ||
43 | |||
44 | module_param(trace_mask, uint, 0444); | ||
45 | module_param(trace_level, int, 0644); | ||
46 | module_param(trace_devs, int, 0644); | ||
47 | |||
48 | enum { | ||
49 | TRACE_PACKET = 0x0001, | ||
50 | TRACE_RQ = 0x0002, | ||
51 | TRACE_UUID = 0x0004, | ||
52 | TRACE_RESYNC = 0x0008, | ||
53 | TRACE_EE = 0x0010, | ||
54 | TRACE_UNPLUG = 0x0020, | ||
55 | TRACE_NL = 0x0040, | ||
56 | TRACE_AL_EXT = 0x0080, | ||
57 | TRACE_INT_RQ = 0x0100, | ||
58 | TRACE_MD_IO = 0x0200, | ||
59 | TRACE_EPOCH = 0x0400, | ||
60 | }; | ||
61 | |||
62 | /* Buffer printing support | ||
63 | * dbg_print_flags: used for Flags arg to drbd_print_buffer | ||
64 | * - DBGPRINT_BUFFADDR; if set, each line starts with the | ||
65 | * virtual address of the line being output. If clear, | ||
66 | * each line starts with the offset from the beginning | ||
67 | * of the buffer. */ | ||
68 | enum dbg_print_flags { | ||
69 | DBGPRINT_BUFFADDR = 0x0001, | ||
70 | }; | ||
71 | |||
72 | /* Macro stuff */ | ||
73 | static char *nl_packet_name(int packet_type) | ||
74 | { | ||
75 | /* Generate packet type strings */ | ||
76 | #define NL_PACKET(name, number, fields) \ | ||
77 | [P_ ## name] = # name, | ||
78 | #define NL_INTEGER Argh! | ||
79 | #define NL_BIT Argh! | ||
80 | #define NL_INT64 Argh! | ||
81 | #define NL_STRING Argh! | ||
82 | |||
83 | static char *nl_tag_name[P_nl_after_last_packet] = { | ||
84 | #include "linux/drbd_nl.h" | ||
85 | }; | ||
86 | |||
87 | return (packet_type < sizeof(nl_tag_name)/sizeof(nl_tag_name[0])) ? | ||
88 | nl_tag_name[packet_type] : "*Unknown*"; | ||
89 | } | ||
90 | /* /Macro stuff */ | ||
91 | |||
92 | static inline int is_mdev_trace(struct drbd_conf *mdev, unsigned int level) | ||
93 | { | ||
94 | return trace_level >= level && ((1 << mdev_to_minor(mdev)) & trace_devs); | ||
95 | } | ||
96 | |||
97 | static void probe_drbd_unplug(struct drbd_conf *mdev, char *msg) | ||
98 | { | ||
99 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
100 | return; | ||
101 | |||
102 | dev_info(DEV, "%s, ap_bio_count=%d\n", msg, atomic_read(&mdev->ap_bio_cnt)); | ||
103 | } | ||
104 | |||
105 | static void probe_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index) | ||
106 | { | ||
107 | static char *uuid_str[UI_EXTENDED_SIZE] = { | ||
108 | [UI_CURRENT] = "CURRENT", | ||
109 | [UI_BITMAP] = "BITMAP", | ||
110 | [UI_HISTORY_START] = "HISTORY_START", | ||
111 | [UI_HISTORY_END] = "HISTORY_END", | ||
112 | [UI_SIZE] = "SIZE", | ||
113 | [UI_FLAGS] = "FLAGS", | ||
114 | }; | ||
115 | |||
116 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
117 | return; | ||
118 | |||
119 | if (index >= UI_EXTENDED_SIZE) { | ||
120 | dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n"); | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | dev_info(DEV, " uuid[%s] now %016llX\n", | ||
125 | uuid_str[index], | ||
126 | (unsigned long long)mdev->ldev->md.uuid[index]); | ||
127 | } | ||
128 | |||
129 | static void probe_drbd_md_io(struct drbd_conf *mdev, int rw, | ||
130 | struct drbd_backing_dev *bdev) | ||
131 | { | ||
132 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
133 | return; | ||
134 | |||
135 | dev_info(DEV, " %s metadata superblock now\n", | ||
136 | rw == READ ? "Reading" : "Writing"); | ||
137 | } | ||
138 | |||
139 | static void probe_drbd_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, char* msg) | ||
140 | { | ||
141 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
142 | return; | ||
143 | |||
144 | dev_info(DEV, "EE %s sec=%llus size=%u e=%p\n", | ||
145 | msg, (unsigned long long)e->sector, e->size, e); | ||
146 | } | ||
147 | |||
148 | static void probe_drbd_epoch(struct drbd_conf *mdev, struct drbd_epoch *epoch, | ||
149 | enum epoch_event ev) | ||
150 | { | ||
151 | static char *epoch_event_str[] = { | ||
152 | [EV_PUT] = "put", | ||
153 | [EV_GOT_BARRIER_NR] = "got_barrier_nr", | ||
154 | [EV_BARRIER_DONE] = "barrier_done", | ||
155 | [EV_BECAME_LAST] = "became_last", | ||
156 | [EV_TRACE_FLUSH] = "issuing_flush", | ||
157 | [EV_TRACE_ADD_BARRIER] = "added_barrier", | ||
158 | [EV_TRACE_SETTING_BI] = "just set barrier_in_next_epoch", | ||
159 | }; | ||
160 | |||
161 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
162 | return; | ||
163 | |||
164 | ev &= ~EV_CLEANUP; | ||
165 | |||
166 | switch (ev) { | ||
167 | case EV_TRACE_ALLOC: | ||
168 | dev_info(DEV, "Allocate epoch %p/xxxx { } nr_epochs=%d\n", epoch, mdev->epochs); | ||
169 | break; | ||
170 | case EV_TRACE_FREE: | ||
171 | dev_info(DEV, "Freeing epoch %p/%d { size=%d } nr_epochs=%d\n", | ||
172 | epoch, epoch->barrier_nr, atomic_read(&epoch->epoch_size), | ||
173 | mdev->epochs); | ||
174 | break; | ||
175 | default: | ||
176 | dev_info(DEV, "Update epoch %p/%d { size=%d active=%d %c%c n%c%c } ev=%s\n", | ||
177 | epoch, epoch->barrier_nr, atomic_read(&epoch->epoch_size), | ||
178 | atomic_read(&epoch->active), | ||
179 | test_bit(DE_HAVE_BARRIER_NUMBER, &epoch->flags) ? 'n' : '-', | ||
180 | test_bit(DE_CONTAINS_A_BARRIER, &epoch->flags) ? 'b' : '-', | ||
181 | test_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &epoch->flags) ? 'i' : '-', | ||
182 | test_bit(DE_BARRIER_IN_NEXT_EPOCH_DONE, &epoch->flags) ? 'd' : '-', | ||
183 | epoch_event_str[ev]); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | static void probe_drbd_netlink(void *data, int is_req) | ||
188 | { | ||
189 | struct cn_msg *msg = data; | ||
190 | |||
191 | if (is_req) { | ||
192 | struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)msg->data; | ||
193 | |||
194 | printk(KERN_INFO "drbd%d: " | ||
195 | "Netlink: << %s (%d) - seq: %x, ack: %x, len: %x\n", | ||
196 | nlp->drbd_minor, | ||
197 | nl_packet_name(nlp->packet_type), | ||
198 | nlp->packet_type, | ||
199 | msg->seq, msg->ack, msg->len); | ||
200 | } else { | ||
201 | struct drbd_nl_cfg_reply *nlp = (struct drbd_nl_cfg_reply *)msg->data; | ||
202 | |||
203 | printk(KERN_INFO "drbd%d: " | ||
204 | "Netlink: >> %s (%d) - seq: %x, ack: %x, len: %x\n", | ||
205 | nlp->minor, | ||
206 | nlp->packet_type == P_nl_after_last_packet ? | ||
207 | "Empty-Reply" : nl_packet_name(nlp->packet_type), | ||
208 | nlp->packet_type, | ||
209 | msg->seq, msg->ack, msg->len); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static void probe_drbd_actlog(struct drbd_conf *mdev, sector_t sector, char* msg) | ||
214 | { | ||
215 | unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9)); | ||
216 | |||
217 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
218 | return; | ||
219 | |||
220 | dev_info(DEV, "%s (sec=%llus, al_enr=%u, rs_enr=%d)\n", | ||
221 | msg, (unsigned long long) sector, enr, | ||
222 | (int)BM_SECT_TO_EXT(sector)); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * drbd_print_buffer() - Hexdump arbitrary binary data into a buffer | ||
227 | * @prefix: String is output at the beginning of each line output. | ||
228 | * @flags: Currently only defined flag: DBGPRINT_BUFFADDR; if set, each | ||
229 | * line starts with the virtual address of the line being | ||
230 | * output. If clear, each line starts with the offset from the | ||
231 | * beginning of the buffer. | ||
232 | * @size: Indicates the size of each entry in the buffer. Supported | ||
233 | * values are sizeof(char), sizeof(short) and sizeof(int) | ||
234 | * @buffer: Start address of buffer | ||
235 | * @buffer_va: Virtual address of start of buffer (normally the same | ||
236 | * as Buffer, but having it separate allows it to hold | ||
237 | * file address for example) | ||
238 | * @length: length of buffer | ||
239 | */ | ||
240 | static void drbd_print_buffer(const char *prefix, unsigned int flags, int size, | ||
241 | const void *buffer, const void *buffer_va, | ||
242 | unsigned int length) | ||
243 | |||
244 | #define LINE_SIZE 16 | ||
245 | #define LINE_ENTRIES (int)(LINE_SIZE/size) | ||
246 | { | ||
247 | const unsigned char *pstart; | ||
248 | const unsigned char *pstart_va; | ||
249 | const unsigned char *pend; | ||
250 | char bytes_str[LINE_SIZE*3+8], ascii_str[LINE_SIZE+8]; | ||
251 | char *pbytes = bytes_str, *pascii = ascii_str; | ||
252 | int offset = 0; | ||
253 | long sizemask; | ||
254 | int field_width; | ||
255 | int index; | ||
256 | const unsigned char *pend_str; | ||
257 | const unsigned char *p; | ||
258 | int count; | ||
259 | |||
260 | /* verify size parameter */ | ||
261 | if (size != sizeof(char) && | ||
262 | size != sizeof(short) && | ||
263 | size != sizeof(int)) { | ||
264 | printk(KERN_DEBUG "drbd_print_buffer: " | ||
265 | "ERROR invalid size %d\n", size); | ||
266 | return; | ||
267 | } | ||
268 | |||
269 | sizemask = size-1; | ||
270 | field_width = size*2; | ||
271 | |||
272 | /* Adjust start/end to be on appropriate boundary for size */ | ||
273 | buffer = (const char *)((long)buffer & ~sizemask); | ||
274 | pend = (const unsigned char *) | ||
275 | (((long)buffer + length + sizemask) & ~sizemask); | ||
276 | |||
277 | if (flags & DBGPRINT_BUFFADDR) { | ||
278 | /* Move start back to nearest multiple of line size, | ||
279 | * if printing address. This results in nicely formatted output | ||
280 | * with addresses being on line size (16) byte boundaries */ | ||
281 | pstart = (const unsigned char *)((long)buffer & ~(LINE_SIZE-1)); | ||
282 | } else { | ||
283 | pstart = (const unsigned char *)buffer; | ||
284 | } | ||
285 | |||
286 | /* Set value of start VA to print if addresses asked for */ | ||
287 | pstart_va = (const unsigned char *)buffer_va | ||
288 | - ((const unsigned char *)buffer-pstart); | ||
289 | |||
290 | /* Calculate end position to nicely align right hand side */ | ||
291 | pend_str = pstart + (((pend-pstart) + LINE_SIZE-1) & ~(LINE_SIZE-1)); | ||
292 | |||
293 | /* Init strings */ | ||
294 | *pbytes = *pascii = '\0'; | ||
295 | |||
296 | /* Start at beginning of first line */ | ||
297 | p = pstart; | ||
298 | count = 0; | ||
299 | |||
300 | while (p < pend_str) { | ||
301 | if (p < (const unsigned char *)buffer || p >= pend) { | ||
302 | /* Before start of buffer or after end- print spaces */ | ||
303 | pbytes += sprintf(pbytes, "%*c ", field_width, ' '); | ||
304 | pascii += sprintf(pascii, "%*c", size, ' '); | ||
305 | p += size; | ||
306 | } else { | ||
307 | /* Add hex and ascii to strings */ | ||
308 | int val; | ||
309 | switch (size) { | ||
310 | default: | ||
311 | case 1: | ||
312 | val = *(unsigned char *)p; | ||
313 | break; | ||
314 | case 2: | ||
315 | val = *(unsigned short *)p; | ||
316 | break; | ||
317 | case 4: | ||
318 | val = *(unsigned int *)p; | ||
319 | break; | ||
320 | } | ||
321 | |||
322 | pbytes += sprintf(pbytes, "%0*x ", field_width, val); | ||
323 | |||
324 | for (index = size; index; index--) { | ||
325 | *pascii++ = isprint(*p) ? *p : '.'; | ||
326 | p++; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | count++; | ||
331 | |||
332 | if (count == LINE_ENTRIES || p >= pend_str) { | ||
333 | /* Null terminate and print record */ | ||
334 | *pascii = '\0'; | ||
335 | printk(KERN_DEBUG "%s%8.8lx: %*s|%*s|\n", | ||
336 | prefix, | ||
337 | (flags & DBGPRINT_BUFFADDR) | ||
338 | ? (long)pstart_va:(long)offset, | ||
339 | LINE_ENTRIES*(field_width+1), bytes_str, | ||
340 | LINE_SIZE, ascii_str); | ||
341 | |||
342 | /* Move onto next line */ | ||
343 | pstart_va += (p-pstart); | ||
344 | pstart = p; | ||
345 | count = 0; | ||
346 | offset += LINE_SIZE; | ||
347 | |||
348 | /* Re-init strings */ | ||
349 | pbytes = bytes_str; | ||
350 | pascii = ascii_str; | ||
351 | *pbytes = *pascii = '\0'; | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | |||
356 | static void probe_drbd_resync(struct drbd_conf *mdev, int level, const char *fmt, va_list args) | ||
357 | { | ||
358 | char str[256]; | ||
359 | |||
360 | if (!is_mdev_trace(mdev, level)) | ||
361 | return; | ||
362 | |||
363 | if (vsnprintf(str, 256, fmt, args) >= 256) | ||
364 | str[255] = 0; | ||
365 | |||
366 | printk(KERN_INFO "%s %s: %s", dev_driver_string(disk_to_dev(mdev->vdisk)), | ||
367 | dev_name(disk_to_dev(mdev->vdisk)), str); | ||
368 | } | ||
369 | |||
370 | static void probe_drbd_bio(struct drbd_conf *mdev, const char *pfx, struct bio *bio, int complete, | ||
371 | struct drbd_request *r) | ||
372 | { | ||
373 | #if defined(CONFIG_LBDAF) || defined(CONFIG_LBD) | ||
374 | #define SECTOR_FORMAT "%Lx" | ||
375 | #else | ||
376 | #define SECTOR_FORMAT "%lx" | ||
377 | #endif | ||
378 | #define SECTOR_SHIFT 9 | ||
379 | |||
380 | unsigned long lowaddr = (unsigned long)(bio->bi_sector << SECTOR_SHIFT); | ||
381 | char *faddr = (char *)(lowaddr); | ||
382 | char rb[sizeof(void *)*2+6] = { 0, }; | ||
383 | struct bio_vec *bvec; | ||
384 | int segno; | ||
385 | |||
386 | const int rw = bio->bi_rw; | ||
387 | const int biorw = (rw & (RW_MASK|RWA_MASK)); | ||
388 | const int biobarrier = (rw & (1<<BIO_RW_BARRIER)); | ||
389 | const int biosync = (rw & ((1<<BIO_RW_UNPLUG) | (1<<BIO_RW_SYNCIO))); | ||
390 | |||
391 | if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS)) | ||
392 | return; | ||
393 | |||
394 | if (r) | ||
395 | sprintf(rb, "Req:%p ", r); | ||
396 | |||
397 | dev_info(DEV, "%s %s:%s%s%s Bio:%p %s- %soffset " SECTOR_FORMAT ", size %x\n", | ||
398 | complete ? "<<<" : ">>>", | ||
399 | pfx, | ||
400 | biorw == WRITE ? "Write" : "Read", | ||
401 | biobarrier ? " : B" : "", | ||
402 | biosync ? " : S" : "", | ||
403 | bio, | ||
404 | rb, | ||
405 | complete ? (bio_flagged(bio, BIO_UPTODATE) ? "Success, " : "Failed, ") : "", | ||
406 | bio->bi_sector << SECTOR_SHIFT, | ||
407 | bio->bi_size); | ||
408 | |||
409 | if (trace_level >= TRACE_LVL_METRICS && | ||
410 | ((biorw == WRITE) ^ complete)) { | ||
411 | printk(KERN_DEBUG " ind page offset length\n"); | ||
412 | __bio_for_each_segment(bvec, bio, segno, 0) { | ||
413 | printk(KERN_DEBUG " [%d] %p %8.8x %8.8x\n", segno, | ||
414 | bvec->bv_page, bvec->bv_offset, bvec->bv_len); | ||
415 | |||
416 | if (trace_level >= TRACE_LVL_ALL) { | ||
417 | char *bvec_buf; | ||
418 | unsigned long flags; | ||
419 | |||
420 | bvec_buf = bvec_kmap_irq(bvec, &flags); | ||
421 | |||
422 | drbd_print_buffer(" ", DBGPRINT_BUFFADDR, 1, | ||
423 | bvec_buf, | ||
424 | faddr, | ||
425 | (bvec->bv_len <= 0x80) | ||
426 | ? bvec->bv_len : 0x80); | ||
427 | |||
428 | bvec_kunmap_irq(bvec_buf, &flags); | ||
429 | |||
430 | if (bvec->bv_len > 0x40) | ||
431 | printk(KERN_DEBUG " ....\n"); | ||
432 | |||
433 | faddr += bvec->bv_len; | ||
434 | } | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | |||
439 | static void probe_drbd_req(struct drbd_request *req, enum drbd_req_event what, char *msg) | ||
440 | { | ||
441 | static const char *rq_event_names[] = { | ||
442 | [created] = "created", | ||
443 | [to_be_send] = "to_be_send", | ||
444 | [to_be_submitted] = "to_be_submitted", | ||
445 | [queue_for_net_write] = "queue_for_net_write", | ||
446 | [queue_for_net_read] = "queue_for_net_read", | ||
447 | [send_canceled] = "send_canceled", | ||
448 | [send_failed] = "send_failed", | ||
449 | [handed_over_to_network] = "handed_over_to_network", | ||
450 | [connection_lost_while_pending] = | ||
451 | "connection_lost_while_pending", | ||
452 | [recv_acked_by_peer] = "recv_acked_by_peer", | ||
453 | [write_acked_by_peer] = "write_acked_by_peer", | ||
454 | [neg_acked] = "neg_acked", | ||
455 | [conflict_discarded_by_peer] = "conflict_discarded_by_peer", | ||
456 | [barrier_acked] = "barrier_acked", | ||
457 | [data_received] = "data_received", | ||
458 | [read_completed_with_error] = "read_completed_with_error", | ||
459 | [read_ahead_completed_with_error] = "reada_completed_with_error", | ||
460 | [write_completed_with_error] = "write_completed_with_error", | ||
461 | [completed_ok] = "completed_ok", | ||
462 | }; | ||
463 | |||
464 | struct drbd_conf *mdev = req->mdev; | ||
465 | |||
466 | const int rw = (req->master_bio == NULL || | ||
467 | bio_data_dir(req->master_bio) == WRITE) ? | ||
468 | 'W' : 'R'; | ||
469 | const unsigned long s = req->rq_state; | ||
470 | |||
471 | if (what != nothing) { | ||
472 | dev_info(DEV, "__req_mod(%p %c ,%s)\n", req, rw, rq_event_names[what]); | ||
473 | } else { | ||
474 | dev_info(DEV, "%s %p %c L%c%c%cN%c%c%c%c%c %u (%llus +%u) %s\n", | ||
475 | msg, req, rw, | ||
476 | s & RQ_LOCAL_PENDING ? 'p' : '-', | ||
477 | s & RQ_LOCAL_COMPLETED ? 'c' : '-', | ||
478 | s & RQ_LOCAL_OK ? 'o' : '-', | ||
479 | s & RQ_NET_PENDING ? 'p' : '-', | ||
480 | s & RQ_NET_QUEUED ? 'q' : '-', | ||
481 | s & RQ_NET_SENT ? 's' : '-', | ||
482 | s & RQ_NET_DONE ? 'd' : '-', | ||
483 | s & RQ_NET_OK ? 'o' : '-', | ||
484 | req->epoch, | ||
485 | (unsigned long long)req->sector, | ||
486 | req->size, | ||
487 | drbd_conn_str(mdev->state.conn)); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | |||
492 | #define drbd_peer_str drbd_role_str | ||
493 | #define drbd_pdsk_str drbd_disk_str | ||
494 | |||
495 | #define PSM(A) \ | ||
496 | do { \ | ||
497 | if (mask.A) { \ | ||
498 | int i = snprintf(p, len, " " #A "( %s )", \ | ||
499 | drbd_##A##_str(val.A)); \ | ||
500 | if (i >= len) \ | ||
501 | return op; \ | ||
502 | p += i; \ | ||
503 | len -= i; \ | ||
504 | } \ | ||
505 | } while (0) | ||
506 | |||
507 | static char *dump_st(char *p, int len, union drbd_state mask, union drbd_state val) | ||
508 | { | ||
509 | char *op = p; | ||
510 | *p = '\0'; | ||
511 | PSM(role); | ||
512 | PSM(peer); | ||
513 | PSM(conn); | ||
514 | PSM(disk); | ||
515 | PSM(pdsk); | ||
516 | |||
517 | return op; | ||
518 | } | ||
519 | |||
520 | #define INFOP(fmt, args...) \ | ||
521 | do { \ | ||
522 | if (trace_level >= TRACE_LVL_ALL) { \ | ||
523 | dev_info(DEV, "%s:%d: %s [%d] %s %s " fmt , \ | ||
524 | file, line, current->comm, current->pid, \ | ||
525 | sockname, recv ? "<<<" : ">>>" , \ | ||
526 | ## args); \ | ||
527 | } else { \ | ||
528 | dev_info(DEV, "%s %s " fmt, sockname, \ | ||
529 | recv ? "<<<" : ">>>" , \ | ||
530 | ## args); \ | ||
531 | } \ | ||
532 | } while (0) | ||
533 | |||
534 | static char *_dump_block_id(u64 block_id, char *buff) | ||
535 | { | ||
536 | if (is_syncer_block_id(block_id)) | ||
537 | strcpy(buff, "SyncerId"); | ||
538 | else | ||
539 | sprintf(buff, "%llx", (unsigned long long)block_id); | ||
540 | |||
541 | return buff; | ||
542 | } | ||
543 | |||
544 | static void probe_drbd_packet(struct drbd_conf *mdev, struct socket *sock, | ||
545 | int recv, union p_polymorph *p, char *file, int line) | ||
546 | { | ||
547 | char *sockname = sock == mdev->meta.socket ? "meta" : "data"; | ||
548 | int cmd = (recv == 2) ? p->header.command : be16_to_cpu(p->header.command); | ||
549 | char tmp[300]; | ||
550 | union drbd_state m, v; | ||
551 | |||
552 | switch (cmd) { | ||
553 | case P_HAND_SHAKE: | ||
554 | INFOP("%s (protocol %u-%u)\n", cmdname(cmd), | ||
555 | be32_to_cpu(p->handshake.protocol_min), | ||
556 | be32_to_cpu(p->handshake.protocol_max)); | ||
557 | break; | ||
558 | |||
559 | case P_BITMAP: /* don't report this */ | ||
560 | case P_COMPRESSED_BITMAP: /* don't report this */ | ||
561 | break; | ||
562 | |||
563 | case P_DATA: | ||
564 | INFOP("%s (sector %llus, id %s, seq %u, f %x)\n", cmdname(cmd), | ||
565 | (unsigned long long)be64_to_cpu(p->data.sector), | ||
566 | _dump_block_id(p->data.block_id, tmp), | ||
567 | be32_to_cpu(p->data.seq_num), | ||
568 | be32_to_cpu(p->data.dp_flags) | ||
569 | ); | ||
570 | break; | ||
571 | |||
572 | case P_DATA_REPLY: | ||
573 | case P_RS_DATA_REPLY: | ||
574 | INFOP("%s (sector %llus, id %s)\n", cmdname(cmd), | ||
575 | (unsigned long long)be64_to_cpu(p->data.sector), | ||
576 | _dump_block_id(p->data.block_id, tmp) | ||
577 | ); | ||
578 | break; | ||
579 | |||
580 | case P_RECV_ACK: | ||
581 | case P_WRITE_ACK: | ||
582 | case P_RS_WRITE_ACK: | ||
583 | case P_DISCARD_ACK: | ||
584 | case P_NEG_ACK: | ||
585 | case P_NEG_RS_DREPLY: | ||
586 | INFOP("%s (sector %llus, size %u, id %s, seq %u)\n", | ||
587 | cmdname(cmd), | ||
588 | (long long)be64_to_cpu(p->block_ack.sector), | ||
589 | be32_to_cpu(p->block_ack.blksize), | ||
590 | _dump_block_id(p->block_ack.block_id, tmp), | ||
591 | be32_to_cpu(p->block_ack.seq_num) | ||
592 | ); | ||
593 | break; | ||
594 | |||
595 | case P_DATA_REQUEST: | ||
596 | case P_RS_DATA_REQUEST: | ||
597 | INFOP("%s (sector %llus, size %u, id %s)\n", cmdname(cmd), | ||
598 | (long long)be64_to_cpu(p->block_req.sector), | ||
599 | be32_to_cpu(p->block_req.blksize), | ||
600 | _dump_block_id(p->block_req.block_id, tmp) | ||
601 | ); | ||
602 | break; | ||
603 | |||
604 | case P_BARRIER: | ||
605 | case P_BARRIER_ACK: | ||
606 | INFOP("%s (barrier %u)\n", cmdname(cmd), p->barrier.barrier); | ||
607 | break; | ||
608 | |||
609 | case P_SYNC_PARAM: | ||
610 | case P_SYNC_PARAM89: | ||
611 | INFOP("%s (rate %u, verify-alg \"%.64s\", csums-alg \"%.64s\")\n", | ||
612 | cmdname(cmd), be32_to_cpu(p->rs_param_89.rate), | ||
613 | p->rs_param_89.verify_alg, p->rs_param_89.csums_alg); | ||
614 | break; | ||
615 | |||
616 | case P_UUIDS: | ||
617 | INFOP("%s Curr:%016llX, Bitmap:%016llX, " | ||
618 | "HisSt:%016llX, HisEnd:%016llX\n", | ||
619 | cmdname(cmd), | ||
620 | (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_CURRENT]), | ||
621 | (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_BITMAP]), | ||
622 | (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_HISTORY_START]), | ||
623 | (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_HISTORY_END])); | ||
624 | break; | ||
625 | |||
626 | case P_SIZES: | ||
627 | INFOP("%s (d %lluMiB, u %lluMiB, c %lldMiB, " | ||
628 | "max bio %x, q order %x)\n", | ||
629 | cmdname(cmd), | ||
630 | (long long)(be64_to_cpu(p->sizes.d_size)>>(20-9)), | ||
631 | (long long)(be64_to_cpu(p->sizes.u_size)>>(20-9)), | ||
632 | (long long)(be64_to_cpu(p->sizes.c_size)>>(20-9)), | ||
633 | be32_to_cpu(p->sizes.max_segment_size), | ||
634 | be32_to_cpu(p->sizes.queue_order_type)); | ||
635 | break; | ||
636 | |||
637 | case P_STATE: | ||
638 | v.i = be32_to_cpu(p->state.state); | ||
639 | m.i = 0xffffffff; | ||
640 | dump_st(tmp, sizeof(tmp), m, v); | ||
641 | INFOP("%s (s %x {%s})\n", cmdname(cmd), v.i, tmp); | ||
642 | break; | ||
643 | |||
644 | case P_STATE_CHG_REQ: | ||
645 | m.i = be32_to_cpu(p->req_state.mask); | ||
646 | v.i = be32_to_cpu(p->req_state.val); | ||
647 | dump_st(tmp, sizeof(tmp), m, v); | ||
648 | INFOP("%s (m %x v %x {%s})\n", cmdname(cmd), m.i, v.i, tmp); | ||
649 | break; | ||
650 | |||
651 | case P_STATE_CHG_REPLY: | ||
652 | INFOP("%s (ret %x)\n", cmdname(cmd), | ||
653 | be32_to_cpu(p->req_state_reply.retcode)); | ||
654 | break; | ||
655 | |||
656 | case P_PING: | ||
657 | case P_PING_ACK: | ||
658 | /* | ||
659 | * Dont trace pings at summary level | ||
660 | */ | ||
661 | if (trace_level < TRACE_LVL_ALL) | ||
662 | break; | ||
663 | /* fall through... */ | ||
664 | default: | ||
665 | INFOP("%s (%u)\n", cmdname(cmd), cmd); | ||
666 | break; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | |||
671 | static int __init drbd_trace_init(void) | ||
672 | { | ||
673 | int ret; | ||
674 | |||
675 | if (trace_mask & TRACE_UNPLUG) { | ||
676 | ret = register_trace_drbd_unplug(probe_drbd_unplug); | ||
677 | WARN_ON(ret); | ||
678 | } | ||
679 | if (trace_mask & TRACE_UUID) { | ||
680 | ret = register_trace_drbd_uuid(probe_drbd_uuid); | ||
681 | WARN_ON(ret); | ||
682 | } | ||
683 | if (trace_mask & TRACE_EE) { | ||
684 | ret = register_trace_drbd_ee(probe_drbd_ee); | ||
685 | WARN_ON(ret); | ||
686 | } | ||
687 | if (trace_mask & TRACE_PACKET) { | ||
688 | ret = register_trace_drbd_packet(probe_drbd_packet); | ||
689 | WARN_ON(ret); | ||
690 | } | ||
691 | if (trace_mask & TRACE_MD_IO) { | ||
692 | ret = register_trace_drbd_md_io(probe_drbd_md_io); | ||
693 | WARN_ON(ret); | ||
694 | } | ||
695 | if (trace_mask & TRACE_EPOCH) { | ||
696 | ret = register_trace_drbd_epoch(probe_drbd_epoch); | ||
697 | WARN_ON(ret); | ||
698 | } | ||
699 | if (trace_mask & TRACE_NL) { | ||
700 | ret = register_trace_drbd_netlink(probe_drbd_netlink); | ||
701 | WARN_ON(ret); | ||
702 | } | ||
703 | if (trace_mask & TRACE_AL_EXT) { | ||
704 | ret = register_trace_drbd_actlog(probe_drbd_actlog); | ||
705 | WARN_ON(ret); | ||
706 | } | ||
707 | if (trace_mask & TRACE_RQ) { | ||
708 | ret = register_trace_drbd_bio(probe_drbd_bio); | ||
709 | WARN_ON(ret); | ||
710 | } | ||
711 | if (trace_mask & TRACE_INT_RQ) { | ||
712 | ret = register_trace_drbd_req(probe_drbd_req); | ||
713 | WARN_ON(ret); | ||
714 | } | ||
715 | if (trace_mask & TRACE_RESYNC) { | ||
716 | ret = register_trace__drbd_resync(probe_drbd_resync); | ||
717 | WARN_ON(ret); | ||
718 | } | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | module_init(drbd_trace_init); | ||
723 | |||
724 | static void __exit drbd_trace_exit(void) | ||
725 | { | ||
726 | if (trace_mask & TRACE_UNPLUG) | ||
727 | unregister_trace_drbd_unplug(probe_drbd_unplug); | ||
728 | if (trace_mask & TRACE_UUID) | ||
729 | unregister_trace_drbd_uuid(probe_drbd_uuid); | ||
730 | if (trace_mask & TRACE_EE) | ||
731 | unregister_trace_drbd_ee(probe_drbd_ee); | ||
732 | if (trace_mask & TRACE_PACKET) | ||
733 | unregister_trace_drbd_packet(probe_drbd_packet); | ||
734 | if (trace_mask & TRACE_MD_IO) | ||
735 | unregister_trace_drbd_md_io(probe_drbd_md_io); | ||
736 | if (trace_mask & TRACE_EPOCH) | ||
737 | unregister_trace_drbd_epoch(probe_drbd_epoch); | ||
738 | if (trace_mask & TRACE_NL) | ||
739 | unregister_trace_drbd_netlink(probe_drbd_netlink); | ||
740 | if (trace_mask & TRACE_AL_EXT) | ||
741 | unregister_trace_drbd_actlog(probe_drbd_actlog); | ||
742 | if (trace_mask & TRACE_RQ) | ||
743 | unregister_trace_drbd_bio(probe_drbd_bio); | ||
744 | if (trace_mask & TRACE_INT_RQ) | ||
745 | unregister_trace_drbd_req(probe_drbd_req); | ||
746 | if (trace_mask & TRACE_RESYNC) | ||
747 | unregister_trace__drbd_resync(probe_drbd_resync); | ||
748 | |||
749 | tracepoint_synchronize_unregister(); | ||
750 | } | ||
751 | |||
752 | module_exit(drbd_trace_exit); | ||