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