Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/cam/cam_all_but_scsi.d
96280 views
#!/usr/sbin/dtrace -s

/* Sample use of the cam dtrace provider */

/*
 * Trace all the non I/O commands flowing through CAM
 */

dtrace:::BEGIN
{
}

/*
 * There's two choke points in CAM. We can intercept the request on the way down
 * in xpt_action, just before it's sent to the SIM. This can be a good place to
 * see what's going on before it happens. However, most I/O happens quite
 * quickly, this isn't much of an advantage. The other place is on completion
 * when the transaction is finally done. The retry mechanism is built into the
 * periph driver, which is responsible for submitting the request.
 *
 * cam::xpt_action is a single logical point that handles both xpt_action and
 * xpt_action_direct. Thie example hooks into it. The style is funky because
 * D doesn't have looping or generalized if constructs.
 *
 * The 'trace' context local variable controls printing of different types
 * of results. This is all controlled by camio.lua.
 */


/*
 * CAM queues a CCB to the SIM in xpt_action. Save interesting bits
 * for later winnowing.
 */
/* fbt::xpt_action_default:entry */
cam::xpt:action
{
	this->ccb = ((union ccb *)arg0);
	this->func = this->ccb->ccb_h.func_code & 0xff;
	this->periph = this->ccb->ccb_h.path->periph;
	this->bus = this->ccb->ccb_h.path->bus;
	this->target = this->ccb->ccb_h.path->target;
	this->device = this->ccb->ccb_h.path->device;
	this->trace = 1;
}

/*
 * Omit the I/O CCBs. Go ahead and pass the other semi I/O enclosure
 * commands, though.
 */
cam::xpt:action
/this->func == XPT_SCSI_IO || this->func == XPT_NVME_IO || this->func == XPT_NVME_ADMIN || this->func == XPT_ATA_IO/
{
	this->trace = 0;
}

/*
 * Print out the non I/O and non ASYNC commands here.
 */
cam::xpt:action
/this->trace && this->func != XPT_ASYNC/
{
	printf("(%s%d:%s%d:%d:%d:%d): %s",
	    this->periph == NULL ? "noperiph" : stringof(this->periph->periph_name),
	    this->periph == NULL ? 0 : this->periph->unit_number,
	    this->bus == NULL ? "nobus" : this->bus->sim->sim_name,
	    this->bus == NULL ? 0 : this->bus->sim->unit_number,
	    this->bus == NULL ? 0 : this->bus->sim->bus_id,
	    this->target == NULL ? 0 : this->target->target_id,
	    this->device == NULL ? 0 : this->device->lun_id,
	    xpt_action_string[this->func]);
}

/*
 * For async calls, print out the async message type.
 */
cam::xpt:action
/this->trace && this->func == XPT_ASYNC/
{
	printf("(%s%d:%s%d:%d:%d:%d): %s %s",
	    this->periph == NULL ? "noperiph" : stringof(this->periph->periph_name),
	    this->periph == NULL ? 0 : this->periph->unit_number,
	    this->bus == NULL ? "nobus" : this->bus->sim->sim_name,
	    this->bus == NULL ? 0 : this->bus->sim->unit_number,
	    this->bus == NULL ? 0 : this->bus->sim->bus_id,
	    this->target == NULL ? 0 : this->target->target_id,
	    this->device == NULL ? 0 : this->device->lun_id,
	    xpt_action_string[this->func],
	    xpt_async_string[this->ccb->casync.async_code]);
}