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