Commit faea38e7863a6e29f110063388eb93840fcd475c

Authored by bellard
1 parent 42ca6388

multiple snapshot support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2086 c046a42c-6fe2-441c-8c8c-71466251a162
... ... @@ -494,12 +494,10 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
494 494 }
495 495 }
496 496  
497   -#if 0
498 497 /* not necessary now */
499 498 static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
500   - void *buf1, int count1)
  499 + uint8_t *buf, int count1)
501 500 {
502   - uint8_t *buf = buf1;
503 501 uint8_t tmp_buf[SECTOR_SIZE];
504 502 int len, nb_sectors, count;
505 503 int64_t sector_num;
... ... @@ -542,9 +540,8 @@ static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
542 540 }
543 541  
544 542 static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
545   - const void *buf1, int count1)
  543 + const uint8_t *buf, int count1)
546 544 {
547   - const uint8_t *buf = buf1;
548 545 uint8_t tmp_buf[SECTOR_SIZE];
549 546 int len, nb_sectors, count;
550 547 int64_t sector_num;
... ... @@ -589,7 +586,6 @@ static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
589 586 }
590 587 return count1;
591 588 }
592   -#endif
593 589  
594 590 /**
595 591 * Read with byte offsets (needed only for file protocols)
... ... @@ -602,7 +598,7 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
602 598 if (!drv)
603 599 return -ENOENT;
604 600 if (!drv->bdrv_pread)
605   - return -ENOTSUP;
  601 + return bdrv_pread_em(bs, offset, buf1, count1);
606 602 return drv->bdrv_pread(bs, offset, buf1, count1);
607 603 }
608 604  
... ... @@ -617,7 +613,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
617 613 if (!drv)
618 614 return -ENOENT;
619 615 if (!drv->bdrv_pwrite)
620   - return -ENOTSUP;
  616 + return bdrv_pwrite_em(bs, offset, buf1, count1);
621 617 return drv->bdrv_pwrite(bs, offset, buf1, count1);
622 618 }
623 619  
... ... @@ -859,6 +855,137 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
859 855 }
860 856 }
861 857  
  858 +int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
  859 + const uint8_t *buf, int nb_sectors)
  860 +{
  861 + BlockDriver *drv = bs->drv;
  862 + if (!drv)
  863 + return -ENOENT;
  864 + if (!drv->bdrv_write_compressed)
  865 + return -ENOTSUP;
  866 + return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
  867 +}
  868 +
  869 +int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
  870 +{
  871 + BlockDriver *drv = bs->drv;
  872 + if (!drv)
  873 + return -ENOENT;
  874 + if (!drv->bdrv_get_info)
  875 + return -ENOTSUP;
  876 + memset(bdi, 0, sizeof(*bdi));
  877 + return drv->bdrv_get_info(bs, bdi);
  878 +}
  879 +
  880 +/**************************************************************/
  881 +/* handling of snapshots */
  882 +
  883 +int bdrv_snapshot_create(BlockDriverState *bs,
  884 + QEMUSnapshotInfo *sn_info)
  885 +{
  886 + BlockDriver *drv = bs->drv;
  887 + if (!drv)
  888 + return -ENOENT;
  889 + if (!drv->bdrv_snapshot_create)
  890 + return -ENOTSUP;
  891 + return drv->bdrv_snapshot_create(bs, sn_info);
  892 +}
  893 +
  894 +int bdrv_snapshot_goto(BlockDriverState *bs,
  895 + const char *snapshot_id)
  896 +{
  897 + BlockDriver *drv = bs->drv;
  898 + if (!drv)
  899 + return -ENOENT;
  900 + if (!drv->bdrv_snapshot_goto)
  901 + return -ENOTSUP;
  902 + return drv->bdrv_snapshot_goto(bs, snapshot_id);
  903 +}
  904 +
  905 +int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
  906 +{
  907 + BlockDriver *drv = bs->drv;
  908 + if (!drv)
  909 + return -ENOENT;
  910 + if (!drv->bdrv_snapshot_delete)
  911 + return -ENOTSUP;
  912 + return drv->bdrv_snapshot_delete(bs, snapshot_id);
  913 +}
  914 +
  915 +int bdrv_snapshot_list(BlockDriverState *bs,
  916 + QEMUSnapshotInfo **psn_info)
  917 +{
  918 + BlockDriver *drv = bs->drv;
  919 + if (!drv)
  920 + return -ENOENT;
  921 + if (!drv->bdrv_snapshot_list)
  922 + return -ENOTSUP;
  923 + return drv->bdrv_snapshot_list(bs, psn_info);
  924 +}
  925 +
  926 +#define NB_SUFFIXES 4
  927 +
  928 +char *get_human_readable_size(char *buf, int buf_size, int64_t size)
  929 +{
  930 + static const char suffixes[NB_SUFFIXES] = "KMGT";
  931 + int64_t base;
  932 + int i;
  933 +
  934 + if (size <= 999) {
  935 + snprintf(buf, buf_size, "%" PRId64, size);
  936 + } else {
  937 + base = 1024;
  938 + for(i = 0; i < NB_SUFFIXES; i++) {
  939 + if (size < (10 * base)) {
  940 + snprintf(buf, buf_size, "%0.1f%c",
  941 + (double)size / base,
  942 + suffixes[i]);
  943 + break;
  944 + } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
  945 + snprintf(buf, buf_size, "%" PRId64 "%c",
  946 + ((size + (base >> 1)) / base),
  947 + suffixes[i]);
  948 + break;
  949 + }
  950 + base = base * 1024;
  951 + }
  952 + }
  953 + return buf;
  954 +}
  955 +
  956 +char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
  957 +{
  958 + char buf1[128], date_buf[128], clock_buf[128];
  959 + struct tm tm;
  960 + time_t ti;
  961 + int64_t secs;
  962 +
  963 + if (!sn) {
  964 + snprintf(buf, buf_size,
  965 + "%-10s%-20s%7s%20s%15s",
  966 + "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
  967 + } else {
  968 + ti = sn->date_sec;
  969 + localtime_r(&ti, &tm);
  970 + strftime(date_buf, sizeof(date_buf),
  971 + "%Y-%m-%d %H:%M:%S", &tm);
  972 + secs = sn->vm_clock_nsec / 1000000000;
  973 + snprintf(clock_buf, sizeof(clock_buf),
  974 + "%02d:%02d:%02d.%03d",
  975 + (int)(secs / 3600),
  976 + (int)((secs / 60) % 60),
  977 + (int)(secs % 60),
  978 + (int)((sn->vm_clock_nsec / 1000000) % 1000));
  979 + snprintf(buf, buf_size,
  980 + "%-10s%-20s%7s%20s%15s",
  981 + sn->id_str, sn->name,
  982 + get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
  983 + date_buf,
  984 + clock_buf);
  985 + }
  986 + return buf;
  987 +}
  988 +
862 989  
863 990 /**************************************************************/
864 991 /* async I/Os */
... ... @@ -1108,4 +1235,5 @@ void bdrv_init(void)
1108 1235 bdrv_register(&bdrv_bochs);
1109 1236 bdrv_register(&bdrv_vpc);
1110 1237 bdrv_register(&bdrv_vvfat);
  1238 + bdrv_register(&bdrv_qcow2);
1111 1239 }
... ...
block_int.h
... ... @@ -57,6 +57,17 @@ struct BlockDriver {
57 57 const uint8_t *buf, int count);
58 58 int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
59 59 int64_t (*bdrv_getlength)(BlockDriverState *bs);
  60 + int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
  61 + const uint8_t *buf, int nb_sectors);
  62 +
  63 + int (*bdrv_snapshot_create)(BlockDriverState *bs,
  64 + QEMUSnapshotInfo *sn_info);
  65 + int (*bdrv_snapshot_goto)(BlockDriverState *bs,
  66 + const char *snapshot_id);
  67 + int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id);
  68 + int (*bdrv_snapshot_list)(BlockDriverState *bs,
  69 + QEMUSnapshotInfo **psn_info);
  70 + int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
