Qemu now supports werror/rerror=retry, so it is necessary to add the new policy in libvirt to support this new feature.
Jiahui Cen (2): libvirt: Add 'retry' support for error policy qemu: Support 'retry' BLOCK_IO_ERROR event.
include/libvirt/libvirt-domain.h | 1 + src/conf/domain_conf.c | 25 +++++++++++++++++++++++++ src/conf/domain_conf.h | 3 +++ src/qemu/qemu_command.c | 4 ++++ src/qemu/qemu_domain.c | 2 ++ src/qemu/qemu_monitor_json.c | 2 +- tools/virsh-domain.c | 3 ++- 7 files changed, 38 insertions(+), 2 deletions(-)
Introduce error_policy=/rerror_policy='retry' to support werror=/rerror=retry mechanism in qemu.
Add retry_interval parameter to control the interval between retries. Add retry_timeout parameter to control the total retry times.
Signed-off-by: Jiahui Cen cenjiahui@huawei.com Signed-off-by: Ying Fang fangying1@huawei.com --- src/conf/domain_conf.c | 25 +++++++++++++++++++++++++ src/conf/domain_conf.h | 3 +++ src/qemu/qemu_command.c | 4 ++++ src/qemu/qemu_domain.c | 2 ++ 4 files changed, 34 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index dbc3e103ff..5c469cedd0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -355,6 +355,7 @@ VIR_ENUM_IMPL(virDomainDiskErrorPolicy, "report", "ignore", "enospace", + "retry", );
VIR_ENUM_IMPL(virDomainDiskIo, @@ -10213,6 +10214,30 @@ virDomainDiskDefDriverParseXML(virDomainDiskDefPtr def, } VIR_FREE(tmp);
+ def->retry_interval = -1; + if ((tmp = virXMLPropString(cur, "retry_interval")) && + ((def->error_policy != VIR_DOMAIN_DISK_ERROR_POLICY_RETRY && + def->rerror_policy != VIR_DOMAIN_DISK_ERROR_POLICY_RETRY) || + (virStrToLong_l(tmp, NULL, 10, &def->retry_interval) < 0) || + (def->retry_interval < 0))) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk retry interval '%s'"), tmp); + return -1; + } + VIR_FREE(tmp); + + def->retry_timeout = -1; + if ((tmp = virXMLPropString(cur, "retry_timeout")) && + ((def->error_policy != VIR_DOMAIN_DISK_ERROR_POLICY_RETRY && + def->rerror_policy != VIR_DOMAIN_DISK_ERROR_POLICY_RETRY) || + (virStrToLong_l(tmp, NULL, 10, &def->retry_timeout) < 0) || + (def->retry_timeout < 0))) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk retry interval '%s'"), tmp); + return -1; + } + VIR_FREE(tmp); + if ((tmp = virXMLPropString(cur, "io")) && (def->iomode = virDomainDiskIoTypeFromString(tmp)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 16e625331c..86a86d3090 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -396,6 +396,7 @@ typedef enum { VIR_DOMAIN_DISK_ERROR_POLICY_REPORT, VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE, VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE, + VIR_DOMAIN_DISK_ERROR_POLICY_RETRY,
VIR_DOMAIN_DISK_ERROR_POLICY_LAST } virDomainDiskErrorPolicy; @@ -561,6 +562,8 @@ struct _virDomainDiskDef { int cachemode; /* enum virDomainDiskCache */ int error_policy; /* enum virDomainDiskErrorPolicy */ int rerror_policy; /* enum virDomainDiskErrorPolicy */ + long retry_interval; + long retry_timeout; int iomode; /* enum virDomainDiskIo */ int ioeventfd; /* enum virTristateSwitch */ int event_idx; /* enum virTristateSwitch */ diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 315deb5cfd..fdfb56a560 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1723,6 +1723,10 @@ qemuBuildDiskFrontendAttributeErrorPolicy(virDomainDiskDefPtr disk, virBufferAsprintf(buf, ",werror=%s", wpolicy); if (rpolicy) virBufferAsprintf(buf, ",rerror=%s", rpolicy); + if (disk->retry_interval >= 0) + virBufferAsprintf(buf, ",retry_interval=%ld", disk->retry_interval); + if (disk->retry_timeout >= 0) + virBufferAsprintf(buf, ",retry_timeout=%ld", disk->retry_timeout); }
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index f89ff20a84..58493706a1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -12308,6 +12308,8 @@ qemuDomainDiskChangeSupported(virDomainDiskDefPtr disk, CHECK_EQ(cachemode, "cache", true); CHECK_EQ(error_policy, "error_policy", true); CHECK_EQ(rerror_policy, "rerror_policy", true); + CHECK_EQ(retry_interval, "retry_interval", true); + CHECK_EQ(retry_timeout, "retry_timeout", true); CHECK_EQ(iomode, "io", true); CHECK_EQ(ioeventfd, "ioeventfd", true); CHECK_EQ(event_idx, "event_idx", true);
Accept BLOCK_IO_ERROR event with action='retry' from qemu.
Signed-off-by: Jiahui Cen cenjiahui@huawei.com Signed-off-by: Ying Fang fangying1@huawei.com --- include/libvirt/libvirt-domain.h | 1 + src/qemu/qemu_monitor_json.c | 2 +- tools/virsh-domain.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index b440818ec2..90cb652db1 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3701,6 +3701,7 @@ typedef enum { VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0, /* No action, IO error ignored */ VIR_DOMAIN_EVENT_IO_ERROR_PAUSE, /* Guest CPUs are paused */ VIR_DOMAIN_EVENT_IO_ERROR_REPORT, /* IO error reported to guest OS */ + VIR_DOMAIN_EVENT_IO_ERROR_RETRY, /* Failed IO retried */
# ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_IO_ERROR_LAST diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 619717eae5..ef25764a98 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -898,7 +898,7 @@ static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr da VIR_ENUM_DECL(qemuMonitorIOErrorAction); VIR_ENUM_IMPL(qemuMonitorIOErrorAction, VIR_DOMAIN_EVENT_IO_ERROR_LAST, - "ignore", "stop", "report", + "ignore", "stop", "report", "retry", );
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 0a623086a4..65d5c831ec 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13065,7 +13065,8 @@ VIR_ENUM_IMPL(virshDomainEventIOError, VIR_DOMAIN_EVENT_IO_ERROR_LAST, N_("none"), N_("pause"), - N_("report")); + N_("report"), + N_("retry"));
static const char * virshDomainEventIOErrorToString(int action)