[libvirt] [PATCH] QEMU & remote support for virDomainBlockPeek
Richard W.M. Jones
rjones at redhat.com
Thu Jun 5 18:42:10 UTC 2008
This patch adds support for virDomainBlockPeek over remote.
Also adds a QEMU driver implementation.
Also there is a minor fix in the Xen driver impl.
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
-------------- next part --------------
? scripts/Makefile
? scripts/Makefile.in
Index: qemud/remote.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/remote.c,v
retrieving revision 1.35
diff -u -r1.35 remote.c
--- qemud/remote.c 23 May 2008 08:24:44 -0000 1.35
+++ qemud/remote.c 5 Jun 2008 18:43:10 -0000
@@ -890,6 +890,54 @@
}
static int
+remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client,
+ remote_message_header *req,
+ remote_domain_block_peek_args *args,
+ remote_domain_block_peek_ret *ret)
+{
+ virDomainPtr dom;
+ char *path;
+ unsigned long long offset;
+ size_t size;
+ unsigned int flags;
+ CHECK_CONN (client);
+
+ dom = get_nonnull_domain (client->conn, args->dom);
+ if (dom == NULL) {
+ remoteDispatchError (client, req, "%s", _("domain not found"));
+ return -2;
+ }
+ path = args->path;
+ offset = args->offset;
+ size = args->size;
+ flags = args->flags;
+
+ if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
+ remoteDispatchError (client, req,
+ "%s", _("size > maximum buffer size"));
+ return -2;
+ }
+
+ ret->buffer.buffer_len = size;
+ ret->buffer.buffer_val = malloc (size);
+ if (!ret->buffer.buffer_val) {
+ remoteDispatchError (client, req, "%s", strerror (errno));
+ return -2;
+ }
+
+ if (virDomainBlockPeek (dom, path, offset, size,
+ ret->buffer.buffer_val, flags) == -1) {
+ /* free (ret->buffer.buffer_val); - caller frees */
+ virDomainFree (dom);
+ return -1;
+ }
+ virDomainFree (dom);
+
+ return 0;
+}
+
+static int
remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
struct qemud_client *client,
remote_message_header *req,
Index: qemud/remote_protocol.x
===================================================================
RCS file: /data/cvs/libvirt/qemud/remote_protocol.x,v
retrieving revision 1.13
diff -u -r1.13 remote_protocol.x
--- qemud/remote_protocol.x 23 May 2008 08:24:44 -0000 1.13
+++ qemud/remote_protocol.x 5 Jun 2008 18:43:11 -0000
@@ -96,6 +96,12 @@
/* Maximum number of auth types */
const REMOTE_AUTH_TYPE_LIST_MAX = 20;
+/* Maximum length of a block or memory peek buffer message.
+ * Note applications need to be aware of this limit and issue multiple
+ * requests for large amounts of data.
+ */
+const REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX = 65536;
+
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
@@ -322,6 +328,18 @@
hyper tx_drop;
};
+struct remote_domain_block_peek_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string path;
+ unsigned hyper offset;
+ unsigned size;
+ unsigned flags;
+};
+
+struct remote_domain_block_peek_ret {
+ opaque buffer<REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX>;
+};
+
struct remote_list_domains_args {
int maxids;
};
@@ -1036,7 +1054,9 @@
REMOTE_PROC_STORAGE_VOL_GET_PATH = 100,
REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101,
- REMOTE_PROC_NODE_GET_FREE_MEMORY = 102
+ REMOTE_PROC_NODE_GET_FREE_MEMORY = 102,
+
+ REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103
};
/* Custom RPC structure. */
Index: src/driver.h
===================================================================
RCS file: /data/cvs/libvirt/src/driver.h,v
retrieving revision 1.48
diff -u -r1.48 driver.h
--- src/driver.h 5 Jun 2008 13:17:45 -0000 1.48
+++ src/driver.h 5 Jun 2008 18:43:11 -0000
@@ -230,7 +230,8 @@
(virDomainPtr domain,
const char *path,
unsigned long long offset, size_t size,
- void *buffer);
+ void *buffer,
+ unsigned int flags);
typedef int
(*virDrvDomainMigratePrepare)
Index: src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.144
diff -u -r1.144 libvirt.c
--- src/libvirt.c 5 Jun 2008 13:17:45 -0000 1.144
+++ src/libvirt.c 5 Jun 2008 18:43:14 -0000
@@ -2659,7 +2659,8 @@
}
if (conn->driver->domainBlockPeek)
- return conn->driver->domainBlockPeek (dom, path, offset, size, buffer);
+ return conn->driver->domainBlockPeek (dom, path, offset, size,
+ buffer, flags);
virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
Index: src/qemu_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_driver.c,v
retrieving revision 1.83
diff -u -r1.83 qemu_driver.c
--- src/qemu_driver.c 5 Jun 2008 13:17:45 -0000 1.83
+++ src/qemu_driver.c 5 Jun 2008 18:43:17 -0000
@@ -3163,6 +3163,64 @@
#endif
}
+static int
+qemudDomainBlockPeek (virDomainPtr dom,
+ const char *path,
+ unsigned long long offset, size_t size,
+ void *buffer,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
+ struct qemud_vm *vm = qemudFindVMByUUID (driver, dom->uuid);
+ int i;
+ int fd, ret = -1;
+
+ if (!vm) {
+ qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ _("no domain with matching uuid"));
+ return -1;
+ }
+
+ if (!path || path[0] == '\0') {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
+ _("NULL or empty path"));
+ return -1;
+ }
+
+ /* Check the path belongs to this domain. */
+ for (i = 0; i < vm->def->ndisks; ++i) {
+ if (STREQ (vm->def->disks[i].src, path)) goto found;
+ }
+ qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
+ _("invalid path"));
+ return -1;
+
+found:
+ /* The path is correct, now try to open it and get its size. */
+ fd = open (path, O_RDONLY);
+ if (fd == -1) {
+ qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
+ "%s", strerror (errno));
+ goto done;
+ }
+
+ /* Seek and read. */
+ /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
+ * be 64 bits on all platforms.
+ */
+ if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
+ saferead (fd, buffer, size) == (ssize_t) -1) {
+ qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
+ "%s", strerror (errno));
+ goto done;
+ }
+
+ ret = 0;
+ done:
+ if (fd >= 0) close (fd);
+ return ret;
+}
+
static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
const unsigned char *uuid) {
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
@@ -3521,7 +3579,7 @@
NULL, /* domainMigrateFinish */
qemudDomainBlockStats, /* domainBlockStats */
qemudDomainInterfaceStats, /* domainInterfaceStats */
- NULL, /* domainBlockPeek */
+ qemudDomainBlockPeek, /* domainBlockPeek */
#if HAVE_NUMACTL
qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
qemudNodeGetFreeMemory, /* getFreeMemory */
Index: src/remote_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/remote_internal.c,v
retrieving revision 1.76
diff -u -r1.76 remote_internal.c
--- src/remote_internal.c 22 May 2008 15:20:25 -0000 1.76
+++ src/remote_internal.c 5 Jun 2008 18:43:20 -0000
@@ -2374,6 +2374,52 @@
return 0;
}
+static int
+remoteDomainBlockPeek (virDomainPtr domain,
+ const char *path,
+ unsigned long long offset,
+ size_t size,
+ void *buffer,
+ unsigned int flags)
+{
+ remote_domain_block_peek_args args;
+ remote_domain_block_peek_ret ret;
+ GET_PRIVATE (domain->conn, -1);
+
+ if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
+ errorf (domain->conn, VIR_ERR_RPC,
+ _("block peek request too large for remote protocol, %zi > %d"),
+ size, REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX);
+ return -1;
+ }
+
+ make_nonnull_domain (&args.dom, domain);
+ args.path = (char *) path;
+ args.offset = offset;
+ args.size = size;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_PEEK,
+ (xdrproc_t) xdr_remote_domain_block_peek_args,
+ (char *) &args,
+ (xdrproc_t) xdr_remote_domain_block_peek_ret,
+ (char *) &ret) == -1)
+ return -1;
+
+ if (ret.buffer.buffer_len != size) {
+ errorf (domain->conn, VIR_ERR_RPC,
+ _("returned buffer is not same size as requested"));
+ free (ret.buffer.buffer_val);
+ return -1;
+ }
+
+ memcpy (buffer, ret.buffer.buffer_val, size);
+ free (ret.buffer.buffer_val);
+
+ return 0;
+}
+
/*----------------------------------------------------------------------*/
static int
@@ -4784,6 +4830,7 @@
.domainMigrateFinish = remoteDomainMigrateFinish,
.domainBlockStats = remoteDomainBlockStats,
.domainInterfaceStats = remoteDomainInterfaceStats,
+ .domainBlockPeek = remoteDomainBlockPeek,
.nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory,
.getFreeMemory = remoteNodeGetFreeMemory,
};
Index: src/xen_unified.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_unified.c,v
retrieving revision 1.45
diff -u -r1.45 xen_unified.c
--- src/xen_unified.c 5 Jun 2008 13:17:45 -0000 1.45
+++ src/xen_unified.c 5 Jun 2008 18:43:21 -0000
@@ -1237,7 +1237,7 @@
static int
xenUnifiedDomainBlockPeek (virDomainPtr dom, const char *path,
unsigned long long offset, size_t size,
- void *buffer)
+ void *buffer, unsigned int flags ATTRIBUTE_UNUSED)
{
int r;
GET_PRIVATE (dom->conn);
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.195
diff -u -r1.195 xend_internal.c
--- src/xend_internal.c 5 Jun 2008 13:17:45 -0000 1.195
+++ src/xend_internal.c 5 Jun 2008 18:43:24 -0000
@@ -4541,7 +4541,6 @@
struct sexpr *root;
struct check_path_data data;
int fd, ret = -1;
- struct stat statbuf;
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
@@ -4583,7 +4582,7 @@
/* The path is correct, now try to open it and get its size. */
fd = open (path, O_RDONLY);
- if (fd == -1 || fstat (fd, &statbuf) == -1) {
+ if (fd == -1) {
virXendError (domain->conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
goto done;
}
More information about the libvir-list
mailing list