60 71  
61 72 struct BlockDriver *next;
62 73 };
... ...
monitor.c
... ... @@ -380,18 +380,6 @@ static void do_log(const char *items)
380 380 cpu_set_log(mask);
381 381 }
382 382  
383   -static void do_savevm(const char *filename)
384   -{
385   - if (qemu_savevm(filename) < 0)
386   - term_printf("I/O error when saving VM to '%s'\n", filename);
387   -}
388   -
389   -static void do_loadvm(const char *filename)
390   -{
391   - if (qemu_loadvm(filename) < 0)
392   - term_printf("I/O error when loading VM from '%s'\n", filename);
393   -}
394   -
395 383 static void do_stop(void)
396 384 {
397 385 vm_stop(EXCP_INTERRUPT);
... ... @@ -1155,10 +1143,12 @@ static term_cmd_t term_cmds[] = {
1155 1143 "filename", "save screen into PPM image 'filename'" },
1156 1144 { "log", "s", do_log,
1157 1145 "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
1158   - { "savevm", "F", do_savevm,
1159   - "filename", "save the whole virtual machine state to 'filename'" },
1160   - { "loadvm", "F", do_loadvm,
1161   - "filename", "restore the whole virtual machine state from 'filename'" },
  1146 + { "savevm", "s?", do_savevm,
  1147 + "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" },
  1148 + { "loadvm", "s", do_loadvm,
  1149 + "tag|id", "restore a VM snapshot from its tag or id" },
  1150 + { "delvm", "s", do_delvm,
  1151 + "tag|id", "delete a VM snapshot from its tag or id" },
1162 1152 { "stop", "", do_stop,
1163 1153 "", "stop emulation", },
1164 1154 { "c|cont", "", do_cont,
... ... @@ -1241,6 +1231,8 @@ static term_cmd_t info_cmds[] = {
1241 1231 "", "show profiling information", },
1242 1232 { "capture", "", do_info_capture,
1243 1233 "show capture information" },
  1234 + { "snapshots", "", do_info_snapshots,
  1235 + "show the currently saved VM snapshots" },
1244 1236 { NULL, NULL, },
1245 1237 };
1246 1238  
... ...
qemu-img.c
... ... @@ -159,36 +159,6 @@ void help(void)
159 159 exit(1);
160 160 }
161 161  
162   -
163   -#define NB_SUFFIXES 4
164   -
165   -static void get_human_readable_size(char *buf, int buf_size, int64_t size)
166   -{
167   - static const char suffixes[NB_SUFFIXES] = "KMGT";
168   - int64_t base;
169   - int i;
170   -
171   - if (size <= 999) {
172   - snprintf(buf, buf_size, "%" PRId64, size);
173   - } else {
174   - base = 1024;
175   - for(i = 0; i < NB_SUFFIXES; i++) {
176   - if (size < (10 * base)) {
177   - snprintf(buf, buf_size, "%0.1f%c",
178   - (double)size / base,
179   - suffixes[i]);
180   - break;
181   - } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
182   - snprintf(buf, buf_size, "%" PRId64 "%c",
183   - ((size + (base >> 1)) / base),
184   - suffixes[i]);
185   - break;
186   - }
187   - base = base * 1024;
188   - }
189   - }
190   -}
191   -
192 162 #if defined(WIN32)
193 163 /* XXX: put correct support for win32 */
194 164 static int read_password(char *buf, int buf_size)
... ... @@ -486,6 +456,7 @@ static int img_convert(int argc, char **argv)
486 456 int64_t total_sectors, nb_sectors, sector_num;
487 457 uint8_t buf[IO_BUF_SIZE];
488 458 const uint8_t *buf1;
  459 + BlockDriverInfo bdi;
