Changeset
linux-user/mmap.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
Git apply log
Switched to a new branch '20180516152708.9ECB1A5D5F2@smcpolin-M01.vmware.com'
Applying: linux-user: Remove extra mapping
To https://github.com/patchew-project/qemu
 * [new tag]         patchew/20180516152708.9ECB1A5D5F2@smcpolin-M01.vmware.com -> patchew/20180516152708.9ECB1A5D5F2@smcpolin-M01.vmware.com
Test passed: checkpatch

loading

Test passed: docker-mingw@fedora

loading

Test passed: docker-quick@centos7

loading

Test passed: s390x

loading

[Qemu-devel] [PATCH] linux-user: Remove extra mapping
Posted by Steve Mcpolin, 6 days ago
When a guest mmap()'d a file, a transient MAP_ANONYMOUS mapping was
created, which required the kernel to reserve this memory, then
subsequently released by applying a mapping with just the requested
flags and fd.
This transient mapping causes spurious failures when the available
memory is smaller than the mapping.  This patch avoids this transient
mapping.

Signed-off-by: Steve Mcpolin <smcpolin@vmware.com>
---
 linux-user/mmap.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 9168a20..f91841f 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -453,21 +453,28 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         /* Note: we prefer to control the mapping address. It is
            especially important if qemu_host_page_size >
            qemu_real_host_page_size */
-        p = mmap(g2h(start), host_len, prot,
-                 flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
-        if (p == MAP_FAILED)
-            goto fail;
-        /* update start so that it points to the file position at 'offset' */
-        host_start = (unsigned long)p;
-        if (!(flags & MAP_ANONYMOUS)) {
-            p = mmap(g2h(start), len, prot,
+        if (flags & MAP_ANONYMOUS) {
+            offset = 0;
+            host_offset = 0;
+            fd = -1;
+        }
+        p = mmap(g2h(start), len, prot,
                      flags | MAP_FIXED, fd, host_offset);
-            if (p == MAP_FAILED) {
-                munmap(g2h(start), host_len);
-                goto fail;
+        host_start = (uintptr_t)p;
+        if (p != MAP_FAILED && host_len > HOST_PAGE_ALIGN(len)) {
+            void *q;
+            q = mmap(g2h(start + len), host_len - HOST_PAGE_ALIGN(len),
+                     prot, MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+            if (q == MAP_FAILED) {
+                p = MAP_FAILED;
             }
-            host_start += offset - host_offset;
         }
+        if (p == MAP_FAILED) {
+            munmap(g2h(start), host_len);
+            goto fail;
+        }
+        host_start += offset - host_offset;
+        /* update start so that it points to the file position at 'offset' */
         start = h2g(host_start);
     } else {
         if (start & ~TARGET_PAGE_MASK) {
-- 
2.7.4