From 60181b02c77f533105f904ab9e023bc22f65ad48 Mon Sep 17 00:00:00 2001 From: Yan Wang Date: Tue, 29 Mar 2022 12:05:56 +0800 Subject: [PATCH] scsi-bus: fix incorrect call for blk_error_retry_reset_timeout() Fix commit 52115ca0("scsi-disk: Add support for retry on errors"). Call Stack: ... scsi_read_data() scsi_do_read(r, 0) scsi_disk_req_check_error() blk_error_retry_reset_timeout() blk->retry_start_time = 0; It will cause IO hang when storage network disconnected. Before the storage network recovered, the upper call stack will reset the retry_start_time, and cause the next IO operation not returned immediately. Signed-off-by: Yan Wang Signed-off-by: shaodenghui --- hw/scsi/scsi-disk.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 97d8c5bb30..845a2a7d5d 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -258,10 +258,8 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) } } -static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) +static bool scsi_disk_req_handle_error(SCSIDiskReq *r, int ret, bool acct_failed) { - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); return true; @@ -271,6 +269,17 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) return scsi_handle_rw_error(r, ret, acct_failed); } + return false; +} + +static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) +{ + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + if (r->req.io_canceled || ret < 0) { + return scsi_disk_req_handle_error(r, ret, acct_failed); + } + blk_error_retry_reset_timeout(s->qdev.conf.blk); return false; } @@ -423,7 +432,7 @@ static void scsi_do_read(SCSIDiskReq *r, int ret) SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s)); assert (r->req.aiocb == NULL); - if (scsi_disk_req_check_error(r, ret, false)) { + if (scsi_disk_req_handle_error(r, ret, false)) { goto done; } @@ -464,6 +473,9 @@ static void scsi_do_read_cb(void *opaque, int ret) block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); } else { block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); + if (!r->req.io_canceled) { + blk_error_retry_reset_timeout(s->qdev.conf.blk); + } } scsi_do_read(opaque, ret); aio_context_release(blk_get_aio_context(s->qdev.conf.blk)); -- 2.27.0