[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FYI: shred now enables direct-mode I/O when possible
From: |
Jim Meyering |
Subject: |
FYI: shred now enables direct-mode I/O when possible |
Date: |
Tue, 08 Jun 2004 09:05:05 +0200 |
FYI, I've just checked in these changes, but haven't tested on Solaris.
2004-06-08 Jim Meyering <address@hidden>
* src/shred.c (direct_mode): Turn it on/off with directio, too.
2004-06-07 Jim Meyering <address@hidden>
Enable direct-mode I/O (bypassing the buffer cache), if possible.
Prompted by a suggestion from Kalle Olavi Niemitalo
in http://bugs.debian.org/207035.
* src/shred.c (direct_mode): New function.
(do_wipefd): Turn on direct-mode I/O.
(dopass): If a file's first write fails with EINVAL,
turn off direct-mode I/O and retry the write.
Index: src/shred.c
===================================================================
RCS file: /fetish/cu/src/shred.c,v
retrieving revision 1.95
retrieving revision 1.97
diff -u -p -r1.95 -r1.97
--- src/shred.c 4 Jun 2004 17:43:55 -0000 1.95
+++ src/shred.c 8 Jun 2004 06:47:43 -0000 1.97
@@ -810,6 +810,31 @@ dosync (int fd, char const *qname)
return 0;
}
+/* Turn on or off direct I/O mode for file descriptor FD, if possible.
+ Try to turn it on if ENABLE is true. Otherwise, try to turn it off. */
+static void
+direct_mode (int fd, bool enable)
+{
+ if (O_DIRECT)
+ {
+ int fd_flags = fcntl (fd, F_GETFL);
+ if (0 < fd_flags)
+ {
+ int new_flags = (enable
+ ? (fd_flags | O_DIRECT)
+ : (fd_flags & ~O_DIRECT));
+ if (new_flags != fd_flags)
+ fcntl (fd, F_SETFL, new_flags);
+ }
+ }
+
+#if HAVE_DIRECTIO && defined DIRECTIO_ON && defined DIRECTIO_OFF
+ /* This is Solaris-specific. See the following for details:
+ http://docs.sun.com/db/doc/816-0213/6m6ne37so?q=directio&a=view */
+ directio (fd, enable ? DIRECTIO_ON : DIRECTIO_OFF);
+#endif
+}
+
/*
* Do pass number k of n, writing "size" bytes of the given pattern "type"
* to the file descriptor fd. Qname, k and n are passed in only for verbose
@@ -836,6 +861,7 @@ dopass (int fd, char const *qname, off_t
size_t ralign = lcm (getpagesize (), sizeof *r); /* Fill alignment. */
char pass_string[PASS_NAME_SIZE]; /* Name of current pass */
bool write_error = false;
+ bool first_write = true;
/* Printable previous offset into the file */
char previous_offset_buf[LONGEST_HUMAN_READABLE + 1];
@@ -890,7 +916,7 @@ dopass (int fd, char const *qname, off_t
if (type < 0)
fillrand (s, r, rsize, lim);
/* Loop to retry partial writes. */
- for (soff = 0; soff < lim; soff += ssize)
+ for (soff = 0; soff < lim; soff += ssize, first_write = false)
{
ssize = write (fd, (char *) r + soff, lim - soff);
if (ssize <= 0)
@@ -906,6 +932,20 @@ dopass (int fd, char const *qname, off_t
{
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-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)
+ {
+ direct_mode (fd, false);
+ ssize = 0;
+ continue;
+ }
error (0, errnum, _("%s: error writing at offset %s"),
qname, umaxtostr ((uintmax_t) offset + soff, buf));
/*
@@ -1243,6 +1283,8 @@ do_wipefd (int fd, char const *qname, st
return false;
}
+ direct_mode (fd, true);
+
/* Allocate pass array */
passarray = xnmalloc (flags->n_iterations, sizeof *passarray);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- FYI: shred now enables direct-mode I/O when possible,
Jim Meyering <=