Commit e1a8c9b6 authored by Dr. David Alan Gilbert's avatar Dr. David Alan Gilbert Committed by Amit Shah
Browse files

socket shutdown



Add QEMUFile interface to allow a socket to be 'shut down' - i.e. any
reads/writes will fail (and any blocking read/write will be woken).

Signed-off-by: default avatarDr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: default avatarAmit Shah <amit.shah@redhat.com>
Signed-off-by: default avatarAmit Shah <amit.shah@redhat.com>
parent 8580b064
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -84,6 +84,14 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque,
                               size_t size,
                               int *bytes_sent);

/*
 * Stop any read or write (depending on flags) on the underlying
 * transport on the QEMUFile.
 * Existing blocking reads/writes must be woken
 * Returns 0 on success, -err on error
 */
typedef int (QEMUFileShutdownFunc)(void *opaque, bool rd, bool wr);

typedef struct QEMUFileOps {
    QEMUFilePutBufferFunc *put_buffer;
    QEMUFileGetBufferFunc *get_buffer;
@@ -94,6 +102,7 @@ typedef struct QEMUFileOps {
    QEMURamHookFunc *after_ram_iterate;
    QEMURamHookFunc *hook_ram_load;
    QEMURamSaveFunc *save_page;
    QEMUFileShutdownFunc *shut_down;
} QEMUFileOps;

struct QEMUSizedBuffer {
@@ -177,6 +186,7 @@ void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
int64_t qemu_file_get_rate_limit(QEMUFile *f);
int qemu_file_get_error(QEMUFile *f);
void qemu_file_set_error(QEMUFile *f, int ret);
int qemu_file_shutdown(QEMUFile *f);
void qemu_fflush(QEMUFile *f);

static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
+7 −0
Original line number Diff line number Diff line
@@ -44,6 +44,13 @@ int socket_set_fast_reuse(int fd);
int send_all(int fd, const void *buf, int len1);
int recv_all(int fd, void *buf, int len1, bool single_read);

#ifdef WIN32
/* Windows has different names for the same constants with the same values */
#define SHUT_RD   0
#define SHUT_WR   1
#define SHUT_RDWR 2
#endif

/* callback function for nonblocking connect
 * valid fd on success, negative error code on failure
 */
+19 −4
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "qemu/sockets.h"
#include "block/coroutine.h"
#include "migration/qemu-file.h"
#include "migration/qemu-file-internal.h"

typedef struct QEMUFileSocket {
    int fd;
@@ -84,6 +85,17 @@ static int socket_close(void *opaque)
    return 0;
}

static int socket_shutdown(void *opaque, bool rd, bool wr)
{
    QEMUFileSocket *s = opaque;

    if (shutdown(s->fd, rd ? (wr ? SHUT_RDWR : SHUT_RD) : SHUT_WR)) {
        return -errno;
    } else {
        return 0;
    }
}

static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
                                  int64_t pos)
{
@@ -194,13 +206,16 @@ QEMUFile *qemu_fdopen(int fd, const char *mode)
static const QEMUFileOps socket_read_ops = {
    .get_fd     = socket_get_fd,
    .get_buffer = socket_get_buffer,
    .close =      socket_close
    .close      = socket_close,
    .shut_down  = socket_shutdown

};

static const QEMUFileOps socket_write_ops = {
    .get_fd        = socket_get_fd,
    .writev_buffer = socket_writev_buffer,
    .close =      socket_close
    .close         = socket_close,
    .shut_down     = socket_shutdown
};

QEMUFile *qemu_fopen_socket(int fd, const char *mode)
+12 −0
Original line number Diff line number Diff line
@@ -30,6 +30,18 @@
#include "migration/qemu-file-internal.h"
#include "trace.h"

/*
 * Stop a file from being read/written - not all backing files can do this
 * typically only sockets can.
 */
int qemu_file_shutdown(QEMUFile *f)
{
    if (!f->ops->shut_down) {
        return -ENOSYS;
    }
    return f->ops->shut_down(f->opaque, true, true);
}

bool qemu_file_mode_is_not_valid(const char *mode)
{
    if (mode == NULL ||