Skip to content

Commit

Permalink
scsi: core: Remove the cmd field from struct scsi_request
Browse files Browse the repository at this point in the history
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: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Christoph Hellwig authored and Martin K. Petersen committed Mar 2, 2022
1 parent 71bada3 commit ce70fd9
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 168 deletions.
4 changes: 3 additions & 1 deletion drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
6 changes: 4 additions & 2 deletions drivers/block/pktcdvd.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,13 +693,15 @@ 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;

rq = scsi_alloc_request(q, (cgc->data_direction == CGC_DATA_WRITE) ?
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,
Expand All @@ -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)
Expand Down
23 changes: 11 additions & 12 deletions drivers/scsi/scsi_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
goto out_put_request;
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) {
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions drivers/scsi/scsi_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 14 additions & 14 deletions drivers/scsi/scsi_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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]);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2022,21 +2021,23 @@ 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;

req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN, 0);
if (IS_ERR(req))
return;
rq = scsi_req(req);
scmd = blk_mq_rq_to_pdu(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->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;
Expand Down Expand Up @@ -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));
Expand Down
37 changes: 17 additions & 20 deletions drivers/scsi/scsi_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,19 +345,15 @@ EXPORT_SYMBOL(scsi_cmd_allowed);
static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq,
struct sg_io_hdr *hdr, fmode_t mode)
{
struct scsi_request *req = scsi_req(rq);
struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);

if (hdr->cmd_len < 6)
return -EMSGSIZE;
if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
if (copy_from_user(scmd->cmnd, hdr->cmdp, hdr->cmd_len))
return -EFAULT;
if (!scsi_cmd_allowed(req->cmd, mode))
if (!scsi_cmd_allowed(scmd->cmnd, mode))
return -EPERM;

/*
* fill in request structure
*/
req->cmd_len = hdr->cmd_len;
scmd->cmd_len = hdr->cmd_len;

rq->timeout = msecs_to_jiffies(hdr->timeout);
if (!rq->timeout)
Expand Down Expand Up @@ -416,6 +412,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
int at_head = 0;
struct request *rq;
struct scsi_request *req;
struct scsi_cmnd *scmd;
struct bio *bio;

if (hdr->interface_id != 'S')
Expand Down Expand Up @@ -444,16 +441,16 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
if (IS_ERR(rq))
return PTR_ERR(rq);
req = scsi_req(rq);
scmd = blk_mq_rq_to_pdu(rq);

if (hdr->cmd_len > BLK_MAX_CDB) {
req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
if (!req->cmd)
goto out_put_request;
if (hdr->cmd_len > sizeof(scmd->cmnd)) {
ret = -EINVAL;
goto out_put_request;
}

ret = scsi_fill_sghdr_rq(sdev, rq, hdr, mode);
if (ret < 0)
goto out_free_cdb;
goto out_put_request;

ret = 0;
if (hdr->iovec_count) {
Expand All @@ -463,7 +460,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
hdr->iovec_count, 0, &iov, &i);
if (ret < 0)
goto out_free_cdb;
goto out_put_request;

/* SG_IO howto says that the shorter of the two wins */
iov_iter_truncate(&i, hdr->dxfer_len);
Expand All @@ -475,7 +472,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)
hdr->dxfer_len, GFP_KERNEL);

if (ret)
goto out_free_cdb;
goto out_put_request;

bio = rq->bio;
req->retries = 0;
Expand All @@ -488,8 +485,6 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode)

ret = scsi_complete_sghdr_rq(rq, hdr, bio);

out_free_cdb:
scsi_req_free_cmd(req);
out_put_request:
blk_mq_free_request(rq);
return ret;
Expand Down Expand Up @@ -530,6 +525,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode,
struct scsi_request *req;
int err;
unsigned int in_len, out_len, bytes, opcode, cmdlen;
struct scsi_cmnd *scmd;
char *buffer = NULL;

