Re: [PATCH 01/15] scsi: Add struct for args to execution functions

John Garry
2022-11-22T09:16:49Z

On 22/11/2022 03:39, Mike Christie wrote:
> This begins to move the SCSI execution functions to use a struct for
> passing in optional args. This patch adds the new struct, temporarily
> converts scsi_execute and scsi_execute_req and adds a new helper
> scsi_execute_cmd.
>
> The next patches will convert scsi_execute and scsi_execute_req users to
> scsi_execute_cmd then remove scsi_execute and scsi_execute_req.
>
> Signed-off-by: Mike Christie <michael.christie@oracle.com>
> ---
> drivers/scsi/scsi_lib.c | 50 ++++++++++++++-----------------
> include/scsi/scsi_device.h | 61 +++++++++++++++++++++++++++++---------
> 2 files changed, 69 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index ec890865abae..327eb2df5583 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -185,39 +185,31 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
> __scsi_queue_insert(cmd, reason, true);
> }
>
> -
> /**
> - * __scsi_execute - insert request and wait for the result
> - * @sdev: scsi device
> + * __scsi_execute_cmd - insert request and wait for the result
> + * @sdev: scsi_device
> * @cmd: scsi command
> - * @data_direction: data direction
> + * @opf: block layer request cmd_flags
> * @buffer: data buffer
> * @bufflen: len of buffer
> - * @sense: optional sense buffer
> - * @sshdr: optional decoded sense header
> * @timeout: request timeout in HZ
> * @retries: number of times to retry request
> - * @flags: flags for ->cmd_flags
> - * @rq_flags: flags for ->rq_flags
> - * @resid: optional residual length
> + * @args: Optional args. See struct definition for field descriptions
> *
> * Returns the scsi_cmnd result field if a command was executed, or a negative
> * Linux error code if we didn't get that far.
> */
> -int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> - int data_direction, void *buffer, unsigned bufflen,
> - unsigned char *sense, struct scsi_sense_hdr *sshdr,
> - int timeout, int retries, blk_opf_t flags,
> - req_flags_t rq_flags, int *resid)
> +int __scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd,
> + blk_opf_t opf, void *buffer, unsigned int bufflen,
> + int timeout, int retries,
> + const struct scsi_exec_args *args)

I suppose that you could alternatively continue to pass a struct instead
of a struct pointer, so no need for the checks for args being NULL. As I
see, all the direct callers of __scsi_execute_cmd() pass NULL anyway, so
another macro in scsi_device.h could make it concise to implement.

