os: use posix_fallocate in creating sharable buffers
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>
Fri, 29 Nov 2013 15:48:51 +0000 (17:48 +0200)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 3 Dec 2013 00:20:27 +0000 (16:20 -0800)
If posix_fallocate is available, use it instead of ftruncate. Unlike
ftruncate, when posix_fallocate succeeds, it guarantees that you cannot
run out of disk space, when later writing to the mmap()'ed file.

With posix_fallocate, if os_create_anonymous_file() succeeds, the
program cannot get a SIGBUS later from accessing this file via mmap. If
there is insufficient disk space, the function fails and errno is set to
ENOSPC.

This is useful on systems, that limit the available buffer space by
having XDG_RUNTIME_DIR on a small tmpfs.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
configure.ac
shared/os-compatibility.c

index bd8ff44..2bf5f78 100644 (file)
@@ -55,7 +55,7 @@ AC_CHECK_DECL(CLOCK_MONOTONIC,[],
              [[#include <time.h>]])
 AC_CHECK_HEADERS([execinfo.h])
 
-AC_CHECK_FUNCS([mkostemp strchrnul initgroups])
+AC_CHECK_FUNCS([mkostemp strchrnul initgroups posix_fallocate])
 
 COMPOSITOR_MODULES="wayland-server >= 1.3.90 pixman-1"
 
index 4f96dd4..611e7c8 100644 (file)
@@ -132,6 +132,12 @@ create_tmpfile_cloexec(char *tmpname)
  * The file is suitable for buffer sharing between processes by
  * transmitting the file descriptor over Unix sockets using the
  * SCM_RIGHTS methods.
+ *
+ * If the C library implements posix_fallocate(), it is used to
+ * guarantee that disk space is available for the file at the
+ * given size. If disk space is insufficent, errno is set to ENOSPC.
+ * If posix_fallocate() is not supported, program may receive
+ * SIGBUS on accessing mmap()'ed file contents instead.
  */
 int
 os_create_anonymous_file(off_t size)
@@ -140,6 +146,7 @@ os_create_anonymous_file(off_t size)
        const char *path;
        char *name;
        int fd;
+       int ret;
 
        path = getenv("XDG_RUNTIME_DIR");
        if (!path) {
@@ -161,10 +168,20 @@ os_create_anonymous_file(off_t size)
        if (fd < 0)
                return -1;
 
-       if (ftruncate(fd, size) < 0) {
+#ifdef HAVE_POSIX_FALLOCATE
+       ret = posix_fallocate(fd, 0, size);
+       if (ret != 0) {
                close(fd);
+               errno = ret;
                return -1;
        }
+#else
+       ret = ftruncate(fd, size);
+       if (ret < 0) {
+               close(fd);
+               return -1;
+       }
+#endif
 
        return fd;
 }