1 /* 2 * VMStateInfo's for basic typse 3 * 4 * Copyright (c) 2009-2017 Red Hat Inc 5 * 6 * Authors: 7 * Juan Quintela <quintela@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qemu/cpu-float.h" 15 #include "qemu-file.h" 16 #include "migration.h" 17 #include "migration/vmstate.h" 18 #include "qemu/error-report.h" 19 #include "qemu/queue.h" 20 #include "trace.h" 21 22 /* bool */ 23 24 static int get_bool(QEMUFile *f, void *pv, size_t size, 25 const VMStateField *field) 26 { 27 bool *v = pv; 28 *v = qemu_get_byte(f); 29 return 0; 30 } 31 32 static int put_bool(QEMUFile *f, void *pv, size_t size, 33 const VMStateField *field, JSONWriter *vmdesc) 34 { 35 bool *v = pv; 36 qemu_put_byte(f, *v); 37 return 0; 38 } 39 40 const VMStateInfo vmstate_info_bool = { 41 .name = "bool", 42 .get = get_bool, 43 .put = put_bool, 44 }; 45 46 /* 8 bit int */ 47 48 static int get_int8(QEMUFile *f, void *pv, size_t size, 49 const VMStateField *field) 50 { 51 int8_t *v = pv; 52 qemu_get_s8s(f, v); 53 return 0; 54 } 55 56 static int put_int8(QEMUFile *f, void *pv, size_t size, 57 const VMStateField *field, JSONWriter *vmdesc) 58 { 59 int8_t *v = pv; 60 qemu_put_s8s(f, v); 61 return 0; 62 } 63 64 const VMStateInfo vmstate_info_int8 = { 65 .name = "int8", 66 .get = get_int8, 67 .put = put_int8, 68 }; 69 70 /* 16 bit int */ 71 72 static int get_int16(QEMUFile *f, void *pv, size_t size, 73 const VMStateField *field) 74 { 75 int16_t *v = pv; 76 qemu_get_sbe16s(f, v); 77 return 0; 78 } 79 80 static int put_int16(QEMUFile *f, void *pv, size_t size, 81 const VMStateField *field, JSONWriter *vmdesc) 82 { 83 int16_t *v = pv; 84 qemu_put_sbe16s(f, v); 85 return 0; 86 } 87 88 const VMStateInfo vmstate_info_int16 = { 89 .name = "int16", 90 .get = get_int16, 91 .put = put_int16, 92 }; 93 94 /* 32 bit int */ 95 96 static int get_int32(QEMUFile *f, void *pv, size_t size, 97 const VMStateField *field) 98 { 99 int32_t *v = pv; 100 qemu_get_sbe32s(f, v); 101 return 0; 102 } 103 104 static int put_int32(QEMUFile *f, void *pv, size_t size, 105 const VMStateField *field, JSONWriter *vmdesc) 106 { 107 int32_t *v = pv; 108 qemu_put_sbe32s(f, v); 109 return 0; 110 } 111 112 const VMStateInfo vmstate_info_int32 = { 113 .name = "int32", 114 .get = get_int32, 115 .put = put_int32, 116 }; 117 118 /* 32 bit int. See that the received value is the same than the one 119 in the field */ 120 121 static int get_int32_equal(QEMUFile *f, void *pv, size_t size, 122 const VMStateField *field) 123 { 124 int32_t *v = pv; 125 int32_t v2; 126 qemu_get_sbe32s(f, &v2); 127 128 if (*v == v2) { 129 return 0; 130 } 131 error_report("%" PRIx32 " != %" PRIx32, *v, v2); 132 if (field->err_hint) { 133 error_printf("%s\n", field->err_hint); 134 } 135 return -EINVAL; 136 } 137 138 const VMStateInfo vmstate_info_int32_equal = { 139 .name = "int32 equal", 140 .get = get_int32_equal, 141 .put = put_int32, 142 }; 143 144 /* 32 bit int. Check that the received value is non-negative 145 * and less than or equal to the one in the field. 146 */ 147 148 static int get_int32_le(QEMUFile *f, void *pv, size_t size, 149 const VMStateField *field) 150 { 151 int32_t *cur = pv; 152 int32_t loaded; 153 qemu_get_sbe32s(f, &loaded); 154 155 if (loaded >= 0 && loaded <= *cur) { 156 *cur = loaded; 157 return 0; 158 } 159 error_report("Invalid value %" PRId32 160 " expecting positive value <= %" PRId32, 161 loaded, *cur); 162 return -EINVAL; 163 } 164 165 const VMStateInfo vmstate_info_int32_le = { 166 .name = "int32 le", 167 .get = get_int32_le, 168 .put = put_int32, 169 }; 170 171 /* 64 bit int */ 172 173 static int get_int64(QEMUFile *f, void *pv, size_t size, 174 const VMStateField *field) 175 { 176 int64_t *v = pv; 177 qemu_get_sbe64s(f, v); 178 return 0; 179 } 180 181 static int put_int64(QEMUFile *f, void *pv, size_t size, 182 const VMStateField *field, JSONWriter *vmdesc) 183 { 184 int64_t *v = pv; 185 qemu_put_sbe64s(f, v); 186 return 0; 187 } 188 189 const VMStateInfo vmstate_info_int64 = { 190 .name = "int64", 191 .get = get_int64, 192 .put = put_int64, 193 }; 194 195 /* 8 bit unsigned int */ 196 197 static int get_uint8(QEMUFile *f, void *pv, size_t size, 198 const VMStateField *field) 199 { 200 uint8_t *v = pv; 201 qemu_get_8s(f, v); 202 return 0; 203 } 204 205 static int put_uint8(QEMUFile *f, void *pv, size_t size, 206 const VMStateField *field, JSONWriter *vmdesc) 207 { 208 uint8_t *v = pv; 209 qemu_put_8s(f, v); 210 return 0; 211 } 212 213 const VMStateInfo vmstate_info_uint8 = { 214 .name = "uint8", 215 .get = get_uint8, 216 .put = put_uint8, 217 }; 218 219 /* 16 bit unsigned int */ 220 221 static int get_uint16(QEMUFile *f, void *pv, size_t size, 222 const VMStateField *field) 223 { 224 uint16_t *v = pv; 225 qemu_get_be16s(f, v); 226 return 0; 227 } 228 229 static int put_uint16(QEMUFile *f, void *pv, size_t size, 230 const VMStateField *field, JSONWriter *vmdesc) 231 { 232 uint16_t *v = pv; 233 qemu_put_be16s(f, v); 234 return 0; 235 } 236 237 const VMStateInfo vmstate_info_uint16 = { 238 .name = "uint16", 239 .get = get_uint16, 240 .put = put_uint16, 241 }; 242 243 /* 32 bit unsigned int */ 244 245 static int get_uint32(QEMUFile *f, void *pv, size_t size, 246 const VMStateField *field) 247 { 248 uint32_t *v = pv; 249 qemu_get_be32s(f, v); 250 return 0; 251 } 252 253 static int put_uint32(QEMUFile *f, void *pv, size_t size, 254 const VMStateField *field, JSONWriter *vmdesc) 255 { 256 uint32_t *v = pv; 257 qemu_put_be32s(f, v); 258 return 0; 259 } 260 261 const VMStateInfo vmstate_info_uint32 = { 262 .name = "uint32", 263 .get = get_uint32, 264 .put = put_uint32, 265 }; 266 267 /* 32 bit uint. See that the received value is the same than the one 268 in the field */ 269 270 static int get_uint32_equal(QEMUFile *f, void *pv, size_t size, 271 const VMStateField *field) 272 { 273 uint32_t *v = pv; 274 uint32_t v2; 275 qemu_get_be32s(f, &v2); 276 277 if (*v == v2) { 278 return 0; 279 } 280 error_report("%" PRIx32 " != %" PRIx32, *v, v2); 281 if (field->err_hint) { 282 error_printf("%s\n", field->err_hint); 283 } 284 return -EINVAL; 285 } 286 287 const VMStateInfo vmstate_info_uint32_equal = { 288 .name = "uint32 equal", 289 .get = get_uint32_equal, 290 .put = put_uint32, 291 }; 292 293 /* 64 bit unsigned int */ 294 295 static int get_uint64(QEMUFile *f, void *pv, size_t size, 296 const VMStateField *field) 297 { 298 uint64_t *v = pv; 299 qemu_get_be64s(f, v); 300 return 0; 301 } 302 303 static int put_uint64(QEMUFile *f, void *pv, size_t size, 304 const VMStateField *field, JSONWriter *vmdesc) 305 { 306 uint64_t *v = pv; 307 qemu_put_be64s(f, v); 308 return 0; 309 } 310 311 const VMStateInfo vmstate_info_uint64 = { 312 .name = "uint64", 313 .get = get_uint64, 314 .put = put_uint64, 315 }; 316 317 static int get_nullptr(QEMUFile *f, void *pv, size_t size, 318 const VMStateField *field) 319 320 { 321 if (qemu_get_byte(f) == VMS_NULLPTR_MARKER) { 322 return 0; 323 } 324 error_report("vmstate: get_nullptr expected VMS_NULLPTR_MARKER"); 325 return -EINVAL; 326 } 327 328 static int put_nullptr(QEMUFile *f, void *pv, size_t size, 329 const VMStateField *field, JSONWriter *vmdesc) 330 331 { 332 if (pv == NULL) { 333 qemu_put_byte(f, VMS_NULLPTR_MARKER); 334 return 0; 335 } 336 error_report("vmstate: put_nullptr must be called with pv == NULL"); 337 return -EINVAL; 338 } 339 340 const VMStateInfo vmstate_info_nullptr = { 341 .name = "uint64", 342 .get = get_nullptr, 343 .put = put_nullptr, 344 }; 345 346 /* 64 bit unsigned int. See that the received value is the same than the one 347 in the field */ 348 349 static int get_uint64_equal(QEMUFile *f, void *pv, size_t size, 350 const VMStateField *field) 351 { 352 uint64_t *v = pv; 353 uint64_t v2; 354 qemu_get_be64s(f, &v2); 355 356 if (*v == v2) { 357 return 0; 358 } 359 error_report("%" PRIx64 " != %" PRIx64, *v, v2); 360 if (field->err_hint) { 361 error_printf("%s\n", field->err_hint); 362 } 363 return -EINVAL; 364 } 365 366 const VMStateInfo vmstate_info_uint64_equal = { 367 .name = "int64 equal", 368 .get = get_uint64_equal, 369 .put = put_uint64, 370 }; 371 372 /* 8 bit int. See that the received value is the same than the one 373 in the field */ 374 375 static int get_uint8_equal(QEMUFile *f, void *pv, size_t size, 376 const VMStateField *field) 377 { 378 uint8_t *v = pv; 379 uint8_t v2; 380 qemu_get_8s(f, &v2); 381 382 if (*v == v2) { 383 return 0; 384 } 385 error_report("%x != %x", *v, v2); 386 if (field->err_hint) { 387 error_printf("%s\n", field->err_hint); 388 } 389 return -EINVAL; 390 } 391 392 const VMStateInfo vmstate_info_uint8_equal = { 393 .name = "uint8 equal", 394 .get = get_uint8_equal, 395 .put = put_uint8, 396 }; 397 398 /* 16 bit unsigned int int. See that the received value is the same than the one 399 in the field */ 400 401 static int get_uint16_equal(QEMUFile *f, void *pv, size_t size, 402 const VMStateField *field) 403 { 404 uint16_t *v = pv; 405 uint16_t v2; 406 qemu_get_be16s(f, &v2); 407 408 if (*v == v2) { 409 return 0; 410 } 411 error_report("%x != %x", *v, v2); 412 if (field->err_hint) { 413 error_printf("%s\n", field->err_hint); 414 } 415 return -EINVAL; 416 } 417 418 const VMStateInfo vmstate_info_uint16_equal = { 419 .name = "uint16 equal", 420 .get = get_uint16_equal, 421 .put = put_uint16, 422 }; 423 424 /* CPU_DoubleU type */ 425 426 static int get_cpudouble(QEMUFile *f, void *pv, size_t size, 427 const VMStateField *field) 428 { 429 CPU_DoubleU *v = pv; 430 qemu_get_be32s(f, &v->l.upper); 431 qemu_get_be32s(f, &v->l.lower); 432 return 0; 433 } 434 435 static int put_cpudouble(QEMUFile *f, void *pv, size_t size, 436 const VMStateField *field, JSONWriter *vmdesc) 437 { 438 CPU_DoubleU *v = pv; 439 qemu_put_be32s(f, &v->l.upper); 440 qemu_put_be32s(f, &v->l.lower); 441 return 0; 442 } 443 444 const VMStateInfo vmstate_info_cpudouble = { 445 .name = "CPU_Double_U", 446 .get = get_cpudouble, 447 .put = put_cpudouble, 448 }; 449 450 /* uint8_t buffers */ 451 452 static int get_buffer(QEMUFile *f, void *pv, size_t size, 453 const VMStateField *field) 454 { 455 uint8_t *v = pv; 456 qemu_get_buffer(f, v, size); 457 return 0; 458 } 459 460 static int put_buffer(QEMUFile *f, void *pv, size_t size, 461 const VMStateField *field, JSONWriter *vmdesc) 462 { 463 uint8_t *v = pv; 464 qemu_put_buffer(f, v, size); 465 return 0; 466 } 467 468 const VMStateInfo vmstate_info_buffer = { 469 .name = "buffer", 470 .get = get_buffer, 471 .put = put_buffer, 472 }; 473 474 /* unused buffers: space that was used for some fields that are 475 not useful anymore */ 476 477 static int get_unused_buffer(QEMUFile *f, void *pv, size_t size, 478 const VMStateField *field) 479 { 480 uint8_t buf[1024]; 481 int block_len; 482 483 while (size > 0) { 484 block_len = MIN(sizeof(buf), size); 485 size -= block_len; 486 qemu_get_buffer(f, buf, block_len); 487 } 488 return 0; 489 } 490 491 static int put_unused_buffer(QEMUFile *f, void *pv, size_t size, 492 const VMStateField *field, JSONWriter *vmdesc) 493 { 494 static const uint8_t buf[1024]; 495 int block_len; 496 497 while (size > 0) { 498 block_len = MIN(sizeof(buf), size); 499 size -= block_len; 500 qemu_put_buffer(f, buf, block_len); 501 } 502 503 return 0; 504 } 505 506 const VMStateInfo vmstate_info_unused_buffer = { 507 .name = "unused_buffer", 508 .get = get_unused_buffer, 509 .put = put_unused_buffer, 510 }; 511 512 /* vmstate_info_tmp, see VMSTATE_WITH_TMP, the idea is that we allocate 513 * a temporary buffer and the pre_load/pre_save methods in the child vmsd 514 * copy stuff from the parent into the child and do calculations to fill 515 * in fields that don't really exist in the parent but need to be in the 516 * stream. 517 */ 518 static int get_tmp(QEMUFile *f, void *pv, size_t size, 519 const VMStateField *field) 520 { 521 int ret; 522 const VMStateDescription *vmsd = field->vmsd; 523 int version_id = field->version_id; 524 void *tmp = g_malloc(size); 525 526 /* Writes the parent field which is at the start of the tmp */ 527 *(void **)tmp = pv; 528 ret = vmstate_load_state(f, vmsd, tmp, version_id); 529 g_free(tmp); 530 return ret; 531 } 532 533 static int put_tmp(QEMUFile *f, void *pv, size_t size, 534 const VMStateField *field, JSONWriter *vmdesc) 535 { 536 const VMStateDescription *vmsd = field->vmsd; 537 void *tmp = g_malloc(size); 538 int ret; 539 540 /* Writes the parent field which is at the start of the tmp */ 541 *(void **)tmp = pv; 542 ret = vmstate_save_state(f, vmsd, tmp, vmdesc); 543 g_free(tmp); 544 545 return ret; 546 } 547 548 const VMStateInfo vmstate_info_tmp = { 549 .name = "tmp", 550 .get = get_tmp, 551 .put = put_tmp, 552 }; 553 554 /* bitmaps (as defined by bitmap.h). Note that size here is the size 555 * of the bitmap in bits. The on-the-wire format of a bitmap is 64 556 * bit words with the bits in big endian order. The in-memory format 557 * is an array of 'unsigned long', which may be either 32 or 64 bits. 558 */ 559 /* This is the number of 64 bit words sent over the wire */ 560 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) 561 static int get_bitmap(QEMUFile *f, void *pv, size_t size, 562 const VMStateField *field) 563 { 564 unsigned long *bmp = pv; 565 int i, idx = 0; 566 for (i = 0; i < BITS_TO_U64S(size); i++) { 567 uint64_t w = qemu_get_be64(f); 568 bmp[idx++] = w; 569 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) { 570 bmp[idx++] = w >> 32; 571 } 572 } 573 return 0; 574 } 575 576 static int put_bitmap(QEMUFile *f, void *pv, size_t size, 577 const VMStateField *field, JSONWriter *vmdesc) 578 { 579 unsigned long *bmp = pv; 580 int i, idx = 0; 581 for (i = 0; i < BITS_TO_U64S(size); i++) { 582 uint64_t w = bmp[idx++]; 583 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) { 584 w |= ((uint64_t)bmp[idx++]) << 32; 585 } 586 qemu_put_be64(f, w); 587 } 588 589 return 0; 590 } 591 592 const VMStateInfo vmstate_info_bitmap = { 593 .name = "bitmap", 594 .get = get_bitmap, 595 .put = put_bitmap, 596 }; 597 598 /* get for QTAILQ 599 * meta data about the QTAILQ is encoded in a VMStateField structure 600 */ 601 static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size, 602 const VMStateField *field) 603 { 604 int ret = 0; 605 const VMStateDescription *vmsd = field->vmsd; 606 /* size of a QTAILQ element */ 607 size_t size = field->size; 608 /* offset of the QTAILQ entry in a QTAILQ element */ 609 size_t entry_offset = field->start; 610 int version_id = field->version_id; 611 void *elm; 612 613 trace_get_qtailq(vmsd->name, version_id); 614 if (version_id > vmsd->version_id) { 615 error_report("%s %s", vmsd->name, "too new"); 616 trace_get_qtailq_end(vmsd->name, "too new", -EINVAL); 617 618 return -EINVAL; 619 } 620 if (version_id < vmsd->minimum_version_id) { 621 error_report("%s %s", vmsd->name, "too old"); 622 trace_get_qtailq_end(vmsd->name, "too old", -EINVAL); 623 return -EINVAL; 624 } 625 626 while (qemu_get_byte(f)) { 627 elm = g_malloc(size); 628 ret = vmstate_load_state(f, vmsd, elm, version_id); 629 if (ret) { 630 return ret; 631 } 632 QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset); 633 } 634 635 trace_get_qtailq_end(vmsd->name, "end", ret); 636 return ret; 637 } 638 639 /* put for QTAILQ */ 640 static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size, 641 const VMStateField *field, JSONWriter *vmdesc) 642 { 643 const VMStateDescription *vmsd = field->vmsd; 644 /* offset of the QTAILQ entry in a QTAILQ element*/ 645 size_t entry_offset = field->start; 646 void *elm; 647 int ret; 648 649 trace_put_qtailq(vmsd->name, vmsd->version_id); 650 651 QTAILQ_RAW_FOREACH(elm, pv, entry_offset) { 652 qemu_put_byte(f, true); 653 ret = vmstate_save_state(f, vmsd, elm, vmdesc); 654 if (ret) { 655 return ret; 656 } 657 } 658 qemu_put_byte(f, false); 659 660 trace_put_qtailq_end(vmsd->name, "end"); 661 662 return 0; 663 } 664 const VMStateInfo vmstate_info_qtailq = { 665 .name = "qtailq", 666 .get = get_qtailq, 667 .put = put_qtailq, 668 }; 669 670 struct put_gtree_data { 671 QEMUFile *f; 672 const VMStateDescription *key_vmsd; 673 const VMStateDescription *val_vmsd; 674 JSONWriter *vmdesc; 675 int ret; 676 }; 677 678 static gboolean put_gtree_elem(gpointer key, gpointer value, gpointer data) 679 { 680 struct put_gtree_data *capsule = (struct put_gtree_data *)data; 681 QEMUFile *f = capsule->f; 682 int ret; 683 684 qemu_put_byte(f, true); 685 686 /* put the key */ 687 if (!capsule->key_vmsd) { 688 qemu_put_be64(f, (uint64_t)(uintptr_t)(key)); /* direct key */ 689 } else { 690 ret = vmstate_save_state(f, capsule->key_vmsd, key, capsule->vmdesc); 691 if (ret) { 692 capsule->ret = ret; 693 return true; 694 } 695 } 696 697 /* put the data */ 698 ret = vmstate_save_state(f, capsule->val_vmsd, value, capsule->vmdesc); 699 if (ret) { 700 capsule->ret = ret; 701 return true; 702 } 703 return false; 704 } 705 706 static int put_gtree(QEMUFile *f, void *pv, size_t unused_size, 707 const VMStateField *field, JSONWriter *vmdesc) 708 { 709 bool direct_key = (!field->start); 710 const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1]; 711 const VMStateDescription *val_vmsd = &field->vmsd[0]; 712 const char *key_vmsd_name = direct_key ? "direct" : key_vmsd->name; 713 struct put_gtree_data capsule = { 714 .f = f, 715 .key_vmsd = key_vmsd, 716 .val_vmsd = val_vmsd, 717 .vmdesc = vmdesc, 718 .ret = 0}; 719 GTree **pval = pv; 720 GTree *tree = *pval; 721 uint32_t nnodes = g_tree_nnodes(tree); 722 int ret; 723 724 trace_put_gtree(field->name, key_vmsd_name, val_vmsd->name, nnodes); 725 qemu_put_be32(f, nnodes); 726 g_tree_foreach(tree, put_gtree_elem, (gpointer)&capsule); 727 qemu_put_byte(f, false); 728 ret = capsule.ret; 729 if (ret) { 730 error_report("%s : failed to save gtree (%d)", field->name, ret); 731 } 732 trace_put_gtree_end(field->name, key_vmsd_name, val_vmsd->name, ret); 733 return ret; 734 } 735 736 static int get_gtree(QEMUFile *f, void *pv, size_t unused_size, 737 const VMStateField *field) 738 { 739 bool direct_key = (!field->start); 740 const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1]; 741 const VMStateDescription *val_vmsd = &field->vmsd[0]; 742 const char *key_vmsd_name = direct_key ? "direct" : key_vmsd->name; 743 int version_id = field->version_id; 744 size_t key_size = field->start; 745 size_t val_size = field->size; 746 int nnodes, count = 0; 747 GTree **pval = pv; 748 GTree *tree = *pval; 749 void *key, *val; 750 int ret = 0; 751 752 /* in case of direct key, the key vmsd can be {}, ie. check fields */ 753 if (!direct_key && version_id > key_vmsd->version_id) { 754 error_report("%s %s", key_vmsd->name, "too new"); 755 return -EINVAL; 756 } 757 if (!direct_key && version_id < key_vmsd->minimum_version_id) { 758 error_report("%s %s", key_vmsd->name, "too old"); 759 return -EINVAL; 760 } 761 if (version_id > val_vmsd->version_id) { 762 error_report("%s %s", val_vmsd->name, "too new"); 763 return -EINVAL; 764 } 765 if (version_id < val_vmsd->minimum_version_id) { 766 error_report("%s %s", val_vmsd->name, "too old"); 767 return -EINVAL; 768 } 769 770 nnodes = qemu_get_be32(f); 771 trace_get_gtree(field->name, key_vmsd_name, val_vmsd->name, nnodes); 772 773 while (qemu_get_byte(f)) { 774 if ((++count) > nnodes) { 775 ret = -EINVAL; 776 break; 777 } 778 if (direct_key) { 779 key = (void *)(uintptr_t)qemu_get_be64(f); 780 } else { 781 key = g_malloc0(key_size); 782 ret = vmstate_load_state(f, key_vmsd, key, version_id); 783 if (ret) { 784 error_report("%s : failed to load %s (%d)", 785 field->name, key_vmsd->name, ret); 786 goto key_error; 787 } 788 } 789 val = g_malloc0(val_size); 790 ret = vmstate_load_state(f, val_vmsd, val, version_id); 791 if (ret) { 792 error_report("%s : failed to load %s (%d)", 793 field->name, val_vmsd->name, ret); 794 goto val_error; 795 } 796 g_tree_insert(tree, key, val); 797 } 798 if (count != nnodes) { 799 error_report("%s inconsistent stream when loading the gtree", 800 field->name); 801 return -EINVAL; 802 } 803 trace_get_gtree_end(field->name, key_vmsd_name, val_vmsd->name, ret); 804 return ret; 805 val_error: 806 g_free(val); 807 key_error: 808 if (!direct_key) { 809 g_free(key); 810 } 811 trace_get_gtree_end(field->name, key_vmsd_name, val_vmsd->name, ret); 812 return ret; 813 } 814 815 816 const VMStateInfo vmstate_info_gtree = { 817 .name = "gtree", 818 .get = get_gtree, 819 .put = put_gtree, 820 }; 821 822 static int put_qlist(QEMUFile *f, void *pv, size_t unused_size, 823 const VMStateField *field, JSONWriter *vmdesc) 824 { 825 const VMStateDescription *vmsd = field->vmsd; 826 /* offset of the QTAILQ entry in a QTAILQ element*/ 827 size_t entry_offset = field->start; 828 void *elm; 829 int ret; 830 831 trace_put_qlist(field->name, vmsd->name, vmsd->version_id); 832 QLIST_RAW_FOREACH(elm, pv, entry_offset) { 833 qemu_put_byte(f, true); 834 ret = vmstate_save_state(f, vmsd, elm, vmdesc); 835 if (ret) { 836 error_report("%s: failed to save %s (%d)", field->name, 837 vmsd->name, ret); 838 return ret; 839 } 840 } 841 qemu_put_byte(f, false); 842 trace_put_qlist_end(field->name, vmsd->name); 843 844 return 0; 845 } 846 847 static int get_qlist(QEMUFile *f, void *pv, size_t unused_size, 848 const VMStateField *field) 849 { 850 int ret = 0; 851 const VMStateDescription *vmsd = field->vmsd; 852 /* size of a QLIST element */ 853 size_t size = field->size; 854 /* offset of the QLIST entry in a QLIST element */ 855 size_t entry_offset = field->start; 856 int version_id = field->version_id; 857 void *elm, *prev = NULL; 858 859 trace_get_qlist(field->name, vmsd->name, vmsd->version_id); 860 if (version_id > vmsd->version_id) { 861 error_report("%s %s", vmsd->name, "too new"); 862 return -EINVAL; 863 } 864 if (version_id < vmsd->minimum_version_id) { 865 error_report("%s %s", vmsd->name, "too old"); 866 return -EINVAL; 867 } 868 869 while (qemu_get_byte(f)) { 870 elm = g_malloc(size); 871 ret = vmstate_load_state(f, vmsd, elm, version_id); 872 if (ret) { 873 error_report("%s: failed to load %s (%d)", field->name, 874 vmsd->name, ret); 875 g_free(elm); 876 return ret; 877 } 878 if (!prev) { 879 QLIST_RAW_INSERT_HEAD(pv, elm, entry_offset); 880 } else { 881 QLIST_RAW_INSERT_AFTER(pv, prev, elm, entry_offset); 882 } 883 prev = elm; 884 } 885 trace_get_qlist_end(field->name, vmsd->name); 886 887 return ret; 888 } 889 890 const VMStateInfo vmstate_info_qlist = { 891 .name = "qlist", 892 .get = get_qlist, 893 .put = put_qlist, 894 }; 895