Turns out the bidi handling could cause a use after free in this
version, I'll respin it with a fix for that.
On Wed, Feb 26, 2014 at 06:23:21AM -0800, Christoph Hellwig wrote:
> By folding scsi_end_request into its only caller we can significantly clean
> up the completion logic. We can use simple goto labels now to only have
> a single place to finish or requeue command there instead of the previous
> convoluted logic.
>
> Note that the switch from __scsi_release_buffers without the bidi check
> argument to scsi_release_buffers is always correct as we handle bidi
> commands separately in scsi_io_completion and they never reach the path
> scsi_end_request was called from.
>
> Signed-off-by: Christoph Hellwig
> ---
> drivers/scsi/scsi_lib.c | 119
> +--
> 1 file changed, 32 insertions(+), 87 deletions(-)
>
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 62ec84b..51063ca 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -540,66 +540,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
>
> static void __scsi_release_buffers(struct scsi_cmnd *, int);
>
> -/*
> - * Function:scsi_end_request()
> - *
> - * Purpose: Post-processing of completed commands (usually invoked at end
> - * of upper level post-processing and scsi_io_completion).
> - *
> - * Arguments: cmd - command that is complete.
> - * error- 0 if I/O indicates success, < 0 for I/O error.
> - * bytes- number of bytes of completed I/O
> - * requeue - indicates whether we should requeue leftovers.
> - *
> - * Lock status: Assumed that lock is not held upon entry.
> - *
> - * Returns: cmd if requeue required, NULL otherwise.
> - *
> - * Notes: This is called for block device requests in order to
> - * mark some number of sectors as complete.
> - *
> - * We are guaranteeing that the request queue will be goosed
> - * at some point during this call.
> - * Notes:If cmd was requeued, upon return it will be a stale pointer.
> - */
> -static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
> - int bytes, int requeue)
> -{
> - struct request_queue *q = cmd->device->request_queue;
> - struct request *req = cmd->request;
> -
> - /*
> - * If there are blocks left over at the end, set up the command
> - * to queue the remainder of them.
> - */
> - if (blk_end_request(req, error, bytes)) {
> - /* kill remainder if no retrys */
> - if (error && scsi_noretry_cmd(cmd))
> - blk_end_request_all(req, error);
> - else {
> - if (requeue) {
> - /*
> - * Bleah. Leftovers again. Stick the
> - * leftovers in the front of the
> - * queue, and goose the queue again.
> - */
> - scsi_release_buffers(cmd);
> - scsi_requeue_command(q, cmd);
> - cmd = NULL;
> - }
> - return cmd;
> - }
> - }
> -
> - /*
> - * This will goose the queue request function at the end, so we don't
> - * need to worry about launching another command.
> - */
> - __scsi_release_buffers(cmd, 0);
> - scsi_next_command(cmd);
> - return NULL;
> -}
> -
> static inline unsigned int scsi_sgtable_index(unsigned short nents)
> {
> unsigned int index;
> @@ -751,16 +691,9 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd
> *cmd, int result)
> *
> * Returns: Nothing
> *
> - * Notes: This function is matched in terms of capabilities to
> - * the function that created the scatter-gather list.
> - * In other words, if there are no bounce buffers
> - * (the normal case for most drivers), we don't need
> - * the logic to deal with cleaning up afterwards.
> - *
> - * We must call scsi_end_request(). This will finish off
> - * the specified number of sectors. If we are done, the
> - * command block will be released and the queue function
> - * will be goosed. If we are not done then we have to
> + * Notes: We will finish off the specified number of sectors. If we
> + * are done, the command block will be released and the queue
> + * function will be goosed. If we are not done then we have to
> * figure out what to do next:
> *
> * a) We can call scsi_requeue_command(). The request
> @@ -769,7 +702,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd
> *cmd, int result)
> * be used if we made forward progress, or if we want
> *