if (!sic)
Expand Down Expand Up @@ -561,22 +557,23 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode,
goto error_free_buffer;
}
req = scsi_req(rq);
scmd = blk_mq_rq_to_pdu(rq);

cmdlen = COMMAND_SIZE(opcode);

/*
* get command and data to send to device, if any
*/
err = -EFAULT;
req->cmd_len = cmdlen;
if (copy_from_user(req->cmd, sic->data, cmdlen))
scmd->cmd_len = cmdlen;
if (copy_from_user(scmd->cmnd, sic->data, cmdlen))
goto error;

if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
goto error;

err = -EPERM;
if (!scsi_cmd_allowed(req->cmd, mode))
if (!scsi_cmd_allowed(scmd->cmnd, mode))
goto error;

/* default. possible overridden later */
Expand Down
19 changes: 8 additions & 11 deletions drivers/scsi/scsi_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
{
struct request *req;
struct scsi_request *rq;
struct scsi_cmnd *scmd;
int ret;

req = scsi_alloc_request(sdev->request_queue,
Expand All @@ -231,8 +232,9 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
if (ret)
goto out;
}
rq->cmd_len = COMMAND_SIZE(cmd[0]);
memcpy(rq->cmd, cmd, rq->cmd_len);
scmd = blk_mq_rq_to_pdu(req);
scmd->cmd_len = COMMAND_SIZE(cmd[0]);
memcpy(scmd->cmnd, cmd, scmd->cmd_len);
rq->retries = retries;
req->timeout = timeout;
req->cmd_flags |= flags;
Expand Down Expand Up @@ -1126,9 +1128,9 @@ static void scsi_initialize_rq(struct request *rq)
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
struct scsi_request *req = &cmd->req;

memset(req->__cmd, 0, sizeof(req->__cmd));
req->cmd = req->__cmd;
req->cmd_len = BLK_MAX_CDB;
memset(cmd->cmnd, 0, sizeof(cmd->cmnd));
cmd->cmd_len = MAX_COMMAND_SIZE;

req->sense_len = 0;

init_rcu_head(&cmd->rcu);
Expand Down Expand Up @@ -1196,8 +1198,6 @@ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev,
memset(&cmd->sdb, 0, sizeof(cmd->sdb));
}

cmd->cmd_len = scsi_req(req)->cmd_len;
cmd->cmnd = scsi_req(req)->cmd;
cmd->transfersize = blk_rq_bytes(req);
cmd->allowed = scsi_req(req)->retries;
return BLK_STS_OK;
Expand Down Expand Up @@ -1567,8 +1567,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
cmd->prot_type = 0;
cmd->prot_flags = 0;
cmd->submitter = 0;
cmd->cmd_len = 0;
cmd->cmnd = NULL;
memset(&cmd->sdb, 0, sizeof(cmd->sdb));
cmd->underflow = 0;
cmd->transfersize = 0;
Expand Down Expand Up @@ -1616,8 +1614,7 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
return ret;
}

cmd->cmnd = scsi_req(req)->cmd = scsi_req(req)->__cmd;
memset(cmd->cmnd, 0, BLK_MAX_CDB);
memset(cmd->cmnd, 0, sizeof(cmd->cmnd));
return scsi_cmd_to_driver(cmd)->init_command(cmd);
}

Expand Down
5 changes: 1 addition & 4 deletions drivers/scsi/scsi_logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void scmd_printk(const char *level, const struct scsi_cmnd *scmd,
char *logbuf;
size_t off = 0, logbuf_len;

if (!scmd || !scmd->cmnd)
if (!scmd)
return;

logbuf = scsi_log_reserve_buffer(&logbuf_len);
Expand Down Expand Up @@ -183,9 +183,6 @@ void scsi_print_command(struct scsi_cmnd *cmd)
char *logbuf;
size_t off, logbuf_len;

if (!cmd->cmnd)
return;

logbuf = scsi_log_reserve_buffer(&logbuf_len);
if (!logbuf)
return;
Expand Down
Loading

0 comments on commit ce70fd9

Please sign in to comment.