summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS10
-rw-r--r--src/shred.c21
-rwxr-xr-xtests/misc/shred-exact.sh11
3 files changed, 27 insertions, 15 deletions
diff --git a/NEWS b/NEWS
index 6f685b478..79665ac8b 100644
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,11 @@ GNU coreutils NEWS -*- outline -*-
rm -I now prompts for confirmation before removing a write protected file.
[Bug introduced in coreutils-6.8]
+ shred once again uses direct I/O on systems requiring aligned buffers.
+ Also direct I/O failures for odd sized writes at end of file are now handled.
+ [The "last write" bug was introduced in coreutils-5.3.0 but masked
+ by the alignment bug introduced in coreutils-6.0]
+
tail --retry -f now waits for the files specified to appear. Before, tail
would immediately exit when such a file is inaccessible during the initial
open.
@@ -92,9 +97,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, and increases write block
- size from 12KiB to 64KiB when possible.
- [Direct I/O regression introduced in coreutils-6.0]
+ shred increases write block size from 12KiB to 64KiB when possible,
+ to align with other utilities and reduce the system call overhead.
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 9ff723865..98dd8726c 100644
--- a/src/shred.c
+++ b/src/shred.c
@@ -394,7 +394,7 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
char pass_string[PASS_NAME_SIZE]; /* Name of current pass */
bool write_error = false;
bool other_error = false;
- bool first_write = true;
+ bool tried_without_directio = false;
/* Printable previous offset into the file */
char previous_offset_buf[LONGEST_HUMAN_READABLE + 1];
@@ -443,7 +443,7 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
if (type < 0)
randread (s, pbuf, lim);
/* Loop to retry partial writes. */
- for (soff = 0; soff < lim; soff += ssize, first_write = false)
+ for (soff = 0; soff < lim; soff += ssize)
{
ssize = write (fd, pbuf + soff, lim - soff);
if (ssize <= 0)
@@ -459,17 +459,15 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
int errnum = errno;
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
- /* If the first write of the first pass for a given file
- has just failed with EINVAL, turn off direct mode I/O
- and try again. This works around a bug in Linux kernel
- 2.4 whereby opening with O_DIRECT would succeed for some
- file system types (e.g., ext3), but any attempt to
- access a file through the resulting descriptor would
- fail with EINVAL. */
- if (k == 1 && first_write && errno == EINVAL)
+ /* Retry without direct I/O since this may not be supported
+ at all on some (file) systems, or with the current size.
+ I.E. a specified --size that is not aligned, or when
+ dealing with slop at the end of a file with --exact. */
+ if (k == 1 && !tried_without_directio && errno == EINVAL)
{
direct_mode (fd, false);
ssize = 0;
+ tried_without_directio = true;
continue;
}
error (0, errnum, _("%s: error writing at offset %s"),
@@ -478,7 +476,8 @@ dopass (int fd, char const *qname, off_t *sizep, int type,
/* 'shred' is often used on bad media, before throwing it
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. */
+ SECTOR_SIZE, except at the end. This size constraint
+ also enables direct I/O on some (file) systems. */
verify (PERIODIC_OUTPUT_SIZE % SECTOR_SIZE == 0);
verify (NONPERIODIC_OUTPUT_SIZE % SECTOR_SIZE == 0);
if (errnum == EIO && 0 <= size && (soff | SECTOR_MASK) < lim)
diff --git a/tests/misc/shred-exact.sh b/tests/misc/shred-exact.sh
index 0cdc91fc0..eb30a7d69 100755
--- a/tests/misc/shred-exact.sh
+++ b/tests/misc/shred-exact.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# make sure that neither --exact nor --zero gobbles a command line argument
+# Test functionality of --exact
# Copyright (C) 2000-2013 Free Software Foundation, Inc.
@@ -20,6 +20,7 @@
print_ver_ shred
+# make sure that neither --exact nor --zero gobbles a command line argument
for opt in --exact --zero; do
echo a > a || fail=1
echo bb > b || fail=1
@@ -33,4 +34,12 @@ for opt in --exact --zero; do
test -f c && fail=1
done
+
+# make sure direct I/O is handled appropriately at end of file
+# Create a 1MiB file as we'll probably not be using blocks larger than that
+# (i.e. we want to test failed writes not at the start).
+truncate -s1MiB file.slop || framework_failure_
+truncate -s+1 file.slop || framework_failure_
+shred --exact -n1 file.slop || fail=1
+
Exit $fail