Annotation of qemu/migration-tcp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU live migration
                      3:  *
                      4:  * Copyright IBM, Corp. 2008
                      5:  *
                      6:  * Authors:
                      7:  *  Anthony Liguori   <aliguori@us.ibm.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:  *
                     12:  */
                     13: 
                     14: #include "qemu-common.h"
                     15: #include "qemu_socket.h"
                     16: #include "migration.h"
                     17: #include "qemu-char.h"
                     18: #include "sysemu.h"
                     19: #include "console.h"
                     20: #include "buffered_file.h"
                     21: #include "block.h"
                     22: 
                     23: //#define DEBUG_MIGRATION_TCP
                     24: 
                     25: #ifdef DEBUG_MIGRATION_TCP
                     26: #define dprintf(fmt, ...) \
                     27:     do { printf("migration-tcp: " fmt, ## __VA_ARGS__); } while (0)
                     28: #else
                     29: #define dprintf(fmt, ...) \
                     30:     do { } while (0)
                     31: #endif
                     32: 
                     33: static int socket_errno(FdMigrationState *s)
                     34: {
                     35:     return socket_error();
                     36: }
                     37: 
                     38: static int socket_write(FdMigrationState *s, const void * buf, size_t size)
                     39: {
                     40:     return send(s->fd, buf, size, 0);
                     41: }
                     42: 
                     43: static int tcp_close(FdMigrationState *s)
                     44: {
                     45:     dprintf("tcp_close\n");
                     46:     if (s->fd != -1) {
                     47:         close(s->fd);
                     48:         s->fd = -1;
                     49:     }
                     50:     return 0;
                     51: }
                     52: 
                     53: 
                     54: static void tcp_wait_for_connect(void *opaque)
                     55: {
                     56:     FdMigrationState *s = opaque;
                     57:     int val, ret;
                     58:     socklen_t valsize = sizeof(val);
                     59: 
                     60:     dprintf("connect completed\n");
                     61:     do {
                     62:         ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
                     63:     } while (ret == -1 && (s->get_error(s)) == EINTR);
                     64: 
                     65:     if (ret < 0) {
                     66:         migrate_fd_error(s);
                     67:         return;
                     68:     }
                     69: 
                     70:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
                     71: 
                     72:     if (val == 0)
                     73:         migrate_fd_connect(s);
                     74:     else {
                     75:         dprintf("error connecting %d\n", val);
                     76:         migrate_fd_error(s);
                     77:     }
                     78: }
                     79: 
                     80: MigrationState *tcp_start_outgoing_migration(const char *host_port,
                     81:                                              int64_t bandwidth_limit,
                     82:                                              int async)
                     83: {
                     84:     struct sockaddr_in addr;
                     85:     FdMigrationState *s;
                     86:     int ret;
                     87: 
                     88:     if (parse_host_port(&addr, host_port) < 0)
                     89:         return NULL;
                     90: 
                     91:     s = qemu_mallocz(sizeof(*s));
                     92: 
                     93:     s->get_error = socket_errno;
                     94:     s->write = socket_write;
                     95:     s->close = tcp_close;
                     96:     s->mig_state.cancel = migrate_fd_cancel;
                     97:     s->mig_state.get_status = migrate_fd_get_status;
                     98:     s->mig_state.release = migrate_fd_release;
                     99: 
                    100:     s->state = MIG_STATE_ACTIVE;
                    101:     s->detach = !async;
                    102:     s->bandwidth_limit = bandwidth_limit;
                    103:     s->fd = socket(PF_INET, SOCK_STREAM, 0);
                    104:     if (s->fd == -1) {
                    105:         qemu_free(s);
                    106:         return NULL;
                    107:     }
                    108: 
                    109:     socket_set_nonblock(s->fd);
                    110: 
                    111:     if (s->detach == 1) {
                    112:         dprintf("detaching from monitor\n");
                    113:         monitor_suspend();
                    114:         s->detach = 2;
                    115:     }
                    116: 
                    117:     do {
                    118:         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
                    119:         if (ret == -1)
                    120:             ret = -(s->get_error(s));
                    121: 
                    122:         if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
                    123:             qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
                    124:     } while (ret == -EINTR);
                    125: 
                    126:     if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
                    127:         dprintf("connect failed\n");
                    128:         close(s->fd);
                    129:         qemu_free(s);
                    130:         return NULL;
                    131:     } else if (ret >= 0)
                    132:         migrate_fd_connect(s);
                    133: 
                    134:     return &s->mig_state;
                    135: }
                    136: 
                    137: static void tcp_accept_incoming_migration(void *opaque)
                    138: {
                    139:     struct sockaddr_in addr;
                    140:     socklen_t addrlen = sizeof(addr);
                    141:     int s = (unsigned long)opaque;
                    142:     QEMUFile *f;
                    143:     int c, ret;
                    144: 
                    145:     do {
                    146:         c = accept(s, (struct sockaddr *)&addr, &addrlen);
                    147:     } while (c == -1 && socket_error() == EINTR);
                    148: 
                    149:     dprintf("accepted migration\n");
                    150: 
                    151:     if (c == -1) {
                    152:         fprintf(stderr, "could not accept migration connection\n");
                    153:         return;
                    154:     }
                    155: 
                    156:     f = qemu_fopen_socket(c);
                    157:     if (f == NULL) {
                    158:         fprintf(stderr, "could not qemu_fopen socket\n");
                    159:         goto out;
                    160:     }
                    161: 
                    162:     vm_stop(0); /* just in case */
                    163:     ret = qemu_loadvm_state(f);
                    164:     if (ret < 0) {
                    165:         fprintf(stderr, "load of migration failed\n");
                    166:         goto out_fopen;
                    167:     }
                    168:     qemu_announce_self();
                    169:     dprintf("successfully loaded vm state\n");
                    170: 
                    171:     /* we've successfully migrated, close the server socket */
                    172:     qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
                    173:     close(s);
                    174: 
                    175:     vm_start();
                    176: 
                    177: out_fopen:
                    178:     qemu_fclose(f);
                    179: out:
                    180:     close(c);
                    181: }
                    182: 
                    183: int tcp_start_incoming_migration(const char *host_port)
                    184: {
                    185:     struct sockaddr_in addr;
                    186:     int val;
                    187:     int s;
                    188: 
                    189:     if (parse_host_port(&addr, host_port) < 0) {
                    190:         fprintf(stderr, "invalid host/port combination: %s\n", host_port);
                    191:         return -EINVAL;
                    192:     }
                    193: 
                    194:     s = socket(PF_INET, SOCK_STREAM, 0);
                    195:     if (s == -1)
                    196:         return -socket_error();
                    197: 
                    198:     val = 1;
                    199:     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
                    200: 
                    201:     if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
                    202:         goto err;
                    203: 
                    204:     if (listen(s, 1) == -1)
                    205:         goto err;
                    206: 
                    207:     qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
                    208:                          (void *)(unsigned long)s);
                    209: 
                    210:     return 0;
                    211: 
                    212: err:
                    213:     close(s);
                    214:     return -socket_error();
                    215: }

unix.superglobalmegacorp.com