Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Dec 2025 23:08:02 -0700
From:      Warner Losh <imp@bsdimp.com>
To:        Martin <iio7@protonmail.com>
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Subject:   Re: Prevent spin-up of USB HD after upgrading to FreeBSD 15
Message-ID:  <CANCZdfpkf9_nWKDTUZ3VSK-XyfgvC5RheqRw4gxG3jtuCbrA1w@mail.gmail.com>
In-Reply-To: <2ol9PnW7p50uz0__d_HOZzN2nfR0mB_SFeYzSBYdfCzuVJRDQ7xLNL6nlOAqu-PTMiN9ONG01J1mTL4vEFQc66oZVMJTJuGxFDkOG2yQwRc=@protonmail.com>
References:  <j7XoSQMU-9G-lOiNcAsrUE4FmIzX26V971Z5fLI7RtfIyvm_6PoXbSksem-pXoMZNy9CchKhGl7C2T9xkQAlL84Y89Y5byUOkOuIwSnBtlY=@protonmail.com> <CANCZdfooL8vCCKbm0txCb%2BTDffGhxc1fDD4SwVLM08tDZPz=GA@mail.gmail.com> <t565nv2ZOb8O-k2pel6bLS_AsjvqgIA6Io6cGvbkWjcPbC_miDkRrqzEWflTpN5hvINq7vwhuZ6y8avls__jRm464UoxN944kTpB-8yXXQc=@protonmail.com> <CANCZdfp7WSETfqxq=bc9fqrFFncYcRgzeJ%2BnyX3xZoOo-xPiAQ@mail.gmail.com> <2ol9PnW7p50uz0__d_HOZzN2nfR0mB_SFeYzSBYdfCzuVJRDQ7xLNL6nlOAqu-PTMiN9ONG01J1mTL4vEFQc66oZVMJTJuGxFDkOG2yQwRc=@protonmail.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]

