]> xenbits.xensource.com Git - libvirt.git/commitdiff
virDomainBlockPeek QEMU and remote support
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 5 Jun 2008 21:12:26 +0000 (21:12 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 5 Jun 2008 21:12:26 +0000 (21:12 +0000)
* qemud/remote.c, qemud/remote_protocol.x, src/remote_internal.c:
  Remote support.
* qemud/remote_dispatch_localvars.h,
  qemud/remote_dispatch_proc_switch.h,
  qemud/remote_dispatch_prototypes.h,
  qemud/remote_protocol.c,
  qemud/remote_protocol.h:
  Generated files for remote support.
* src/xen_unified.c, src/driver.h, src/libvirt.c: Small fix -
  pass flags around internally.
* src/qemu_driver.c: Support for QEMU.
* src/xend_internal.c: Remove redundant fstat call from Xen.

14 files changed:
ChangeLog
qemud/remote.c
qemud/remote_dispatch_localvars.h
qemud/remote_dispatch_proc_switch.h
qemud/remote_dispatch_prototypes.h
qemud/remote_protocol.c
qemud/remote_protocol.h
qemud/remote_protocol.x
src/driver.h
src/libvirt.c
src/qemu_driver.c
src/remote_internal.c
src/xen_unified.c
src/xend_internal.c

index c8d99975be547dc642d30ade000b7342884c512a..b5e00b5460371b87984aa098e03293af08bc81a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Thu Jun  5 22:08:00 BST 2008 Richard W.M. Jones <rjones@redhat.com>
+
+       virDomainBlockPeek QEMU and remote support
+       * qemud/remote.c, qemud/remote_protocol.x, src/remote_internal.c:
+         Remote support.
+       * qemud/remote_dispatch_localvars.h,
+         qemud/remote_dispatch_proc_switch.h,
+         qemud/remote_dispatch_prototypes.h,
+         qemud/remote_protocol.c,
+         qemud/remote_protocol.h:
+         Generated files for remote support.
+       * src/xen_unified.c, src/driver.h, src/libvirt.c: Small fix -
+         pass flags around internally.
+       * src/qemu_driver.c: Support for QEMU.
+       * src/xend_internal.c: Remove redundant fstat call from Xen.
+
 Thu Jun  5 14:10:00 BST 2008 Richard W.M. Jones <rjones@redhat.com>
 
        virDomainBlockPeek call
index 2ba91b1a0469cabe47114d8703f231f2b56ac83f..6837fdcd544c1df633a10b50c341439f1c4eb273 100644 (file)
@@ -889,6 +889,54 @@ remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED
     return 0;
 }
 
+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,
index fa5f173209aab7da7483afe51f1d1282b2eb45cb..56963ab053b6dbf2737a048e67442ddd7edd03f7 100644 (file)
@@ -41,6 +41,8 @@ remote_list_domains_ret lv_remote_list_domains_ret;
 remote_network_define_xml_args lv_remote_network_define_xml_args;
 remote_network_define_xml_ret lv_remote_network_define_xml_ret;
 remote_get_type_ret lv_remote_get_type_ret;
+remote_domain_block_peek_args lv_remote_domain_block_peek_args;
+remote_domain_block_peek_ret lv_remote_domain_block_peek_ret;
 remote_storage_vol_delete_args lv_remote_storage_vol_delete_args;
 remote_network_dump_xml_args lv_remote_network_dump_xml_args;
 remote_network_dump_xml_ret lv_remote_network_dump_xml_ret;
index 4c6e4db6c02d4c5aae466ccc3d02bb61526f1279..00c98fe94a9ad6e5dae0e6886c55501c9a06ba45 100644 (file)
@@ -47,6 +47,15 @@ case REMOTE_PROC_DOMAIN_ATTACH_DEVICE:
         args = (char *) &lv_remote_domain_attach_device_args;
         memset (&lv_remote_domain_attach_device_args, 0, sizeof lv_remote_domain_attach_device_args);
         break;
