summary refs log tree commit diff stats
path: root/util/mmap-alloc.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-04-26 14:30:18 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-04-26 14:30:18 +0100
commit06e64339555096a2bc2d08c7e012b36a9977062c (patch)
treed671da8ca994cbd1fe74aac0f9d7152e67ca14b7 /util/mmap-alloc.c
parentf7526eece29cd2e36a63b6703508b24453095eb8 (diff)
parent119906afa5ca610adb87c55ab0d8e53c9104bfc3 (diff)
downloadfocaccia-qemu-06e64339555096a2bc2d08c7e012b36a9977062c.tar.gz
focaccia-qemu-06e64339555096a2bc2d08c7e012b36a9977062c.zip
Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging
Machine queue, 2019-04-25

* 4.1 machine-types (Cornelia Huck)
* Support MAP_SYNC on pmem memory backends (Zhang Yi)
* -cpu parsing fixes and cleanups (Eduardo Habkost)
* machine initialization cleanups (Wei Yang, Markus Armbruster)

# gpg: Signature made Thu 25 Apr 2019 18:54:57 BST
# gpg:                using RSA key 2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full]
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/machine-next-pull-request:
  util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap()
  linux-headers: add linux/mman.h.
  scripts/update-linux-headers: add linux/mman.h
  util/mmap-alloc: Add a 'is_pmem' parameter to qemu_ram_mmap
  cpu: Fix crash with empty -cpu option
  cpu: Rename parse_cpu_model() to parse_cpu_option()
  vl: Simplify machine_parse()
  vl: Clean up after previous commit
  vl.c: allocate TYPE_MACHINE list once during bootup
  vl.c: make find_default_machine() local
  hw: add compat machines for 4.1

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util/mmap-alloc.c')
-rw-r--r--util/mmap-alloc.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c
index 8565885420..f7f177d0ea 100644
--- a/util/mmap-alloc.c
+++ b/util/mmap-alloc.c
@@ -10,6 +10,13 @@
  * later.  See the COPYING file in the top-level directory.
  */
 
+#ifdef CONFIG_LINUX
+#include <linux/mman.h>
+#else  /* !CONFIG_LINUX */
+#define MAP_SYNC              0x0
+#define MAP_SHARED_VALIDATE   0x0
+#endif /* CONFIG_LINUX */
+
 #include "qemu/osdep.h"
 #include "qemu/mmap-alloc.h"
 #include "qemu/host-utils.h"
@@ -75,9 +82,14 @@ size_t qemu_mempath_getpagesize(const char *mem_path)
     return getpagesize();
 }
 
-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
+void *qemu_ram_mmap(int fd,
+                    size_t size,
+                    size_t align,
+                    bool shared,
+                    bool is_pmem)
 {
     int flags;
+    int map_sync_flags = 0;
     int guardfd;
     size_t offset;
     size_t pagesize;
@@ -128,9 +140,40 @@ void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
     flags = MAP_FIXED;
     flags |= fd == -1 ? MAP_ANONYMOUS : 0;
     flags |= shared ? MAP_SHARED : MAP_PRIVATE;
+    if (shared && is_pmem) {
+        map_sync_flags = MAP_SYNC | MAP_SHARED_VALIDATE;
+    }
+
     offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr;
 
-    ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0);
+    ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE,
+               flags | map_sync_flags, fd, 0);
+
+    if (ptr == MAP_FAILED && map_sync_flags) {
+        if (errno == ENOTSUP) {
+            char *proc_link, *file_name;
+            int len;
+            proc_link = g_strdup_printf("/proc/self/fd/%d", fd);
+            file_name = g_malloc0(PATH_MAX);
+            len = readlink(proc_link, file_name, PATH_MAX - 1);
+            if (len < 0) {
+                len = 0;
+            }
+            file_name[len] = '\0';
+            fprintf(stderr, "Warning: requesting persistence across crashes "
+                    "for backend file %s failed. Proceeding without "
+                    "persistence, data might become corrupted in case of host "
+                    "crash.\n", file_name);
+            g_free(proc_link);
+            g_free(file_name);
+        }
+        /*
+         * if map failed with MAP_SHARED_VALIDATE | MAP_SYNC,
+         * we will remove these flags to handle compatibility.
+         */
+        ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE,
+                   flags, fd, 0);
+    }
 
     if (ptr == MAP_FAILED) {
         munmap(guardptr, total);