[PATCH] Fix shared memory mapping

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "Roy.Li" <rongqing.li@xxxxxxxxxxxxx>

On a number of arches, any fixed and shared mmap() mapping address must be
aligned to 16k, or MIPS cpu askes that the address must be aligned to not
violate cache aliasing constraints.

If we create a shared memory like below:

        addr_orig = mmap (NULL, bytes, PROT_NONE,
                          MAP_ANONYMOUS| MAP_PRIVATE, -1, 0);

        addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
                MAP_FIXED | MAP_SHARED, fd, 0);

If the first mmap() upper is not shared then the first mmap() will succeed
because these restrictions do not apply to private mappings. The second
mmap() wants a shared memory mapping but the address returned by the first
one is only page-aligned and not aligned to 16k, or violate cache aliasing
constraints on MIPS cpu, will lead to second mmap failure.

Signed-off-by: Roy.Li <rongqing.li@xxxxxxxxxxxxx>
---
 configure.ac |   25 +++++++++++++++++++++++++
 exec/cpg.c   |   13 +++++++++----
 lib/cpg.c    |   10 ++++++++--
 3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 523d2cf..d3a9c25 100644
--- a/configure.ac
+++ b/configure.ac
@@ -647,6 +647,31 @@ else
   AC_SUBST(VERSCRIPT_LDFLAGS, [""])
 fi
 
+arch_force_shmlba=no
+AC_MSG_CHECKING([for architecture in ${host_cpu}])
+case $host_cpu in
+	sparc*)
+		AC_MSG_RESULT([${host_cpu}])
+		arch_force_shmlba=yes
+		;;
+	arm*)
+		AC_MSG_RESULT([${host_cpu}])
+		arch_force_shmlba=yes
+		;;
+	mips*)
+		AC_MSG_RESULT([${host_cpu}])
+		arch_force_shmlba=yes
+		;;
+	*)
+		AC_MSG_RESULT([${host_cpu}])
+	;;
+esac
+
+if test $arch_force_shmlba = yes; then
+	AC_DEFINE_UNQUOTED([FORCE_SHM_ALIGN], [1],
+	       [shared and fixed mmap must align on cache alias or 16k])
+fi
+
 # define global include dirs
 INCLUDE_DIRS="$INCLUDE_DIRS -I\$(top_builddir)/include -I\$(top_srcdir)/include"
 INCLUDE_DIRS="$INCLUDE_DIRS -I\$(top_builddir)/include/corosync -I\$(top_srcdir)/include/corosync"
diff --git a/exec/cpg.c b/exec/cpg.c
index 695f311..04260e0 100644
--- a/exec/cpg.c
+++ b/exec/cpg.c
@@ -1606,6 +1606,7 @@ memory_map (
 	void *addr_orig;
 	void *addr;
 	int32_t res;
+	int flags = MAP_ANONYMOUS;
 
 	fd = open (path, O_RDWR, 0600);
 
@@ -1620,15 +1621,19 @@ memory_map (
 		goto error_close_unlink;
 	}
 
-	addr_orig = mmap (NULL, bytes, PROT_NONE,
-		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+#ifdef FORCE_SHM_ALIGN
+	flags |= MAP_SHARED;
+#else
+	flags |= MAP_PRIVATE;
+#endif /* FORCE_SHM_ALIGN */
+
+	addr_orig = mmap (NULL, bytes, PROT_NONE, flags, -1, 0);
 
 	if (addr_orig == MAP_FAILED) {
 		goto error_close_unlink;
 	}
 
-	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
-		MAP_FIXED | MAP_SHARED, fd, 0);
+	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE, flags, fd, 0);
 
 	if (addr != addr_orig) {
 		munmap(addr_orig, bytes);
diff --git a/lib/cpg.c b/lib/cpg.c
index b96df4e..7cc3ce9 100644
--- a/lib/cpg.c
+++ b/lib/cpg.c
@@ -737,6 +737,7 @@ memory_map (char *path, const char *file, void **buf, size_t bytes)
 	int32_t i;
 	size_t written;
 	size_t page_size; 
+	int flags = MAP_ANONYMOUS;
 
 	snprintf (path, PATH_MAX, "/dev/shm/%s", file);
 
@@ -772,8 +773,13 @@ retry_write:
 	}
 	free (buffer);
 
-	addr_orig = mmap (NULL, bytes, PROT_NONE,
-		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+#ifdef FORCE_SHM_ALIGN
+	flags |= MAP_SHARED;
+#else
+	flags |= MAP_PRIVATE;
+#endif /* FORCE_SHM_ALIGN */
+
+	addr_orig = mmap (NULL, bytes, PROT_NONE, flags, -1, 0);
 
 	if (addr_orig == MAP_FAILED) {
 		goto error_close_unlink;
-- 
1.7.10.4

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss




[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux