[RFC] add support for fallocate()

Sebastian Andrzej Siewior sebastian at breakpoint.cc
Fri Feb 12 14:08:09 MST 2010


fallocate() is linux specific and will preallocate the space on disk for
the entire file. FALLOC_FL_KEEP_SIZE does not change the filesize as
reported by stat(). An aborted transfer will have preallocated disk space
which is not "visible" via stat(). This shouldn't matter unless the user
does complet his transfer.
An alternative would be to use ftruncate() and shorten the file to the
size which has been transfered in case of an error.
posix_fallocate() isn't used because this function maybe implemented by
multiple write() calls which is not what I had in mind.

Signed-off-by: Sebastian Andrzej Siewior <sebastian at breakpoint.cc>
---
 configure.in |    9 +++++++++
 receiver.c   |    9 ++++++++-
 rsync.h      |    4 ++++
 syscall.c    |    9 +++++++++
 4 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/configure.in b/configure.in
index 9de88d1..3e6ce55 100644
--- a/configure.in
+++ b/configure.in
@@ -761,6 +761,15 @@ if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" != x"no"; then
     AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [Define to 1 if gettimeofday() takes a time-zone arg])
 fi
 
+AC_CACHE_CHECK([if fallocate with mode FALLOC_FL_KEEP_SIZE is available],rsync_cv_HAVE_FALLOCATE,[
+AC_TRY_LINK([#include <fcntl.h>
+#include <linux/falloc.h>],
+[exit(fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 10));],
+rsync_cv_HAVE_FALLOCATE=yes,rsync_cv_HAVE_FALLOCATE=no)])
+if test x"$rsync_cv_HAVE_FALLOCATE" != x"no"; then
+    AC_DEFINE(HAVE_FALLOCATE, 1, [Define to 1 if fallocate() and FALLOC_FL_KEEP_SIZE are available])
+fi
+
 AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
 AC_TRY_RUN([
 #include <sys/types.h>
diff --git a/receiver.c b/receiver.c
index 6688dda..0fa8782 100644
--- a/receiver.c
+++ b/receiver.c
@@ -774,7 +774,14 @@ int recv_files(int f_in, int f_out, char *local_name)
 				send_msg_int(MSG_NO_SEND, ndx);
 			continue;
 		}
-
+#ifdef HAVE_FALLOCATE
+		if (!sparse_files)
+			/*
+			 * If this fails then either the filesystem does not
+			 * support this feature or we run out of disk space.
+			 */
+			do_fallocate(fd2, FALLOC_FL_KEEP_SIZE, 0, F_LENGTH(file));
+#endif
 		/* log the transfer */
 		if (log_before_transfer)
 			log_item(FCLIENT, file, iflags, NULL);
diff --git a/rsync.h b/rsync.h
index 731f4fe..b293edc 100644
--- a/rsync.h
+++ b/rsync.h
@@ -1241,3 +1241,7 @@ int inet_pton(int af, const char *src, void *dst);
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+#ifdef HAVE_FALLOCATE
+#include <linux/falloc.h>
+#endif
diff --git a/syscall.c b/syscall.c
index aba0009..854010e 100644
--- a/syscall.c
+++ b/syscall.c
@@ -189,6 +189,15 @@ int do_open(const char *pathname, int flags, mode_t mode)
 	return open(pathname, flags | O_BINARY, mode);
 }
 
+#ifdef HAVE_FALLOCATE
+int do_fallocate(int fd, int mode, OFF_T offset, OFF_T len)
+{
+	RETURN_ERROR_IF(dry_run, 0);
+	RETURN_ERROR_IF_RO_OR_LO;
+	return fallocate(fd, mode, offset, len);
+}
+#endif
+
 #ifdef HAVE_CHMOD
 int do_chmod(const char *path, mode_t mode)
 {
-- 
1.6.6.1



More information about the rsync mailing list