Commit c88676f89c3e2b4eefdfe2ef647e1ea07fe052ae

Authored by bellard
1 parent d15a771d

use zlib to compress ram snapshots - correctly save qemu clock


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2095 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 226 additions and 29 deletions
... ... @@ -29,6 +29,7 @@
29 29 #include <time.h>
30 30 #include <errno.h>
31 31 #include <sys/time.h>
  32 +#include <zlib.h>
32 33  
33 34 #ifndef _WIN32
34 35 #include <sys/times.h>
... ... @@ -822,17 +823,21 @@ static void timer_save(QEMUFile *f, void *opaque)
822 823 }
823 824 qemu_put_be64s(f, &cpu_ticks_offset);
824 825 qemu_put_be64s(f, &ticks_per_sec);
  826 + qemu_put_be64s(f, &cpu_clock_offset);
825 827 }
826 828  
827 829 static int timer_load(QEMUFile *f, void *opaque, int version_id)
828 830 {
829   - if (version_id != 1)
  831 + if (version_id != 1 && version_id != 2)
830 832 return -EINVAL;
831 833 if (cpu_ticks_enabled) {
832 834 return -EINVAL;
833 835 }
834 836 qemu_get_be64s(f, &cpu_ticks_offset);
835 837 qemu_get_be64s(f, &ticks_per_sec);
  838 + if (version_id == 2) {
  839 + qemu_get_be64s(f, &cpu_clock_offset);
  840 + }
836 841 return 0;
837 842 }
838 843  
... ... @@ -5114,24 +5119,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
5114 5119 /***********************************************************/
5115 5120 /* ram save/restore */
5116 5121  
5117   -/* we just avoid storing empty pages */
5118   -static void ram_put_page(QEMUFile *f, const uint8_t *buf, int len)
5119   -{
5120   - int i, v;
5121   -
5122   - v = buf[0];
5123   - for(i = 1; i < len; i++) {
5124   - if (buf[i] != v)
5125   - goto normal_save;
5126   - }
5127   - qemu_put_byte(f, 1);
5128   - qemu_put_byte(f, v);
5129   - return;
5130   - normal_save:
5131   - qemu_put_byte(f, 0);
5132   - qemu_put_buffer(f, buf, len);
5133   -}
5134   -
5135 5122 static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
5136 5123 {
5137 5124 int v;
... ... @@ -5152,28 +5139,238 @@ static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
5152 5139 return 0;
5153 5140 }
5154 5141  
  5142 +static int ram_load_v1(QEMUFile *f, void *opaque)
  5143 +{
  5144 + int i, ret;
  5145 +
  5146 + if (qemu_get_be32(f) != phys_ram_size)
  5147 + return -EINVAL;
  5148 + for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
  5149 + ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
  5150 + if (ret)
  5151 + return ret;
  5152 + }
  5153 + return 0;
  5154 +}
  5155 +
  5156 +#define BDRV_HASH_BLOCK_SIZE 1024
  5157 +#define IOBUF_SIZE 4096
  5158 +#define RAM_CBLOCK_MAGIC 0xfabe
  5159 +
  5160 +typedef struct RamCompressState {
  5161 + z_stream zstream;
  5162 + QEMUFile *f;
  5163 + uint8_t buf[IOBUF_SIZE];
  5164 +} RamCompressState;
  5165 +
  5166 +static int ram_compress_open(RamCompressState *s, QEMUFile *f)
  5167 +{
  5168 + int ret;
  5169 + memset(s, 0, sizeof(*s));
  5170 + s->f = f;
  5171 + ret = deflateInit2(&s->zstream, 1,
  5172 + Z_DEFLATED, 15,
  5173 + 9, Z_DEFAULT_STRATEGY);
  5174 + if (ret != Z_OK)
  5175 + return -1;
  5176 + s->zstream.avail_out = IOBUF_SIZE;
  5177 + s->zstream.next_out = s->buf;
  5178 + return 0;
  5179 +}
  5180 +
  5181 +static void ram_put_cblock(RamCompressState *s, const uint8_t *buf, int len)
  5182 +{
  5183 + qemu_put_be16(s->f, RAM_CBLOCK_MAGIC);
  5184 + qemu_put_be16(s->f, len);
  5185 + qemu_put_buffer(s->f, buf, len);
  5186 +}
  5187 +
  5188 +static int ram_compress_buf(RamCompressState *s, const uint8_t *buf, int len)
  5189 +{
  5190 + int ret;
  5191 +
  5192 + s->zstream.avail_in = len;
  5193 + s->zstream.next_in = (uint8_t *)buf;
  5194 + while (s->zstream.avail_in > 0) {
  5195 + ret = deflate(&s->zstream, Z_NO_FLUSH);
  5196 + if (ret != Z_OK)
  5197 + return -1;
  5198 + if (s->zstream.avail_out == 0) {
  5199 + ram_put_cblock(s, s->buf, IOBUF_SIZE);
  5200 + s->zstream.avail_out = IOBUF_SIZE;
  5201 + s->zstream.next_out = s->buf;
  5202 + }
  5203 + }
  5204 + return 0;
  5205 +}
  5206 +
  5207 +static void ram_compress_close(RamCompressState *s)
  5208 +{
  5209 + int len, ret;
  5210 +
  5211 + /* compress last bytes */
  5212 + for(;;) {
  5213 + ret = deflate(&s->zstream, Z_FINISH);
  5214 + if (ret == Z_OK || ret == Z_STREAM_END) {
  5215 + len = IOBUF_SIZE - s->zstream.avail_out;
  5216 + if (len > 0) {
  5217 + ram_put_cblock(s, s->buf, len);
  5218 + }
  5219 + s->zstream.avail_out = IOBUF_SIZE;
  5220 + s->zstream.next_out = s->buf;
  5221 + if (ret == Z_STREAM_END)
  5222 + break;
  5223 + } else {
  5224 + goto fail;
  5225 + }
  5226 + }
  5227 +fail:
  5228 + deflateEnd(&s->zstream);
  5229 +}
  5230 +
  5231 +typedef struct RamDecompressState {
  5232 + z_stream zstream;
  5233 + QEMUFile *f;
  5234 + uint8_t buf[IOBUF_SIZE];
  5235 +} RamDecompressState;
  5236 +
  5237 +static int ram_decompress_open(RamDecompressState *s, QEMUFile *f)
  5238 +{
  5239 + int ret;
  5240 + memset(s, 0, sizeof(*s));
  5241 + s->f = f;
  5242 + ret = inflateInit(&s->zstream);
  5243 + if (ret != Z_OK)
  5244 + return -1;
  5245 + return 0;
  5246 +}
  5247 +
  5248 +static int ram_decompress_buf(RamDecompressState *s, uint8_t *buf, int len)
  5249 +{
  5250 + int ret, clen;
  5251 +
  5252 + s->zstream.avail_out = len;
  5253 + s->zstream.next_out = buf;
  5254 + while (s->zstream.avail_out > 0) {
  5255 + if (s->zstream.avail_in == 0) {
  5256 + if (qemu_get_be16(s->f) != RAM_CBLOCK_MAGIC)
  5257 + return -1;
  5258 + clen = qemu_get_be16(s->f);
  5259 + if (clen > IOBUF_SIZE)
  5260 + return -1;
  5261 + qemu_get_buffer(s->f, s->buf, clen);
  5262 + s->zstream.avail_in = clen;
  5263 + s->zstream.next_in = s->buf;
  5264 + }
  5265 + ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
  5266 + if (ret != Z_OK && ret != Z_STREAM_END) {
  5267 + return -1;
  5268 + }
  5269 + }
  5270 + return 0;
  5271 +}
  5272 +
  5273 +static void ram_decompress_close(RamDecompressState *s)
  5274 +{
  5275 + inflateEnd(&s->zstream);
  5276 +}
  5277 +
