From 342fc56f5837ba7486e16ab9362d8aff5305659e Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Tue, 31 Jan 2012 07:42:31 +0100 Subject: [PATCH] Remote protocol for virDomainGetDiskErrors --- daemon/remote.c | 103 +++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 77 ++++++++++++++++++++++++++ src/remote/remote_protocol.x | 23 +++++++- src/remote_protocol-structs | 17 ++++++ 4 files changed, 219 insertions(+), 1 deletion(-) diff --git a/daemon/remote.c b/daemon/remote.c index e7d9b2fd9f..8fbcf43b63 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -98,6 +98,12 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val, int limit, int *nparams); +static int +remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors, + int nerrors, + remote_domain_disk_error **ret_errors_val, + u_int *ret_errors_len); + #include "remote_dispatch.h" #include "qemu_dispatch.h" @@ -3591,6 +3597,69 @@ cleanup: return rv; } +static int remoteDispatchDomainGetDiskErrors( + virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_get_disk_errors_args *args, + remote_domain_get_disk_errors_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainDiskErrorPtr errors = NULL; + int len; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + + if (args->maxerrors > REMOTE_DOMAIN_DISK_ERRORS_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", + _("maxerrors too large")); + goto cleanup; + } + + if (args->maxerrors && + VIR_ALLOC_N(errors, args->maxerrors) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virDomainGetDiskErrors(dom, errors, + args->maxerrors, + args->flags)) < 0) + goto cleanup; + + ret->nerrors = len; + if (errors && + remoteSerializeDomainDiskErrors(errors, len, + &ret->errors.errors_val, + &ret->errors.errors_len) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + if (dom) + virDomainFree(dom); + if (errors) { + int i; + for (i = 0; i < len; i++) + VIR_FREE(errors[i].disk); + } + VIR_FREE(errors); + return rv; +} + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire @@ -3721,3 +3790,37 @@ make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDo snapshot_dst->name = strdup(snapshot_src->name); make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain); } + +static int +remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors, + int nerrors, + remote_domain_disk_error **ret_errors_val, + u_int *ret_errors_len) +{ + remote_domain_disk_error *val = NULL; + int i = 0; + + if (VIR_ALLOC_N(val, nerrors) < 0) + goto no_memory; + + for (i = 0; i < nerrors; i++) { + if (!(val[i].disk = strdup(errors[i].disk))) + goto no_memory; + val[i].error = errors[i].error; + } + + *ret_errors_len = nerrors; + *ret_errors_val = val; + + return 0; + +no_memory: + if (val) { + int j; + for (j = 0; j < i; j++) + VIR_FREE(val[j].disk); + VIR_FREE(val); + } + virReportOOMError(); + return -1; +} diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 031becda67..09b5ace666 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1423,6 +1423,39 @@ cleanup: return rv; } +static int +remoteDeserializeDomainDiskErrors(remote_domain_disk_error *ret_errors_val, + u_int ret_errors_len, + int limit, + virDomainDiskErrorPtr errors, + int maxerrors) +{ + int i = 0; + int j; + + if (ret_errors_len > limit || ret_errors_len > maxerrors) { + remoteError(VIR_ERR_RPC, "%s", + _("returned number of disk errors exceeds limit")); + goto error; + } + + for (i = 0; i < ret_errors_len; i++) { + if (!(errors[i].disk = strdup(ret_errors_val[i].disk))) { + virReportOOMError(); + goto error; + } + errors[i].error = ret_errors_val[i].error; + } + + return 0; + +error: + for (j = 0; j < i; j++) + VIR_FREE(errors[i].disk); + + return -1; +} + static int remoteDomainBlockStatsFlags(virDomainPtr domain, const char *path, @@ -4438,6 +4471,49 @@ remoteIsAlive(virConnectPtr conn) } +static int +remoteDomainGetDiskErrors(virDomainPtr dom, + virDomainDiskErrorPtr errors, + unsigned int maxerrors, + unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_disk_errors_args args; + remote_domain_get_disk_errors_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.maxerrors = maxerrors; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_DISK_ERRORS, + (xdrproc_t) xdr_remote_domain_get_disk_errors_args, + (char *) &args, + (xdrproc_t) xdr_remote_domain_get_disk_errors_ret, + (char *) &ret) == -1) + goto done; + + if (remoteDeserializeDomainDiskErrors(ret.errors.errors_val, + ret.errors.errors_len, + REMOTE_DOMAIN_DISK_ERRORS_MAX, + errors, + maxerrors) < 0) + goto cleanup; + + rv = ret.nerrors; + +cleanup: + xdr_free((xdrproc_t) xdr_remote_domain_get_disk_errors_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + #include "remote_client_bodies.h" #include "qemu_client_bodies.h" @@ -4840,6 +4916,7 @@ static virDriver remote_driver = { .domainSetNumaParameters = remoteDomainSetNumaParameters, /* 0.9.9 */ .domainGetNumaParameters = remoteDomainGetNumaParameters, /* 0.9.9 */ .domainGetCPUStats = remoteDomainGetCPUStats, /* 0.9.10 */ + .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index b2c84261af..10fd2940a8 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -219,6 +219,11 @@ const REMOTE_DOMAIN_GET_CPU_STATS_NCPUS_MAX = 128; */ const REMOTE_DOMAIN_GET_CPU_STATS_MAX = 2048; +/* + * Upper limit on number of disks with errors + */ +const REMOTE_DOMAIN_DISK_ERRORS_MAX = 256; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -359,6 +364,10 @@ struct remote_node_get_memory_stats { unsigned hyper value; }; +struct remote_domain_disk_error { + remote_nonnull_string disk; + int error; +}; /*----- Calls. -----*/ @@ -2397,6 +2406,17 @@ struct remote_domain_shutdown_flags_args { unsigned int flags; }; +struct remote_domain_get_disk_errors_args { + remote_nonnull_domain dom; + unsigned int maxerrors; + unsigned int flags; +}; + +struct remote_domain_get_disk_errors_ret { + remote_domain_disk_error errors; + int nerrors; +}; + /*----- Protocol. -----*/ @@ -2708,7 +2728,8 @@ enum remote_procedure { REMOTE_PROC_STORAGE_VOL_RESIZE = 260, /* autogen autogen */ REMOTE_PROC_DOMAIN_PM_SUSPEND_FOR_DURATION = 261, /* autogen autogen */ - REMOTE_PROC_DOMAIN_GET_CPU_STATS = 262 /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_GET_CPU_STATS = 262, /* skipgen skipgen */ + REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263 /* skipgen skipgen */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index e9137a90b9..ee2207ca52 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -94,6 +94,10 @@ struct remote_node_get_memory_stats { remote_nonnull_string field; uint64_t value; }; +struct remote_domain_disk_error { + remote_nonnull_string disk; + int error; +}; struct remote_open_args { remote_string name; u_int flags; @@ -1866,6 +1870,18 @@ struct remote_domain_shutdown_flags_args { remote_nonnull_domain dom; u_int flags; }; +struct remote_domain_get_disk_errors_args { + remote_nonnull_domain dom; + u_int maxerrors; + u_int flags; +}; +struct remote_domain_get_disk_errors_ret { + struct { + u_int errors_len; + remote_domain_disk_error * errors_val; + } errors; + int nerrors; +}; enum remote_procedure { REMOTE_PROC_OPEN = 1, REMOTE_PROC_CLOSE = 2, @@ -2129,4 +2145,5 @@ enum remote_procedure { REMOTE_PROC_STORAGE_VOL_RESIZE = 260, REMOTE_PROC_DOMAIN_PM_SUSPEND_FOR_DURATION = 261, REMOTE_PROC_DOMAIN_GET_CPU_STATS = 262, + REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263, };