]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
dd: preserve semantics of O_DIRECT even for final block
authorJim Meyering <meyering@redhat.com>
Fri, 7 Aug 2009 14:21:35 +0000 (16:21 +0200)
committerJim Meyering <meyering@redhat.com>
Fri, 7 Aug 2009 14:21:35 +0000 (16:21 +0200)
* src/dd.c: Include "ignore-value.h"
(iwrite): When disabling O_DIRECT, try to compensate
via POSIX_FADV_DONTNEED and fsync.
Suggested by Eric Sandeen.

src/dd.c

index 43ad7189fd3cf502863628dca37276948f3ebb21..d9e4c85b8bdc4d91c0e36d0a5d9c5f24b8e9f67d 100644 (file)
--- a/src/dd.c
+++ b/src/dd.c
@@ -29,6 +29,7 @@
 #include "fd-reopen.h"
 #include "gethrxtime.h"
 #include "human.h"
+#include "ignore-value.h"
 #include "long-options.h"
 #include "quote.h"
 #include "quotearg.h"
@@ -843,6 +844,22 @@ iwrite (int fd, char const *buf, size_t size)
       if (fcntl (STDOUT_FILENO, F_SETFL, old_flags & ~O_DIRECT) != 0)
         error (0, errno, _("failed to turn off O_DIRECT: %s"),
                quote (output_file));
+
+      /* Since we have just turned off O_DIRECT for the final write,
+         here we try to preserve some of its semantics.  First, use
+         posix_fadvise to tell the system not to pollute the buffer
+         cache with this data.  Don't bother to diagnose lseek or
+         posix_fadvise failure. */
+#ifdef POSIX_FADV_DONTNEED
+      off_t off = lseek (STDOUT_FILENO, 0, SEEK_CUR);
+      if (0 <= off)
+        ignore_value (posix_fadvise (STDOUT_FILENO,
+                                     off, 0, POSIX_FADV_DONTNEED));
+#endif
+
+      /* Attempt to ensure that that final block is committed
+         to disk as quickly as possible.  */
+      conversions_mask |= C_FSYNC;
     }
 
   while (total_written < size)