diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2017-02-13 18:49:26 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2017-02-13 18:49:26 +0000 |
| commit | ec7a9bd5bb2c46c60cc0ec9b9d9f2ce404226ec0 (patch) | |
| tree | ae717012129be5c9c27827e1eab623ff467ddb1c /migration/qemu-file.c | |
| parent | 305e6c8a2ff7a6e3f4942b50e853230f18eeb5a9 (diff) | |
| parent | 982b78c5e37864c06fd7b5f156d80bf02628a855 (diff) | |
| download | focaccia-qemu-ec7a9bd5bb2c46c60cc0ec9b9d9f2ce404226ec0.tar.gz focaccia-qemu-ec7a9bd5bb2c46c60cc0ec9b9d9f2ce404226ec0.zip | |
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20170213a' into staging
Migration
Amit: migration: remove myself as maintainer
MAINTAINERS: update my email address
Ashijeet: migrate: Introduce zero RAM checks to skip RAM migration
Pavel: Postcopy release RAM
Halil: consolidate VMStateField.start
Hailiang: COLO: fix setting checkpoint-delay not working properly
COLO: Shutdown related socket fd while do failover
COLO: Don't process failover request while loading VM's state
Me:
migration: Add VMSTATE_UNUSED_VARRAY_UINT32
migration: Add VMSTATE_WITH_TMP
tests/migration: Add test for VMSTATE_WITH_TMP
virtio-net VMState conversion and new VMSTATE macros
# gpg: Signature made Mon 13 Feb 2017 17:36:39 GMT
# gpg: using RSA key 0x0516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7
* remotes/dgilbert/tags/pull-migration-20170213a:
virtio/migration: Migrate virtio-net to VMState
tests/migration: Add test for VMSTATE_WITH_TMP
migration: Add VMSTATE_WITH_TMP
migration: Add VMSTATE_UNUSED_VARRAY_UINT32
COLO: Don't process failover request while loading VM's state
COLO: Shutdown related socket fd while do failover
COLO: fix setting checkpoint-delay not working properly
migration: consolidate VMStateField.start
migrate: Introduce zero RAM checks to skip RAM migration
migration: discard non-dirty ram pages after the start of postcopy
add 'release-ram' migrate capability
migration: add MigrationState arg for ram_save_/compressed_/page()
MAINTAINERS: update my email address
migration: remove myself as maintainer
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'migration/qemu-file.c')
| -rw-r--r-- | migration/qemu-file.c | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/migration/qemu-file.c b/migration/qemu-file.c index e9fae31158..195fa94fcf 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -49,6 +49,7 @@ struct QEMUFile { int buf_size; /* 0 when writing */ uint8_t buf[IO_BUF_SIZE]; + DECLARE_BITMAP(may_free, MAX_IOV_SIZE); struct iovec iov[MAX_IOV_SIZE]; unsigned int iovcnt; @@ -132,6 +133,41 @@ bool qemu_file_is_writable(QEMUFile *f) return f->ops->writev_buffer; } +static void qemu_iovec_release_ram(QEMUFile *f) +{ + struct iovec iov; + unsigned long idx; + + /* Find and release all the contiguous memory ranges marked as may_free. */ + idx = find_next_bit(f->may_free, f->iovcnt, 0); + if (idx >= f->iovcnt) { + return; + } + iov = f->iov[idx]; + + /* The madvise() in the loop is called for iov within a continuous range and + * then reinitialize the iov. And in the end, madvise() is called for the + * last iov. + */ + while ((idx = find_next_bit(f->may_free, f->iovcnt, idx + 1)) < f->iovcnt) { + /* check for adjacent buffer and coalesce them */ + if (iov.iov_base + iov.iov_len == f->iov[idx].iov_base) { + iov.iov_len += f->iov[idx].iov_len; + continue; + } + if (qemu_madvise(iov.iov_base, iov.iov_len, QEMU_MADV_DONTNEED) < 0) { + error_report("migrate: madvise DONTNEED failed %p %zd: %s", + iov.iov_base, iov.iov_len, strerror(errno)); + } + iov = f->iov[idx]; + } + if (qemu_madvise(iov.iov_base, iov.iov_len, QEMU_MADV_DONTNEED) < 0) { + error_report("migrate: madvise DONTNEED failed %p %zd: %s", + iov.iov_base, iov.iov_len, strerror(errno)); + } + memset(f->may_free, 0, sizeof(f->may_free)); +} + /** * Flushes QEMUFile buffer * @@ -151,6 +187,8 @@ void qemu_fflush(QEMUFile *f) if (f->iovcnt > 0) { expect = iov_size(f->iov, f->iovcnt); ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos); + + qemu_iovec_release_ram(f); } if (ret >= 0) { @@ -304,13 +342,19 @@ int qemu_fclose(QEMUFile *f) return ret; } -static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size) +static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size, + bool may_free) { /* check for adjacent buffer and coalesce them */ if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base + - f->iov[f->iovcnt - 1].iov_len) { + f->iov[f->iovcnt - 1].iov_len && + may_free == test_bit(f->iovcnt - 1, f->may_free)) + { f->iov[f->iovcnt - 1].iov_len += size; } else { + if (may_free) { + set_bit(f->iovcnt, f->may_free); + } f->iov[f->iovcnt].iov_base = (uint8_t *)buf; f->iov[f->iovcnt++].iov_len = size; } @@ -320,14 +364,15 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size) } } -void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size) +void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size, + bool may_free) { if (f->last_error) { return; } f->bytes_xfer += size; - add_to_iovec(f, buf, size); + add_to_iovec(f, buf, size, may_free); } void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size) @@ -345,7 +390,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size) } memcpy(f->buf + f->buf_index, buf, l); f->bytes_xfer += l; - add_to_iovec(f, f->buf + f->buf_index, l); + add_to_iovec(f, f->buf + f->buf_index, l, false); f->buf_index += l; if (f->buf_index == IO_BUF_SIZE) { qemu_fflush(f); @@ -366,7 +411,7 @@ void qemu_put_byte(QEMUFile *f, int v) f->buf[f->buf_index] = v; f->bytes_xfer++; - add_to_iovec(f, f->buf + f->buf_index, 1); + add_to_iovec(f, f->buf + f->buf_index, 1, false); f->buf_index++; if (f->buf_index == IO_BUF_SIZE) { qemu_fflush(f); @@ -647,7 +692,7 @@ ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size, } qemu_put_be32(f, blen); if (f->ops->writev_buffer) { - add_to_iovec(f, f->buf + f->buf_index, blen); + add_to_iovec(f, f->buf + f->buf_index, blen, false); } f->buf_index += blen; if (f->buf_index == IO_BUF_SIZE) { |