diff --git a/block-Add-sanity-check-when-setting-retry-parameters.patch b/block-Add-sanity-check-when-setting-retry-parameters.patch new file mode 100644 index 0000000..d48fa5d --- /dev/null +++ b/block-Add-sanity-check-when-setting-retry-parameters.patch @@ -0,0 +1,156 @@ +From f329ec9bd971ba7776cadb57e7311bfb6da41060 Mon Sep 17 00:00:00 2001 +From: Jiahui Cen +Date: Thu, 18 Mar 2021 19:45:11 +0800 +Subject: [PATCH 9/9] block: Add sanity check when setting retry parameters + +Add sanity check when setting retry parameters to avoid invalid retry +configuration. + +Signed-off-by: Jiahui Cen +Signed-off-by: Alex Chen +--- + hw/core/qdev-prop-internal.h | 2 ++ + hw/core/qdev-properties-system.c | 45 +++++++++++++++++++++++++++++ + hw/core/qdev-properties.c | 4 +-- + include/hw/block/block.h | 7 +++-- + include/hw/qdev-properties-system.h | 8 +++++ + 5 files changed, 61 insertions(+), 5 deletions(-) + +diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h +index d7b77844fe..68b1b9d10c 100644 +--- a/hw/core/qdev-prop-internal.h ++++ b/hw/core/qdev-prop-internal.h +@@ -22,6 +22,8 @@ void qdev_propinfo_set_default_value_uint(ObjectProperty *op, + + void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); ++void qdev_propinfo_get_int64(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp); + void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); + +diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c +index 6a6ff03be7..b93ed9b4dd 100644 +--- a/hw/core/qdev-properties-system.c ++++ b/hw/core/qdev-properties-system.c +@@ -612,6 +612,51 @@ const PropertyInfo qdev_prop_blockdev_on_error = { + .set_default_value = qdev_propinfo_set_default_value_enum, + }; + ++static void set_retry_time(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ DeviceState *dev = DEVICE(obj); ++ Property *prop = opaque; ++ int64_t value, *ptr = object_field_prop_ptr(obj, prop); ++ Error *local_err = NULL; ++ ++ if (dev->realized) { ++ qdev_prop_set_after_realize(dev, name, errp); ++ return; ++ } ++ ++ visit_type_int64(v, name, &value, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ ++ /* value should not be negative */ ++ if (value < 0) { ++ error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, ++ dev->id ? : "", name, (int64_t)value, 0L, LONG_MAX); ++ return; ++ } ++ ++ *ptr = value; ++} ++ ++const PropertyInfo qdev_prop_blockdev_retry_interval = { ++ .name = "BlockdevRetryInterval", ++ .description = "Interval for retry error handling policy", ++ .get = qdev_propinfo_get_int64, ++ .set = set_retry_time, ++ .set_default_value = qdev_propinfo_set_default_value_int, ++}; ++ ++const PropertyInfo qdev_prop_blockdev_retry_timeout = { ++ .name = "BlockdevRetryTimeout", ++ .description = "Timeout for retry error handling policy", ++ .get = qdev_propinfo_get_int64, ++ .set = set_retry_time, ++ .set_default_value = qdev_propinfo_set_default_value_int, ++}; ++ + /* --- BIOS CHS translation */ + + QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); +diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c +index c34aac6ebc..2d5f662663 100644 +--- a/hw/core/qdev-properties.c ++++ b/hw/core/qdev-properties.c +@@ -396,7 +396,7 @@ static void set_uint64(Object *obj, Visitor *v, const char *name, + visit_type_uint64(v, name, ptr, errp); + } + +-static void get_int64(Object *obj, Visitor *v, const char *name, ++void qdev_propinfo_get_int64(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) + { + Property *prop = opaque; +@@ -423,7 +423,7 @@ const PropertyInfo qdev_prop_uint64 = { + + const PropertyInfo qdev_prop_int64 = { + .name = "int64", +- .get = get_int64, ++ .get = qdev_propinfo_get_int64, + .set = set_int64, + .set_default_value = qdev_propinfo_set_default_value_int, + }; +diff --git a/include/hw/block/block.h b/include/hw/block/block.h +index 24fb7d77af..282929e8f0 100644 +--- a/include/hw/block/block.h ++++ b/include/hw/block/block.h +@@ -82,9 +82,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) + BLOCKDEV_ON_ERROR_AUTO), \ + DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \ + BLOCKDEV_ON_ERROR_AUTO), \ +- DEFINE_PROP_INT64("retry_interval", _state, _conf.retry_interval, \ +- -1), \ +- DEFINE_PROP_INT64("retry_timeout", _state, _conf.retry_timeout, -1) ++ DEFINE_PROP_BLOCKDEV_RETRY_INTERVAL("retry_interval", _state, \ ++ _conf.retry_interval, 1000), \ ++ DEFINE_PROP_BLOCKDEV_RETRY_TIMEOUT("retry_timeout", _state, \ ++ _conf.retry_timeout, 0) + + /* Backend access helpers */ + +diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h +index 0ac327ae60..906a027676 100644 +--- a/include/hw/qdev-properties-system.h ++++ b/include/hw/qdev-properties-system.h +@@ -9,6 +9,8 @@ extern const PropertyInfo qdev_prop_reserved_region; + extern const PropertyInfo qdev_prop_multifd_compression; + extern const PropertyInfo qdev_prop_losttickpolicy; + extern const PropertyInfo qdev_prop_blockdev_on_error; ++extern const PropertyInfo qdev_prop_blockdev_retry_interval; ++extern const PropertyInfo qdev_prop_blockdev_retry_timeout; + extern const PropertyInfo qdev_prop_bios_chs_trans; + extern const PropertyInfo qdev_prop_fdc_drive_type; + extern const PropertyInfo qdev_prop_drive; +@@ -47,6 +49,12 @@ extern const PropertyInfo qdev_prop_pcie_link_width; + #define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \ + DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \ + BlockdevOnError) ++#define DEFINE_PROP_BLOCKDEV_RETRY_INTERVAL(_n, _s, _f, _d) \ ++ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_retry_interval, \ ++ int64_t) ++#define DEFINE_PROP_BLOCKDEV_RETRY_TIMEOUT(_n, _s, _f, _d) \ ++ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_retry_timeout, \ ++ int64_t) + #define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \ + DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int) + #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \ +-- +2.27.0 + diff --git a/block-backend-Stop-retrying-when-draining.patch b/block-backend-Stop-retrying-when-draining.patch new file mode 100644 index 0000000..baf5c6c --- /dev/null +++ b/block-backend-Stop-retrying-when-draining.patch @@ -0,0 +1,38 @@ +From 06db37983cfd20d7e92001ac3cb06867a281f1c9 Mon Sep 17 00:00:00 2001 +From: Jiahui Cen +Date: Thu, 25 Feb 2021 18:03:57 +0800 +Subject: [PATCH 8/9] block-backend: Stop retrying when draining + +Retrying failed requests when draining would make the draining hung. So it +is better not to trigger the retry timer when draining. And after the +virtual devices go back to work, they would retry those queued requests. + +Signed-off-by: Jiahui Cen +Signed-off-by: Ying Fang +Signed-off-by: Alex Chen +--- + block/block-backend.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index d3d90a95a5..49d236b2a4 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -1874,9 +1874,11 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action, + send_qmp_error_event(blk, action, is_read, error); + qemu_system_vmstop_request(RUN_STATE_IO_ERROR); + } else if (action == BLOCK_ERROR_ACTION_RETRY) { +- timer_mod(blk->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + +- blk->retry_interval); +- send_qmp_error_event(blk, action, is_read, error); ++ if (!blk->quiesce_counter) { ++ timer_mod(blk->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + ++ blk->retry_interval); ++ send_qmp_error_event(blk, action, is_read, error); ++ } + } else { + send_qmp_error_event(blk, action, is_read, error); + } +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index fffd126..59cba74 100644 --- a/qemu.spec +++ b/qemu.spec @@ -37,6 +37,10 @@ Patch0024: target-i386-Modify-the-VM-s-physical-bits-value-set-.patch Patch0025: vfio-pci-Ascend310-need-4Bytes-quirk-in-bar4.patch Patch0026: vfio-pci-Ascend710-need-4Bytes-quirk-in-bar0.patch Patch0027: vfio-pci-Ascend910-need-4Bytes-quirk-in-bar0.patch +Patch0028: scsi-bus-Refactor-the-code-that-retries-requests.patch +Patch0029: scsi-disk-Add-support-for-retry-on-errors.patch +Patch0030: block-backend-Stop-retrying-when-draining.patch +Patch0031: block-Add-sanity-check-when-setting-retry-parameters.patch BuildRequires: flex BuildRequires: gcc @@ -481,6 +485,12 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 imxcc +- scsi-bus: Refactor the code that retries requests +- scsi-disk: Add support for retry on errors +- block-backend: Stop retrying when draining +- block: Add sanity check when setting retry parameters + * Fri Feb 11 2022 imxcc - vfio/pci: Ascend310 need 4Bytes quirk in bar4 - vfio/pci: Ascend710 need 4Bytes quirk in bar0 diff --git a/scsi-bus-Refactor-the-code-that-retries-requests.patch b/scsi-bus-Refactor-the-code-that-retries-requests.patch new file mode 100644 index 0000000..84802c4 --- /dev/null +++ b/scsi-bus-Refactor-the-code-that-retries-requests.patch @@ -0,0 +1,69 @@ +From 391dd8f1458c8db0b848450718af5c69285e5705 Mon Sep 17 00:00:00 2001 +From: Jiahui Cen +Date: Thu, 21 Jan 2021 15:46:54 +0800 +Subject: [PATCH 6/9] scsi-bus: Refactor the code that retries requests + +Move the code that retries requests from scsi_dma_restart_bh() to its own, +non-static, function. This will allow us to call it from the +retry_request_cb() of scsi-disk in a future patch. + +Signed-off-by: Jiahui Cen +Signed-off-by: Ying Fang +Signed-off-by: Alex Chen +--- + hw/scsi/scsi-bus.c | 16 +++++++++++----- + include/hw/scsi/scsi.h | 1 + + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 77325d8cc7..5e6f891b9d 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -143,14 +143,10 @@ void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host, + qbus_set_bus_hotplug_handler(BUS(bus)); + } + +-static void scsi_dma_restart_bh(void *opaque) ++void scsi_retry_requests(SCSIDevice *s) + { +- SCSIDevice *s = opaque; + SCSIRequest *req, *next; + +- qemu_bh_delete(s->bh); +- s->bh = NULL; +- + aio_context_acquire(blk_get_aio_context(s->conf.blk)); + QTAILQ_FOREACH_SAFE(req, &s->requests, next, next) { + scsi_req_ref(req); +@@ -174,6 +170,16 @@ static void scsi_dma_restart_bh(void *opaque) + object_unref(OBJECT(s)); + } + ++static void scsi_dma_restart_bh(void *opaque) ++{ ++ SCSIDevice *s = opaque; ++ ++ qemu_bh_delete(s->bh); ++ s->bh = NULL; ++ ++ scsi_retry_requests(s); ++} ++ + void scsi_req_retry(SCSIRequest *req) + { + /* No need to save a reference, because scsi_dma_restart_bh just +diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h +index a567a5ed86..e5d90cd9dc 100644 +--- a/include/hw/scsi/scsi.h ++++ b/include/hw/scsi/scsi.h +@@ -212,6 +212,7 @@ void scsi_req_cancel_complete(SCSIRequest *req); + void scsi_req_cancel(SCSIRequest *req); + void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier); + void scsi_req_retry(SCSIRequest *req); ++void scsi_retry_requests(SCSIDevice *s); + void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense); + void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense); + void scsi_device_report_change(SCSIDevice *dev, SCSISense sense); +-- +2.27.0 + diff --git a/scsi-disk-Add-support-for-retry-on-errors.patch b/scsi-disk-Add-support-for-retry-on-errors.patch new file mode 100644 index 0000000..69f7614 --- /dev/null +++ b/scsi-disk-Add-support-for-retry-on-errors.patch @@ -0,0 +1,77 @@ +From 52115ca0ad925b1d719eb46e22c455aa5839534a Mon Sep 17 00:00:00 2001 +From: Jiahui Cen +Date: Thu, 21 Jan 2021 15:46:55 +0800 +Subject: [PATCH 7/9] scsi-disk: Add support for retry on errors + +Mark failed requests as to be retried and implement retry_request_cb to +handle these requests. + +Signed-off-by: Jiahui Cen +Signed-off-by: Ying Fang +Signed-off-by: Alex Chen +--- + hw/scsi/scsi-disk.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index d4914178ea..d278efc701 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -246,6 +246,10 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) + scsi_req_retry(&r->req); + return true; + ++ case BLOCK_ERROR_ACTION_RETRY: ++ scsi_req_retry(&r->req); ++ return true; ++ + default: + g_assert_not_reached(); + } +@@ -253,6 +257,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) + { ++ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); ++ + if (r->req.io_canceled) { + scsi_req_cancel_complete(&r->req); + return true; +@@ -262,6 +268,7 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) + return scsi_handle_rw_error(r, ret, acct_failed); + } + ++ blk_error_retry_reset_timeout(s->qdev.conf.blk); + return false; + } + +@@ -2278,6 +2285,13 @@ static void scsi_disk_resize_cb(void *opaque) + } + } + ++static void scsi_disk_retry_request(void *opaque) ++{ ++ SCSIDiskState *s = opaque; ++ ++ scsi_retry_requests(&s->qdev); ++} ++ + static void scsi_cd_change_media_cb(void *opaque, bool load, Error **errp) + { + SCSIDiskState *s = opaque; +@@ -2326,10 +2340,12 @@ static const BlockDevOps scsi_disk_removable_block_ops = { + .is_medium_locked = scsi_cd_is_medium_locked, + + .resize_cb = scsi_disk_resize_cb, ++ .retry_request_cb = scsi_disk_retry_request, + }; + + static const BlockDevOps scsi_disk_block_ops = { + .resize_cb = scsi_disk_resize_cb, ++ .retry_request_cb = scsi_disk_retry_request, + }; + + static void scsi_disk_unit_attention_reported(SCSIDevice *dev) +-- +2.27.0 +