5155 5278 static void ram_save(QEMUFile *f, void *opaque)
5156 5279 {
5157 5280 int i;
  5281 + RamCompressState s1, *s = &s1;
  5282 + uint8_t buf[10];
  5283 +
5158 5284 qemu_put_be32(f, phys_ram_size);
5159   - for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
5160   - ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
  5285 + if (ram_compress_open(s, f) < 0)
  5286 + return;
  5287 + for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) {
  5288 +#if 0
  5289 + if (tight_savevm_enabled) {
  5290 + int64_t sector_num;
  5291 + int j;
  5292 +
  5293 + /* find if the memory block is available on a virtual
  5294 + block device */
  5295 + sector_num = -1;
  5296 + for(j = 0; j < MAX_DISKS; j++) {
  5297 + if (bs_table[j]) {
  5298 + sector_num = bdrv_hash_find(bs_table[j],
  5299 + phys_ram_base + i, BDRV_HASH_BLOCK_SIZE);
  5300 + if (sector_num >= 0)
  5301 + break;
  5302 + }
  5303 + }
  5304 + if (j == MAX_DISKS)
  5305 + goto normal_compress;
  5306 + buf[0] = 1;
  5307 + buf[1] = j;
  5308 + cpu_to_be64wu((uint64_t *)(buf + 2), sector_num);
  5309 + ram_compress_buf(s, buf, 10);
  5310 + } else
  5311 +#endif
  5312 + {
  5313 + // normal_compress:
  5314 + buf[0] = 0;
  5315 + ram_compress_buf(s, buf, 1);
  5316 + ram_compress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE);
  5317 + }
