diff mbox series

[v14,1/2] util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap()

Message ID 20190422004849.26463-2-richardw.yang@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series support MAP_SYNC for memory-backend-file | expand

Commit Message

Wei Yang April 22, 2019, 12:48 a.m. UTC
From: Zhang Yi <yi.z.zhang@linux.intel.com>

When a file supporting DAX is used as vNVDIMM backend, mmap it with
MAP_SYNC flag in addition which can ensure file system metadata
synced in each guest writes to the backend file, without other QEMU
actions (e.g., periodic fsync() by QEMU).

Current, We have below different possible use cases:

1. pmem=on is set, shared=on is set, MAP_SYNC supported:
   a: backend is a dax supporting file.
    - MAP_SYNC will active.
   b: backend is not a dax supporting file.
    - mmap will trigger a warning. then MAP_SYNC flag will be ignored

2. The rest of cases:
   - we will never pass the MAP_SYNC to mmap2

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
[ehabkost: Rebased patch to latest code on master]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
Tested-by: Wei Yang <richardw.yang@linux.intel.com>

---
v14: rebase on top of current upstream
---
 util/mmap-alloc.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

Comments

Stefan Hajnoczi April 23, 2019, 9:25 a.m. UTC | #1
On Mon, Apr 22, 2019 at 08:48:48AM +0800, Wei Yang wrote:
> From: Zhang Yi <yi.z.zhang@linux.intel.com>
> 
> When a file supporting DAX is used as vNVDIMM backend, mmap it with
> MAP_SYNC flag in addition which can ensure file system metadata
> synced in each guest writes to the backend file, without other QEMU
> actions (e.g., periodic fsync() by QEMU).
> 
> Current, We have below different possible use cases:
> 
> 1. pmem=on is set, shared=on is set, MAP_SYNC supported:
>    a: backend is a dax supporting file.
>     - MAP_SYNC will active.
>    b: backend is not a dax supporting file.
>     - mmap will trigger a warning. then MAP_SYNC flag will be ignored
> 
> 2. The rest of cases:
>    - we will never pass the MAP_SYNC to mmap2
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
> [ehabkost: Rebased patch to latest code on master]
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
> Tested-by: Wei Yang <richardw.yang@linux.intel.com>
> 
> ---
> v14: rebase on top of current upstream
> ---
>  util/mmap-alloc.c | 41 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c
> index 9713f4b960..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 */

MAP_SHARED_VALIDATE is is from 2017:

  commit 1c9725974074a047f6080eecc62c50a8e840d050
  Author: Dan Williams <dan.j.williams@intel.com>
  Date:   Wed Nov 1 16:36:30 2017 +0100

    mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap flags

This code fails to compile on Linux hosts with pre-4.15 headers.

Instead you could use the following (even on Linux!):

  #ifndef MAP_SYNC
  #define MAP_SYNC 0
  #endif
  #ifndef MAP_SHARED_VALIDATE
  #define MAP_SHARED_VALIDATE 0
  #endif

Either way:

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Wei Yang April 24, 2019, 1:01 a.m. UTC | #2
On Tue, Apr 23, 2019 at 10:25:18AM +0100, Stefan Hajnoczi wrote:
[...]
>> +#ifdef CONFIG_LINUX
>> +#include <linux/mman.h>
>> +#else  /* !CONFIG_LINUX */
>> +#define MAP_SYNC              0x0
>> +#define MAP_SHARED_VALIDATE   0x0
>> +#endif /* CONFIG_LINUX */
>
>MAP_SHARED_VALIDATE is is from 2017:
>
>  commit 1c9725974074a047f6080eecc62c50a8e840d050
>  Author: Dan Williams <dan.j.williams@intel.com>
>  Date:   Wed Nov 1 16:36:30 2017 +0100
>
>    mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap flags
>
>This code fails to compile on Linux hosts with pre-4.15 headers.
>

Ok, qemu build will fail on pre-4.15 linux.

>Instead you could use the following (even on Linux!):
>
>  #ifndef MAP_SYNC
>  #define MAP_SYNC 0
>  #endif
>  #ifndef MAP_SHARED_VALIDATE
>  #define MAP_SHARED_VALIDATE 0
>  #endif
>
>Either way:

You mean replace the above code to:

#ifdef CONFIG_LINUX
#include <linux/mman.h>
#endif /* CONFIG_LINUX */

#ifndef MAP_SYNC
#define MAP_SYNC 0
#endif
#ifndef MAP_SHARED_VALIDATE
#define MAP_SHARED_VALIDATE 0
#endif

>
>Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Stefan Hajnoczi April 25, 2019, 8:26 a.m. UTC | #3
On Wed, Apr 24, 2019 at 09:01:05AM +0800, Wei Yang wrote:
> On Tue, Apr 23, 2019 at 10:25:18AM +0100, Stefan Hajnoczi wrote:
> [...]
> >> +#ifdef CONFIG_LINUX
> >> +#include <linux/mman.h>
> >> +#else  /* !CONFIG_LINUX */
> >> +#define MAP_SYNC              0x0
> >> +#define MAP_SHARED_VALIDATE   0x0
> >> +#endif /* CONFIG_LINUX */
> >
> >MAP_SHARED_VALIDATE is is from 2017:
> >
> >  commit 1c9725974074a047f6080eecc62c50a8e840d050
> >  Author: Dan Williams <dan.j.williams@intel.com>
> >  Date:   Wed Nov 1 16:36:30 2017 +0100
> >
> >    mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap flags
> >
> >This code fails to compile on Linux hosts with pre-4.15 headers.
> >
> 
> Ok, qemu build will fail on pre-4.15 linux.
> 
> >Instead you could use the following (even on Linux!):
> >
> >  #ifndef MAP_SYNC
> >  #define MAP_SYNC 0
> >  #endif
> >  #ifndef MAP_SHARED_VALIDATE
> >  #define MAP_SHARED_VALIDATE 0
> >  #endif
> >
> >Either way:
> 
> You mean replace the above code to:
> 
> #ifdef CONFIG_LINUX
> #include <linux/mman.h>
> #endif /* CONFIG_LINUX */
> 
> #ifndef MAP_SYNC
> #define MAP_SYNC 0
> #endif
> #ifndef MAP_SHARED_VALIDATE
> #define MAP_SHARED_VALIDATE 0
> #endif

Yes, please.

This is not critical but I bet someone will hit this issue when
compiling a new QEMU on an old host.  This small tweak will save them
time.

Stefan
diff mbox series

Patch

diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c
index 9713f4b960..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"
@@ -82,6 +89,7 @@  void *qemu_ram_mmap(int fd,
                     bool is_pmem)
 {
     int flags;
+    int map_sync_flags = 0;
     int guardfd;
     size_t offset;
     size_t pagesize;
@@ -132,9 +140,40 @@  void *qemu_ram_mmap(int fd,
     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);