@@ -3843,15 +3843,8 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
return ret;
}
-/*
- * Unmap pages of memory from start to start+length such that
- * they a) read as 0, b) Trigger whatever fault mechanism
- * the OS provides for postcopy.
- * The pages must be unmapped by the end of the function.
- * Returns: 0 on success, none-0 on failure
- *
- */
-int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length)
+static int __ram_block_discard_range(RAMBlock *rb, uint64_t start,
+ size_t length, bool lazy)
{
int ret = -1;
@@ -3904,13 +3897,18 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length)
#endif
}
if (need_madvise) {
- /* For normal RAM this causes it to be unmapped,
+#ifdef CONFIG_MADVISE
+#ifdef MADV_FREE
+ int advice = (lazy && !need_fallocate) ? MADV_FREE : MADV_DONTNEED;
+#else
+ int advice = MADV_DONTNEED;
+#endif
+ /* For normal RAM this causes it to be lazy freed or unmapped,
* for shared memory it causes the local mapping to disappear
* and to fall back on the file contents (which we just
* fallocate'd away).
*/
-#if defined(CONFIG_MADVISE)
- ret = madvise(host_startaddr, length, MADV_DONTNEED);
+ ret = madvise(host_startaddr, length, advice);
if (ret) {
ret = -errno;
error_report("ram_block_discard_range: Failed to discard range "
@@ -3938,6 +3936,23 @@ err:
return ret;
}
+/*
+ * Unmap pages of memory from start to start+length such that
+ * they a) read as 0, b) Trigger whatever fault mechanism
+ * the OS provides for postcopy.
+ * The pages must be unmapped by the end of the function.
+ * Returns: 0 on success, none-0 on failure
+ *
+ */
+int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length)
+{
+ return __ram_block_discard_range(rb, start, length, false);
+}
+
+int ram_block_free_range(RAMBlock *rb, uint64_t start, size_t length)
+{
+ return __ram_block_discard_range(rb, start, length, true);
+}
bool ramblock_is_pmem(RAMBlock *rb)
{
return rb->flags & RAM_PMEM;
@@ -346,7 +346,7 @@ static void virtio_balloon_handle_report(VirtIODevice *vdev, VirtQueue *vq)
if ((ram_offset | size) & (rb_page_size - 1))
continue;
- ram_block_discard_range(rb, ram_offset, size);
+ ram_block_free_range(rb, ram_offset, size);
}
virtqueue_push(vq, elem, 0);
@@ -104,6 +104,7 @@ typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
+int ram_block_free_range(RAMBlock *rb, uint64_t start, size_t length);
#endif