> index 5d83a162d03b..c1d5e4e36125 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -1635,8 +1635,11 @@ static blk_status_t scsi_mq_prep_fn(struct request 
> *req)
>  
>  static void scsi_mq_done(struct scsi_cmnd *cmd)
>  {
> +     if (unlikely(test_and_set_bit(__SCMD_COMPLETE, &cmd->flags)))
> +             return;
>       trace_scsi_dispatch_cmd_done(cmd);
> -     blk_mq_complete_request(cmd->request);
> +     if (unlikely(!blk_mq_complete_request(cmd->request)))
> +             clear_bit(__SCMD_COMPLETE, &cmd->flags);
>  }

This looks a little odd to me.  If we didn't complete the command
someone else did.  Why would we clear the bit in this case?

>  static void scsi_mq_put_budget(struct blk_mq_hw_ctx *hctx)
> @@ -1701,6 +1704,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx 
> *hctx,
>                       goto out_dec_host_busy;
>               req->rq_flags |= RQF_DONTPREP;
>       } else {
> +             cmd->flags &= ~SCMD_COMPLETE;
>               blk_mq_start_request(req);
>       }
>  
> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
> index d6fd2aba0380..ded7c7194a28 100644
> --- a/include/scsi/scsi_cmnd.h
> +++ b/include/scsi/scsi_cmnd.h
> @@ -58,6 +58,9 @@ struct scsi_pointer {
>  #define SCMD_TAGGED          (1 << 0)
>  #define SCMD_UNCHECKED_ISA_DMA       (1 << 1)
>  #define SCMD_INITIALIZED     (1 << 2)
> +
> +#define __SCMD_COMPLETE              3
> +#define SCMD_COMPLETE                (1 << __SCMD_COMPLETE)

This mixing of atomic and non-atomic bitops looks rather dangerous
to me.  Can you add a new atomic_flags just for the completed flag,
and always use the bitops on it for now? I think we can eventually
kill most of the existing flags except for SCMD_TAGGED over the
next merge window or two and then move that over as well.

Otherwise the concept looks fine to me.

Reply via email to