+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
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,
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;
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;
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);
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)
{
#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];
};
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;
};
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;
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*);
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 ();
/* 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];
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;
};
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. */
(virDomainPtr domain,
const char *path,
unsigned long long offset, size_t size,
- void *buffer);
+ void *buffer,
+ unsigned int flags);
typedef int
(*virDrvDomainMigratePrepare)
}
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;
#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;
NULL, /* domainMigrateFinish */
qemudDomainBlockStats, /* domainBlockStats */
qemudDomainInterfaceStats, /* domainInterfaceStats */
- NULL, /* domainBlockPeek */
+ qemudDomainBlockPeek, /* domainBlockPeek */
#if HAVE_NUMACTL
qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
qemudNodeGetFreeMemory, /* getFreeMemory */
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
.domainMigrateFinish = remoteDomainMigrateFinish,
.domainBlockStats = remoteDomainBlockStats,
.domainInterfaceStats = remoteDomainInterfaceStats,
+ .domainBlockPeek = remoteDomainBlockPeek,
.nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory,
.getFreeMemory = remoteNodeGetFreeMemory,
};
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);
struct sexpr *root;
struct check_path_data data;
int fd, ret = -1;
- struct stat statbuf;
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
/* 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;
}