Skip to content

Commit

Permalink
socket shutdown
Browse files Browse the repository at this point in the history
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: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
  • Loading branch information
dagrh authored and Amit Shah committed Jan 16, 2015
1 parent 8580b06 commit e1a8c9b
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
10 changes: 10 additions & 0 deletions include/migration/qemu-file.h
Expand Up @@ -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;
Expand All @@ -94,6 +102,7 @@ typedef struct QEMUFileOps {
QEMURamHookFunc *after_ram_iterate;
QEMURamHookFunc *hook_ram_load;
QEMURamSaveFunc *save_page;
QEMUFileShutdownFunc *shut_down;
} QEMUFileOps;

struct QEMUSizedBuffer {
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions include/qemu/sockets.h
Expand Up @@ -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
*/
Expand Down
23 changes: 19 additions & 4 deletions migration/qemu-file-unix.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -192,15 +204,18 @@ QEMUFile *qemu_fdopen(int fd, const char *mode)
}

static const QEMUFileOps socket_read_ops = {
.get_fd = socket_get_fd,
.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,
.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)
Expand Down
12 changes: 12 additions & 0 deletions migration/qemu-file.c
Expand Up @@ -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 ||
Expand Down

0 comments on commit e1a8c9b

Please sign in to comment.