Annotation of qemu/migration-tcp.c, revision 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