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 */
+
#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);
--
2.19.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>
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> -- Wei Yang Help you, Help me
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
© 2016 - 2026 Red Hat, Inc.