Subject: [PATCH]: use posix_fallocate where supported

From: Kelly Anderson <[email-masked]>
Date: Tue, 13 Sep 2011 23:55:26 -0600

Hi,

I put together a patch 2 or 3 years ago (back when posix_fallocate was 
first introduced in glibc).
I've been using coreutils ever since with that patch applied with no 
problems.  The only error
I ever encountered (I had my patch error when posix_fallocate failed at 
that time) was when
I tried to copy a 25Gig file to a vfat partition, that's what it should 
do with a file over
4Gigs on a fat32 partition.  Anyway, I changed my patch to silently 
ignore posix_fallocate
errors, so coreutils would error the same as it currently does.

I copy a lot of large media files around on my servers and I want their 
space/continuity
to be allocated as efficiently as possible.

This patch has been tested for 2 to 3 years by me, so it should be good 
to go.
The patch applies to coreutils 8.13.

--- ./configure.ac.orig    2011-08-19 13:40:11.000000000 -0600
+++ ./configure.ac    2011-09-13 23:29:57.277354329 -0600
@@ -242,6 +242,18 @@ AC_DEFUN([coreutils_DUMMY_1],
  ])
  coreutils_DUMMY_1

+dnl * Old glibcs have broken posix_fallocate(). Make sure not to use it.
+AC_TRY_COMPILE([
+  #define _XOPEN_SOURCE 600
+  #include <stdlib.h>
+  #if defined(__GLIBC__) && (__GLIBC__ < 2 || __GLIBC_MINOR__ < 7)
+    possibly broken posix_fallocate
+  #endif
+], [
+  posix_fallocate(0, 0, 0);
+], [
+  AC_DEFINE([HAVE_POSIX_FALLOCATE], [1], [Define if you have a working 
posix_fallocate()]) ])
+
  AC_MSG_CHECKING([ut_host in struct utmp])
  AC_CACHE_VAL([su_cv_func_ut_host_in_utmp],
  [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
--- ./src/copy.c.orig    2011-07-28 04:38:27.000000000 -0600
+++ ./src/copy.c    2011-09-13 23:29:57.280354149 -0600
@@ -1026,6 +1026,16 @@ copy_reg (char const *src_name, char con
            size_t blcm = buffer_lcm (io_blksize (src_open_sb), buf_size,
                                      blcm_max);

+#ifdef HAVE_POSIX_FALLOCATE
+          if (S_ISREG(src_open_sb.st_mode)
+ && ! S_ISFIFO(sb.st_mode)
+ && src_open_sb.st_size >= buf_size)
+          {
+            /* ignore errors, some filesystems may error if filesize 
exceeds the filesystem's limit */
+            posix_fallocate (dest_desc, 0, src_open_sb.st_size);
+          }
+#endif
+
            /* Do not bother with a buffer larger than the input file, 
plus one
               byte to make sure the file has not grown while reading 
it.  */
            if (S_ISREG (src_open_sb.st_mode) && src_open_sb.st_size < 
buf_size)