xref: /freebsd/tools/cam/cam_all_but_scsi.d (revision cd1aa5f9917cc7de255e854954c818e5ef3e9c9b)
1 #!/usr/sbin/dtrace -s
2 
3 /* Sample use of the cam dtrace provider */
4 
5 /*
6  * Trace all the non I/O commands flowing through CAM
7  */
8 
9 dtrace:::BEGIN
10 {
11 }
12 
13 /*
14  * There's two choke points in CAM. We can intercept the request on the way down
15  * in xpt_action, just before it's sent to the SIM. This can be a good place to
16  * see what's going on before it happens. However, most I/O happens quite
17  * quickly, this isn't much of an advantage. The other place is on completion
18  * when the transaction is finally done. The retry mechanism is built into the
19  * periph driver, which is responsible for submitting the request.
20  *
21  * cam::xpt_action is a single logical point that handles both xpt_action and
22  * xpt_action_direct. Thie example hooks into it. The style is funky because
23  * D doesn't have looping or generalized if constructs.
24  *
25  * The 'trace' context local variable controls printing of different types
26  * of results. This is all controlled by camio.lua.
27  */
28 
29 
30 /*
31  * CAM queues a CCB to the SIM in xpt_action. Save interesting bits
32  * for later winnowing.
33  */
34 /* fbt::xpt_action_default:entry */
35 cam::xpt:action
36 {
37 	this->ccb = ((union ccb *)arg0);
38 	this->func = this->ccb->ccb_h.func_code & 0xff;
39 	this->periph = this->ccb->ccb_h.path->periph;
40 	this->bus = this->ccb->ccb_h.path->bus;
41 	this->target = this->ccb->ccb_h.path->target;
42 	this->device = this->ccb->ccb_h.path->device;
43 	this->trace = 1;
44 }
45 
46 /*
47  * Omit the I/O CCBs. Go ahead and pass the other semi I/O enclosure
48  * commands, though.
49  */
50 cam::xpt:action
51 /this->func == XPT_SCSI_IO || this->func == XPT_NVME_IO || this->func == XPT_NVME_ADMIN || this->func == XPT_ATA_IO/
52 {
53 	this->trace = 0;
54 }
55 
56 /*
57  * Print out the non I/O and non ASYNC commands here.
58  */
59 cam::xpt:action
60 /this->trace && this->func != XPT_ASYNC/
61 {
62 	printf("(%s%d:%s%d:%d:%d:%d): %s",
63 	    this->periph == NULL ? "noperiph" : stringof(this->periph->periph_name),
64 	    this->periph == NULL ? 0 : this->periph->unit_number,
65 	    this->bus == NULL ? "nobus" : this->bus->sim->sim_name,
66 	    this->bus == NULL ? 0 : this->bus->sim->unit_number,
67 	    this->bus == NULL ? 0 : this->bus->sim->bus_id,
68 	    this->target == NULL ? 0 : this->target->target_id,
69 	    this->device == NULL ? 0 : this->device->lun_id,
70 	    xpt_action_string[this->func]);
71 }
72 
73 /*
74  * For async calls, print out the async message type.
75  */
76 cam::xpt:action
77 /this->trace && this->func == XPT_ASYNC/
78 {
79 	printf("(%s%d:%s%d:%d:%d:%d): %s %s",
80 	    this->periph == NULL ? "noperiph" : stringof(this->periph->periph_name),
81 	    this->periph == NULL ? 0 : this->periph->unit_number,
82 	    this->bus == NULL ? "nobus" : this->bus->sim->sim_name,
83 	    this->bus == NULL ? 0 : this->bus->sim->unit_number,
84 	    this->bus == NULL ? 0 : this->bus->sim->bus_id,
85 	    this->target == NULL ? 0 : this->target->target_id,
86 	    this->device == NULL ? 0 : this->device->lun_id,
87 	    xpt_action_string[this->func],
88 	    xpt_async_string[this->ccb->casync.async_code]);
89 }
90