symbian-qemu-0.9.1-12/qemu-symbian-svp/migration.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 "migration.h"
       
    16 #include "console.h"
       
    17 #include "buffered_file.h"
       
    18 #include "sysemu.h"
       
    19 #include "block.h"
       
    20 #include "qemu_socket.h"
       
    21 
       
    22 //#define DEBUG_MIGRATION
       
    23 
       
    24 #ifdef DEBUG_MIGRATION
       
    25 #define dprintf(fmt, ...) \
       
    26     do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
       
    27 #else
       
    28 #define dprintf(fmt, ...) \
       
    29     do { } while (0)
       
    30 #endif
       
    31 
       
    32 /* Migration speed throttling */
       
    33 static uint32_t max_throttle = (32 << 20);
       
    34 
       
    35 static MigrationState *current_migration;
       
    36 
       
    37 void qemu_start_incoming_migration(const char *uri)
       
    38 {
       
    39     const char *p;
       
    40 
       
    41     if (strstart(uri, "tcp:", &p))
       
    42         tcp_start_incoming_migration(p);
       
    43 #if !defined(WIN32)
       
    44     else if (strstart(uri, "exec:", &p))
       
    45         exec_start_incoming_migration(p);
       
    46 #endif
       
    47     else
       
    48         fprintf(stderr, "unknown migration protocol: %s\n", uri);
       
    49 }
       
    50 
       
    51 void do_migrate(int detach, const char *uri)
       
    52 {
       
    53     MigrationState *s = NULL;
       
    54     const char *p;
       
    55 
       
    56     if (strstart(uri, "tcp:", &p))
       
    57         s = tcp_start_outgoing_migration(p, max_throttle, detach);
       
    58 #if !defined(WIN32)
       
    59     else if (strstart(uri, "exec:", &p))
       
    60         s = exec_start_outgoing_migration(p, max_throttle, detach);
       
    61 #endif
       
    62     else
       
    63         term_printf("unknown migration protocol: %s\n", uri);
       
    64 
       
    65     if (s == NULL)
       
    66         term_printf("migration failed\n");
       
    67     else {
       
    68         if (current_migration)
       
    69             current_migration->release(current_migration);
       
    70 
       
    71         current_migration = s;
       
    72     }
       
    73 }
       
    74 
       
    75 void do_migrate_cancel(void)
       
    76 {
       
    77     MigrationState *s = current_migration;
       
    78 
       
    79     if (s)
       
    80         s->cancel(s);
       
    81 }
       
    82 
       
    83 void do_migrate_set_speed(const char *value)
       
    84 {
       
    85     double d;
       
    86     char *ptr;
       
    87 
       
    88     d = strtod(value, &ptr);
       
    89     switch (*ptr) {
       
    90     case 'G': case 'g':
       
    91         d *= 1024;
       
    92     case 'M': case 'm':
       
    93         d *= 1024;
       
    94     case 'K': case 'k':
       
    95         d *= 1024;
       
    96     default:
       
    97         break;
       
    98     }
       
    99 
       
   100     max_throttle = (uint32_t)d;
       
   101 }
       
   102 
       
   103 void do_info_migrate(void)
       
   104 {
       
   105     MigrationState *s = current_migration;
       
   106     
       
   107     if (s) {
       
   108         term_printf("Migration status: ");
       
   109         switch (s->get_status(s)) {
       
   110         case MIG_STATE_ACTIVE:
       
   111             term_printf("active\n");
       
   112             break;
       
   113         case MIG_STATE_COMPLETED:
       
   114             term_printf("completed\n");
       
   115             break;
       
   116         case MIG_STATE_ERROR:
       
   117             term_printf("failed\n");
       
   118             break;
       
   119         case MIG_STATE_CANCELLED:
       
   120             term_printf("cancelled\n");
       
   121             break;
       
   122         }
       
   123     }
       
   124 }
       
   125 
       
   126 /* shared migration helpers */
       
   127 
       
   128 void migrate_fd_error(FdMigrationState *s)
       
   129 {
       
   130     dprintf("setting error state\n");
       
   131     s->state = MIG_STATE_ERROR;
       
   132     migrate_fd_cleanup(s);
       
   133 }
       
   134 
       
   135 void migrate_fd_cleanup(FdMigrationState *s)
       
   136 {
       
   137     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
       
   138 
       
   139     if (s->file) {
       
   140         dprintf("closing file\n");
       
   141         qemu_fclose(s->file);
       
   142     }
       
   143 
       
   144     if (s->fd != -1)
       
   145         close(s->fd);
       
   146 
       
   147     /* Don't resume monitor until we've flushed all of the buffers */
       
   148     if (s->detach == 2) {
       
   149         monitor_resume();
       
   150         s->detach = 0;
       
   151     }
       
   152 
       
   153     s->fd = -1;
       
   154 }
       
   155 
       
   156 void migrate_fd_put_notify(void *opaque)
       
   157 {
       
   158     FdMigrationState *s = opaque;
       
   159 
       
   160     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
       
   161     qemu_file_put_notify(s->file);
       
   162 }
       
   163 
       
   164 ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
       
   165 {
       
   166     FdMigrationState *s = opaque;
       
   167     ssize_t ret;
       
   168 
       
   169     do {
       
   170         ret = s->write(s, data, size);
       
   171     } while (ret == -1 && ((s->get_error(s)) == EINTR || (s->get_error(s)) == EWOULDBLOCK));
       
   172 
       
   173     if (ret == -1)
       
   174         ret = -(s->get_error(s));
       
   175 
       
   176     if (ret == -EAGAIN)
       
   177         qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
       
   178 
       
   179     return ret;
       
   180 }
       
   181 
       
   182 void migrate_fd_connect(FdMigrationState *s)
       
   183 {
       
   184     int ret;
       
   185 
       
   186     s->file = qemu_fopen_ops_buffered(s,
       
   187                                       s->bandwidth_limit,
       
   188                                       migrate_fd_put_buffer,
       
   189                                       migrate_fd_put_ready,
       
   190                                       migrate_fd_wait_for_unfreeze,
       
   191                                       migrate_fd_close);
       
   192 
       
   193     dprintf("beginning savevm\n");
       
   194     ret = qemu_savevm_state_begin(s->file);
       
   195     if (ret < 0) {
       
   196         dprintf("failed, %d\n", ret);
       
   197         migrate_fd_error(s);
       
   198         return;
       
   199     }
       
   200 
       
   201     migrate_fd_put_ready(s);
       
   202 }
       
   203 
       
   204 void migrate_fd_put_ready(void *opaque)
       
   205 {
       
   206     FdMigrationState *s = opaque;
       
   207 
       
   208     if (s->state != MIG_STATE_ACTIVE) {
       
   209         dprintf("put_ready returning because of non-active state\n");
       
   210         return;
       
   211     }
       
   212 
       
   213     dprintf("iterate\n");
       
   214     if (qemu_savevm_state_iterate(s->file) == 1) {
       
   215         dprintf("done iterating\n");
       
   216         vm_stop(0);
       
   217 
       
   218         bdrv_flush_all();
       
   219         qemu_savevm_state_complete(s->file);
       
   220         s->state = MIG_STATE_COMPLETED;
       
   221         migrate_fd_cleanup(s);
       
   222     }
       
   223 }
       
   224 
       
   225 int migrate_fd_get_status(MigrationState *mig_state)
       
   226 {
       
   227     FdMigrationState *s = migrate_to_fms(mig_state);
       
   228     return s->state;
       
   229 }
       
   230 
       
   231 void migrate_fd_cancel(MigrationState *mig_state)
       
   232 {
       
   233     FdMigrationState *s = migrate_to_fms(mig_state);
       
   234 
       
   235     if (s->state != MIG_STATE_ACTIVE)
       
   236         return;
       
   237 
       
   238     dprintf("cancelling migration\n");
       
   239 
       
   240     s->state = MIG_STATE_CANCELLED;
       
   241 
       
   242     migrate_fd_cleanup(s);
       
   243 }
       
   244 
       
   245 void migrate_fd_release(MigrationState *mig_state)
       
   246 {
       
   247     FdMigrationState *s = migrate_to_fms(mig_state);
       
   248 
       
   249     dprintf("releasing state\n");
       
   250    
       
   251     if (s->state == MIG_STATE_ACTIVE) {
       
   252         s->state = MIG_STATE_CANCELLED;
       
   253         migrate_fd_cleanup(s);
       
   254     }
       
   255     free(s);
       
   256 }
       
   257 
       
   258 void migrate_fd_wait_for_unfreeze(void *opaque)
       
   259 {
       
   260     FdMigrationState *s = opaque;
       
   261     int ret;
       
   262 
       
   263     dprintf("wait for unfreeze\n");
       
   264     if (s->state != MIG_STATE_ACTIVE)
       
   265         return;
       
   266 
       
   267     do {
       
   268         fd_set wfds;
       
   269 
       
   270         FD_ZERO(&wfds);
       
   271         FD_SET(s->fd, &wfds);
       
   272 
       
   273         ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
       
   274     } while (ret == -1 && (s->get_error(s)) == EINTR);
       
   275 }
       
   276 
       
   277 int migrate_fd_close(void *opaque)
       
   278 {
       
   279     FdMigrationState *s = opaque;
       
   280     return s->close(s);
       
   281 }