Diff for /qemu/savevm.c between versions 1.1.1.8 and 1.1.1.9

version 1.1.1.8, 2018/04/24 18:23:42 version 1.1.1.9, 2018/04/24 18:33:41
Line 78 Line 78
 #include "sysemu.h"  #include "sysemu.h"
 #include "qemu-timer.h"  #include "qemu-timer.h"
 #include "qemu-char.h"  #include "qemu-char.h"
 #include "blockdev.h"  
 #include "audio/audio.h"  #include "audio/audio.h"
 #include "migration.h"  #include "migration.h"
 #include "qemu_socket.h"  #include "qemu_socket.h"
Line 611  int qemu_file_rate_limit(QEMUFile *f) Line 610  int qemu_file_rate_limit(QEMUFile *f)
     return 0;      return 0;
 }  }
   
 size_t qemu_file_get_rate_limit(QEMUFile *f)  int64_t qemu_file_get_rate_limit(QEMUFile *f)
 {  {
     if (f->get_rate_limit)      if (f->get_rate_limit)
         return f->get_rate_limit(f->opaque);          return f->get_rate_limit(f->opaque);
Line 619  size_t qemu_file_get_rate_limit(QEMUFile Line 618  size_t qemu_file_get_rate_limit(QEMUFile
     return 0;      return 0;
 }  }
   
 size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate)  int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
 {  {
     /* any failed or completed migration keeps its state to allow probing of      /* any failed or completed migration keeps its state to allow probing of
      * migration data, but has no associated file anymore */       * migration data, but has no associated file anymore */
Line 675  uint64_t qemu_get_be64(QEMUFile *f) Line 674  uint64_t qemu_get_be64(QEMUFile *f)
     return v;      return v;
 }  }
   
   /* bool */
   
   static int get_bool(QEMUFile *f, void *pv, size_t size)
   {
       bool *v = pv;
       *v = qemu_get_byte(f);
       return 0;
   }
   
   static void put_bool(QEMUFile *f, void *pv, size_t size)
   {
       bool *v = pv;
       qemu_put_byte(f, *v);
   }
   
   const VMStateInfo vmstate_info_bool = {
       .name = "bool",
       .get  = get_bool,
       .put  = put_bool,
   };
   
 /* 8 bit int */  /* 8 bit int */
   
 static int get_int8(QEMUFile *f, void *pv, size_t size)  static int get_int8(QEMUFile *f, void *pv, size_t size)
Line 1380  static int vmstate_load(QEMUFile *f, Sav Line 1400  static int vmstate_load(QEMUFile *f, Sav
     return vmstate_load_state(f, se->vmsd, se->opaque, version_id);      return vmstate_load_state(f, se->vmsd, se->opaque, version_id);
 }  }
   
 static int vmstate_save(QEMUFile *f, SaveStateEntry *se)  static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
 {  {
     if (se->no_migrate) {  
         return -1;  
     }  
   
     if (!se->vmsd) {         /* Old style */      if (!se->vmsd) {         /* Old style */
         se->save_state(f, se->opaque);          se->save_state(f, se->opaque);
         return 0;          return;
     }      }
     vmstate_save_state(f,se->vmsd, se->opaque);      vmstate_save_state(f,se->vmsd, se->opaque);
   
     return 0;  
 }  }
   
 #define QEMU_VM_FILE_MAGIC           0x5145564d  #define QEMU_VM_FILE_MAGIC           0x5145564d
Line 1406  static int vmstate_save(QEMUFile *f, Sav Line 1420  static int vmstate_save(QEMUFile *f, Sav
 #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)
   {
       SaveStateEntry *se;
   
       QTAILQ_FOREACH(se, &savevm_handlers, entry) {
           if (se->no_migrate) {
               monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
                              se->idstr);
               return true;
           }
       }
       return false;
   }
   
 int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,  int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
                             int shared)                              int shared)
 {  {
Line 1487  int qemu_savevm_state_iterate(Monitor *m Line 1515  int qemu_savevm_state_iterate(Monitor *m
 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)  int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
 {  {
     SaveStateEntry *se;      SaveStateEntry *se;
     int r;  
   
     cpu_synchronize_all_states();      cpu_synchronize_all_states();
   
Line 1520  int qemu_savevm_state_complete(Monitor * Line 1547  int qemu_savevm_state_complete(Monitor *
         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);
   
         r = vmstate_save(f, se);          vmstate_save(f, se);
         if (r < 0) {  
             monitor_printf(mon, "cannot migrate with device '%s'\n", se->idstr);  
             return r;  
         }  
     }      }
   
     qemu_put_byte(f, QEMU_VM_EOF);      qemu_put_byte(f, QEMU_VM_EOF);
Line 1554  static int qemu_savevm_state(Monitor *mo Line 1577  static int qemu_savevm_state(Monitor *mo
     saved_vm_running = vm_running;      saved_vm_running = vm_running;
     vm_stop(0);      vm_stop(0);
   
     bdrv_flush_all();      if (qemu_savevm_state_blocked(mon)) {
           ret = -EINVAL;
           goto out;
       }
   
     ret = qemu_savevm_state_begin(mon, f, 0, 0);      ret = qemu_savevm_state_begin(mon, f, 0, 0);
     if (ret < 0)      if (ret < 0)
Line 1612  static const VMStateDescription *vmstate Line 1638  static const VMStateDescription *vmstate
 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,  static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
                                    void *opaque)                                     void *opaque)
 {  {
       const VMStateSubsection *sub = vmsd->subsections;
   
       if (!sub || !sub->needed) {
           return 0;
       }
   
     while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) {      while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) {
         char idstr[256];          char idstr[256];
         int ret;          int ret;
         uint8_t version_id, subsection, len;          uint8_t version_id, len;
         const VMStateDescription *sub_vmsd;          const VMStateDescription *sub_vmsd;
   
         subsection = qemu_get_byte(f);          qemu_get_byte(f); /* subsection */
         len = qemu_get_byte(f);          len = qemu_get_byte(f);
         qemu_get_buffer(f, (uint8_t *)idstr, len);          qemu_get_buffer(f, (uint8_t *)idstr, len);
         idstr[len] = 0;          idstr[len] = 0;
         version_id = qemu_get_be32(f);          version_id = qemu_get_be32(f);
   
         sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);          sub_vmsd = vmstate_get_subsection(sub, idstr);
         if (sub_vmsd == NULL) {          if (sub_vmsd == NULL) {
             return -ENOENT;              return -ENOENT;
         }          }
           assert(!sub_vmsd->subsections);
         ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);          ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
         if (ret) {          if (ret) {
             return ret;              return ret;
Line 1651  static void vmstate_subsection_save(QEMU Line 1684  static void vmstate_subsection_save(QEMU
             qemu_put_byte(f, len);              qemu_put_byte(f, len);
             qemu_put_buffer(f, (uint8_t *)vmsd->name, len);              qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
             qemu_put_be32(f, vmsd->version_id);              qemu_put_be32(f, vmsd->version_id);
               assert(!vmsd->subsections);
             vmstate_save_state(f, vmsd, opaque);              vmstate_save_state(f, vmsd, opaque);
         }          }
         sub++;          sub++;
Line 1673  int qemu_loadvm_state(QEMUFile *f) Line 1707  int qemu_loadvm_state(QEMUFile *f)
     unsigned int v;      unsigned int v;
     int ret;      int ret;
   
       if (qemu_savevm_state_blocked(default_mon)) {
           return -EINVAL;
       }
   
     v = qemu_get_be32(f);      v = qemu_get_be32(f);
     if (v != QEMU_VM_FILE_MAGIC)      if (v != QEMU_VM_FILE_MAGIC)
         return -EINVAL;          return -EINVAL;
Line 1837  void do_savevm(Monitor *mon, const QDict Line 1875  void do_savevm(Monitor *mon, const QDict
     uint32_t vm_state_size;      uint32_t vm_state_size;
 #ifdef _WIN32  #ifdef _WIN32
     struct _timeb tb;      struct _timeb tb;
       struct tm *ptm;
 #else  #else
     struct timeval tv;      struct timeval tv;
       struct tm tm;
 #endif  #endif
     const char *name = qdict_get_try_str(qdict, "name");      const char *name = qdict_get_try_str(qdict, "name");
   
Line 1862  void do_savevm(Monitor *mon, const QDict Line 1902  void do_savevm(Monitor *mon, const QDict
         monitor_printf(mon, "No block device can accept snapshots\n");          monitor_printf(mon, "No block device can accept snapshots\n");
         return;          return;
     }      }
     /* ??? Should this occur after vm_stop?  */  
     qemu_aio_flush();  
   
     saved_vm_running = vm_running;      saved_vm_running = vm_running;
     vm_stop(0);      vm_stop(0);
   
     memset(sn, 0, sizeof(*sn));      memset(sn, 0, sizeof(*sn));
     if (name) {  
         ret = bdrv_snapshot_find(bs, old_sn, name);  
         if (ret >= 0) {  
             pstrcpy(sn->name, sizeof(sn->name), old_sn->name);  
             pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);  
         } else {  
             pstrcpy(sn->name, sizeof(sn->name), name);  
         }  
     }  
   
     /* fill auxiliary fields */      /* fill auxiliary fields */
 #ifdef _WIN32  #ifdef _WIN32
Line 1891  void do_savevm(Monitor *mon, const QDict Line 1920  void do_savevm(Monitor *mon, const QDict
 #endif  #endif
     sn->vm_clock_nsec = qemu_get_clock(vm_clock);      sn->vm_clock_nsec = qemu_get_clock(vm_clock);
   
       if (name) {
           ret = bdrv_snapshot_find(bs, old_sn, name);
           if (ret >= 0) {
               pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
               pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
           } else {
               pstrcpy(sn->name, sizeof(sn->name), name);
           }
       } else {
   #ifdef _WIN32
           ptm = localtime(&tb.time);
           strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
   #else
           /* cast below needed for OpenBSD where tv_sec is still 'long' */
           localtime_r((const time_t *)&tv.tv_sec, &tm);
           strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
   #endif
       }
   
     /* Delete old snapshots of the same name */      /* Delete old snapshots of the same name */
     if (name && del_existing_snapshots(mon, name) < 0) {      if (name && del_existing_snapshots(mon, name) < 0) {
         goto the_end;          goto the_end;
Line 1932  void do_savevm(Monitor *mon, const QDict Line 1980  void do_savevm(Monitor *mon, const QDict
   
 int load_vmstate(const char *name)  int load_vmstate(const char *name)
 {  {
     BlockDriverState *bs, *bs1;      BlockDriverState *bs, *bs_vm_state;
     QEMUSnapshotInfo sn;      QEMUSnapshotInfo sn;
     QEMUFile *f;      QEMUFile *f;
     int ret;      int ret;
   
     /* Verify if there is a device that doesn't support snapshots and is writable */      bs_vm_state = bdrv_snapshots();
       if (!bs_vm_state) {
           error_report("No block device supports snapshots");
           return -ENOTSUP;
       }
   
       /* Don't even try to load empty VM states */
       ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
       if (ret < 0) {
           return ret;
       } else if (sn.vm_state_size == 0) {
           return -EINVAL;
       }
   
       /* Verify if there is any device that doesn't support snapshots and is
       writable and check if the requested snapshot is available too. */
     bs = NULL;      bs = NULL;
     while ((bs = bdrv_next(bs))) {      while ((bs = bdrv_next(bs))) {
   
Line 1950  int load_vmstate(const char *name) Line 2013  int load_vmstate(const char *name)
                                bdrv_get_device_name(bs));                                 bdrv_get_device_name(bs));
             return -ENOTSUP;              return -ENOTSUP;
         }          }
     }  
   
     bs = bdrv_snapshots();          ret = bdrv_snapshot_find(bs, &sn, name);
     if (!bs) {          if (ret < 0) {
         error_report("No block device supports snapshots");              error_report("Device '%s' does not have the requested snapshot '%s'",
         return -EINVAL;                             bdrv_get_device_name(bs), name);
               return ret;
           }
     }      }
   
     /* 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();      qemu_aio_flush();
   
     bs1 = NULL;      bs = NULL;
     while ((bs1 = bdrv_next(bs1))) {      while ((bs = bdrv_next(bs))) {
         if (bdrv_can_snapshot(bs1)) {          if (bdrv_can_snapshot(bs)) {
             ret = bdrv_snapshot_goto(bs1, name);              ret = bdrv_snapshot_goto(bs, name);
             if (ret < 0) {              if (ret < 0) {
                 switch(ret) {                  error_report("Error %d while activating snapshot '%s' on '%s'",
                 case -ENOTSUP:                               ret, name, bdrv_get_device_name(bs));
                     error_report("%sSnapshots not supported on device '%s'",                  return ret;
                                  bs != bs1 ? "Warning: " : "",  
                                  bdrv_get_device_name(bs1));  
                     break;  
                 case -ENOENT:  
                     error_report("%sCould not find snapshot '%s' on device '%s'",  
                                  bs != bs1 ? "Warning: " : "",  
                                  name, bdrv_get_device_name(bs1));  
                     break;  
                 default:  
                     error_report("%sError %d while activating snapshot on '%s'",  
                                  bs != bs1 ? "Warning: " : "",  
                                  ret, bdrv_get_device_name(bs1));  
                     break;  
                 }  
                 /* fatal on snapshot block device */  
                 if (bs == bs1)  
                     return 0;  
             }              }
         }          }
     }      }
   
     /* Don't even try to load empty VM states */  
     ret = bdrv_snapshot_find(bs, &sn, name);  
     if ((ret >= 0) && (sn.vm_state_size == 0))  
         return -EINVAL;  
   
     /* restore the VM state */      /* restore the VM state */
     f = qemu_fopen_bdrv(bs, 0);      f = qemu_fopen_bdrv(bs_vm_state, 0);
     if (!f) {      if (!f) {
         error_report("Could not open VM state file");          error_report("Could not open VM state file");
         return -EINVAL;          return -EINVAL;
     }      }
   
     ret = qemu_loadvm_state(f);      ret = qemu_loadvm_state(f);
   
     qemu_fclose(f);      qemu_fclose(f);
     if (ret < 0) {      if (ret < 0) {
         error_report("Error %d while loading VM state", ret);          error_report("Error %d while loading VM state", ret);
         return ret;          return ret;
     }      }
   
     return 0;      return 0;
 }  }
   
Line 2042  void do_delvm(Monitor *mon, const QDict  Line 2087  void do_delvm(Monitor *mon, const QDict 
 void do_info_snapshots(Monitor *mon)  void do_info_snapshots(Monitor *mon)
 {  {
     BlockDriverState *bs, *bs1;      BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo *sn_tab, *sn;      QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
     int nb_sns, i;      int nb_sns, i, ret, available;
       int total;
       int *available_snapshots;
     char buf[256];      char buf[256];
   
     bs = bdrv_snapshots();      bs = bdrv_snapshots();
Line 2051  void do_info_snapshots(Monitor *mon) Line 2098  void do_info_snapshots(Monitor *mon)
         monitor_printf(mon, "No available block device supports snapshots\n");          monitor_printf(mon, "No available block device supports snapshots\n");
         return;          return;
     }      }
     monitor_printf(mon, "Snapshot devices:");  
     bs1 = NULL;  
     while ((bs1 = bdrv_next(bs1))) {  
         if (bdrv_can_snapshot(bs1)) {  
             if (bs == bs1)  
                 monitor_printf(mon, " %s", bdrv_get_device_name(bs1));  
         }  
     }  
     monitor_printf(mon, "\n");  
   
     nb_sns = bdrv_snapshot_list(bs, &sn_tab);      nb_sns = bdrv_snapshot_list(bs, &sn_tab);
     if (nb_sns < 0) {      if (nb_sns < 0) {
         monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);          monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
         return;          return;
     }      }
     monitor_printf(mon, "Snapshot list (from %s):\n",  
                    bdrv_get_device_name(bs));      if (nb_sns == 0) {
     monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));          monitor_printf(mon, "There is no snapshot available.\n");
     for(i = 0; i < nb_sns; i++) {          return;
       }
   
       available_snapshots = qemu_mallocz(sizeof(int) * nb_sns);
       total = 0;
       for (i = 0; i < nb_sns; i++) {
         sn = &sn_tab[i];          sn = &sn_tab[i];
         monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));          available = 1;
           bs1 = NULL;
   
           while ((bs1 = bdrv_next(bs1))) {
               if (bdrv_can_snapshot(bs1) && bs1 != bs) {
                   ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str);
                   if (ret < 0) {
                       available = 0;
                       break;
                   }
               }
           }
   
           if (available) {
               available_snapshots[total] = i;
               total++;
           }
     }      }
   
       if (total > 0) {
           monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
           for (i = 0; i < total; i++) {
               sn = &sn_tab[available_snapshots[i]];
               monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
           }
       } else {
           monitor_printf(mon, "There is no suitable snapshot available\n");
       }
   
     qemu_free(sn_tab);      qemu_free(sn_tab);
       qemu_free(available_snapshots);
   
 }  }

Removed from v.1.1.1.8  
changed lines
  Added in v.1.1.1.9


unix.superglobalmegacorp.com