Skip to content

Commit

Permalink
scsi: core: Don't memset() the entire scsi_cmnd in scsi_init_command()
Browse files Browse the repository at this point in the history
Replace the big fat memset that requires saving and restoring various
fields with just initializing those fields that need initialization.

All the clearing to 0 is moved to scsi_prepare_cmd() as scsi_ioctl_reset()
alreadly uses kzalloc() to allocate a pre-zeroed command.

This is still conservative and can probably be optimized further.

Link: https://lore.kernel.org/r/20220224175552.988286-3-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 c49ff72 commit 71bada3
Showing 1 changed file with 28 additions and 32 deletions.
60 changes: 28 additions & 32 deletions drivers/scsi/scsi_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1163,45 +1163,16 @@ static void scsi_cleanup_rq(struct request *rq)
/* Called before a request is prepared. See also scsi_mq_prep_fn(). */
void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
{
void *buf = cmd->sense_buffer;
void *prot = cmd->prot_sdb;
struct request *rq = scsi_cmd_to_rq(cmd);
unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS;
unsigned long jiffies_at_alloc;
int retries, to_clear;
bool in_flight;
int budget_token = cmd->budget_token;

if (!blk_rq_is_passthrough(rq) && !(flags & SCMD_INITIALIZED)) {
flags |= SCMD_INITIALIZED;

if (!blk_rq_is_passthrough(rq) && !(cmd->flags & SCMD_INITIALIZED)) {
cmd->flags |= SCMD_INITIALIZED;
scsi_initialize_rq(rq);
}

jiffies_at_alloc = cmd->jiffies_at_alloc;
retries = cmd->retries;
in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state);
/*
* Zero out the cmd, except for the embedded scsi_request. Only clear
* the driver-private command data if the LLD does not supply a
* function to initialize that data.
*/
to_clear = sizeof(*cmd) - sizeof(cmd->req);
if (!dev->host->hostt->init_cmd_priv)
to_clear += dev->host->hostt->cmd_size;
memset((char *)cmd + sizeof(cmd->req), 0, to_clear);

cmd->device = dev;
cmd->sense_buffer = buf;
cmd->prot_sdb = prot;
cmd->flags = flags;
INIT_LIST_HEAD(&cmd->eh_entry);
INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
cmd->jiffies_at_alloc = jiffies_at_alloc;
cmd->retries = retries;
if (in_flight)
__set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
cmd->budget_token = budget_token;

}

static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev,
Expand Down Expand Up @@ -1586,10 +1557,35 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
struct scsi_device *sdev = req->q->queuedata;
struct Scsi_Host *shost = sdev->host;
bool in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state);
struct scatterlist *sg;

scsi_init_command(sdev, cmd);

cmd->eh_eflags = 0;
cmd->allowed = 0;
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;
cmd->host_scribble = NULL;
cmd->result = 0;
cmd->extra_len = 0;
cmd->state = 0;
if (in_flight)
__set_bit(SCMD_STATE_INFLIGHT, &cmd->state);

/*
* Only clear the driver-private command data if the LLD does not supply
* a function to initialize that data.
*/
if (!shost->hostt->init_cmd_priv)
memset(cmd + 1, 0, shost->hostt->cmd_size);

cmd->prot_op = SCSI_PROT_NORMAL;
if (blk_rq_bytes(req))
cmd->sc_data_direction = rq_dma_dir(req);
Expand Down

0 comments on commit 71bada3

Please sign in to comment.