[-- Attachment #2 --]
#!/usr/sbin/dtrace -s

inline string xpt_action_string[int key] =
	key ==  0 ? "XPT_NOOP" :
	key ==  1 ? "XPT_SCSI_IO" :
	key ==  2 ? "XPT_GDEV_TYPE" :
	key ==  3 ? "XPT_GDEVLIST" :
	key ==  4 ? "XPT_PATH_INQ" :
	key ==  5 ? "XPT_REL_SIMQ" :
	key ==  6 ? "XPT_SASYNC_CB" :
	key ==  7 ? "XPT_SDEV_TYPE" :
	key ==  8 ? "XPT_SCAN_BUS" :
	key ==  9 ? "XPT_DEV_MATCH" :
	key == 10 ? "XPT_DEBUG" :
	key == 11 ? "XPT_PATH_STATS" :
	key == 12 ? "XPT_GDEV_STATS" :
	key == 13 ? "XPT_0X0d" :
	key == 14 ? "XPT_DEV_ADVINFO" :
	key == 15 ? "XPT_ASYNC" :
	key == 16 ? "XPT_ABORT" :
	key == 17 ? "XPT_RESET_BUS" :
	key == 18 ? "XPT_RESET_DEV" :
	key == 19 ? "XPT_TERM_IO" :
	key == 20 ? "XPT_SCAN_LUN" :
	key == 21 ? "XPT_GET_TRAN_SETTINGS" :
	key == 22 ? "XPT_SET_TRAN_SETTINGS" :
	key == 23 ? "XPT_CALC_GEOMETRY" :
	key == 24 ? "XPT_ATA_IO" :
	key == 25 ? "XPT_SET_SIM_KNOB" :
	key == 26 ? "XPT_GET_SIM_KNOB" :
	key == 27 ? "XPT_SMP_IO" :
	key == 28 ? "XPT_NVME_IO" :
	key == 29 ? "XPT_MMC_IO" :
	key == 30 ? "XPT_SCAN_TGT" :
	key == 31 ? "XPT_NVME_ADMIN" :
	"Too big" ;

/*
 * key >> 5 gives the group:
 * Group 0:  six byte commands
 * Group 1:  ten byte commands
 * Group 2:  ten byte commands
 * Group 3:  reserved (7e and 7f are de-facto 32 bytes though)
 * Group 4:  sixteen byte commands
 * Group 5:  twelve byte commands
 * Group 6:  vendor specific
 * Group 7:  vendor specific
 */
inline int scsi_cdb_len[int key] =
	key == 0 ? 6 :
	key == 1 ? 10 :
	key == 2 ? 10 :
	key == 3 ? 1 :		/* reserved */
	key == 4 ? 16 :
	key == 5 ? 12 :
	key == 6 ? 1 :	 	/* reserved */
	/* key == 7 */ 1;	/* reserved */


inline int CAM_CDB_POINTER = 1;
inline int XPT_SCSI_IO = 0x01;
inline int XPT_ATA_IO = 0x18;
inline int XPT_NVME_IO = 0x1c;
inline int XPT_NVME_ADMIN = 0x1f;

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. It handles
 * when / how / if to retry, so doing the intercept in xpt_done or
 * xpt_done_direct will allow reporting of the results as well. There's the
 * CAM status which is set by the SIM to indicate if the command succeeded,
 * timed out, had additional status from the transport layer, etc.
 *
 * For this data collection, we use the completion point and we ignore the
 * submission point. We could use it to add metadata to each submission like
 * arrival time so we can measure the elapsed time of the command. At present,
 * we don't do that.
 *
 * Note, there's a number of probes with different predicates. We have to do
 * this because there's no 'if' or 'loop' constructs in D. In addition, there's
 * no functions, so some reporting of status has to be done with macros (we need
 * a separate predicate for each length of the submitted command, which in SCSI
 * can be diverse). These macros are done by the c preprocessor, for want of
 * something better.... though this may involve cross products and such, so it
 * may be revisited. If cross products are required, then camio.lua can do the
 * substitutions.
 *
 * The 'trace' context local variable controls printing of different types
 * of results. This is all controlled by camio.lua.
 *
 * It may make more sense to move the constants out of this file into an include
 * file. And to move the D snippets into camio.lua so that we only register for
 * the transaction types that we're interested in. It might also make sense to
 * keep this in sync with fragments that move into camio.lua
 *
 * XXX at present, this is vastly simplified by not decoding the error stuff.
 * It might make sense to create real SDTs to allow some basic formatting to
 * be done in the kernel. Also, we're doing submission because done
 * isn't working.
 */

/*
 * CAM queues a CCB to the SIM in xpt_action
 */
fbt::xpt_action_default:entry
{
	this->ccb = ((union ccb *)arg0);
	this->func = this->ccb->ccb_h.func_code & 0xff;
	this->periph = this->ccb->ccb_h.path->periph;
	this->trace = 0;
}

/* The generated D script for what we're tracing follows */
/****
 **** XPT_SCSI_IO section
 ****/

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO/
{
	this->hdr = &this->ccb->ccb_h;
	this->csio = &this->ccb->csio;
	this->cdb = this->hdr->flags & CAM_CDB_POINTER ?
		this->csio->cdb_io.cdb_ptr :
		&this->csio->cdb_io.cdb_bytes[0];
	this->cdb_len = this->csio->cdb_len ? this->csio->cdb_len :
		scsi_cdb_len[this->cdb[0] >> 5];
}

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO/
{
	this->trace = 1;
}

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO && this->trace && this->cdb_len == 1/
{
	printf("%s%d: CDB: %02x\n",
	    stringof(this->periph->periph_name), this->periph->unit_number,
	    this->cdb[0]);
}

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO && this->trace && this->cdb_len == 6/
{
	printf("%s%d: CDB: %02x %02x %02x %02x %02x %02x\n",
	    stringof(this->periph->periph_name), this->periph->unit_number,
	    this->cdb[0], this->cdb[1], this->cdb[2],
	    this->cdb[3], this->cdb[4], this->cdb[5]);
}

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO && this->trace && this->cdb_len == 10/
{
	printf("%s%d: CDB: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
	    stringof(this->periph->periph_name), this->periph->unit_number,
	    this->cdb[0], this->cdb[1], this->cdb[2],
	    this->cdb[3], this->cdb[4], this->cdb[5],
	    this->cdb[6], this->cdb[7], this->cdb[8],
	    this->cdb[9]);
}

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO && this->trace && this->cdb_len == 12/
{
	printf("%s%d: CDB: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
	    stringof(this->periph->periph_name), this->periph->unit_number,
	    this->cdb[0], this->cdb[1], this->cdb[2],
	    this->cdb[3], this->cdb[4], this->cdb[5],
	    this->cdb[6], this->cdb[7], this->cdb[8],
	    this->cdb[9], this->cdb[10], this->cdb[11]);
}

fbt::xpt_action_default:entry
/this->func == XPT_SCSI_IO && this->trace && this->cdb_len == 16/
{
	printf("%s%d: CDB: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
	    stringof(this->periph->periph_name), this->periph->unit_number,
	    this->cdb[0], this->cdb[1], this->cdb[2],
	    this->cdb[3], this->cdb[4], this->cdb[5],
	    this->cdb[6], this->cdb[7], this->cdb[8],
	    this->cdb[9], this->cdb[10],this->cdb[11],
	    this->cdb[12],this->cdb[13],this->cdb[14],
	    this->cdb[15]);
}
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CANCZdfpkf9_nWKDTUZ3VSK-XyfgvC5RheqRw4gxG3jtuCbrA1w>