Annotation of qemu/migration-unix.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  * QEMU live migration via Unix Domain Sockets
                      3:  *
                      4:  * Copyright Red Hat, Inc. 2009
                      5:  *
                      6:  * Authors:
                      7:  *  Chris Lalancette <clalance@redhat.com>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU GPL, version 2.  See
                     10:  * the COPYING file in the top-level directory.
                     11:  *
1.1.1.5 ! root       12:  * Contributions after 2012-01-13 are licensed under the terms of the
        !            13:  * GNU GPL, version 2 or (at your option) any later version.
1.1       root       14:  */
                     15: 
                     16: #include "qemu-common.h"
                     17: #include "qemu_socket.h"
                     18: #include "migration.h"
                     19: #include "qemu-char.h"
                     20: #include "buffered_file.h"
                     21: #include "block.h"
                     22: 
                     23: //#define DEBUG_MIGRATION_UNIX
                     24: 
                     25: #ifdef DEBUG_MIGRATION_UNIX
1.1.1.2   root       26: #define DPRINTF(fmt, ...) \
1.1       root       27:     do { printf("migration-unix: " fmt, ## __VA_ARGS__); } while (0)
                     28: #else
1.1.1.2   root       29: #define DPRINTF(fmt, ...) \
1.1       root       30:     do { } while (0)
                     31: #endif
                     32: 
1.1.1.4   root       33: static int unix_errno(MigrationState *s)
1.1       root       34: {
                     35:     return errno;
                     36: }
                     37: 
1.1.1.4   root       38: static int unix_write(MigrationState *s, const void * buf, size_t size)
1.1       root       39: {
                     40:     return write(s->fd, buf, size);
                     41: }
                     42: 
1.1.1.4   root       43: static int unix_close(MigrationState *s)
1.1       root       44: {
1.1.1.5 ! root       45:     int r = 0;
1.1.1.2   root       46:     DPRINTF("unix_close\n");
1.1       root       47:     if (s->fd != -1) {
1.1.1.5 ! root       48:         if (close(s->fd) < 0) {
        !            49:             r = -errno;
        !            50:         }
1.1       root       51:         s->fd = -1;
                     52:     }
1.1.1.5 ! root       53:     return r;
1.1       root       54: }
                     55: 
                     56: static void unix_wait_for_connect(void *opaque)
                     57: {
1.1.1.4   root       58:     MigrationState *s = opaque;
1.1       root       59:     int val, ret;
                     60:     socklen_t valsize = sizeof(val);
                     61: 
1.1.1.2   root       62:     DPRINTF("connect completed\n");
1.1       root       63:     do {
                     64:         ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
1.1.1.4   root       65:     } while (ret == -1 && errno == EINTR);
1.1       root       66: 
                     67:     if (ret < 0) {
                     68:         migrate_fd_error(s);
                     69:         return;
                     70:     }
                     71: 
                     72:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
                     73: 
                     74:     if (val == 0)
                     75:         migrate_fd_connect(s);
                     76:     else {
1.1.1.2   root       77:         DPRINTF("error connecting %d\n", val);
1.1       root       78:         migrate_fd_error(s);
                     79:     }
                     80: }
                     81: 
1.1.1.4   root       82: int unix_start_outgoing_migration(MigrationState *s, const char *path)
1.1       root       83: {
                     84:     struct sockaddr_un addr;
                     85:     int ret;
                     86: 
                     87:     addr.sun_family = AF_UNIX;
                     88:     snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
                     89:     s->get_error = unix_errno;
                     90:     s->write = unix_write;
                     91:     s->close = unix_close;
1.1.1.4   root       92: 
1.1       root       93:     s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
1.1.1.4   root       94:     if (s->fd == -1) {
1.1.1.2   root       95:         DPRINTF("Unable to open socket");
1.1.1.4   root       96:         return -errno;
1.1       root       97:     }
                     98: 
                     99:     socket_set_nonblock(s->fd);
                    100: 
                    101:     do {
                    102:         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
1.1.1.4   root      103:         if (ret == -1) {
                    104:             ret = -errno;
                    105:         }
                    106:         if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
1.1       root      107:            qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s);
1.1.1.4   root      108:             return 0;
                    109:         }
1.1       root      110:     } while (ret == -EINTR);
                    111: 
1.1.1.4   root      112:     if (ret < 0) {
1.1.1.2   root      113:         DPRINTF("connect failed\n");
1.1.1.4   root      114:         migrate_fd_error(s);
                    115:         return ret;
1.1       root      116:     }
1.1.1.4   root      117:     migrate_fd_connect(s);
                    118:     return 0;
1.1       root      119: }
                    120: 
                    121: static void unix_accept_incoming_migration(void *opaque)
                    122: {
                    123:     struct sockaddr_un addr;
                    124:     socklen_t addrlen = sizeof(addr);
1.1.1.3   root      125:     int s = (intptr_t)opaque;
1.1       root      126:     QEMUFile *f;
1.1.1.2   root      127:     int c;
1.1       root      128: 
                    129:     do {
                    130:         c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
1.1.1.4   root      131:     } while (c == -1 && errno == EINTR);
1.1       root      132: 
1.1.1.2   root      133:     DPRINTF("accepted migration\n");
1.1       root      134: 
                    135:     if (c == -1) {
                    136:         fprintf(stderr, "could not accept migration connection\n");
1.1.1.4   root      137:         goto out2;
1.1       root      138:     }
                    139: 
                    140:     f = qemu_fopen_socket(c);
                    141:     if (f == NULL) {
                    142:         fprintf(stderr, "could not qemu_fopen socket\n");
                    143:         goto out;
                    144:     }
                    145: 
1.1.1.2   root      146:     process_incoming_migration(f);
1.1       root      147:     qemu_fclose(f);
                    148: out:
1.1.1.4   root      149:     close(c);
                    150: out2:
1.1.1.2   root      151:     qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
                    152:     close(s);
1.1       root      153: }
                    154: 
                    155: int unix_start_incoming_migration(const char *path)
                    156: {
1.1.1.4   root      157:     struct sockaddr_un addr;
                    158:     int s;
                    159:     int ret;
1.1       root      160: 
1.1.1.2   root      161:     DPRINTF("Attempting to start an incoming migration\n");
1.1       root      162: 
1.1.1.4   root      163:     s = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
                    164:     if (s == -1) {
1.1       root      165:         fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno));
1.1.1.4   root      166:         return -errno;
1.1       root      167:     }
                    168: 
1.1.1.4   root      169:     memset(&addr, 0, sizeof(addr));
                    170:     addr.sun_family = AF_UNIX;
                    171:     snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
1.1       root      172: 
1.1.1.4   root      173:     unlink(addr.sun_path);
                    174:     if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
                    175:         ret = -errno;
                    176:         fprintf(stderr, "bind(unix:%s): %s\n", addr.sun_path, strerror(errno));
1.1       root      177:         goto err;
                    178:     }
1.1.1.4   root      179:     if (listen(s, 1) == -1) {
                    180:         fprintf(stderr, "listen(unix:%s): %s\n", addr.sun_path,
                    181:                 strerror(errno));
                    182:         ret = -errno;
1.1       root      183:         goto err;
                    184:     }
                    185: 
1.1.1.4   root      186:     qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL,
                    187:                          (void *)(intptr_t)s);
1.1       root      188: 
                    189:     return 0;
                    190: 
                    191: err:
1.1.1.4   root      192:     close(s);
                    193:     return ret;
1.1       root      194: }

unix.superglobalmegacorp.com