> {
> struct request *req;
> struct scsi_cmnd *scmd;
> int ret;
>
> - req = scsi_alloc_request(sdev->request_queue,
> - data_direction == DMA_TO_DEVICE ?
> - REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
> - rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
> + req = scsi_alloc_request(sdev->request_queue, opf,
> + args ? args->req_flags : 0);
> if (IS_ERR(req))
> return PTR_ERR(req);
>
> @@ -232,8 +224,6 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> memcpy(scmd->cmnd, cmd, scmd->cmd_len);
> scmd->allowed = retries;
> req->timeout = timeout;
> - req->cmd_flags |= flags;
> - req->rq_flags |= rq_flags | RQF_QUIET;

Are we accidentally losing RQF_QUIET? Or does it matter?

The rest looks good, IMHO.

Thanks,
John

>
> /*
> * head injection *required* here otherwise quiesce won't work
> @@ -249,20 +239,24 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> if (unlikely(scmd->resid_len > 0 && scmd->resid_len <= bufflen))
> memset(buffer + bufflen - scmd->resid_len, 0, scmd->resid_len);
>
> - if (resid)
> - *resid = scmd->resid_len;
> - if (sense && scmd->sense_len)
> - memcpy(sense, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
> - if (sshdr)
> - scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len,
> - sshdr);
> + if (args) {
> + if (args->resid)
> + *args->resid = scmd->resid_len;
> + if (args->sense && scmd->sense_len)
> + memcpy(args->sense, scmd->sense_buffer,
> + SCSI_SENSE_BUFFERSIZE);
> + if (args->sshdr)
> + scsi_normalize_sense(scmd->sense_buffer,
> + scmd->sense_len, args->sshdr);
> + }
> +
> ret = scmd->result;
> out:
> blk_mq_free_request(req);
>
> return ret;
> }
> -EXPORT_SYMBOL(__scsi_execute);
> +EXPORT_SYMBOL(__scsi_execute_cmd);
>
> /*
> * Wake up the error handler if necessary. Avoid as follows that the error
> diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
> index 24bdbf7999ab..578f344e330d 100644
> --- a/include/scsi/scsi_device.h
> +++ b/include/scsi/scsi_device.h
> @@ -454,28 +454,61 @@ extern const char *scsi_device_state_name(enum scsi_device_state);
> extern int scsi_is_sdev_device(const struct device *);
> extern int scsi_is_target_device(const struct device *);
> extern void scsi_sanitize_inquiry_string(unsigned char *s, int len);
> -extern int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> - int data_direction, void *buffer, unsigned bufflen,
> - unsigned char *sense, struct scsi_sense_hdr *sshdr,
> - int timeout, int retries, blk_opf_t flags,
> - req_flags_t rq_flags, int *resid);
> +
> +/* Optional arguments to __scsi_execute_cmd */
> +struct scsi_exec_args {
> + unsigned char *sense; /* sense buffer */
> + unsigned int sense_len; /* sense buffer len */
> + struct scsi_sense_hdr *sshdr; /* decoded sense header */
> + blk_mq_req_flags_t req_flags; /* BLK_MQ_REQ flags */
> + int *resid; /* residual length */
> +};
> +
> +int __scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd,
> + blk_opf_t opf, void *buffer, unsigned int bufflen,
> + int timeout, int retries,
> + const struct scsi_exec_args *args);
> +
> /* Make sure any sense buffer is the correct size. */
> -#define scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, \
> - sshdr, timeout, retries, flags, rq_flags, resid) \
> +#define scsi_execute_cmd(sdev, cmd, opf, buffer, bufflen, timeout, \
> + retries, args) \
> ({ \
> - BUILD_BUG_ON((sense) != NULL && \
> - sizeof(sense) != SCSI_SENSE_BUFFERSIZE); \
> - __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, \
> - sense, sshdr, timeout, retries, flags, rq_flags, \
> - resid); \
> + BUILD_BUG_ON(args.sense && \
> + args.sense_len != SCSI_SENSE_BUFFERSIZE); \
> + __scsi_execute_cmd(sdev, cmd, opf, buffer, bufflen, timeout, \
> + retries, &args); \
> })
> +
> +/* Make sure any sense buffer is the correct size. */
> +#define scsi_execute(_sdev, _cmd, _data_dir, _buffer, _bufflen, _sense, \
> + _sshdr, _timeout, _retries, _flags, _rq_flags, \
> + _resid) \
> +({ \
> + BUILD_BUG_ON((_sense) != NULL && \
> + sizeof(_sense) != SCSI_SENSE_BUFFERSIZE); \
> + __scsi_execute_cmd(_sdev, _cmd, (_data_dir == DMA_TO_DEVICE ? \
> + REQ_OP_DRV_OUT : REQ_OP_DRV_IN) | _flags, \
> + _buffer, _bufflen, _timeout, _retries, \
> + &((struct scsi_exec_args) { \
> + .sense = _sense, \
> + .sshdr = _sshdr, \
> + .req_flags = _rq_flags & RQF_PM ? \
> + BLK_MQ_REQ_PM : 0, \
> + .resid = _resid, })); \
> +})
> +
> static inline int scsi_execute_req(struct scsi_device *sdev,
> const unsigned char *cmd, int data_direction, void *buffer,
> unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
> int retries, int *resid)
> {
> - return scsi_execute(sdev, cmd, data_direction, buffer,
> - bufflen, NULL, sshdr, timeout, retries, 0, 0, resid);
> + return __scsi_execute_cmd(sdev, cmd,
> + data_direction == DMA_TO_DEVICE ?
> + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, buffer,
> + bufflen, timeout, retries,
> + &(struct scsi_exec_args) {
> + .sshdr = sshdr,
> + .resid = resid });
> }
> extern void sdev_disable_disk_events(struct scsi_device *sdev);
> extern void sdev_enable_disk_events(struct scsi_device *sdev);