From f21c51fbd0fa4d7e0d416b994d4bfda5a4370540 Mon Sep 17 00:00:00 2001
From: Carlo Alberto Ferraris <cafxx@strayorange.com>
Date: Sat, 25 Mar 2017 14:35:07 +0900
Subject: [PATCH] use posix_fadvise to prefetch files when creating archives

---
 src/common.h |  2 ++
 src/create.c |  1 +
 src/misc.c   | 13 +++++++++++++
 src/sparse.c |  1 +
 4 files changed, 17 insertions(+)

diff --git a/src/common.h b/src/common.h
index 99a1dd8..f084e04 100644
--- a/src/common.h
+++ b/src/common.h
@@ -724,6 +724,8 @@ void *page_aligned_alloc (void **ptr, size_t size);
 int set_file_atime (int fd, int parentfd, char const *file,
 		    struct timespec atime);
 
+void prefetch(int fd, off_t offset, size_t len);
+
 /* Module names.c.  */
 
 extern size_t name_count;
diff --git a/src/create.c b/src/create.c
index 18e98d2..60800ec 100644
--- a/src/create.c
+++ b/src/create.c
@@ -1064,6 +1064,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
 
   finish_header (st, blk, block_ordinal);
 
+  prefetch(fd, 0, st->stat.st_size);
   mv_begin_write (st->file_name, st->stat.st_size, st->stat.st_size);
   while (size_left > 0)
     {
diff --git a/src/misc.c b/src/misc.c
index 632de29..72d8e30 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -24,6 +24,7 @@
 #include <xgetcwd.h>
 #include <unlinkdir.h>
 #include <utimens.h>
+#include <fcntl.h>
 
 #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
 # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
@@ -1248,3 +1249,15 @@ tar_savedir (const char *name, int must_exist)
 
   return ret;
 }
+
+/* Opportunistally signal to the OS that we are soon going to sequentially read
+   once a byte range from fd. If not supported or signaling to the OS fails this
+   function should then behave as a no-op.
+*/
+void
+prefetch(int fd, off_t offset, size_t len)
+{
+#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L
+  posix_fadvise(fd, offset, len, POSIX_FADV_WILLNEED|POSIX_FADV_SEQUENTIAL|POSIX_FADV_NOREUSE);
+#endif
+}
diff --git a/src/sparse.c b/src/sparse.c
index b3a3fd3..0fbd159 100644
--- a/src/sparse.c
+++ b/src/sparse.c
@@ -503,6 +503,7 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
 	{
 	  size_t i;
 
+	  prefetch(fd, 0, file.stat_info->stat.st_size);
 	  mv_begin_write (file.stat_info->file_name,
 		          file.stat_info->stat.st_size,
 		          file.stat_info->archive_file_size - file.dumped_size);
-- 
2.12.1

