diff --git a/glnx-fdio.c b/glnx-fdio.c
index 19de9ec21b5df1a52f0bfce5ed29dc607c3125fa..87e2dbb9853883a236b4b32f2f7feaedf8ff22d0 100644
--- a/glnx-fdio.c
+++ b/glnx-fdio.c
@@ -920,7 +920,6 @@ glnx_file_replace_contents_with_perms_at (int                   dfd,
                                           GCancellable         *cancellable,
                                           GError              **error)
 {
-  int r;
   char *dnbuf = strdupa (subpath);
   const char *dn = dirname (dnbuf);
 
@@ -940,16 +939,8 @@ glnx_file_replace_contents_with_perms_at (int                   dfd,
   if (len == -1)
     len = strlen ((char*)buf);
 
-  /* Note that posix_fallocate does *not* set errno but returns it. */
-  if (len > 0)
-    {
-      r = posix_fallocate (tmpf.fd, 0, len);
-      if (r != 0)
-        {
-          errno = r;
-          return glnx_throw_errno_prefix (error, "fallocate");
-        }
-    }
+  if (!glnx_try_fallocate (tmpf.fd, 0, len, error))
+    return FALSE;
 
   if (glnx_loop_write (tmpf.fd, buf, len) < 0)
     return glnx_throw_errno (error);
diff --git a/glnx-fdio.h b/glnx-fdio.h
index dda32d1a79e7c2ab72cea2bb7751794aeb112a5b..e52c823776231a8cf837e849d7d8b8ed061a0f11 100644
--- a/glnx-fdio.h
+++ b/glnx-fdio.h
@@ -166,6 +166,38 @@ int glnx_renameat2_noreplace (int olddirfd, const char *oldpath,
 int glnx_renameat2_exchange (int olddirfd, const char *oldpath,
                              int newdirfd, const char *newpath);
 
+/**
+ * glnx_try_fallocate:
+ * @fd: File descriptor
+ * @size: Size
+ * @error: Error
+ *
+ * Wrapper for Linux fallocate().  Explicitly ignores a @size of zero.
+ * Also, will silently do nothing if the underlying filesystem doesn't
+ * support it.  Use this instead of posix_fallocate(), since the glibc fallback
+ * is bad: https://sourceware.org/bugzilla/show_bug.cgi?id=18515
+ */
+static inline gboolean
+glnx_try_fallocate (int      fd,
+                    off_t    offset,
+                    off_t    size,
+                    GError **error)
+{
+  /* This is just nicer than throwing an error */
+  if (size == 0)
+    return TRUE;
+
+  if (fallocate (fd, 0, offset, size) < 0)
+    {
+      if (errno == ENOSYS || errno == EOPNOTSUPP)
+        ; /* Ignore */
+      else
+        return glnx_throw_errno_prefix (error, "fallocate");
+    }
+
+  return TRUE;
+}
+
 /**
  * glnx_fstat:
  * @fd: FD to stat