489 460  
490 461 fmt = NULL;
491 462 out_fmt = "raw";
... ... @@ -525,9 +496,9 @@ static int img_convert(int argc, char **argv)
525 496 drv = bdrv_find_format(out_fmt);
526 497 if (!drv)
527 498 error("Unknown file format '%s'", fmt);
528   - if (compress && drv != &bdrv_qcow)
  499 + if (compress && drv != &bdrv_qcow && drv != &bdrv_qcow2)
529 500 error("Compression not supported for this file format");
530   - if (encrypt && drv != &bdrv_qcow)
  501 + if (encrypt && drv != &bdrv_qcow && drv != &bdrv_qcow2)
531 502 error("Encryption not supported for this file format");
532 503 if (compress && encrypt)
533 504 error("Compression and encryption not supported at the same time");
... ... @@ -544,7 +515,9 @@ static int img_convert(int argc, char **argv)
544 515 out_bs = bdrv_new_open(out_filename, out_fmt);
545 516  
546 517 if (compress) {
547   - cluster_size = qcow_get_cluster_size(out_bs);
  518 + if (bdrv_get_info(out_bs, &bdi) < 0)
  519 + error("could not get block driver info");
  520 + cluster_size = bdi.cluster_size;
548 521 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
549 522 error("invalid cluster size");
550 523 cluster_sectors = cluster_size >> 9;
... ... @@ -562,12 +535,15 @@ static int img_convert(int argc, char **argv)
562 535 if (n < cluster_sectors)
563 536 memset(buf + n * 512, 0, cluster_size - n * 512);
564 537 if (is_not_zero(buf, cluster_size)) {
565   - if (qcow_compress_cluster(out_bs, sector_num, buf) != 0)
  538 + if (bdrv_write_compressed(out_bs, sector_num, buf,
  539 + cluster_sectors) != 0)
566 540 error("error while compressing sector %" PRId64,
567 541 sector_num);
568 542 }
569 543 sector_num += n;
570 544 }
  545 + /* signal EOF to align */
  546 + bdrv_write_compressed(out_bs, 0, NULL, 0);
