]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fallocate: use POSIX_FADV_DONTNEED to discard cached data
authorKarel Zak <kzak@redhat.com>
Tue, 18 Feb 2014 12:01:52 +0000 (13:01 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 18 Feb 2014 12:01:52 +0000 (13:01 +0100)
The patch discard cached data in 1MiB (or bigger) steps.

Thanks to Pádraig Brady.

Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/fallocate.c

index 6c2b1ea347422019e43e35078a5910d8dcccd435..a2545039ed14d1e8d6ddeea098c54464e7ea466b 100644 (file)
@@ -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;
        }