Diff for /qemu/savevm.c between versions 1.1.1.11 and 1.1.1.12

version 1.1.1.11, 2018/04/24 19:17:03 version 1.1.1.12, 2018/04/24 19:34:13
Line 83 Line 83
 #include "qemu-queue.h"  #include "qemu-queue.h"
 #include "qemu-timer.h"  #include "qemu-timer.h"
 #include "cpus.h"  #include "cpus.h"
   #include "memory.h"
   #include "qmp-commands.h"
   
 #define SELF_ANNOUNCE_ROUNDS 5  #define SELF_ANNOUNCE_ROUNDS 5
   
Line 235  static int stdio_pclose(void *opaque) Line 237  static int stdio_pclose(void *opaque)
     QEMUFileStdio *s = opaque;      QEMUFileStdio *s = opaque;
     int ret;      int ret;
     ret = pclose(s->stdio_file);      ret = pclose(s->stdio_file);
       if (ret == -1) {
           ret = -errno;
       }
     g_free(s);      g_free(s);
     return ret;      return ret;
 }  }
Line 242  static int stdio_pclose(void *opaque) Line 247  static int stdio_pclose(void *opaque)
 static int stdio_fclose(void *opaque)  static int stdio_fclose(void *opaque)
 {  {
     QEMUFileStdio *s = opaque;      QEMUFileStdio *s = opaque;
     fclose(s->stdio_file);      int ret = 0;
       if (fclose(s->stdio_file) == EOF) {
           ret = -errno;
       }
     g_free(s);      g_free(s);
     return 0;      return ret;
 }  }
   
 QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)  QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
Line 436  void qemu_file_set_error(QEMUFile *f, in Line 444  void qemu_file_set_error(QEMUFile *f, in
     f->last_error = ret;      f->last_error = ret;
 }  }
   
   /** Sets last_error conditionally
    *
    * Sets last_error only if ret is negative _and_ no error
    * was set before.
    */
   static void qemu_file_set_if_error(QEMUFile *f, int ret)
   {
       if (ret < 0 && !f->last_error) {
           qemu_file_set_error(f, ret);
       }
   }
   
   /** Flushes QEMUFile buffer
    *
    * In case of error, last_error is set.
    */
 void qemu_fflush(QEMUFile *f)  void qemu_fflush(QEMUFile *f)
 {  {
     if (!f->put_buffer)      if (!f->put_buffer)
Line 448  void qemu_fflush(QEMUFile *f) Line 472  void qemu_fflush(QEMUFile *f)
         if (len > 0)          if (len > 0)
             f->buf_offset += f->buf_index;              f->buf_offset += f->buf_index;
         else          else
             f->last_error = -EINVAL;              qemu_file_set_error(f, -EINVAL);
         f->buf_index = 0;          f->buf_index = 0;
     }      }
 }  }
Line 479  static void qemu_fill_buffer(QEMUFile *f Line 503  static void qemu_fill_buffer(QEMUFile *f
     } else if (len == 0) {      } else if (len == 0) {
         f->last_error = -EIO;          f->last_error = -EIO;
     } else if (len != -EAGAIN)      } else if (len != -EAGAIN)
         f->last_error = len;          qemu_file_set_error(f, len);
 }  }
   
 int qemu_fclose(QEMUFile *f)  /** Calls close function and set last_error if needed
    *
    * Internal function. qemu_fflush() must be called before this.
    *
    * Returns f->close() return value, or 0 if close function is not set.
    */
   static int qemu_close(QEMUFile *f)
 {  {
     int ret = 0;      int ret = 0;
     qemu_fflush(f);      if (f->close) {
     if (f->close)  
         ret = f->close(f->opaque);          ret = f->close(f->opaque);
           qemu_file_set_if_error(f, ret);
       }
       return ret;
   }
   
   /** Closes the file
    *
    * Returns negative error value if any error happened on previous operations or
    * while closing the file. Returns 0 or positive number on success.
    *
    * The meaning of return value on success depends on the specific backend
    * being used.
    */
   int qemu_fclose(QEMUFile *f)
   {
       int ret;
       qemu_fflush(f);
       ret = qemu_close(f);
       /* If any error was spotted before closing, we should report it
        * instead of the close() return value.
        */
       if (f->last_error) {
           ret = f->last_error;
       }
     g_free(f);      g_free(f);
     return ret;      return ret;
 }  }