571 547 } else {
572 548 sector_num = 0;
573 549 for(;;) {
... ... @@ -630,6 +606,24 @@ static int64_t get_allocated_file_size(const char *filename)
630 606 }
631 607 #endif
632 608  
  609 +static void dump_snapshots(BlockDriverState *bs)
  610 +{
  611 + QEMUSnapshotInfo *sn_tab, *sn;
  612 + int nb_sns, i;
  613 + char buf[256];
  614 +
  615 + nb_sns = bdrv_snapshot_list(bs, &sn_tab);
  616 + if (nb_sns <= 0)
  617 + return;
  618 + printf("Snapshot list:\n");
  619 + printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
  620 + for(i = 0; i < nb_sns; i++) {
  621 + sn = &sn_tab[i];
  622 + printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
  623 + }
  624 + qemu_free(sn_tab);
  625 +}
  626 +
633 627 static int img_info(int argc, char **argv)
634 628 {
635 629 int c;
... ... @@ -640,6 +634,7 @@ static int img_info(int argc, char **argv)
640 634 int64_t total_sectors, allocated_size;
641 635 char backing_filename[1024];
642 636 char backing_filename2[1024];
  637 + BlockDriverInfo bdi;
643 638  
644 639 fmt = NULL;
645 640 for(;;) {
... ... @@ -690,13 +685,19 @@ static int img_info(int argc, char **argv)
690 685 dsize_buf);
691 686 if (bdrv_is_encrypted(bs))
692 687 printf("encrypted: yes\n");
  688 + if (bdrv_get_info(bs, &bdi) >= 0) {
  689 + if (bdi.cluster_size != 0)
  690 + printf("cluster_size: %d\n", bdi.cluster_size);
  691 + }
693 692 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
694   - if (backing_filename[0] != '\0')
  693 + if (backing_filename[0] != '\0') {
695 694 path_combine(backing_filename2, sizeof(backing_filename2),
696 695 filename, backing_filename);
697 696 printf("backing file: %s (actual path: %s)\n",
698 697 backing_filename,
699 698 backing_filename2);
  699 + }
  700 + dump_snapshots(bs);
700 701 bdrv_delete(bs);
701 702 return 0;
702 703 }
... ...
... ... @@ -113,7 +113,11 @@ char phys_ram_file[1024];
113 113 void *ioport_opaque[MAX_IOPORTS];
114 114 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
115 115 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
116   -BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
  116 +/* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
  117 + to store the VM snapshots */
  118 +BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
  119 +/* point to the block driver where the snapshots are managed */
  120 +BlockDriverState *bs_snapshots;
117 121 int vga_ram_size;
118 122 int bios_size;
119 123 static DisplayState display_state;
... ... @@ -4085,14 +4089,190 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
4085 4089 /***********************************************************/
4086 4090 /* savevm/loadvm support */
4087 4091  
  4092 +#define IO_BUF_SIZE 32768
  4093 +
  4094 +struct QEMUFile {
  4095 + FILE *outfile;
  4096 + BlockDriverState *bs;
  4097 + int is_file;
  4098 + int is_writable;
  4099 + int64_t base_offset;
  4100 + int64_t buf_offset; /* start of buffer when writing, end of buffer
  4101 + when reading */
  4102 + int buf_index;
  4103 + int buf_size; /* 0 when writing */
  4104 + uint8_t buf[IO_BUF_SIZE];
  4105 +};
  4106 +
  4107 +QEMUFile *qemu_fopen(const char *filename, const char *mode)
  4108 +{
  4109 + QEMUFile *f;
  4110 +
  4111 + f = qemu_mallocz(sizeof(QEMUFile));
  4112 + if (!f)
  4113 + return NULL;
  4114 + if (!strcmp(mode, "wb")) {
  4115 + f->is_writable = 1;
  4116 + } else if (!strcmp(mode, "rb")) {
  4117 + f->is_writable = 0;
  4118 + } else {
  4119 + goto fail;
  4120 + }
  4121 + f->outfile = fopen(filename, mode);
  4122 + if (!f->outfile)
  4123 + goto fail;
  4124 + f->is_file = 1;
  4125 + return f;
  4126 + fail:
  4127 + if (f->outfile)
  4128 + fclose(f->outfile);
  4129 + qemu_free(f);
  4130 + return NULL;
  4131 +}
  4132 +
  4133 +QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
  4134 +{
  4135 + QEMUFile *f;
  4136 +
  4137 + f = qemu_mallocz(sizeof(QEMUFile));
  4138 + if (!f)
  4139 + return NULL;
  4140 + f->is_file = 0;
  4141 + f->bs = bs;
  4142 + f->is_writable = is_writable;
  4143 + f->base_offset = offset;
  4144 + return f;
  4145 +}
  4146 +
  4147 +void qemu_fflush(QEMUFile *f)
  4148 +{
  4149 + if (!f->is_writable)
  4150 + return;
  4151 + if (f->buf_index > 0) {
  4152 + if (f->is_file) {
  4153 + fseek(f->outfile, f->buf_offset, SEEK_SET);
  4154 + fwrite(f->buf, 1, f->buf_index, f->outfile);
  4155 + } else {
  4156 + bdrv_pwrite(f->bs, f->base_offset + f->buf_offset,
  4157 + f->buf, f->buf_index);
  4158 + }
  4159 + f->buf_offset += f->buf_index;
  4160 + f->buf_index = 0;
  4161 + }
  4162 +}
  4163 +
  4164 +static void qemu_fill_buffer(QEMUFile *f)
  4165 +{
  4166 + int len;
  4167 +
  4168 + if (f->is_writable)
  4169 + return;
  4170 + if (f->is_file) {
  4171 + fseek(f->outfile, f->buf_offset, SEEK_SET);
  4172 + len = fread(f->buf, 1, IO_BUF_SIZE, f->outfile);
  4173 + if (len < 0)
  4174 + len = 0;
  4175 + } else {
  4176 + len = bdrv_pread(f->bs, f->base_offset + f->buf_offset,
  4177 + f->buf, IO_BUF_SIZE);
  4178 + if (len < 0)
  4179 + len = 0;
  4180 + }
  4181 + f->buf_index = 0;
  4182 + f->buf_size = len;
  4183 + f->buf_offset += len;
  4184 +}
  4185 +
  4186 +void qemu_fclose(QEMUFile *f)
  4187 +{
  4188 + if (f->is_writable)
  4189 + qemu_fflush(f);
  4190 + if (f->is_file) {
  4191 + fclose(f->outfile);
  4192 + }
  4193 + qemu_free(f);
  4194 +}
  4195 +
4088 4196 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
4089 4197 {
4090   - fwrite(buf, 1, size, f);
  4198 + int l;
  4199 + while (size > 0) {
  4200 + l = IO_BUF_SIZE - f->buf_index;
  4201 + if (l > size)
  4202 + l = size;
  4203 + memcpy(f->buf + f->buf_index, buf, l);
  4204 + f->buf_index += l;
  4205 + buf += l;
  4206 + size -= l;
  4207 + if (f->buf_index >= IO_BUF_SIZE)
  4208 + qemu_fflush(f);
  4209 + }
4091 4210 }
4092 4211  
4093 4212 void qemu_put_byte(QEMUFile *f, int v)
4094 4213 {
4095   - fputc(v, f);
  4214 + f->buf[f->buf_index++] = v;
  4215 + if (f->buf_index >= IO_BUF_SIZE)
  4216 + qemu_fflush(f);
  4217 +}
  4218 +
  4219 +int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
  4220 +{
  4221 + int size, l;
  4222 +
  4223 + size = size1;
  4224 + while (size > 0) {
  4225 + l = f->buf_size - f->buf_index;
  4226 + if (l == 0) {
  4227 + qemu_fill_buffer(f);
  4228 + l = f->buf_size - f->buf_index;
  4229 + if (l == 0)
  4230 + break;
  4231 + }
  4232 + if (l > size)
  4233 + l = size;
  4234 + memcpy(buf, f->buf + f->buf_index, l);
  4235 + f->buf_index += l;
  4236 + buf += l;
  4237 + size -= l;
  4238 + }
  4239 + return size1 - size;
  4240 +}
  4241 +
  4242 +int qemu_get_byte(QEMUFile *f)
  4243 +{
  4244 + if (f->buf_index >= f->buf_size) {
  4245 + qemu_fill_buffer(f);
  4246 + if (f->buf_index >= f->buf_size)
  4247 + return 0;
  4248 + }
  4249 + return f->buf[f->buf_index++];
  4250 +}
  4251 +
  4252 +int64_t qemu_ftell(QEMUFile *f)
  4253 +{
  4254 + return f->buf_offset - f->buf_size + f->buf_index;
  4255 +}
  4256 +
  4257 +int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
  4258 +{
  4259 + if (whence == SEEK_SET) {
  4260 + /* nothing to do */
  4261 + } else if (whence == SEEK_CUR) {
  4262 + pos += qemu_ftell(f);
  4263 + } else {
  4264 + /* SEEK_END not supported */
  4265 + return -1;
  4266 + }
  4267 + if (f->is_writable) {
  4268 + qemu_fflush(f);
  4269 + f->buf_offset = pos;
  4270 + } else {
  4271 + f->buf_offset = pos;
  4272 + f->buf_index = 0;
  4273 + f->buf_size = 0;
  4274 + }
  4275 + return pos;
4096 4276 }
4097 4277  
4098 4278 void qemu_put_be16(QEMUFile *f, unsigned int v)
... ... @@ -4115,21 +4295,6 @@ void qemu_put_be64(QEMUFile *f, uint64_t v)
4115 4295 qemu_put_be32(f, v);
4116 4296 }
4117 4297  
4118   -int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
4119   -{
4120   - return fread(buf, 1, size, f);
4121   -}
4122   -
4123   -int qemu_get_byte(QEMUFile *f)
4124   -{
4125   - int v;
4126   - v = fgetc(f);
4127   - if (v == EOF)
4128   - return 0;
4129   - else
4130   - return v;
4131   -}
4132   -
4133 4298 unsigned int qemu_get_be16(QEMUFile *f)
4134 4299 {
4135 4300 unsigned int v;
... ... @@ -4156,18 +4321,6 @@ uint64_t qemu_get_be64(QEMUFile *f)
4156 4321 return v;
4157 4322 }
4158 4323  
4159   -int64_t qemu_ftell(QEMUFile *f)
4160   -{
4161   - return ftell(f);
4162   -}
4163   -
4164   -int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
4165   -{
4166   - if (fseek(f, pos, whence) < 0)
4167   - return -1;
4168   - return ftell(f);
4169   -}
4170   -
4171 4324 typedef struct SaveStateEntry {
4172 4325 char idstr[256];
4173 4326 int instance_id;
... ... @@ -4209,25 +4362,18 @@ int register_savevm(const char *idstr,
4209 4362 }
4210 4363  
4211 4364 #define QEMU_VM_FILE_MAGIC 0x5145564d
4212   -#define QEMU_VM_FILE_VERSION 0x00000001
  4365 +#define QEMU_VM_FILE_VERSION 0x00000002
4213 4366  
4214   -int qemu_savevm(const char *filename)
  4367 +int qemu_savevm_state(QEMUFile *f)
4215 4368 {
4216 4369 SaveStateEntry *se;
4217   - QEMUFile *f;
4218   - int len, len_pos, cur_pos, saved_vm_running, ret;
4219   -
4220   - saved_vm_running = vm_running;
4221   - vm_stop(0);
4222   -
4223   - f = fopen(filename, "wb");
4224   - if (!f) {
4225   - ret = -1;
4226   - goto the_end;
4227   - }
  4370 + int len, ret;
  4371 + int64_t cur_pos, len_pos, total_len_pos;
4228 4372  
4229 4373 qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
4230 4374 qemu_put_be32(f, QEMU_VM_FILE_VERSION);
  4375 + total_len_pos = qemu_ftell(f);
  4376 + qemu_put_be64(f, 0); /* total size */
4231 4377  
4232 4378 for(se = first_se; se != NULL; se = se->next) {
4233 4379 /* ID string */
... ... @@ -4239,24 +4385,24 @@ int qemu_savevm(const char *filename)
4239 4385 qemu_put_be32(f, se->version_id);
4240 4386  
4241 4387 /* record size: filled later */
4242   - len_pos = ftell(f);
  4388 + len_pos = qemu_ftell(f);
4243 4389 qemu_put_be32(f, 0);
4244 4390  
4245 4391 se->save_state(f, se->opaque);
4246 4392  
4247 4393 /* fill record size */
4248   - cur_pos = ftell(f);
4249   - len = ftell(f) - len_pos - 4;
4250   - fseek(f, len_pos, SEEK_SET);
  4394 + cur_pos = qemu_ftell(f);
  4395 + len = cur_pos - len_pos - 4;
  4396 + qemu_fseek(f, len_pos, SEEK_SET);
4251 4397 qemu_put_be32(f, len);
4252   - fseek(f, cur_pos, SEEK_SET);
  4398 + qemu_fseek(f, cur_pos, SEEK_SET);
4253 4399 }
  4400 + cur_pos = qemu_ftell(f);
  4401 + qemu_fseek(f, total_len_pos, SEEK_SET);
  4402 + qemu_put_be64(f, cur_pos - total_len_pos - 8);
  4403 + qemu_fseek(f, cur_pos, SEEK_SET);
4254 4404  
4255   - fclose(f);
4256 4405 ret = 0;
4257   - the_end:
4258   - if (saved_vm_running)
4259   - vm_start();
4260 4406 return ret;
4261 4407 }
4262 4408  
... ... @@ -4272,38 +4418,29 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
4272 4418 return NULL;
4273 4419 }
4274 4420  
4275   -int qemu_loadvm(const char *filename)
  4421 +int qemu_loadvm_state(QEMUFile *f)
