Merge remote-tracking branch 'bonzini/nbd-next' into staging

* bonzini/nbd-next: (30 commits)
  qmp: add NBD server commands
  block: add close notifiers
  block: prepare code for adding block notifiers
  qemu-sockets: add socket_listen, socket_connect, socket_parse
  tests: do not include tools-obj-y Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  qemu-sockets: return InetSocketAddress from inet_parse
  qapi: add socket address types
  build: add QAPI files to the tools
  vnc: drop QERR_VNC_SERVER_FAILED
  qemu-sockets: add error propagation to Unix socket functions
  qemu-sockets: add error propagation to inet_parse
  qemu-sockets: add error propagation to inet_dgram_opts
  qemu-sockets: add error propagation to inet_connect_addr
  qemu-sockets: include strerror or gai_strerror output in error messages
  vnc: add error propagation to vnc_display_open
  vnc: reorganize code for reverse mode
  vnc: introduce a single label for error returns
  vnc: avoid Yoda conditionals
  qemu-ga: ask and print error information from qemu-sockets
  nbd: ask and print error information from qemu-sockets
  ...
This commit is contained in:
Anthony Liguori
2012-10-24 09:39:49 -05:00
28 changed files with 764 additions and 421 deletions
+2 -3
View File
@@ -161,11 +161,10 @@ qemu-img.o: qemu-img-cmds.h
tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
qemu-timer-common.o main-loop.o notify.o \
iohandler.o cutils.o iov.o async.o
iohandler.o cutils.o iov.o async.o error.o
tools-obj-$(CONFIG_POSIX) += compatfd.o
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) $(qapi-obj-y) \
qapi-visit.o qapi-types.o
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
+5 -4
View File
@@ -43,11 +43,12 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o
block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o
block-obj-y += qemu-progress.o qemu-sockets.o uri.o
block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o
block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
block-obj-y += block/
block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
@@ -60,7 +61,7 @@ endif
# suppress *all* target specific code in case of system emulation, i.e. a
# single QEMU executable should support all CPUs and machines.
common-obj-y = $(block-obj-y) blockdev.o block/
common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
common-obj-y += net.o net/
common-obj-y += qom/
common-obj-y += readline.o console.o cursor.o
@@ -93,7 +94,7 @@ common-obj-y += bt-host.o bt-vhci.o
common-obj-y += dma-helpers.o
common-obj-y += iov.o acl.o
common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += notify.o event_notifier.o
common-obj-y += event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
common-obj-y += qtest.o
common-obj-y += vl.o
@@ -239,9 +240,9 @@ QEMU_CFLAGS+=$(GLIB_CFLAGS)
nested-vars += \
qga-obj-y \
block-obj-y \
qom-obj-y \
qapi-obj-y \
block-obj-y \
user-obj-y \
common-obj-y \
extra-obj-y
+14 -5
View File
@@ -30,6 +30,7 @@
#include "module.h"
#include "qjson.h"
#include "sysemu.h"
#include "notify.h"
#include "qemu-coroutine.h"
#include "qmp-commands.h"
#include "qemu-timer.h"
@@ -312,9 +313,16 @@ BlockDriverState *bdrv_new(const char *device_name)
QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
}
bdrv_iostatus_disable(bs);
notifier_list_init(&bs->close_notifiers);
return bs;
}
void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify)
{
notifier_list_add(&bs->close_notifiers, notify);
}
BlockDriver *bdrv_find_format(const char *format_name)
{
BlockDriver *drv1;
@@ -1098,12 +1106,13 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
void bdrv_close(BlockDriverState *bs)
{
bdrv_flush(bs);
if (bs->drv) {
if (bs->job) {
block_job_cancel_sync(bs->job);
}
bdrv_drain_all();
if (bs->job) {
block_job_cancel_sync(bs->job);
}
bdrv_drain_all();
notifier_list_notify(&bs->close_notifiers, bs);
if (bs->drv) {
if (bs == bs_snapshots) {
bs_snapshots = NULL;
}
+1
View File
@@ -144,6 +144,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
void bdrv_reopen_commit(BDRVReopenState *reopen_state);
void bdrv_reopen_abort(BDRVReopenState *reopen_state);
void bdrv_close(BlockDriverState *bs);
void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify);
int bdrv_attach_dev(BlockDriverState *bs, void *dev);
void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev);
void bdrv_detach_dev(BlockDriverState *bs, void *dev);
+2
View File
@@ -233,6 +233,8 @@ struct BlockDriverState {
BlockDriverState *backing_hd;
BlockDriverState *file;
NotifierList close_notifiers;
/* number of in-flight copy-on-read requests */
unsigned int copy_on_read_in_flight;
+119
View File
@@ -0,0 +1,119 @@
/*
* Serving QEMU block devices via NBD
*
* Copyright (c) 2012 Red Hat, Inc.
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* later. See the COPYING file in the top-level directory.
*/
#include "blockdev.h"
#include "hw/block-common.h"
#include "monitor.h"
#include "qerror.h"
#include "sysemu.h"
#include "qmp-commands.h"
#include "trace.h"
#include "nbd.h"
#include "qemu_socket.h"
static int server_fd = -1;
static void nbd_accept(void *opaque)
{
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
if (fd >= 0) {
nbd_client_new(NULL, fd, nbd_client_put);
}
}
void qmp_nbd_server_start(SocketAddress *addr, Error **errp)
{
if (server_fd != -1) {
error_setg(errp, "NBD server already running");
return;
}
server_fd = socket_listen(addr, errp);
if (server_fd != -1) {
qemu_set_fd_handler2(server_fd, NULL, nbd_accept, NULL, NULL);
}
}
/* Hook into the BlockDriverState notifiers to close the export when
* the file is closed.
*/
typedef struct NBDCloseNotifier {
Notifier n;
NBDExport *exp;
QTAILQ_ENTRY(NBDCloseNotifier) next;
} NBDCloseNotifier;
static QTAILQ_HEAD(, NBDCloseNotifier) close_notifiers =
QTAILQ_HEAD_INITIALIZER(close_notifiers);
static void nbd_close_notifier(Notifier *n, void *data)
{
NBDCloseNotifier *cn = DO_UPCAST(NBDCloseNotifier, n, n);
notifier_remove(&cn->n);
QTAILQ_REMOVE(&close_notifiers, cn, next);
nbd_export_close(cn->exp);
nbd_export_put(cn->exp);
g_free(cn);
}
static void nbd_server_put_ref(NBDExport *exp)
{
BlockDriverState *bs = nbd_export_get_blockdev(exp);
drive_put_ref(drive_get_by_blockdev(bs));
}
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
Error **errp)
{
BlockDriverState *bs;
NBDExport *exp;
NBDCloseNotifier *n;
if (nbd_export_find(device)) {
error_setg(errp, "NBD server already exporting device '%s'", device);
return;
}
bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
}
exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
nbd_server_put_ref);
nbd_export_set_name(exp, device);
drive_get_ref(drive_get_by_blockdev(bs));
n = g_malloc0(sizeof(NBDCloseNotifier));
n->n.notify = nbd_close_notifier;
n->exp = exp;
bdrv_add_close_notifier(bs, &n->n);
QTAILQ_INSERT_TAIL(&close_notifiers, n, next);
}
void qmp_nbd_server_stop(Error **errp)
{
while (!QTAILQ_EMPTY(&close_notifiers)) {
NBDCloseNotifier *cn = QTAILQ_FIRST(&close_notifiers);
nbd_close_notifier(&cn->n, nbd_export_get_blockdev(cn->exp));
}
qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
close(server_fd);
server_fd = -1;
}
+1 -1
View File
@@ -378,7 +378,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
/* vnc.c */
void vnc_display_init(DisplayState *ds);
void vnc_display_close(DisplayState *ds);
int vnc_display_open(DisplayState *ds, const char *display);
void vnc_display_open(DisplayState *ds, const char *display, Error **errp);
void vnc_display_add_client(DisplayState *ds, int csock, int skipauth);
int vnc_display_disable_login(DisplayState *ds);
char *vnc_display_local_addr(DisplayState *ds);
+28
View File
@@ -43,6 +43,34 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
*errp = err;
}
void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
const char *fmt, ...)
{
Error *err;
char *msg1;
va_list ap;
if (errp == NULL) {
return;
}
assert(*errp == NULL);
err = g_malloc0(sizeof(*err));
va_start(ap, fmt);
msg1 = g_strdup_vprintf(fmt, ap);
if (os_errno != 0) {
err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno));
g_free(msg1);
} else {
err->msg = msg1;
}
va_end(ap);
err->err_class = err_class;
*errp = err;
}
Error *error_copy(const Error *err)
{
Error *err_new;
+9
View File
@@ -29,11 +29,20 @@ typedef struct Error Error;
*/
void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4);
/**
* Set an indirect pointer to an error given a ErrorClass value and a
* printf-style human message, followed by a strerror() string if
* @os_error is not zero.
*/
void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
/**
* Same as error_set(), but sets a generic error
*/
#define error_setg(err, fmt, ...) \
error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
#define error_setg_errno(err, os_error, fmt, ...) \
error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
/**
* Returns true if an indirect pointer to an error is pointing to a valid
+7 -19
View File
@@ -60,22 +60,18 @@ static int exec_close(MigrationState *s)
return ret;
}
int exec_start_outgoing_migration(MigrationState *s, const char *command)
void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
FILE *f;
f = popen(command, "w");
if (f == NULL) {
DPRINTF("Unable to popen exec target\n");
goto err_after_popen;
error_setg_errno(errp, errno, "failed to popen the migration target");
return;
}
s->fd = fileno(f);
if (s->fd == -1) {
DPRINTF("Unable to retrieve file descriptor for popen'd handle\n");
goto err_after_open;
}
assert(s->fd != -1);
socket_set_nonblock(s->fd);
s->opaque = qemu_popen(f, "w");
@@ -85,12 +81,6 @@ int exec_start_outgoing_migration(MigrationState *s, const char *command)
s->write = file_write;
migrate_fd_connect(s);
return 0;
err_after_open:
pclose(f);
err_after_popen:
return -1;
}
static void exec_accept_incoming_migration(void *opaque)
@@ -102,19 +92,17 @@ static void exec_accept_incoming_migration(void *opaque)
qemu_fclose(f);
}
int exec_start_incoming_migration(const char *command)
void exec_start_incoming_migration(const char *command, Error **errp)
{
QEMUFile *f;
DPRINTF("Attempting to start an incoming migration\n");
f = qemu_popen_cmd(command, "r");
if(f == NULL) {
DPRINTF("Unable to apply qemu wrapper to popen file\n");
return -errno;
error_setg_errno(errp, errno, "failed to popen the migration source");
return;
}
qemu_set_fd_handler2(qemu_stdio_fd(f), NULL,
exec_accept_incoming_migration, NULL, f);
return 0;
}
+7 -20
View File
@@ -73,30 +73,19 @@ static int fd_close(MigrationState *s)
return 0;
}
int fd_start_outgoing_migration(MigrationState *s, const char *fdname)
void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
{
s->fd = monitor_get_fd(cur_mon, fdname, NULL);
s->fd = monitor_get_fd(cur_mon, fdname, errp);
if (s->fd == -1) {
DPRINTF("fd_migration: invalid file descriptor identifier\n");
goto err_after_get_fd;
}
if (fcntl(s->fd, F_SETFL, O_NONBLOCK) == -1) {
DPRINTF("Unable to set nonblocking mode on file descriptor\n");
goto err_after_open;
return;
}
fcntl(s->fd, F_SETFL, O_NONBLOCK);
s->get_error = fd_errno;
s->write = fd_write;
s->close = fd_close;
migrate_fd_connect(s);
return 0;
err_after_open:
close(s->fd);
err_after_get_fd:
return -1;
}
static void fd_accept_incoming_migration(void *opaque)
@@ -108,7 +97,7 @@ static void fd_accept_incoming_migration(void *opaque)
qemu_fclose(f);
}
int fd_start_incoming_migration(const char *infd)
void fd_start_incoming_migration(const char *infd, Error **errp)
{
int fd;
QEMUFile *f;
@@ -118,11 +107,9 @@ int fd_start_incoming_migration(const char *infd)
fd = strtol(infd, NULL, 0);
f = qemu_fdopen(fd, "rb");
if(f == NULL) {
DPRINTF("Unable to apply qemu wrapper to file descriptor\n");
return -errno;
error_setg_errno(errp, errno, "failed to open the source descriptor");
return;
}
qemu_set_fd_handler2(fd, NULL, fd_accept_incoming_migration, NULL, f);
return 0;
}
+4 -15
View File
@@ -68,21 +68,13 @@ static void tcp_wait_for_connect(int fd, void *opaque)
}
}
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
Error **errp)
void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp)
{
s->get_error = socket_errno;
s->write = socket_write;
s->close = tcp_close;
s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s,
errp);
if (error_is_set(errp)) {
migrate_fd_error(s);
return -1;
}
return 0;
s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
}
static void tcp_accept_incoming_migration(void *opaque)
@@ -119,18 +111,15 @@ out2:
close(s);
}
int tcp_start_incoming_migration(const char *host_port, Error **errp)
void tcp_start_incoming_migration(const char *host_port, Error **errp)
{
int s;
s = inet_listen(host_port, NULL, 256, SOCK_STREAM, 0, errp);
if (s < 0) {
return -1;
return;
}
qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
(void *)(intptr_t)s);
return 0;
}
+13 -82
View File
@@ -53,69 +53,28 @@ static int unix_close(MigrationState *s)
return r;
}
static void unix_wait_for_connect(void *opaque)
static void unix_wait_for_connect(int fd, void *opaque)
{
MigrationState *s = opaque;
int val, ret;
socklen_t valsize = sizeof(val);
DPRINTF("connect completed\n");
do {
ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
} while (ret == -1 && errno == EINTR);
if (ret < 0) {
if (fd < 0) {
DPRINTF("migrate connect error\n");
s->fd = -1;
migrate_fd_error(s);
return;
}
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
if (val == 0)
} else {
DPRINTF("migrate connect success\n");
s->fd = fd;
migrate_fd_connect(s);
else {
DPRINTF("error connecting %d\n", val);
migrate_fd_error(s);
}
}
int unix_start_outgoing_migration(MigrationState *s, const char *path)
void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp)
{
struct sockaddr_un addr;
int ret;
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
s->get_error = unix_errno;
s->write = unix_write;
s->close = unix_close;
s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
if (s->fd == -1) {
DPRINTF("Unable to open socket");
return -errno;
}
socket_set_nonblock(s->fd);
do {
ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) {
ret = -errno;
}
if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s);
return 0;
}
} while (ret == -EINTR);
if (ret < 0) {
DPRINTF("connect failed\n");
migrate_fd_error(s);
return ret;
}
migrate_fd_connect(s);
return 0;
s->fd = unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
}
static void unix_accept_incoming_migration(void *opaque)
@@ -152,43 +111,15 @@ out2:
close(s);
}
int unix_start_incoming_migration(const char *path)
void unix_start_incoming_migration(const char *path, Error **errp)
{
struct sockaddr_un addr;
int s;
int ret;
DPRINTF("Attempting to start an incoming migration\n");
s = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
if (s == -1) {
fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno));
return -errno;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
unlink(addr.sun_path);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
ret = -errno;
fprintf(stderr, "bind(unix:%s): %s\n", addr.sun_path, strerror(errno));
goto err;
}
if (listen(s, 1) == -1) {
fprintf(stderr, "listen(unix:%s): %s\n", addr.sun_path,
strerror(errno));
ret = -errno;
goto err;
s = unix_listen(path, NULL, 0, errp);
if (s < 0) {
return;
}
qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL,
(void *)(intptr_t)s);
return 0;
err:
close(s);
return ret;
}
+14 -20
View File
@@ -64,26 +64,23 @@ MigrationState *migrate_get_current(void)
return &current_migration;
}
int qemu_start_incoming_migration(const char *uri, Error **errp)
void qemu_start_incoming_migration(const char *uri, Error **errp)
{
const char *p;
int ret;
if (strstart(uri, "tcp:", &p))
ret = tcp_start_incoming_migration(p, errp);
tcp_start_incoming_migration(p, errp);
#if !defined(WIN32)
else if (strstart(uri, "exec:", &p))
ret = exec_start_incoming_migration(p);
exec_start_incoming_migration(p, errp);
else if (strstart(uri, "unix:", &p))
ret = unix_start_incoming_migration(p);
unix_start_incoming_migration(p, errp);
else if (strstart(uri, "fd:", &p))
ret = fd_start_incoming_migration(p);
fd_start_incoming_migration(p, errp);
#endif
else {
fprintf(stderr, "unknown migration protocol: %s\n", uri);
ret = -EPROTONOSUPPORT;
error_setg(errp, "unknown migration protocol: %s\n", uri);
}
return ret;
}
void process_incoming_migration(QEMUFile *f)
@@ -483,10 +480,10 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
bool has_inc, bool inc, bool has_detach, bool detach,
Error **errp)
{
Error *local_err = NULL;
MigrationState *s = migrate_get_current();
MigrationParams params;
const char *p;
int ret;
params.blk = blk;
params.shared = inc;
@@ -508,26 +505,23 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
s = migrate_init(&params);
if (strstart(uri, "tcp:", &p)) {
ret = tcp_start_outgoing_migration(s, p, errp);
tcp_start_outgoing_migration(s, p, &local_err);
#if !defined(WIN32)
} else if (strstart(uri, "exec:", &p)) {
ret = exec_start_outgoing_migration(s, p);
exec_start_outgoing_migration(s, p, &local_err);
} else if (strstart(uri, "unix:", &p)) {
ret = unix_start_outgoing_migration(s, p);
unix_start_outgoing_migration(s, p, &local_err);
} else if (strstart(uri, "fd:", &p)) {
ret = fd_start_outgoing_migration(s, p);
fd_start_outgoing_migration(s, p, &local_err);
#endif
} else {
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
return;
}
if (ret < 0) {
if (!error_is_set(errp)) {
DPRINTF("migration failed: %s\n", strerror(-ret));
/* FIXME: we should return meaningful errors */
error_set(errp, QERR_UNDEFINED_ERROR);
}
if (local_err) {
migrate_fd_error(s);
error_propagate(errp, local_err);
return;
}
+9 -10
View File
@@ -49,7 +49,7 @@ struct MigrationState
void process_incoming_migration(QEMUFile *f);
int qemu_start_incoming_migration(const char *uri, Error **errp);
void qemu_start_incoming_migration(const char *uri, Error **errp);
uint64_t migrate_max_downtime(void);
@@ -57,22 +57,21 @@ void do_info_migrate_print(Monitor *mon, const QObject *data);
void do_info_migrate(Monitor *mon, QObject **ret_data);
int exec_start_incoming_migration(const char *host_port);
void exec_start_incoming_migration(const char *host_port, Error **errp);
int exec_start_outgoing_migration(MigrationState *s, const char *host_port);
void exec_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp);
int tcp_start_incoming_migration(const char *host_port, Error **errp);
void tcp_start_incoming_migration(const char *host_port, Error **errp);
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
Error **errp);
void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp);
int unix_start_incoming_migration(const char *path);
void unix_start_incoming_migration(const char *path, Error **errp);
int unix_start_outgoing_migration(MigrationState *s, const char *path);
void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp);
int fd_start_incoming_migration(const char *path);
void fd_start_incoming_migration(const char *path, Error **errp);
int fd_start_outgoing_migration(MigrationState *s, const char *fdname);
void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp);
void migrate_fd_error(MigrationState *s);
+31 -8
View File
@@ -208,7 +208,14 @@ int tcp_socket_outgoing(const char *address, uint16_t port)
int tcp_socket_outgoing_spec(const char *address_and_port)
{
return inet_connect(address_and_port, NULL);
Error *local_err = NULL;
int fd = inet_connect(address_and_port, &local_err);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
}
return fd;
}
int tcp_socket_incoming(const char *address, uint16_t port)
@@ -220,22 +227,38 @@ int tcp_socket_incoming(const char *address, uint16_t port)
int tcp_socket_incoming_spec(const char *address_and_port)
{
char *ostr = NULL;
int olen = 0;
return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0, NULL);
Error *local_err = NULL;
int fd = inet_listen(address_and_port, NULL, 0, SOCK_STREAM, 0, &local_err);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
}
return fd;
}
int unix_socket_incoming(const char *path)
{
char *ostr = NULL;
int olen = 0;
Error *local_err = NULL;
int fd = unix_listen(path, NULL, 0, &local_err);
return unix_listen(path, ostr, olen);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
}
return fd;
}
int unix_socket_outgoing(const char *path)
{
return unix_connect(path);
Error *local_err = NULL;
int fd = unix_connect(path, &local_err);
if (local_err != NULL) {
qerror_report_err(local_err);
error_free(local_err);
}
return fd;
}
/* Basic flow for negotiation
+96
View File
@@ -2518,6 +2518,59 @@
'id': 'str',
'opts': 'NetClientOptions' } }
##
# @InetSocketAddress
#
# Captures a socket address or address range in the Internet namespace.
#
# @host: host part of the address
#
# @port: port part of the address, or lowest port if @to is present
#
# @to: highest port to try
#
# @ipv4: whether to accept IPv4 addresses, default try both IPv4 and IPv6
# #optional
#
# @ipv6: whether to accept IPv6 addresses, default try both IPv4 and IPv6
# #optional
#
# Since 1.3
##
{ 'type': 'InetSocketAddress',
'data': {
'host': 'str',
'port': 'str',
'*to': 'uint16',
'*ipv4': 'bool',
'*ipv6': 'bool' } }
##
# @UnixSocketAddress
#
# Captures a socket address in the local ("Unix socket") namespace.
#
# @path: filesystem path to use
#
# Since 1.3
##
{ 'type': 'UnixSocketAddress',
'data': {
'path': 'str' } }
##
# @SocketAddress
#
# Captures the address of a socket, which could also be a named file descriptor
#
# Since 1.3
##
{ 'union': 'SocketAddress',
'data': {
'inet': 'InetSocketAddress',
'unix': 'UnixSocketAddress',
'fd': 'String' } }
##
# @getfd:
#
@@ -2810,3 +2863,46 @@
# Since: 0.14.0
##
{ 'command': 'screendump', 'data': {'filename': 'str'} }
##
# @nbd-server-start:
#
# Start an NBD server listening on the given host and port. Block
# devices can then be exported using @nbd-server-add. The NBD
# server will present them as named exports; for example, another
# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
#
# @addr: Address on which to listen.
#
# Returns: error if the server is already running.
#
# Since: 1.3.0
##
{ 'command': 'nbd-server-start',
'data': { 'addr': 'SocketAddress' } }
##
# @nbd-server-add:
#
# Export a device to QEMU's embedded NBD server.
#
# @device: Block device to be exported
#
# @writable: Whether clients should be able to write to the device via the
# NBD connection (default false). #optional
#
# Returns: error if the device is already marked for export.
#
# Since: 1.3.0
##
{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool'} }
##
# @nbd-server-stop:
#
# Stop QEMU's embedded NBD server, and unregister all devices previously
# added via @nbd-server-add.
#
# Since: 1.3.0
##
{ 'command': 'nbd-server-stop' }
+17 -7
View File
@@ -2097,14 +2097,14 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
{
CharDriverState *chr = NULL;
NetCharDriver *s = NULL;
Error *local_err = NULL;
int fd = -1;
chr = g_malloc0(sizeof(CharDriverState));
s = g_malloc0(sizeof(NetCharDriver));
fd = inet_dgram_opts(opts);
fd = inet_dgram_opts(opts, &local_err);
if (fd < 0) {
fprintf(stderr, "inet_dgram_opts failed\n");
goto return_err;
}
@@ -2118,6 +2118,10 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
return chr;
return_err:
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
}
g_free(chr);
g_free(s);
if (fd >= 0) {
@@ -2428,6 +2432,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
{
CharDriverState *chr = NULL;
TCPCharDriver *s = NULL;
Error *local_err = NULL;
int fd = -1;
int is_listen;
int is_waitconnect;
@@ -2448,15 +2453,15 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
if (is_unix) {
if (is_listen) {
fd = unix_listen_opts(opts);
fd = unix_listen_opts(opts, &local_err);
} else {
fd = unix_connect_opts(opts);
fd = unix_connect_opts(opts, &local_err, NULL, NULL);
}
} else {
if (is_listen) {
fd = inet_listen_opts(opts, 0, NULL);
fd = inet_listen_opts(opts, 0, &local_err);
} else {
fd = inet_connect_opts(opts, NULL, NULL, NULL);
fd = inet_connect_opts(opts, &local_err, NULL, NULL);
}
}
if (fd < 0) {
@@ -2517,8 +2522,13 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
return chr;
fail:
if (fd >= 0)
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
}
if (fd >= 0) {
closesocket(fd);
}
g_free(s);
g_free(chr);
return NULL;
+283 -143
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -38,6 +38,12 @@ const char *qemu_get_vm_name(void)
Monitor *cur_mon;
int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
{
error_setg(errp, "only QEMU supports file descriptor passing");
return -1;
}
void vm_stop(RunState state)
{
abort();

Some files were not shown because too many files have changed in this diff Show More