|
33 | 33 | #include "options.h"
|
34 | 34 | #include "qapi/error.h"
|
35 | 35 | #include "rdma.h"
|
| 36 | +#include "io/channel-file.h" |
36 | 37 |
|
37 | 38 | #define IO_BUF_SIZE 32768
|
38 | 39 | #define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 64)
|
@@ -255,6 +256,10 @@ static void qemu_iovec_release_ram(QEMUFile *f)
|
255 | 256 | memset(f->may_free, 0, sizeof(f->may_free));
|
256 | 257 | }
|
257 | 258 |
|
| 259 | +bool qemu_file_is_seekable(QEMUFile *f) |
| 260 | +{ |
| 261 | + return qio_channel_has_feature(f->ioc, QIO_CHANNEL_FEATURE_SEEKABLE); |
| 262 | +} |
258 | 263 |
|
259 | 264 | /**
|
260 | 265 | * Flushes QEMUFile buffer
|
@@ -447,6 +452,107 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size)
|
447 | 452 | }
|
448 | 453 | }
|
449 | 454 |
|
| 455 | +void qemu_put_buffer_at(QEMUFile *f, const uint8_t *buf, size_t buflen, |
| 456 | + off_t pos) |
| 457 | +{ |
| 458 | + Error *err = NULL; |
| 459 | + size_t ret; |
| 460 | + |
| 461 | + if (f->last_error) { |
| 462 | + return; |
| 463 | + } |
| 464 | + |
| 465 | + qemu_fflush(f); |
| 466 | + ret = qio_channel_pwrite(f->ioc, (char *)buf, buflen, pos, &err); |
| 467 | + |
| 468 | + if (err) { |
| 469 | + qemu_file_set_error_obj(f, -EIO, err); |
| 470 | + return; |
| 471 | + } |
| 472 | + |
| 473 | + if ((ssize_t)ret == QIO_CHANNEL_ERR_BLOCK) { |
| 474 | + qemu_file_set_error_obj(f, -EAGAIN, NULL); |
| 475 | + return; |
| 476 | + } |
| 477 | + |
| 478 | + if (ret != buflen) { |
| 479 | + error_setg(&err, "Partial write of size %zu, expected %zu", ret, |
| 480 | + buflen); |
| 481 | + qemu_file_set_error_obj(f, -EIO, err); |
| 482 | + return; |
| 483 | + } |
| 484 | + |
| 485 | + stat64_add(&mig_stats.qemu_file_transferred, buflen); |
| 486 | + |
| 487 | + return; |
| 488 | +} |
| 489 | + |
| 490 | + |
| 491 | +size_t qemu_get_buffer_at(QEMUFile *f, const uint8_t *buf, size_t buflen, |
| 492 | + off_t pos) |
| 493 | +{ |
| 494 | + Error *err = NULL; |
| 495 | + size_t ret; |
| 496 | + |
| 497 | + if (f->last_error) { |
| 498 | + return 0; |
| 499 | + } |
| 500 | + |
| 501 | + ret = qio_channel_pread(f->ioc, (char *)buf, buflen, pos, &err); |
| 502 | + |
| 503 | + if ((ssize_t)ret == -1 || err) { |
| 504 | + qemu_file_set_error_obj(f, -EIO, err); |
| 505 | + return 0; |
| 506 | + } |
| 507 | + |
| 508 | + if ((ssize_t)ret == QIO_CHANNEL_ERR_BLOCK) { |
| 509 | + qemu_file_set_error_obj(f, -EAGAIN, NULL); |
| 510 | + return 0; |
| 511 | + } |
| 512 | + |
| 513 | + if (ret != buflen) { |
| 514 | + error_setg(&err, "Partial read of size %zu, expected %zu", ret, buflen); |
| 515 | + qemu_file_set_error_obj(f, -EIO, err); |
| 516 | + return 0; |
| 517 | + } |
| 518 | + |
| 519 | + return ret; |
| 520 | +} |
| 521 | + |
| 522 | +void qemu_set_offset(QEMUFile *f, off_t off, int whence) |
| 523 | +{ |
| 524 | + Error *err = NULL; |
| 525 | + off_t ret; |
| 526 | + |
| 527 | + if (qemu_file_is_writable(f)) { |
| 528 | + qemu_fflush(f); |
| 529 | + } else { |
| 530 | + /* Drop all cached buffers if existed; will trigger a re-fill later */ |
| 531 | + f->buf_index = 0; |
| 532 | + f->buf_size = 0; |
| 533 | + } |
| 534 | + |
| 535 | + ret = qio_channel_io_seek(f->ioc, off, whence, &err); |
| 536 | + if (ret == (off_t)-1) { |
| 537 | + qemu_file_set_error_obj(f, -EIO, err); |
| 538 | + } |
| 539 | +} |
| 540 | + |
| 541 | +off_t qemu_get_offset(QEMUFile *f) |
| 542 | +{ |
| 543 | + Error *err = NULL; |
| 544 | + off_t ret; |
| 545 | + |
| 546 | + qemu_fflush(f); |
| 547 | + |
| 548 | + ret = qio_channel_io_seek(f->ioc, 0, SEEK_CUR, &err); |
| 549 | + if (ret == (off_t)-1) { |
| 550 | + qemu_file_set_error_obj(f, -EIO, err); |
| 551 | + } |
| 552 | + return ret; |
| 553 | +} |
| 554 | + |
| 555 | + |
450 | 556 | void qemu_put_byte(QEMUFile *f, int v)
|
451 | 557 | {
|
452 | 558 | if (f->last_error) {
|
|
0 commit comments