Commit ce70fd9a authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Martin K. Petersen
Browse files

scsi: core: Remove the cmd field from struct scsi_request

Now that each scsi_request is backed by a scsi_cmnd, there is no need to
indirect the CDB storage.  Change all submitters of SCSI passthrough
requests to store the CDB information directly in the scsi_cmnd, and while
doing so allocate the full 32 bytes that cover all Linux supported SCSI
hosts instead of requiring dynamic allocation for > 16 byte CDBs.  On
64-bit systems this does not change the size of the scsi_cmnd at all, while
on 32-bit systems it slightly increases it for now, but that increase will
be made up by the removal of the remaining scsi_request fields.

Link: https://lore.kernel.org/r/20220224175552.988286-4-hch@lst.de


Reviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 71bada34
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1022,7 +1022,9 @@ void ata_scsi_sdev_config(struct scsi_device *sdev)
 */
bool ata_scsi_dma_need_drain(struct request *rq)
{
	return atapi_cmd_type(scsi_req(rq)->cmd[0]) == ATAPI_MISC;
	struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);

	return atapi_cmd_type(scmd->cmnd[0]) == ATAPI_MISC;
}
EXPORT_SYMBOL_GPL(ata_scsi_dma_need_drain);

+4 −2
Original line number Diff line number Diff line
@@ -693,6 +693,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc)
{
	struct request_queue *q = bdev_get_queue(pd->bdev);
	struct scsi_cmnd *scmd;
	struct request *rq;
	int ret = 0;

@@ -700,6 +701,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
			     REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
	if (IS_ERR(rq))
		return PTR_ERR(rq);
	scmd = blk_mq_rq_to_pdu(rq);

	if (cgc->buflen) {
		ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen,
@@ -708,8 +710,8 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
			goto out;
	}

	scsi_req(rq)->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
	memcpy(scsi_req(rq)->cmd, cgc->cmd, CDROM_PACKET_SIZE);
	scmd->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
	memcpy(scmd->cmnd, cgc->cmd, CDROM_PACKET_SIZE);

	rq->timeout = 60*HZ;
	if (cgc->quiet)
+11 −12
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
		fmode_t mode, unsigned int timeout)
{
	struct scsi_request *sreq;
	struct scsi_cmnd *scmd;
	struct request *rq;
	struct bio *bio;
	int ret;
@@ -33,19 +34,19 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,

	ret = -ENOMEM;
	sreq = scsi_req(rq);
	sreq->cmd_len = hdr->request_len;
	if (sreq->cmd_len > BLK_MAX_CDB) {
		sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
		if (!sreq->cmd)
	scmd = blk_mq_rq_to_pdu(rq);
	scmd->cmd_len = hdr->request_len;
	if (scmd->cmd_len > sizeof(scmd->cmnd)) {
		ret = -EINVAL;
		goto out_put_request;
	}

	ret = -EFAULT;
	if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
		goto out_free_cmd;
	if (copy_from_user(scmd->cmnd, uptr64(hdr->request), scmd->cmd_len))
		goto out_put_request;
	ret = -EPERM;
	if (!scsi_cmd_allowed(sreq->cmd, mode))
		goto out_free_cmd;
	if (!scsi_cmd_allowed(scmd->cmnd, mode))
		goto out_put_request;

	ret = 0;
	if (hdr->dout_xfer_len) {
@@ -57,7 +58,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
	}

	if (ret)
		goto out_free_cmd;
		goto out_put_request;

	bio = rq->bio;
	blk_execute_rq(rq, !(hdr->flags & BSG_FLAG_Q_AT_TAIL));
@@ -92,8 +93,6 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,

	blk_rq_unmap_user(bio);

out_free_cmd:
	scsi_req_free_cmd(scsi_req(rq));
out_put_request:
	blk_mq_free_request(rq);
	return ret;
+1 −3
Original line number Diff line number Diff line
@@ -36,11 +36,9 @@ void scsi_show_rq(struct seq_file *m, struct request *rq)
	struct scsi_cmnd *cmd = container_of(scsi_req(rq), typeof(*cmd), req);
	int alloc_ms = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc);
	int timeout_ms = jiffies_to_msecs(rq->timeout);
	const u8 *const cdb = READ_ONCE(cmd->cmnd);
	char buf[80] = "(?)";

	if (cdb)
		__scsi_format_command(buf, sizeof(buf), cdb, cmd->cmd_len);
	__scsi_format_command(buf, sizeof(buf), cmd->cmnd, cmd->cmd_len);
	seq_printf(m, ", .cmd=%s, .retries=%d, .result = %#x, .flags=", buf,
		   cmd->retries, cmd->result);
	scsi_flags_show(m, cmd->flags, scsi_cmd_flags,
+14 −14
Original line number Diff line number Diff line
@@ -980,7 +980,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 * @scmd:       SCSI command structure to hijack
 * @ses:        structure to save restore information
 * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
 * @cmnd_size:  size in bytes of @cmnd (must be <= BLK_MAX_CDB)
 * @cmnd_size:  size in bytes of @cmnd (must be <= MAX_COMMAND_SIZE)
 * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
 *
 * This function is used to save a scsi command information before re-execution
@@ -1002,7 +1002,6 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
	 * command.
	 */
	ses->cmd_len = scmd->cmd_len;
	ses->cmnd = scmd->cmnd;
	ses->data_direction = scmd->sc_data_direction;
	ses->sdb = scmd->sdb;
	ses->result = scmd->result;
@@ -1013,8 +1012,8 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,

	scmd->prot_op = SCSI_PROT_NORMAL;
	scmd->eh_eflags = 0;
	scmd->cmnd = ses->eh_cmnd;
	memset(scmd->cmnd, 0, BLK_MAX_CDB);
	memcpy(ses->cmnd, scmd->cmnd, sizeof(ses->cmnd));
	memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
	scmd->result = 0;
	scmd->req.resid_len = 0;
@@ -1033,7 +1032,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
	} else {
		scmd->sc_data_direction = DMA_NONE;
		if (cmnd) {
			BUG_ON(cmnd_size > BLK_MAX_CDB);
			BUG_ON(cmnd_size > sizeof(scmd->cmnd));
			memcpy(scmd->cmnd, cmnd, cmnd_size);
			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
		}
@@ -1066,7 +1065,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
	 * Restore original data
	 */
	scmd->cmd_len = ses->cmd_len;
	scmd->cmnd = ses->cmnd;
	memcpy(scmd->cmnd, ses->cmnd, sizeof(ses->cmnd));
	scmd->sc_data_direction = ses->data_direction;
	scmd->sdb = ses->sdb;
	scmd->result = ses->result;
@@ -2022,6 +2021,7 @@ static void eh_lock_door_done(struct request *req, blk_status_t status)
 */
static void scsi_eh_lock_door(struct scsi_device *sdev)
{
	struct scsi_cmnd *scmd;
	struct request *req;
	struct scsi_request *rq;

@@ -2029,14 +2029,15 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
	if (IS_ERR(req))
		return;
	rq = scsi_req(req);

	rq->cmd[0] = ALLOW_MEDIUM_REMOVAL;
	rq->cmd[1] = 0;
	rq->cmd[2] = 0;
	rq->cmd[3] = 0;
	rq->cmd[4] = SCSI_REMOVAL_PREVENT;
	rq->cmd[5] = 0;
	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
	scmd = blk_mq_rq_to_pdu(req);

	scmd->cmnd[0] = ALLOW_MEDIUM_REMOVAL;
	scmd->cmnd[1] = 0;
	scmd->cmnd[2] = 0;
	scmd->cmnd[3] = 0;
	scmd->cmnd[4] = SCSI_REMOVAL_PREVENT;
	scmd->cmnd[5] = 0;
	scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);

	req->rq_flags |= RQF_QUIET;
	req->timeout = 10 * HZ;
@@ -2399,7 +2400,6 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)

	scmd = (struct scsi_cmnd *)(rq + 1);
	scsi_init_command(dev, scmd);
	scmd->cmnd = scsi_req(rq)->cmd;

	scmd->submitter = SUBMITTED_BY_SCSI_RESET_IOCTL;
	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
Loading