+case REMOTE_PROC_DOMAIN_BLOCK_PEEK:
+        fn = (dispatch_fn) remoteDispatchDomainBlockPeek;
+        args_filter = (xdrproc_t) xdr_remote_domain_block_peek_args;
+        args = (char *) &lv_remote_domain_block_peek_args;
+        memset (&lv_remote_domain_block_peek_args, 0, sizeof lv_remote_domain_block_peek_args);
+        ret_filter = (xdrproc_t) xdr_remote_domain_block_peek_ret;
+        ret = (char *) &lv_remote_domain_block_peek_ret;
+        memset (&lv_remote_domain_block_peek_ret, 0, sizeof lv_remote_domain_block_peek_ret);
+        break;
 case REMOTE_PROC_DOMAIN_BLOCK_STATS:
         fn = (dispatch_fn) remoteDispatchDomainBlockStats;
         args_filter = (xdrproc_t) xdr_remote_domain_block_stats_args;
index 41d026906529d364017eb893dd621df76f5ccf6f..6d68b8cb4cffa35aacb4f57b0c5db0d9cda9c512 100644 (file)
@@ -9,6 +9,7 @@ static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemu
 static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret);
 static int remoteDispatchClose (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, void *ret);
 static int remoteDispatchDomainAttachDevice (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_attach_device_args *args, void *ret);
+static int remoteDispatchDomainBlockPeek (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret);
 static int remoteDispatchDomainBlockStats (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret);
 static int remoteDispatchDomainCoreDump (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_core_dump_args *args, void *ret);
 static int remoteDispatchDomainCreate (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_create_args *args, void *ret);
index 4045801157e1416e5bc4f6b741cae413d30f83af..69045626e94edb8974820f1af3b1166f5664ba15 100644 (file)
@@ -534,6 +534,33 @@ xdr_remote_domain_interface_stats_ret (XDR *xdrs, remote_domain_interface_stats_
         return TRUE;
 }
 