4276 4422 {
4277 4423 SaveStateEntry *se;
4278   - QEMUFile *f;
4279   - int len, cur_pos, ret, instance_id, record_len, version_id;
4280   - int saved_vm_running;
  4424 + int len, ret, instance_id, record_len, version_id;
  4425 + int64_t total_len, end_pos, cur_pos;
4281 4426 unsigned int v;
4282 4427 char idstr[256];
4283 4428  
4284   - saved_vm_running = vm_running;
4285   - vm_stop(0);
4286   -
4287   - f = fopen(filename, "rb");
4288   - if (!f) {
4289   - ret = -1;
4290   - goto the_end;
4291   - }
4292   -
4293 4429 v = qemu_get_be32(f);
4294 4430 if (v != QEMU_VM_FILE_MAGIC)
4295 4431 goto fail;
4296 4432 v = qemu_get_be32(f);
4297 4433 if (v != QEMU_VM_FILE_VERSION) {
4298 4434 fail:
4299   - fclose(f);
4300 4435 ret = -1;
4301 4436 goto the_end;
4302 4437 }
  4438 + total_len = qemu_get_be64(f);
  4439 + end_pos = total_len + qemu_ftell(f);
4303 4440 for(;;) {
4304   - len = qemu_get_byte(f);
4305   - if (feof(f))
  4441 + if (qemu_ftell(f) >= end_pos)
4306 4442 break;
  4443 + len = qemu_get_byte(f);
4307 4444 qemu_get_buffer(f, idstr, len);
4308 4445 idstr[len] = '\0';
4309 4446 instance_id = qemu_get_be32(f);
... ... @@ -4313,7 +4450,7 @@ int qemu_loadvm(const char *filename)
4313 4450 printf("idstr=%s instance=0x%x version=%d len=%d\n",
4314 4451 idstr, instance_id, version_id, record_len);
4315 4452 #endif
4316   - cur_pos = ftell(f);
  4453 + cur_pos = qemu_ftell(f);
4317 4454 se = find_se(idstr, instance_id);
4318 4455 if (!se) {
4319 4456 fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
... ... @@ -4328,12 +4465,281 @@ int qemu_loadvm(const char *filename)
4328 4465 /* always seek to exact end of record */
4329 4466 qemu_fseek(f, cur_pos + record_len, SEEK_SET);
4330 4467 }
4331   - fclose(f);
4332 4468 ret = 0;
4333 4469 the_end:
  4470 + return ret;
  4471 +}
  4472 +
  4473 +/* device can contain snapshots */
  4474 +static int bdrv_can_snapshot(BlockDriverState *bs)
  4475 +{
  4476 + return (bs &&
  4477 + !bdrv_is_removable(bs) &&
  4478 + !bdrv_is_read_only(bs));
  4479 +}
  4480 +
  4481 +/* device must be snapshots in order to have a reliable snapshot */
  4482 +static int bdrv_has_snapshot(BlockDriverState *bs)
  4483 +{
  4484 + return (bs &&
  4485 + !bdrv_is_removable(bs) &&
  4486 + !bdrv_is_read_only(bs));
  4487 +}
  4488 +
  4489 +static BlockDriverState *get_bs_snapshots(void)
  4490 +{
  4491 + BlockDriverState *bs;
  4492 + int i;
  4493 +
  4494 + if (bs_snapshots)
  4495 + return bs_snapshots;
  4496 + for(i = 0; i <= MAX_DISKS; i++) {
  4497 + bs = bs_table[i];
  4498 + if (bdrv_can_snapshot(bs))
  4499 + goto ok;
  4500 + }
  4501 + return NULL;
  4502 + ok:
  4503 + bs_snapshots = bs;
  4504 + return bs;
  4505 +}
  4506 +
  4507 +static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
  4508 + const char *name)
  4509 +{
  4510 + QEMUSnapshotInfo *sn_tab, *sn;
  4511 + int nb_sns, i, ret;
  4512 +
  4513 + ret = -ENOENT;
  4514 + nb_sns = bdrv_snapshot_list(bs, &sn_tab);
  4515 + if (nb_sns < 0)
  4516 + return ret;
  4517 + for(i = 0; i < nb_sns; i++) {
  4518 + sn = &sn_tab[i];
  4519 + if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
  4520 + *sn_info = *sn;
  4521 + ret = 0;
  4522 + break;
  4523 + }
  4524 + }
  4525 + qemu_free(sn_tab);
  4526 + return ret;
  4527 +}
  4528 +
  4529 +void do_savevm(const char *name)
  4530 +{
  4531 + BlockDriverState *bs, *bs1;
  4532 + QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
  4533 + int must_delete, ret, i;
  4534 + BlockDriverInfo bdi1, *bdi = &bdi1;
  4535 + QEMUFile *f;
  4536 + int saved_vm_running;
  4537 + struct timeval tv;
  4538 +
  4539 + bs = get_bs_snapshots();
  4540 + if (!bs) {
  4541 + term_printf("No block device can accept snapshots\n");
  4542 + return;
  4543 + }
  4544 +
  4545 + saved_vm_running = vm_running;
  4546 + vm_stop(0);
  4547 +
  4548 + must_delete = 0;
  4549 + if (name) {
  4550 + ret = bdrv_snapshot_find(bs, old_sn, name);
  4551 + if (ret >= 0) {
  4552 + must_delete = 1;
  4553 + }
  4554 + }
  4555 + memset(sn, 0, sizeof(*sn));
  4556 + if (must_delete) {
  4557 + pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
  4558 + pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
  4559 + } else {
  4560 + if (name)
  4561 + pstrcpy(sn->name, sizeof(sn->name), name);
  4562 + }
  4563 +
  4564 + /* fill auxiliary fields */
  4565 + gettimeofday(&tv, NULL);
  4566 + sn->date_sec = tv.tv_sec;
  4567 + sn->date_nsec = tv.tv_usec * 1000;
  4568 + sn->vm_clock_nsec = qemu_get_clock(vm_clock);
  4569 +
  4570 + if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
  4571 + term_printf("Device %s does not support VM state snapshots\n",
  4572 + bdrv_get_device_name(bs));
  4573 + goto the_end;
  4574 + }
  4575 +
  4576 + /* save the VM state */
  4577 + f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
  4578 + if (!f) {
  4579 + term_printf("Could not open VM state file\n");
  4580 + goto the_end;
  4581 + }
  4582 + ret = qemu_savevm_state(f);
  4583 + sn->vm_state_size = qemu_ftell(f);
  4584 + qemu_fclose(f);
  4585 + if (ret < 0) {
  4586 + term_printf("Error %d while writing VM\n", ret);
  4587 + goto the_end;
  4588 + }
  4589 +
  4590 + /* create the snapshots */
  4591 +
  4592 + for(i = 0; i < MAX_DISKS; i++) {
  4593 + bs1 = bs_table[i];
  4594 + if (bdrv_has_snapshot(bs1)) {
  4595 + if (must_delete) {
  4596 + ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
  4597 + if (ret < 0) {
  4598 + term_printf("Error while deleting snapshot on '%s'\n",
  4599 + bdrv_get_device_name(bs1));
  4600 + }
  4601 + }
  4602 + ret = bdrv_snapshot_create(bs1, sn);
  4603 + if (ret < 0) {
  4604 + term_printf("Error while creating snapshot on '%s'\n",
  4605 + bdrv_get_device_name(bs1));
  4606 + }
  4607 + }
  4608 + }
  4609 +
  4610 + the_end:
