aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-08-27 10:39:01 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-08-27 11:44:01 +0100
commit737643322e5b2308b0887d35561e6e03edf109ae (patch)
treee33b3e0f753e15d49ecedb5134eeb3cab9eb6774
parent6c983cf21b9434df73d7c4f24edfb3a86a92d158 (diff)
downloadpaludis-737643322e5b2308b0887d35561e6e03edf109ae.tar.gz
paludis-737643322e5b2308b0887d35561e6e03edf109ae.tar.xz
Make use of fallocate if available
We don't use posix_fallocate because it's weird with sizes and won't fail on filesystems that don't support it. Fixes: ticket:966
-rw-r--r--configure.ac20
-rw-r--r--paludis/fs_merger.cc23
2 files changed, 43 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 4207740..0b96559 100644
--- a/configure.ac
+++ b/configure.ac
@@ -186,6 +186,26 @@ if test "x$have_dirent_dtype" = "xyes"; then
fi
dnl }}}
+dnl {{{ check for fallocate
+AC_MSG_CHECKING([for fallocate])
+AC_COMPILE_IFELSE([
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <linux/falloc.h>
+int main(int, char **)
+{
+ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 100);
+}
+],
+ [have_fallocate=yes],
+ [have_fallocate=no])
+AC_MSG_RESULT([$have_fallocate])
+if test "x$have_fallocate" = "xyes"; then
+ AC_DEFINE([HAVE_FALLOCATE], [1], [Use fallocate])
+fi
+dnl }}}
+
dnl {{{ check for cxxflags
if test x = x"$LET_ME_RICE"
then
diff --git a/paludis/fs_merger.cc b/paludis/fs_merger.cc
index 4205c3b..57413f5 100644
--- a/paludis/fs_merger.cc
+++ b/paludis/fs_merger.cc
@@ -47,10 +47,15 @@
#include <unordered_map>
#include "config.h"
+
#ifdef HAVE_XATTRS
# include <sys/xattr.h>
#endif
+#ifdef HAVE_FALLOCATE
+# include <linux/falloc.h>
+#endif
+
using namespace paludis;
#include <paludis/fs_merger-se.cc>
@@ -390,6 +395,24 @@ FSMerger::install_file(const FSPath & src, const FSPath & dst_dir, const std::st
throw FSMergerError("Cannot fchmod '" + stringify(dst) + "': " + stringify(::strerror(errno)));
try_to_copy_xattrs(src, output_fd, result);
+#ifdef HAVE_FALLOCATE
+ if (0 != ::fallocate(output_fd, FALLOC_FL_KEEP_SIZE, 0, src_stat.file_size()))
+ switch (errno)
+ {
+ case EOPNOTSUPP:
+ case ENOSYS:
+ break;
+
+ case ENOSPC:
+ throw FSMergerError("fallocate '" + stringify(dst) + "' returned " + stringify(::strerror(errno)));
+
+ default:
+ Log::get_instance()->message("merger.file.fallocate_failed", ll_debug, lc_context) <<
+ "fallocate '" + stringify(dst) + "' returned " + stringify(::strerror(errno));
+ break;
+ }
+#endif
+
char buf[4096];
ssize_t count;
while ((count = read(input_fd, buf, 4096)) > 0)