+bool_t
+xdr_remote_domain_block_peek_args (XDR *xdrs, remote_domain_block_peek_args *objp)
+{
+
+         if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->path))
+                 return FALSE;
+         if (!xdr_u_quad_t (xdrs, &objp->offset))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->size))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_domain_block_peek_ret (XDR *xdrs, remote_domain_block_peek_ret *objp)
+{
+        char **objp_cpp0 = (char **) (void *) &objp->buffer.buffer_val;
+
+         if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->buffer.buffer_len, REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX))
+                 return FALSE;
+        return TRUE;
+}
+
 bool_t
 xdr_remote_list_domains_args (XDR *xdrs, remote_list_domains_args *objp)
 {
index d42afd8f902d673b431c95761bed10613cd88999..8eeaba2f4019f291deb48fb8a8941fbe1082b516 100644 (file)
@@ -33,6 +33,7 @@ typedef remote_nonnull_string *remote_string;
 #define REMOTE_NODE_MAX_CELLS 1024
 #define REMOTE_AUTH_SASL_DATA_MAX 65536
 #define REMOTE_AUTH_TYPE_LIST_MAX 20
+#define REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX 65536
 
 typedef char remote_uuid[VIR_UUID_BUFLEN];
 
@@ -263,6 +264,23 @@ struct remote_domain_interface_stats_ret {
 };
 typedef struct remote_domain_interface_stats_ret remote_domain_interface_stats_ret;
 
+struct remote_domain_block_peek_args {
+        remote_nonnull_domain dom;
+        remote_nonnull_string path;
+        u_quad_t offset;
+        u_int size;
+        u_int flags;
+};
+typedef struct remote_domain_block_peek_args remote_domain_block_peek_args;
+
+struct remote_domain_block_peek_ret {
+        struct {
+                u_int buffer_len;
+                char *buffer_val;
+        } buffer;
+};
+typedef struct remote_domain_block_peek_ret remote_domain_block_peek_ret;
+
 struct remote_list_domains_args {
         int maxids;
 };
@@ -1138,6 +1156,7 @@ enum remote_procedure {
         REMOTE_PROC_STORAGE_VOL_GET_PATH = 100,
         REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101,
         REMOTE_PROC_NODE_GET_FREE_MEMORY = 102,
+        REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -1206,6 +1225,8 @@ extern  bool_t xdr_remote_domain_block_stats_args (XDR *, remote_domain_block_st
 extern  bool_t xdr_remote_domain_block_stats_ret (XDR *, remote_domain_block_stats_ret*);
 extern  bool_t xdr_remote_domain_interface_stats_args (XDR *, remote_domain_interface_stats_args*);
 extern  bool_t xdr_remote_domain_interface_stats_ret (XDR *, remote_domain_interface_stats_ret*);
+extern  bool_t xdr_remote_domain_block_peek_args (XDR *, remote_domain_block_peek_args*);
+extern  bool_t xdr_remote_domain_block_peek_ret (XDR *, remote_domain_block_peek_ret*);
 extern  bool_t xdr_remote_list_domains_args (XDR *, remote_list_domains_args*);
 extern  bool_t xdr_remote_list_domains_ret (XDR *, remote_list_domains_ret*);
 extern  bool_t xdr_remote_num_of_domains_ret (XDR *, remote_num_of_domains_ret*);
@@ -1381,6 +1402,8 @@ extern bool_t xdr_remote_domain_block_stats_args ();
 extern bool_t xdr_remote_domain_block_stats_ret ();
 extern bool_t xdr_remote_domain_interface_stats_args ();
 extern bool_t xdr_remote_domain_interface_stats_ret ();
+extern bool_t xdr_remote_domain_block_peek_args ();
+extern bool_t xdr_remote_domain_block_peek_ret ();
 extern bool_t xdr_remote_list_domains_args ();
 extern bool_t xdr_remote_list_domains_ret ();
 extern bool_t xdr_remote_num_of_domains_ret ();
index 9c151432a6b8dd23d9351ee42ee00c546f1a553d..048fcb68254d1db7c608a5f93679b5f5fabbde56 100644 (file)
@@ -96,6 +96,12 @@ const REMOTE_AUTH_SASL_DATA_MAX = 65536;
 /* 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 @@ struct remote_domain_interface_stats_ret {
     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 @@ enum remote_procedure {
     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 ebdd637e0bf1e77fb166aa1dbadbdc248d973930..ed6d2e513d4540a92c81636a714e6fb602f3092a 100644 (file)
@@ -230,7 +230,8 @@ typedef int
                     (virDomainPtr domain,
                      const char *path,
                      unsigned long long offset, size_t size,
-                     void *buffer);
+                     void *buffer,
+                     unsigned int flags);
 
 typedef int
     (*virDrvDomainMigratePrepare)
index 3e349e1faaef67fb1c803a1f84fa436a43250bfa..53a93e30257feb40dc4373e53bca8967ead81875 100644 (file)
@@ -2659,7 +2659,8 @@ virDomainBlockPeek (virDomainPtr dom,
     }
 
     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 c928027fb3f0cb7f72b2044b82a9db71fdc3054b..969c253eda146544daa1e3776e417adecb5ada48 100644 (file)
@@ -3163,6 +3163,64 @@ qemudDomainInterfaceStats (virDomainPtr dom,
 #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 @@ static virDriver qemuDriver = {
     NULL, /* domainMigrateFinish */
     qemudDomainBlockStats, /* domainBlockStats */
     qemudDomainInterfaceStats, /* domainInterfaceStats */
-    NULL, /* domainBlockPeek */
+    qemudDomainBlockPeek, /* domainBlockPeek */
 #if HAVE_NUMACTL
     qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
     qemudNodeGetFreeMemory,  /* getFreeMemory */
index 4c87ec8632384db7d4edcdee639f03c2031d5777..478c93dc85aff4de0858f82d77116e13ba001c4c 100644 (file)
@@ -2374,6 +2374,52 @@ remoteDomainInterfaceStats (virDomainPtr domain, const char *path,
     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 @@ static virDriver driver = {
     .domainMigrateFinish = remoteDomainMigrateFinish,
     .domainBlockStats = remoteDomainBlockStats,
     .domainInterfaceStats = remoteDomainInterfaceStats,
+    .domainBlockPeek = remoteDomainBlockPeek,
     .nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory,
     .getFreeMemory = remoteNodeGetFreeMemory,
 };
index b77a0ecfd92f49e858a99ff05c3337448af452d1..c74e3a94658b4219ce413f5e7bbc155dfd4ced33 100644 (file)
@@ -1237,7 +1237,7 @@ xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
 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 3cb1a3bde764f88160eeabccc39e04849f8a18e6..b30a8785427420d24ac849cf687848a619539aee 100644 (file)
@@ -4541,7 +4541,6 @@ xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
     struct sexpr *root;
     struct check_path_data data;
     int fd, ret = -1;
-    struct stat statbuf;
 
     priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
 
@@ -4583,7 +4582,7 @@ xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
 
     /* 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;
     }