4334 4611 if (saved_vm_running)
4335 4612 vm_start();
4336   - return ret;
  4613 +}
  4614 +
  4615 +void do_loadvm(const char *name)
  4616 +{
  4617 + BlockDriverState *bs, *bs1;
  4618 + BlockDriverInfo bdi1, *bdi = &bdi1;
  4619 + QEMUFile *f;
  4620 + int i, ret;
  4621 + int saved_vm_running;
  4622 +
  4623 + bs = get_bs_snapshots();
  4624 + if (!bs) {
  4625 + term_printf("No block device supports snapshots\n");
  4626 + return;
  4627 + }
  4628 +
  4629 + saved_vm_running = vm_running;
  4630 + vm_stop(0);
  4631 +
  4632 + for(i = 0; i <= MAX_DISKS; i++) {
  4633 + bs1 = bs_table[i];
  4634 + if (bdrv_has_snapshot(bs1)) {
  4635 + ret = bdrv_snapshot_goto(bs1, name);
  4636 + if (ret < 0) {
  4637 + if (bs != bs1)
  4638 + term_printf("Warning: ");
  4639 + switch(ret) {
  4640 + case -ENOTSUP:
  4641 + term_printf("Snapshots not supported on device '%s'\n",
  4642 + bdrv_get_device_name(bs1));
  4643 + break;
  4644 + case -ENOENT:
  4645 + term_printf("Could not find snapshot '%s' on device '%s'\n",
  4646 + name, bdrv_get_device_name(bs1));
  4647 + break;
  4648 + default:
  4649 + term_printf("Error %d while activating snapshot on '%s'\n",
  4650 + ret, bdrv_get_device_name(bs1));
  4651 + break;
  4652 + }
  4653 + /* fatal on snapshot block device */
  4654 + if (bs == bs1)
  4655 + goto the_end;
  4656 + }
  4657 + }
  4658 + }
  4659 +
  4660 + if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
  4661 + term_printf("Device %s does not support VM state snapshots\n",
  4662 + bdrv_get_device_name(bs));
  4663 + return;
  4664 + }
  4665 +
  4666 + /* restore the VM state */
  4667 + f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
  4668 + if (!f) {
  4669 + term_printf("Could not open VM state file\n");
  4670 + goto the_end;
  4671 + }
  4672 + ret = qemu_loadvm_state(f);
  4673 + qemu_fclose(f);
  4674 + if (ret < 0) {
  4675 + term_printf("Error %d while loading VM state\n", ret);
  4676 + }
  4677 + the_end:
  4678 + if (saved_vm_running)
  4679 + vm_start();
  4680 +}
  4681 +
  4682 +void do_delvm(const char *name)
  4683 +{
  4684 + BlockDriverState *bs, *bs1;
  4685 + int i, ret;
  4686 +
  4687 + bs = get_bs_snapshots();
  4688 + if (!bs) {
  4689 + term_printf("No block device supports snapshots\n");
  4690 + return;
  4691 + }
  4692 +
  4693 + for(i = 0; i <= MAX_DISKS; i++) {
  4694 + bs1 = bs_table[i];
  4695 + if (bdrv_has_snapshot(bs1)) {
  4696 + ret = bdrv_snapshot_delete(bs1, name);
  4697 + if (ret < 0) {
  4698 + if (ret == -ENOTSUP)
  4699 + term_printf("Snapshots not supported on device '%s'\n",
  4700 + bdrv_get_device_name(bs1));
  4701 + else
  4702 + term_printf("Error %d while deleting snapshot on '%s'\n",
  4703 + ret, bdrv_get_device_name(bs1));
  4704 + }
  4705 + }
  4706 + }
  4707 +}
  4708 +
  4709 +void do_info_snapshots(void)
  4710 +{
  4711 + BlockDriverState *bs, *bs1;
  4712 + QEMUSnapshotInfo *sn_tab, *sn;
  4713 + int nb_sns, i;
  4714 + char buf[256];
  4715 +
  4716 + bs = get_bs_snapshots();
  4717 + if (!bs) {
  4718 + term_printf("No available block device supports snapshots\n");
  4719 + return;
  4720 + }
  4721 + term_printf("Snapshot devices:");
  4722 + for(i = 0; i <= MAX_DISKS; i++) {
  4723 + bs1 = bs_table[i];
  4724 + if (bdrv_has_snapshot(bs1)) {
  4725 + if (bs == bs1)
  4726 + term_printf(" %s", bdrv_get_device_name(bs1));
  4727 + }
  4728 + }
  4729 + term_printf("\n");
  4730 +
  4731 + nb_sns = bdrv_snapshot_list(bs, &sn_tab);
  4732 + if (nb_sns < 0) {
  4733 + term_printf("bdrv_snapshot_list: error %d\n", nb_sns);
  4734 + return;
  4735 + }
  4736 + term_printf("Snapshot list (from %s):\n", bdrv_get_device_name(bs));
  4737 + term_printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
  4738 + for(i = 0; i < nb_sns; i++) {
  4739 + sn = &sn_tab[i];
  4740 + term_printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
  4741 + }
  4742 + qemu_free(sn_tab);
4337 4743 }
4338 4744  
4339 4745 /***********************************************************/
... ... @@ -6284,7 +6690,7 @@ int main(int argc, char **argv)
6284 6690 } else
6285 6691 #endif
6286 6692 if (loadvm)
6287   - qemu_loadvm(loadvm);
  6693 + do_loadvm(loadvm);
