lib/replace: test for incoherent mmap.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 22 Mar 2012 00:17:24 +0000 (10:47 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 22 Mar 2012 00:57:37 +0000 (01:57 +0100)
We test for other mmap features here, and both tdb1 and tdb2 want this check.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
lib/replace/libreplace.m4
lib/replace/test/incoherent_mmap.c [new file with mode: 0644]
lib/replace/wscript

index ca0c6846ab58bc76d2f72aeede8636e33b5e8667..e14fadabf157341ae8d75e1d03e167a6d829b0ce 100644 (file)
@@ -107,6 +107,13 @@ if test x"$libreplace_cv_HAVE_MREMAP" = x"yes"; then
     AC_DEFINE(HAVE_MREMAP,1,[Whether mremap works])
 fi
 
+AC_CACHE_CHECK([for incoherent mmap],libreplace_cv_HAVE_INCOHERENT_MMAP,[
+AC_TRY_RUN([#include "$libreplacedir/test/incoherent_mmap.c"],
+           libreplace_cv_HAVE_INCOHERENT_MMAP=yes,libreplace_cv_HAVE_INCOHERENT_MMAP=no,libreplace_cv_HAVE_INCOHERENT_MMAP=cross)])
+if test x"$libreplace_cv_HAVE_INCOHERENT_MMAP" = x"yes"; then
+    AC_DEFINE(HAVE_INCOHERENT_MMAP,1,[Whether mmap is incoherent against write])
+fi
+
 
 AC_CHECK_HEADERS(sys/syslog.h syslog.h)
 AC_CHECK_HEADERS(sys/time.h time.h)
diff --git a/lib/replace/test/incoherent_mmap.c b/lib/replace/test/incoherent_mmap.c
new file mode 100644 (file)
index 0000000..ee288fd
--- /dev/null
@@ -0,0 +1,83 @@
+/* In OpenBSD, if you write to a file, another process doesn't see it
+ * in its mmap.  Returns with exit status 0 if that is the case, 1 if
+ * it's coherent, and other if there's a problem. */
+#include <err.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define DATA "coherent.mmap"
+
+int main(int argc, char *argv[])
+{
+       int tochild[2], toparent[2];
+       int fd;
+       volatile unsigned char *map;
+       unsigned char *page;
+        const char *fname = argv[1];
+       char c = 0;
+
+       if (pipe(tochild) != 0 || pipe(toparent) != 0)
+               err(2, "Creating pipe");
+
+       if (!fname)
+               fname = DATA;
+
+       fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0600);
+       if (fd < 0)
+               err(2, "opening %s", fname);
+       unlink(fname);
+
+       switch (fork()) {
+       case -1:
+               err(2, "Fork");
+       case 0:
+               close(tochild[1]);
+               close(toparent[0]);
+
+               /* Wait for parent to create file. */
+               if (read(tochild[0], &c, 1) != 1)
+                       err(2, "reading from parent");
+
+               /* Alter first byte. */
+               pwrite(fd, &c, 1, 0);
+
+               if (write(toparent[1], &c, 1) != 1)
+                       err(2, "writing to parent");
+               exit(0);
+
+       default:
+               close(tochild[0]);
+               close(toparent[1]);
+
+               /* Create a file and mmap it. */
+               page = malloc(getpagesize());
+               memset(page, 0x42, getpagesize());
+               if (write(fd, page, getpagesize()) != getpagesize())
+                       err(2, "writing first page");
+               map = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
+                          MAP_SHARED, fd, 0);
+               if (map == MAP_FAILED)
+                       err(2, "mapping file");
+
+               if (*map != 0x42)
+                       errx(2, "first byte isn't 0x42!");
+
+               /* Tell child to alter file. */
+               if (write(tochild[1], &c, 1) != 1)
+                       err(2, "writing to child");
+
+               if (read(toparent[0], &c, 1) != 1)
+                       err(2, "reading from child");
+
+               if (*map)
+                       errx(0, "mmap incoherent: first byte isn't 0.");
+
+               exit(1);
+       }
+}
index 36c2f0f3e1e931cac93aa361cac7ddd3d5a096b1..63944c3800b7938fa26cd38f8bac8d480cf55149 100644 (file)
@@ -299,6 +299,13 @@ def configure(conf):
                     addmain=False,
                     msg="Checking for C99 vsnprintf")
 
+    # OpenBSD (and I've heard HPUX) doesn't sync between mmap and write.
+    # FIXME: Anything other than a 0 or 1 exit code should abort configure!
+    conf.CHECK_CODE('#include "test/incoherent_mmap.c"',
+                    addmain=False, add_headers=False, execute=True,
+                    define='HAVE_INCOHERENT_MMAP',
+                    msg="Checking for HAVE_INCOHERENT_MMAP")
+
     conf.SAMBA_BUILD_ENV()
 
     conf.CHECK_CODE('''