summaryrefslogtreecommitdiffstats
path: root/sys-utils/fallocate.c
diff options
context:
space:
mode:
authorKarel Zak2014-02-18 13:01:52 +0100
committerKarel Zak2014-02-18 13:01:52 +0100
commitc12eff4ce05b2236d9479ffd14c5ae4006caeaf6 (patch)
treec31d1ef80303c0a1052809106b2c497c65006d21 /sys-utils/fallocate.c
parentfallocate: use SEEK_DATA on already sparse files (diff)
downloadkernel-qcow2-util-linux-c12eff4ce05b2236d9479ffd14c5ae4006caeaf6.tar.gz
kernel-qcow2-util-linux-c12eff4ce05b2236d9479ffd14c5ae4006caeaf6.tar.xz
kernel-qcow2-util-linux-c12eff4ce05b2236d9479ffd14c5ae4006caeaf6.zip
fallocate: use POSIX_FADV_DONTNEED to discard cached data
The patch discard cached data in 1MiB (or bigger) steps. Thanks to Pádraig Brady. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/fallocate.c')
-rw-r--r--sys-utils/fallocate.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c
index 6c2b1ea34..a2545039e 100644
--- a/sys-utils/fallocate.c
+++ b/sys-utils/fallocate.c
@@ -134,16 +134,28 @@ static void dig_holes(int fd, off_t off, off_t len)
{
off_t end = len ? off + len : 0;
off_t hole_start = 0, hole_sz = 0;
+ off_t cache_start = 0;
uintmax_t ct = 0;
- size_t bufsz;
+ size_t bufsz, cachesz;
char *buf, *empty;
struct stat st;
int sparse = 0;
if (fstat(fd, &st) != 0)
err(EXIT_FAILURE, _("stat failed %s"), filename);
+
bufsz = st.st_blksize;
+ /*
+ * We don't want to call POSIX_FADV_DONTNEED to discard cached
+ * data in PAGE_SIZE steps. IMHO it's overkill (too many syscalls).
+ *
+ * Let's assume that 1MiB (on system with 4K page size) is just
+ * a good compromise.
+ * -- kzak Feb-2014
+ */
+ cachesz = getpagesize() * 256;
+
if (st.st_blocks * 512 < st.st_size) {
if (verbose)
fprintf(stdout, _("%s: already has holes.\n"), filename);
@@ -154,9 +166,10 @@ static void dig_holes(int fd, off_t off, off_t len)
buf = xmalloc(bufsz);
empty = xcalloc(1, bufsz);
+ cache_start = off;
-#if defined(POSIX_FADV_SEQUENTIAL) && defined(POSIX_FADV_NOREUSE) && defined(HAVE_POSIX_FADVISE)
- posix_fadvise(fd, off, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
+#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
+ posix_fadvise(fd, off, 0, POSIX_FADV_SEQUENTIAL);
#endif
while (end == 0 || off < end) {
@@ -188,6 +201,17 @@ static void dig_holes(int fd, off_t off, off_t len)
ct += hole_sz;
hole_sz = hole_start = 0;
}
+
+#if defined(POSIX_FADV_DONTNEED) && defined(HAVE_POSIX_FADVISE)
+ /* discard cached data */
+ if (off - cache_start > (off_t) cachesz) {
+ size_t clen = off - cache_start;
+
+ clen = (clen / cachesz) * cachesz;
+ posix_fadvise(fd, cache_start, clen, POSIX_FADV_DONTNEED);
+ cache_start = cache_start + clen;
+ }
+#endif
off += rsz;
}