6288 6694  
6289 6695 {
6290 6696 /* XXX: simplify init */
... ...
... ... @@ -396,8 +396,11 @@ void cpu_disable_ticks(void);
396 396  
397 397 /* VM Load/Save */
398 398  
399   -typedef FILE QEMUFile;
  399 +typedef struct QEMUFile QEMUFile;
400 400  
  401 +QEMUFile *qemu_fopen(const char *filename, const char *mode);
  402 +void qemu_fflush(QEMUFile *f);
  403 +void qemu_fclose(QEMUFile *f);
401 404 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
402 405 void qemu_put_byte(QEMUFile *f, int v);
403 406 void qemu_put_be16(QEMUFile *f, unsigned int v);
... ... @@ -467,8 +470,6 @@ int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
467 470 typedef void SaveStateHandler(QEMUFile *f, void *opaque);
468 471 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
469 472  
470   -int qemu_loadvm(const char *filename);
471   -int qemu_savevm(const char *filename);
472 473 int register_savevm(const char *idstr,
473 474 int instance_id,
474 475 int version_id,
... ... @@ -481,6 +482,11 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
481 482 void cpu_save(QEMUFile *f, void *opaque);
482 483 int cpu_load(QEMUFile *f, void *opaque, int version_id);
483 484  
  485 +void do_savevm(const char *name);
  486 +void do_loadvm(const char *name);
  487 +void do_delvm(const char *name);
  488 +void do_info_snapshots(void);
  489 +
484 490 /* bottom halves */
485 491 typedef struct QEMUBH QEMUBH;
486 492 typedef void QEMUBHFunc(void *opaque);
... ... @@ -504,6 +510,25 @@ extern BlockDriver bdrv_dmg;
504 510 extern BlockDriver bdrv_bochs;
505 511 extern BlockDriver bdrv_vpc;
506 512 extern BlockDriver bdrv_vvfat;
  513 +extern BlockDriver bdrv_qcow2;
  514 +
  515 +typedef struct BlockDriverInfo {
  516 + /* in bytes, 0 if irrelevant */
  517 + int cluster_size;
  518 + /* offset at which the VM state can be saved (0 if not possible) */
  519 + int64_t vm_state_offset;
  520 +} BlockDriverInfo;
  521 +
  522 +typedef struct QEMUSnapshotInfo {
  523 + char id_str[128]; /* unique snapshot id */
  524 + /* the following fields are informative. They are not needed for
  525 + the consistency of the snapshot */
  526 + char name[256]; /* user choosen name */
  527 + uint32_t vm_state_size; /* VM state info size */
  528 + uint32_t date_sec; /* UTC date of the snapshot */
  529 + uint32_t date_nsec;
  530 + uint64_t vm_clock_nsec; /* VM clock relative to boot */
  531 +} QEMUSnapshotInfo;
507 532  
508 533 #define BDRV_O_RDONLY 0x0000
509 534 #define BDRV_O_RDWR 0x0002
... ... @@ -594,13 +619,22 @@ int bdrv_set_key(BlockDriverState *bs, const char *key);
594 619 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
595 620 void *opaque);
596 621 const char *bdrv_get_device_name(BlockDriverState *bs);
  622 +int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
  623 + const uint8_t *buf, int nb_sectors);
  624 +int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