Line 1125  typedef struct SaveStateEntry { Line 1178  typedef struct SaveStateEntry {
     void *opaque;      void *opaque;
     CompatEntry *compat;      CompatEntry *compat;
     int no_migrate;      int no_migrate;
       int is_ram;
 } SaveStateEntry;  } SaveStateEntry;
   
   
Line 1189  int register_savevm_live(DeviceState *de Line 1243  int register_savevm_live(DeviceState *de
     se->opaque = opaque;      se->opaque = opaque;
     se->vmsd = NULL;      se->vmsd = NULL;
     se->no_migrate = 0;      se->no_migrate = 0;
       /* if this is a live_savem then set is_ram */
       if (save_live_state != NULL) {
           se->is_ram = 1;
       }
   
     if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {      if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
         char *id = dev->parent_bus->info->get_dev_path(dev);          char *id = dev->parent_bus->info->get_dev_path(dev);
Line 1434  void vmstate_save_state(QEMUFile *f, con Line 1492  void vmstate_save_state(QEMUFile *f, con
                 n_elems = field->num;                  n_elems = field->num;
             } else if (field->flags & VMS_VARRAY_INT32) {              } else if (field->flags & VMS_VARRAY_INT32) {
                 n_elems = *(int32_t *)(opaque+field->num_offset);                  n_elems = *(int32_t *)(opaque+field->num_offset);
               } else if (field->flags & VMS_VARRAY_UINT32) {
                   n_elems = *(uint32_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT16) {              } else if (field->flags & VMS_VARRAY_UINT16) {
                 n_elems = *(uint16_t *)(opaque+field->num_offset);                  n_elems = *(uint16_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT8) {              } else if (field->flags & VMS_VARRAY_UINT8) {
Line 1488  static void vmstate_save(QEMUFile *f, Sa Line 1548  static void vmstate_save(QEMUFile *f, Sa
 #define QEMU_VM_SECTION_FULL         0x04  #define QEMU_VM_SECTION_FULL         0x04
 #define QEMU_VM_SUBSECTION           0x05  #define QEMU_VM_SUBSECTION           0x05
   
 bool qemu_savevm_state_blocked(Monitor *mon)  bool qemu_savevm_state_blocked(Error **errp)
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
   
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {      QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->no_migrate) {          if (se->no_migrate) {
             monitor_printf(mon, "state blocked by non-migratable device '%s'\n",              error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr);
                            se->idstr);  
             return true;              return true;
         }          }
     }      }
     return false;      return false;
 }  }
   
 int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,  int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared)
                             int shared)  
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
     int ret;      int ret;
Line 1536  int qemu_savevm_state_begin(Monitor *mon Line 1594  int qemu_savevm_state_begin(Monitor *mon
         qemu_put_be32(f, se->instance_id);          qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);          qemu_put_be32(f, se->version_id);
   
         ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);          ret = se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
         if (ret < 0) {          if (ret < 0) {
             qemu_savevm_state_cancel(mon, f);              qemu_savevm_state_cancel(f);
             return ret;              return ret;
         }          }
     }      }
     ret = qemu_file_get_error(f);      ret = qemu_file_get_error(f);
     if (ret != 0) {      if (ret != 0) {
         qemu_savevm_state_cancel(mon, f);          qemu_savevm_state_cancel(f);
     }      }
   
     return ret;      return ret;
Line 1552  int qemu_savevm_state_begin(Monitor *mon Line 1610  int qemu_savevm_state_begin(Monitor *mon
 }  }
   
 /*  /*
  * this funtion has three return values:   * this function has three return values:
  *   negative: there was one error, and we have -errno.   *   negative: there was one error, and we have -errno.
  *   0 : We haven't finished, caller have to go again   *   0 : We haven't finished, caller have to go again
  *   1 : We have finished, we can go to complete phase   *   1 : We have finished, we can go to complete phase
  */   */
 int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)  int qemu_savevm_state_iterate(QEMUFile *f)
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
     int ret = 1;      int ret = 1;
Line 1570  int qemu_savevm_state_iterate(Monitor *m Line 1628  int qemu_savevm_state_iterate(Monitor *m
         qemu_put_byte(f, QEMU_VM_SECTION_PART);          qemu_put_byte(f, QEMU_VM_SECTION_PART);
         qemu_put_be32(f, se->section_id);          qemu_put_be32(f, se->section_id);
   
         ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);          ret = se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
         if (ret <= 0) {          if (ret <= 0) {
             /* Do not proceed to the next vmstate before this one reported              /* Do not proceed to the next vmstate before this one reported
                completion of the current stage. This serializes the migration                 completion of the current stage. This serializes the migration
Line 1584  int qemu_savevm_state_iterate(Monitor *m Line 1642  int qemu_savevm_state_iterate(Monitor *m
     }      }
     ret = qemu_file_get_error(f);      ret = qemu_file_get_error(f);
     if (ret != 0) {      if (ret != 0) {
         qemu_savevm_state_cancel(mon, f);          qemu_savevm_state_cancel(f);
     }      }
     return ret;      return ret;
 }  }
   
 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)  int qemu_savevm_state_complete(QEMUFile *f)
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
     int ret;      int ret;
Line 1604  int qemu_savevm_state_complete(Monitor * Line 1662  int qemu_savevm_state_complete(Monitor *
         qemu_put_byte(f, QEMU_VM_SECTION_END);          qemu_put_byte(f, QEMU_VM_SECTION_END);
         qemu_put_be32(f, se->section_id);          qemu_put_be32(f, se->section_id);
   
         ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);          ret = se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
         if (ret < 0) {          if (ret < 0) {
             return ret;              return ret;
         }          }
Line 1636  int qemu_savevm_state_complete(Monitor * Line 1694  int qemu_savevm_state_complete(Monitor *
     return qemu_file_get_error(f);      return qemu_file_get_error(f);
 }  }
   
 void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)  void qemu_savevm_state_cancel(QEMUFile *f)
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
   
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {      QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->save_live_state) {          if (se->save_live_state) {
             se->save_live_state(mon, f, -1, se->opaque);              se->save_live_state(f, -1, se->opaque);
         }          }
     }      }
 }  }
   
 static int qemu_savevm_state(Monitor *mon, QEMUFile *f)  static int qemu_savevm_state(QEMUFile *f)
 {  {
     int ret;      int ret;
   
     if (qemu_savevm_state_blocked(mon)) {      if (qemu_savevm_state_blocked(NULL)) {
         ret = -EINVAL;          ret = -EINVAL;
         goto out;          goto out;
     }      }
   
     ret = qemu_savevm_state_begin(mon, f, 0, 0);      ret = qemu_savevm_state_begin(f, 0, 0);
     if (ret < 0)      if (ret < 0)
         goto out;          goto out;
   
     do {      do {
         ret = qemu_savevm_state_iterate(mon, f);          ret = qemu_savevm_state_iterate(f);
         if (ret < 0)          if (ret < 0)
             goto out;              goto out;
     } while (ret == 0);      } while (ret == 0);
   
     ret = qemu_savevm_state_complete(mon, f);      ret = qemu_savevm_state_complete(f);
   
 out:  out:
     if (ret == 0) {      if (ret == 0) {
Line 1676  out: Line 1734  out:
     return ret;      return ret;
 }  }
   
   static int qemu_save_device_state(QEMUFile *f)
   {
       SaveStateEntry *se;
   
       qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
       qemu_put_be32(f, QEMU_VM_FILE_VERSION);
   
       cpu_synchronize_all_states();
   
       QTAILQ_FOREACH(se, &savevm_handlers, entry) {
           int len;
   
           if (se->is_ram) {
               continue;
           }
           if (se->save_state == NULL && se->vmsd == NULL) {
               continue;
           }
   
           /* Section type */
           qemu_put_byte(f, QEMU_VM_SECTION_FULL);
           qemu_put_be32(f, se->section_id);
   
           /* ID string */
           len = strlen(se->idstr);
           qemu_put_byte(f, len);
           qemu_put_buffer(f, (uint8_t *)se->idstr, len);
   
           qemu_put_be32(f, se->instance_id);
           qemu_put_be32(f, se->version_id);
   
           vmstate_save(f, se);
       }
   
       qemu_put_byte(f, QEMU_VM_EOF);
   
       return qemu_file_get_error(f);
   }
   
 static SaveStateEntry *find_se(const char *idstr, int instance_id)  static SaveStateEntry *find_se(const char *idstr, int instance_id)
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
Line 1785  int qemu_loadvm_state(QEMUFile *f) Line 1882  int qemu_loadvm_state(QEMUFile *f)
     unsigned int v;      unsigned int v;
     int ret;      int ret;
   
     if (qemu_savevm_state_blocked(default_mon)) {      if (qemu_savevm_state_blocked(NULL)) {
         return -EINVAL;          return -EINVAL;
     }      }
   
Line 1951  void do_savevm(Monitor *mon, const QDict Line 2048  void do_savevm(Monitor *mon, const QDict
     int ret;      int ret;
     QEMUFile *f;      QEMUFile *f;
     int saved_vm_running;      int saved_vm_running;
     uint32_t vm_state_size;      uint64_t vm_state_size;
 #ifdef _WIN32  #ifdef _WIN32
     struct _timeb tb;      struct _timeb tb;
     struct tm *ptm;      struct tm *ptm;
Line 2009  void do_savevm(Monitor *mon, const QDict Line 2106  void do_savevm(Monitor *mon, const QDict
         }          }
     } else {      } else {
 #ifdef _WIN32  #ifdef _WIN32
         ptm = localtime(&tb.time);          time_t t = tb.time;
           ptm = localtime(&t);
         strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);          strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
 #else  #else
         /* cast below needed for OpenBSD where tv_sec is still 'long' */          /* cast below needed for OpenBSD where tv_sec is still 'long' */
Line 2029  void do_savevm(Monitor *mon, const QDict Line 2127  void do_savevm(Monitor *mon, const QDict
         monitor_printf(mon, "Could not open VM state file\n");          monitor_printf(mon, "Could not open VM state file\n");
         goto the_end;          goto the_end;
     }      }
     ret = qemu_savevm_state(mon, f);      ret = qemu_savevm_state(f);
     vm_state_size = qemu_ftell(f);      vm_state_size = qemu_ftell(f);
     qemu_fclose(f);      qemu_fclose(f);
     if (ret < 0) {      if (ret < 0) {
Line 2057  void do_savevm(Monitor *mon, const QDict Line 2155  void do_savevm(Monitor *mon, const QDict
         vm_start();          vm_start();
 }  }
   
   void qmp_xen_save_devices_state(const char *filename, Error **errp)
   {
       QEMUFile *f;
       int saved_vm_running;
       int ret;
   
       saved_vm_running = runstate_is_running();
       vm_stop(RUN_STATE_SAVE_VM);
   
       f = qemu_fopen(filename, "wb");
       if (!f) {
           error_set(errp, QERR_OPEN_FILE_FAILED, filename);
           goto the_end;
       }
       ret = qemu_save_device_state(f);
       qemu_fclose(f);
       if (ret < 0) {
           error_set(errp, QERR_IO_ERROR);
       }
   
    the_end:
       if (saved_vm_running)
           vm_start();
       return;
   }
   
 int load_vmstate(const char *name)  int load_vmstate(const char *name)
 {  {
     BlockDriverState *bs, *bs_vm_state;      BlockDriverState *bs, *bs_vm_state;
Line 2104  int load_vmstate(const char *name) Line 2228  int load_vmstate(const char *name)
     }      }
   
     /* Flush all IO requests so they don't interfere with the new state.  */      /* Flush all IO requests so they don't interfere with the new state.  */
     qemu_aio_flush();      bdrv_drain_all();
   
     bs = NULL;      bs = NULL;
     while ((bs = bdrv_next(bs))) {      while ((bs = bdrv_next(bs))) {
Line 2229  void do_info_snapshots(Monitor *mon) Line 2353  void do_info_snapshots(Monitor *mon)
     g_free(available_snapshots);      g_free(available_snapshots);
   
 }  }
   
   void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
   {
       qemu_ram_set_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK,
                          memory_region_name(mr), dev);
   }
   
   void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
   {
       /* Nothing do to while the implementation is in RAMBlock */
   }
   
   void vmstate_register_ram_global(MemoryRegion *mr)
   {
       vmstate_register_ram(mr, NULL);
   }

Removed from v.1.1.1.11  
changed lines
  Added in v.1.1.1.12


unix.superglobalmegacorp.com