bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

dd conv=nocache


From: Pádraig Brady
Subject: dd conv=nocache
Date: Tue, 06 Mar 2007 12:21:00 +0000
User-agent: Thunderbird 1.5.0.8 (X11/20061116)

Hi,

I was thinking it would be useful to
add an option to dd to tell it to
instruct the OS not to cache the data.

Personally I use dd to move large files like disc images etc.
around, and I know I will not need the file cached.

A very quick example patch which has only
been tested on linux is attached.

Do you think this is required?
Do you think this is the right interface?

Note, posix_fadvise(POSIX_FADV_DONTNEED) on linux,
invalidates the cache for a file rather than a process.
I.E. if a file is already cached, and a
process calls posix_fadvise(POSIX_FADV_DONTNEED),
then the file is uncached for everyone.
This is not what is usually required, and
I'm working on the kernel guys to get them
to change this.

thanks,
Pádraig.
--- coreutils-6.2/src/dd.c      2006-08-16 19:53:51.000000000 +0000
+++ coreutils-dd/src/dd.c       2007-03-06 08:55:28.000000000 +0000
@@ -117,7 +117,8 @@
     C_NOCREAT = 010000,
     C_EXCL = 020000,
     C_FDATASYNC = 040000,
-    C_FSYNC = 0100000
+    C_FSYNC = 0100000,
+    C_NOCACHE = 0200000
   };
 
 /* Status bit masks.  */
@@ -254,6 +255,7 @@
   {"sync", C_SYNC},            /* Pad input records to ibs with NULs. */
   {"fdatasync", C_FDATASYNC},  /* Synchronize output data before finishing.  */
   {"fsync", C_FSYNC},          /* Also synchronize output metadata.  */
+  {"nocache", C_NOCACHE},      /* Instruct the system not to cache the data.  
*/
   {"", 0}
 };
 
@@ -453,6 +455,7 @@
               with block or unblock, pad with spaces rather than NULs\n\
   fdatasync physically write output file data before finishing\n\
   fsync     likewise, but also write metadata\n\
+  nocache   instruct the system not to cache the data\n\
 "), stdout);
       fputs (_("\
 \n\
@@ -725,6 +728,20 @@
     }
 }
 
+void invalidate_cache(int fd, size_t size)
+{
+  if (! (conversions_mask & C_NOCACHE))
+    return;
+  /* Note be careful to invalidate only what we've read
+  so that we don't dump any readahead cache. */
+  off_t offset = lseek(fd, 0, SEEK_CUR);
+  if (offset && offset!=(off_t)-1) {
+    /* TODO: coalesce into at least page_size requests.
+       Currently there are 4 extra syscalls per block. */
+    posix_fadvise(fd, 0, offset, POSIX_FADV_DONTNEED);
+  }
+}
+
 /* Read from FD into the buffer BUF of size SIZE, processing any
    signals that arrive before bytes are read.  Return the number of
    bytes read if successful, -1 (setting errno) on failure.  */
@@ -737,8 +754,10 @@
       ssize_t nread;
       process_signals ();
       nread = read (fd, buf, size);
-      if (! (nread < 0 && errno == EINTR))
+      if (! (nread < 0 && errno == EINTR)) {
+       invalidate_cache(fd, nread);
        return nread;
+      }
     }
 }
 
@@ -774,6 +793,7 @@
        total_written += nwritten;
     }
 
+  invalidate_cache(fd, total_written);
   return total_written;
 }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]