From ee3dc4f19b80fc1c69ba3a454112f54a17d3d130 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Fri, 21 Nov 2014 20:27:31 -0500 Subject: [PATCH] remote: Implement the remote protocol for virDomainGetFSInfo Add daemon and driver code to (de-)serialize virDomainFSInfo. Signed-off-by: Tomoki Sekiyama --- daemon/remote.c | 114 +++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 93 ++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 32 +++++++++- src/remote_protocol-structs | 21 +++++++ src/rpc/gendispatch.pl | 1 + 5 files changed, 260 insertions(+), 1 deletion(-) diff --git a/daemon/remote.c b/daemon/remote.c index 18f493d97f..75ae9824de 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -6372,6 +6372,120 @@ remoteDispatchNodeAllocPages(virNetServerPtr server ATTRIBUTE_UNUSED, } +static int +remoteDispatchDomainGetFSInfo(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_get_fsinfo_args *args, + remote_domain_get_fsinfo_ret *ret) +{ + int rv = -1; + size_t i, j; + struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + virDomainFSInfoPtr *info = NULL; + virDomainPtr dom = NULL; + remote_domain_fsinfo *dst; + int ninfo = 0; + size_t ndisk; + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + + if ((ninfo = virDomainGetFSInfo(dom, &info, args->flags)) < 0) + goto cleanup; + + if (ninfo > REMOTE_DOMAIN_FSINFO_MAX) { + virReportError(VIR_ERR_RPC, + _("Too many mountpoints in fsinfo: %d for limit %d"), + ninfo, REMOTE_DOMAIN_FSINFO_MAX); + goto cleanup; + } + + if (ninfo) { + if (VIR_ALLOC_N(ret->info.info_val, ninfo) < 0) + goto cleanup; + + ret->info.info_len = ninfo; + + for (i = 0; i < ninfo; i++) { + dst = &ret->info.info_val[i]; + if (VIR_STRDUP(dst->mountpoint, info[i]->mountpoint) < 0) + goto cleanup; + + if (VIR_STRDUP(dst->name, info[i]->name) < 0) + goto cleanup; + + if (VIR_STRDUP(dst->fstype, info[i]->fstype) < 0) + goto cleanup; + + ndisk = info[i]->ndevAlias; + if (ndisk > REMOTE_DOMAIN_FSINFO_DISKS_MAX) { + virReportError(VIR_ERR_RPC, + _("Too many disks in fsinfo: %zd for limit %d"), + ndisk, REMOTE_DOMAIN_FSINFO_DISKS_MAX); + goto cleanup; + } + + if (ndisk > 0) { + if (VIR_ALLOC_N(dst->dev_aliases.dev_aliases_val, ndisk) < 0) + goto cleanup; + + for (j = 0; j < ndisk; j++) { + if (VIR_STRDUP(dst->dev_aliases.dev_aliases_val[j], + info[i]->devAlias[j]) < 0) + goto cleanup; + } + + dst->dev_aliases.dev_aliases_len = ndisk; + } else { + dst->dev_aliases.dev_aliases_val = NULL; + dst->dev_aliases.dev_aliases_len = 0; + } + } + + } else { + ret->info.info_len = 0; + ret->info.info_val = NULL; + } + + ret->ret = ninfo; + + rv = 0; + + cleanup: + if (rv < 0) { + virNetMessageSaveError(rerr); + + if (ret->info.info_val && ninfo > 0) { + for (i = 0; i < ninfo; i++) { + dst = &ret->info.info_val[i]; + VIR_FREE(dst->mountpoint); + if (dst->dev_aliases.dev_aliases_val) { + for (j = 0; j < dst->dev_aliases.dev_aliases_len; j++) + VIR_FREE(dst->dev_aliases.dev_aliases_val[j]); + VIR_FREE(dst->dev_aliases.dev_aliases_val); + } + } + VIR_FREE(ret->info.info_val); + } + } + if (dom) + virDomainFree(dom); + if (ninfo >= 0) + for (i = 0; i < ninfo; i++) + virDomainFSInfoFree(info[i]); + VIR_FREE(info); + + return rv; +} + + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 88f8743bb1..22f0c887a1 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7860,6 +7860,98 @@ remoteNodeAllocPages(virConnectPtr conn, } +static int +remoteDomainGetFSInfo(virDomainPtr dom, + virDomainFSInfoPtr **info, + unsigned int flags) +{ + int rv = -1; + size_t i, j, len; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_fsinfo_args args; + remote_domain_get_fsinfo_ret ret; + remote_domain_fsinfo *src; + virDomainFSInfoPtr *info_ret = NULL; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + args.flags = flags; + + memset(&ret, 0, sizeof(ret)); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_FSINFO, + (xdrproc_t)xdr_remote_domain_get_fsinfo_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_fsinfo_ret, (char *)&ret) == -1) + goto done; + + if (ret.info.info_len > REMOTE_DOMAIN_FSINFO_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Too many mountpoints in fsinfo: %d for limit %d"), + ret.info.info_len, REMOTE_DOMAIN_FSINFO_MAX); + goto cleanup; + } + + if (info) { + if (!ret.info.info_len) { + *info = NULL; + rv = ret.ret; + goto cleanup; + } + + if (VIR_ALLOC_N(info_ret, ret.info.info_len) < 0) + goto cleanup; + + for (i = 0; i < ret.info.info_len; i++) { + src = &ret.info.info_val[i]; + + if (VIR_ALLOC(info_ret[i]) < 0) + goto cleanup; + + if (VIR_STRDUP(info_ret[i]->mountpoint, src->mountpoint) < 0) + goto cleanup; + + if (VIR_STRDUP(info_ret[i]->name, src->name) < 0) + goto cleanup; + + if (VIR_STRDUP(info_ret[i]->fstype, src->fstype) < 0) + goto cleanup; + + len = src->dev_aliases.dev_aliases_len; + info_ret[i]->ndevAlias = len; + if (len && + VIR_ALLOC_N(info_ret[i]->devAlias, len) < 0) + goto cleanup; + + for (j = 0; j < len; j++) { + if (VIR_STRDUP(info_ret[i]->devAlias[j], + src->dev_aliases.dev_aliases_val[j]) < 0) + goto cleanup; + } + } + + *info = info_ret; + info_ret = NULL; + } + + rv = ret.ret; + + cleanup: + if (info_ret) { + for (i = 0; i < ret.info.info_len; i++) + virDomainFSInfoFree(info_ret[i]); + VIR_FREE(info_ret); + } + xdr_free((xdrproc_t)xdr_remote_domain_get_fsinfo_ret, + (char *) &ret); + + done: + remoteDriverUnlock(priv); + return rv; +} + + /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. * These can return NULL if underlying memory allocations fail, @@ -8202,6 +8294,7 @@ static virHypervisorDriver hypervisor_driver = { .connectGetDomainCapabilities = remoteConnectGetDomainCapabilities, /* 1.2.7 */ .connectGetAllDomainStats = remoteConnectGetAllDomainStats, /* 1.2.8 */ .nodeAllocPages = remoteNodeAllocPages, /* 1.2.9 */ + .domainGetFSInfo = remoteDomainGetFSInfo, /* 1.2.11 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 85c95f5daa..cbd3ec733e 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -250,6 +250,12 @@ const REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX = 4096; /* Upper limit of message size for tunable event. */ const REMOTE_DOMAIN_EVENT_TUNABLE_MAX = 2048; +/* Upper limit on number of mountpoints in fsinfo */ +const REMOTE_DOMAIN_FSINFO_MAX = 256; + +/* Upper limit on number of disks per mountpoint in fsinfo */ +const REMOTE_DOMAIN_FSINFO_DISKS_MAX = 256; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -3119,6 +3125,24 @@ struct remote_domain_event_callback_agent_lifecycle_msg { struct remote_connect_get_all_domain_stats_ret { remote_domain_stats_record retStats; }; + +struct remote_domain_fsinfo { + remote_nonnull_string mountpoint; + remote_nonnull_string name; + remote_nonnull_string fstype; + remote_nonnull_string dev_aliases; /* (const char **) */ +}; + +struct remote_domain_get_fsinfo_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + +struct remote_domain_get_fsinfo_ret { + remote_domain_fsinfo info; + unsigned int ret; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -5520,5 +5544,11 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_DOMAIN_EVENT_CALLBACK_AGENT_LIFECYCLE = 348 + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_AGENT_LIFECYCLE = 348, + + /** + * @generate: none + * @acl: domain:fs_freeze + */ + REMOTE_PROC_DOMAIN_GET_FSINFO = 349 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 9769b2a073..2907fd53bd 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2585,6 +2585,26 @@ struct remote_connect_get_all_domain_stats_ret { remote_domain_stats_record * retStats_val; } retStats; }; +struct remote_domain_fsinfo { + remote_nonnull_string mountpoint; + remote_nonnull_string name; + remote_nonnull_string fstype; + struct { + u_int dev_aliases_len; + remote_nonnull_string * dev_aliases_val; + } dev_aliases; +}; +struct remote_domain_get_fsinfo_args { + remote_nonnull_domain dom; + u_int flags; +}; +struct remote_domain_get_fsinfo_ret { + struct { + u_int info_len; + remote_domain_fsinfo * info_val; + } info; + u_int ret; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -2934,4 +2954,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346, REMOTE_PROC_NODE_ALLOC_PAGES = 347, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_AGENT_LIFECYCLE = 348, + REMOTE_PROC_DOMAIN_GET_FSINFO = 349, }; diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index b38d5bb64c..80f35b3b9d 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -66,6 +66,7 @@ sub fixup_name { $name =~ s/Fstrim$/FSTrim/; $name =~ s/Fsfreeze$/FSFreeze/; $name =~ s/Fsthaw$/FSThaw/; + $name =~ s/Fsinfo$/FSInfo/; $name =~ s/Scsi/SCSI/; $name =~ s/Wwn$/WWN/; $name =~ s/Dhcp$/DHCP/; -- GitLab