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