The new flag will make qemu_ram_free() discard the contents of the block. It will be used to let QEMU be configured to avoid flushing file contents to disk when exiting. As MADV_REMOVE is not always supported, the new code will try MADV_NOTNEEDED in case MADV_REMOVE fails.
The new flag will also indicate that ram_block_discard_range() can use MADV_REMOVE when discarding memory pages. I have considered calling MADV_REMOVE unconditionally (as destroying the RAM contents seems to be OK every time ram_block_discard_range() is called), but for safety I decided to restrict the new code to blocks having RAM_NONPERSISTENT set. Signed-off-by: Eduardo Habkost <ehabk...@redhat.com> --- exec.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 585d6ed6d7..a6e9ed4ece 100644 --- a/exec.c +++ b/exec.c @@ -102,6 +102,11 @@ static MemoryRegion io_mem_unassigned; */ #define RAM_RESIZEABLE (1 << 2) +/* RAMBlock contents are not persistent, and we can discard memory contents + * when freeing the memory block. + */ +#define RAM_NONPERSISTENT (1 << 3) + #endif #ifdef TARGET_PAGE_BITS_VARY @@ -2061,6 +2066,10 @@ void qemu_ram_free(RAMBlock *block) ram_block_notify_remove(block->host, block->max_length); } + if (block->flags & RAM_NONPERSISTENT) { + ram_block_discard_range(block, 0, block->max_length); + } + qemu_mutex_lock_ramlist(); QLIST_REMOVE_RCU(block, next); ram_list.mru_block = NULL; @@ -3537,7 +3546,13 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) /* Note: We need the madvise MADV_DONTNEED behaviour of definitely * freeing the page. */ - ret = madvise(host_startaddr, length, MADV_DONTNEED); + if (rb->flags & RAM_NONPERSISTENT) { + ret = madvise(host_startaddr, length, MADV_REMOVE); + } + /* Fallback to MADV_DONTNEED if MADV_REMOVE fails */ + if (ret || !(rb->flags & RAM_NONPERSISTENT)) { + ret = madvise(host_startaddr, length, MADV_DONTNEED); + } #endif } else { /* Huge page case - unfortunately it can't do DONTNEED, but -- 2.11.0.259.g40922b1