5161 5318 }
  5319 + ram_compress_close(s);
5162 5320 }
5163 5321  
5164 5322 static int ram_load(QEMUFile *f, void *opaque, int version_id)
5165 5323 {
5166   - int i, ret;
  5324 + RamDecompressState s1, *s = &s1;
  5325 + uint8_t buf[10];
  5326 + int i;
5167 5327  
5168   - if (version_id != 1)
  5328 + if (version_id == 1)
  5329 + return ram_load_v1(f, opaque);
  5330 + if (version_id != 2)
5169 5331 return -EINVAL;
5170 5332 if (qemu_get_be32(f) != phys_ram_size)
5171 5333 return -EINVAL;
5172   - for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
5173   - ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
5174   - if (ret)
5175   - return ret;
  5334 + if (ram_decompress_open(s, f) < 0)
  5335 + return -EINVAL;
  5336 + for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) {
  5337 + if (ram_decompress_buf(s, buf, 1) < 0) {
  5338 + fprintf(stderr, "Error while reading ram block header\n");
  5339 + goto error;
  5340 + }
  5341 + if (buf[0] == 0) {
  5342 + if (ram_decompress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE) < 0) {
  5343 + fprintf(stderr, "Error while reading ram block address=0x%08x", i);
  5344 + goto error;
  5345 + }
  5346 + } else
  5347 +#if 0
  5348 + if (buf[0] == 1) {
  5349 + int bs_index;
  5350 + int64_t sector_num;
  5351 +
  5352 + ram_decompress_buf(s, buf + 1, 9);
  5353 + bs_index = buf[1];
  5354 + sector_num = be64_to_cpupu((const uint64_t *)(buf + 2));
  5355 + if (bs_index >= MAX_DISKS || bs_table[bs_index] == NULL) {
  5356 + fprintf(stderr, "Invalid block device index %d\n", bs_index);
  5357 + goto error;
  5358 + }
  5359 + if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i,
  5360 + BDRV_HASH_BLOCK_SIZE / 512) < 0) {
  5361 + fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n",
  5362 + bs_index, sector_num);
  5363 + goto error;
  5364 + }
  5365 + } else
  5366 +#endif
  5367 + {
  5368 + error:
  5369 + printf("Error block header\n");
  5370 + return -EINVAL;
  5371 + }
5176 5372 }
  5373 + ram_decompress_close(s);
5177 5374 return 0;
5178 5375 }
5179 5376  
... ... @@ -6612,8 +6809,8 @@ int main(int argc, char **argv)
6612 6809 }
6613 6810 }
6614 6811  
6615   - register_savevm("timer", 0, 1, timer_save, timer_load, NULL);
6616   - register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
  6812 + register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
  6813 + register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
6617 6814  
6618 6815 init_ioports();
6619 6816  
... ...