coreutils
[Top][All Lists]
Advanced

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

[PATCH 2/2] shred: write larger chunks when possible


From: Pádraig Brady
Subject: [PATCH 2/2] shred: write larger chunks when possible
Date: Mon, 4 Nov 2013 23:14:11 +0000

* src/shred.c (dopass): When not needing to write periodic patterns,
use a 64K block size to reduce the number of write syscalls.
---
 NEWS        |    4 ++--
 src/shred.c |   34 +++++++++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index b4804a2..46a3df4 100644
--- a/NEWS
+++ b/NEWS
@@ -87,8 +87,8 @@ GNU coreutils NEWS                                    -*- 
outline -*-
   Reservoir sampling is used to limit memory usage based on the number of
   outputs, rather than the number of inputs.
 
-  shred once again uses direct I/O where available.
-  [Regression introduced in coreutils-6.0]
+  shred once again uses direct I/O where available, and larger I/O blocks
+  when possible.  [Direct I/O regression introduced in coreutils-6.0]
 
   split --line-bytes=SIZE, now only allocates memory as needed rather
   than allocating SIZE bytes at program start.
diff --git a/src/shred.c b/src/shred.c
index 6715ebd..0c861b7 100644
--- a/src/shred.c
+++ b/src/shred.c
@@ -222,6 +222,25 @@ to be recovered later.\n\
   exit (status);
 }
 
+/*
+ * Determine if pattern type is periodic or not.
+ */
+static bool
+periodic_pattern (int type)
+{
+  if (type <= 0)
+    return false;
+
+  char r[3];
+  unsigned int bits = type & 0xfff;
+
+  bits |= bits << 12;
+  r[0] = (bits >> 4) & 255;
+  r[1] = (bits >> 8) & 255;
+  r[2] = bits & 255;
+
+  return (r[0] != r[1]) || (r[0] != r[2]) || (r[1] != r[2]);
+}
 
 /*
  * Fill a buffer with a fixed pattern.
@@ -361,9 +380,13 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
 
   /* Fill pattern buffer.  Aligning it to a page so we can do direct I/O.  */
   size_t page_size = getpagesize();
-#define OUTPUT_SIZE (12 * 1024)
+#define PERIODIC_OUTPUT_SIZE (12 * 1024)
+#define NONPERIODIC_OUTPUT_SIZE (64 * 1024)
+  verify (PERIODIC_OUTPUT_SIZE % 3 == 0);
+  size_t output_size = periodic_pattern (type)
+                       ? PERIODIC_OUTPUT_SIZE : NONPERIODIC_OUTPUT_SIZE;
 #define PAGE_ALIGN_SLOP (page_size - 1)                /* So directio works */
-#define FILLPATTERN_SIZE (((OUTPUT_SIZE + 2) / 3) * 3) /* Multiple of 3 */
+#define FILLPATTERN_SIZE (((output_size + 2) / 3) * 3) /* Multiple of 3 */
 #define PATTERNBUF_SIZE (PAGE_ALIGN_SLOP + FILLPATTERN_SIZE)
   void *fill_pattern_mem = xmalloc (PATTERNBUF_SIZE);
   unsigned char *pbuf = ptr_align (fill_pattern_mem, page_size);
@@ -408,8 +431,8 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
   while (true)
     {
       /* How much to write this time? */
-      lim = OUTPUT_SIZE;
-      if (0 <= size && size - offset < OUTPUT_SIZE)
+      lim = output_size;
+      if (0 <= size && size - offset < output_size)
         {
           if (size < offset)
             break;
@@ -456,7 +479,8 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
                      out.  Thus, it shouldn't give up on bad blocks.  This
                      code works because lim is always a multiple of
                      SECTOR_SIZE, except at the end.  */
-                  verify (OUTPUT_SIZE % SECTOR_SIZE == 0);
+                  verify (PERIODIC_OUTPUT_SIZE % SECTOR_SIZE == 0);
+                  verify (NONPERIODIC_OUTPUT_SIZE % SECTOR_SIZE == 0);
                   if (errnum == EIO && 0 <= size && (soff | SECTOR_MASK) < lim)
                     {
                       size_t soff1 = (soff | SECTOR_MASK) + 1;
-- 
1.7.7.6




reply via email to

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