597 625  
598   -int qcow_get_cluster_size(BlockDriverState *bs);
599   -int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
600   - const uint8_t *buf);
601 626 void bdrv_get_backing_filename(BlockDriverState *bs,
602 627 char *filename, int filename_size);
603   -
  628 +int bdrv_snapshot_create(BlockDriverState *bs,
  629 + QEMUSnapshotInfo *sn_info);
  630 +int bdrv_snapshot_goto(BlockDriverState *bs,
  631 + const char *snapshot_id);
  632 +int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
  633 +int bdrv_snapshot_list(BlockDriverState *bs,
  634 + QEMUSnapshotInfo **psn_info);
  635 +char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
  636 +
  637 +char *get_human_readable_size(char *buf, int buf_size, int64_t size);
604 638 int path_is_absolute(const char *path);
605 639 void path_combine(char *dest, int dest_size,
606 640 const char *base_path,
... ... @@ -824,7 +858,7 @@ void vnc_display_init(DisplayState *ds, int display);
824 858 /* ide.c */
825 859 #define MAX_DISKS 4
826 860  
827   -extern BlockDriverState *bs_table[MAX_DISKS];
  861 +extern BlockDriverState *bs_table[MAX_DISKS + 1];
828 862  
829 863 void isa_ide_init(int iobase, int iobase2, int irq,
830 864 BlockDriverState *hd0, BlockDriverState *hd1);
... ...