scsi: core: Increase scsi_device's iodone_cnt in scsi_timeout()
authorWenchao Hao <haowenchao@huawei.com>
Wed, 23 Nov 2022 12:21:36 +0000 (20:21 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 24 Nov 2022 03:41:31 +0000 (03:41 +0000)
If a SCSI command times out and is going to be aborted, we should increase
the iodone_cnt of the related scsi_device. Otherwise the iodone_cnt would
be smaller than iorequest_cnt.

Increasing iodone_cnt in scsi_timeout() would not cause a double accounting
issue. Brief analysis follows:

 - We add the iodone_cnt when BLK_EH_DONE is returned in
   scsi_timeout(). The related command's timeout event would not happen.

 - If the abort succeeds and the command is not retried, the command would
   be completed with scsi_finish_command() which would not increase
   iodone_cnt.

 - If the abort succeeds and the command is retried, it would be requeue. A
   scsi_dispatch_cmd() would be called and iorequest_cnt would be increased
   again.

 - If the abort fails, the error handler successfully recovers the device,
   and the command is not retried, the command would be completed with
   scsi_finish_command() which would not increase iodone_cnt.

 - If the abort fails, the error handler successfully recovers the device,
   and the command is retried, the iorequest_cnt would be increased again.

Signed-off-by: Wenchao Hao <haowenchao@huawei.com>
Link: https://lore.kernel.org/r/20221123122137.150776-2-haowenchao@huawei.com
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_error.c

index be2a70c5ac6dc1c559aeed96e9179363b62eb202..613d5aeb1e3ce04b9ba85cdca78cfb1c9156705e 100644 (file)
@@ -354,6 +354,7 @@ enum blk_eh_timer_return scsi_timeout(struct request *req)
         */
        if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state))
                return BLK_EH_DONE;
+       atomic_inc(&scmd->device->iodone_cnt);
        if (scsi_abort_command(scmd) != SUCCESS) {
                set_host_byte(scmd, DID_TIME_OUT);
                scsi_eh_scmd_add(scmd);