Add daemon and driver code to (de-)serialize virDomainFSInfo.
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama(a)hds.com>
---
daemon/remote.c | 113 ++++++++++++++++++++++++++++++++++++++++++
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, 259 insertions(+), 1 deletion(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 1d7082e..e50fced 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -6336,6 +6336,119 @@ 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, 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: %d 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 04e5360..dc309cf 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -7829,6 +7829,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,
@@ -8171,6 +8263,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 ebf4530..6b22377 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];
@@ -3111,6 +3117,24 @@ struct remote_connect_get_all_domain_stats_args {
struct remote_connect_get_all_domain_stats_ret {
remote_domain_stats_record retStats<REMOTE_DOMAIN_LIST_MAX>;
};
+
+struct remote_domain_fsinfo {
+ remote_nonnull_string mountpoint;
+ remote_nonnull_string name;
+ remote_nonnull_string fstype;
+ remote_nonnull_string dev_aliases<REMOTE_DOMAIN_FSINFO_DISKS_MAX>; /* (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<REMOTE_DOMAIN_FSINFO_MAX>;
+ unsigned int ret;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -5506,5 +5530,11 @@ enum remote_procedure {
* @generate: none
* @acl: connect:write
*/
- REMOTE_PROC_NODE_ALLOC_PAGES = 347
+ REMOTE_PROC_NODE_ALLOC_PAGES = 347,
+
+ /**
+ * @generate: none
+ * @acl: domain:fs_freeze
+ */
+ REMOTE_PROC_DOMAIN_GET_FSINFO = 348
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 362baf9..ec66a46 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2579,6 +2579,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,
@@ -2927,4 +2947,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_BLOCK_COPY = 345,
REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346,
REMOTE_PROC_NODE_ALLOC_PAGES = 347,
+ REMOTE_PROC_DOMAIN_GET_FSINFO = 348,
};
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index b38d5bb..80f35b3 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/;