aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--common.h5
-rw-r--r--deadshred.c70
-rw-r--r--rnd.c44
4 files changed, 80 insertions, 40 deletions
diff --git a/TODO b/TODO
index d85ebb9..7edc9d8 100644
--- a/TODO
+++ b/TODO
@@ -1 +1,2 @@
Add shred map operand
+Test direction alternation
diff --git a/common.h b/common.h
index c1dbcfc..241f280 100644
--- a/common.h
+++ b/common.h
@@ -76,11 +76,12 @@ const char *wravg_get(struct status *s);
/* rnd.c */
+void init_random(int fd, const char *fname, off_t blksize);
+void destroy_random(void);
#if defined(__GNUC__)
-__attribute__((__const__))
+__attribute__((__pure__))
#endif
size_t max_blksize(void);
-void init_random(int fd, const char *fname);
const char *get_random(size_t needed);
void used_random(ssize_t amount);
diff --git a/deadshred.c b/deadshred.c
index 28a64fe..b1f21f2 100644
--- a/deadshred.c
+++ b/deadshred.c
@@ -3,8 +3,8 @@
#include <libsimple-arg.h>
-USAGE("[-o offset] [-l length | -e postend] device [< random-source]");
-/* TODO add option (-b) to switch start direction */
+USAGE("[-b blocksize] [-o offset] [-l length | -e postend] [-r] device [< random-source]");
+/* TODO document (also in README and man pages) options -b and -r */
struct status status = STATUS_INIT;
@@ -129,18 +129,14 @@ print_status(int done, struct status *s)
static void *
-status_print_loop(void *user)
+status_print_loop(void *initial_status)
{
struct pollfd pfd = {.fd = status_print_pipe[0], .events = POLLIN};
ssize_t r;
int terminate = 0;
- struct status s = STATUS_INIT;
+ struct status s = *(struct status *)initial_status;
size_t status_off;
- (void) user;
-
- s.last_success = start_time;
-
unblock_sigs();
do {
@@ -195,6 +191,7 @@ shredspan(int fd, struct span *span, const char *fname)
struct timespec when = {0, 0};
int bad = span->bad > 0;
int first_fail = 1;
+ int was_successful = 0;
const char *random_data;
off = (status.direction == FORWARDS ? span->start : span->end);
@@ -212,6 +209,10 @@ shredspan(int fd, struct span *span, const char *fname)
if (clock_gettime(clck, &status.now))
eprintf("clock_gettime %s:", clkcstr);
+ if (was_successful) {
+ was_successful = 0;
+ status.last_success = status.now;
+ }
if (libsimple_cmptimespec(&status.now, &when) >= 0) {
libsimple_sumtimespec(&when, &status.now, &status_print_interval);
status_off = 0;
@@ -234,7 +235,7 @@ shredspan(int fd, struct span *span, const char *fname)
n = MIN((off_t)span->blocksize, span->end - off);
} else {
n = off--;
- off &= ~(off_t)(span->blocksize - 1U);
+ off -= off % (off_t)span->blocksize;
if (off < span->start)
off = span->start;
n -= off;
@@ -288,7 +289,7 @@ shredspan(int fd, struct span *span, const char *fname)
status.shredded += (off_t)r;
used_random(r);
wravg_update_write(r, &status);
- status.last_success = status.now;
+ was_successful = 1;
if (span->bad) {
status.bad_bytes -= (off_t)r;
span->bad -= (off_t)r;
@@ -332,26 +333,35 @@ fail:
int
main(int argc, char *argv[])
{
- off_t off = -1, len = -1, end = -1;
+ off_t off = -1, len = -1, end = -1, blk = -1;
size_t i, j;
- int fd;
+ int fd, reverse_direction = 0;
pthread_t status_print_thread;
+ struct status initial_status;
ARGBEGIN {
- case 'o':
- if (off >= 0)
+ case 'b':
+ if (blk >= 0)
usage();
- off = unhumansize(ARG(), FLAG());
+ blk = unhumansize(ARG(), FLAG());
+ break;
+ case 'e':
+ if (len >= 0 || end >= 0)
+ usage();
+ end = unhumansize(ARG(), FLAG());
break;
case 'l':
if (len >= 0 || end >= 0)
usage();
len = unhumansize(ARG(), FLAG());
break;
- case 'e':
- if (len >= 0 || end >= 0)
+ case 'o':
+ if (off >= 0)
usage();
- end = unhumansize(ARG(), FLAG());
+ off = unhumansize(ARG(), FLAG());
+ break;
+ case 'r':
+ reverse_direction = 1;
break;
default:
usage();
@@ -360,11 +370,20 @@ main(int argc, char *argv[])
if (argc != 1)
usage();
+ /* TODO If in foreground, and /dev/tty can be opened,
+ * use /dev/tty — however if stdin is a tty, use
+ * stdin instead — to request configuration unless
+ * bypassed with new option (-Y). The prompt shall
+ * be identify the device and display it's size,
+ * also the section the wipe shall be displayed
+ * if -elo was used. The use shall be required
+ * to enter 'yes' in upper case. */
+
fd = open(argv[0], O_WRONLY | O_DSYNC);
if (fd < 0)
eprintf("open %s O_WRONLY|O_DSYNC:", argv[0]);
- init_random(STDIN_FILENO, "<stdin>");
+ init_random(STDIN_FILENO, "<stdin>", blk);
spans = emalloc(sizeof(*spans));
spans[0].start = 0;
@@ -408,10 +427,8 @@ main(int argc, char *argv[])
setup_sighandler();
block_sigs();
- errno = pthread_create(&status_print_thread, NULL, &status_print_loop, NULL);
- if (errno)
- eprintf("pthread_create NULL:");
-
+ if (reverse_direction)
+ status.direction ^= 1;
if (clock_gettime(clck, &start_time)) {
clck = CLOCK_MONOTONIC;
clkcstr = "CLOCK_MONOTONIC";
@@ -421,6 +438,11 @@ main(int argc, char *argv[])
wravg_init(&start_time, &status);
status.last_success = start_time;
+ initial_status = status;
+ errno = pthread_create(&status_print_thread, NULL, &status_print_loop, &initial_status);
+ if (errno)
+ eprintf("pthread_create NULL:");
+
while (nspans) {
size_t old_nspans = nspans;
for (i = 0; i < old_nspans && !exiting; i++)
@@ -429,7 +451,6 @@ main(int argc, char *argv[])
memmove(&spans[0], &spans[i], (nspans -= i) * sizeof(*spans));
break;
}
- /* TODO bug: this is sometimes reached immediately on write failure */
for (i = 0, j = nspans, nspans -= old_nspans; i < nspans;)
spans[i++] = spans[--j];
status.direction ^= 1;
@@ -439,6 +460,7 @@ main(int argc, char *argv[])
close(fd);
if (status_print_pipe[1] >= 0)
close(status_print_pipe[1]);
+ destroy_random();
errno = pthread_join(status_print_thread, NULL);
if (errno)
diff --git a/rnd.c b/rnd.c
index 7e24bf2..0ed92e2 100644
--- a/rnd.c
+++ b/rnd.c
@@ -2,30 +2,32 @@
#include "common.h"
-static char reservoir[128U << 10];
-static size_t reservoir_off = sizeof(reservoir);
+static char *reservoir;
+static size_t reservoir_off;
+static size_t reservoir_size;
static int random_fd;
static const char *random_fname;
-size_t
-max_blksize(void)
-{
- size_t ret = sizeof(reservoir);
- while (ret & (ret - 1U))
- ret &= ret - 1U;
- return ret;
-}
-
-
void
-init_random(int fd, const char *fname)
+init_random(int fd, const char *fname, off_t blksize)
{
struct stat st;
+ if (blksize <= 0) {
+ blksize = (off_t)64 << 20;
+ } else if (blksize > (off_t)1 << 30) {
+ weprintf("limiting block size to 1G");
+ blksize = 1;
+ blksize <<= 30;
+ }
+
random_fname = fname;
random_fd = fd;
+ reservoir_size = (size_t)blksize;
+ reservoir = emalloc(reservoir_size);
+
errno = 0;
if (isatty(random_fd) || errno == EBADF) {
use_builtin_generator:
@@ -41,13 +43,27 @@ init_random(int fd, const char *fname)
}
+void
+destroy_random(void)
+{
+ free(reservoir);
+}
+
+
+size_t
+max_blksize(void)
+{
+ return reservoir_size;
+}
+
+
const char *
get_random(size_t needed)
{
size_t off;
ssize_t r;
- if (sizeof(reservoir) - reservoir_off >= needed)
+ if (reservoir_size - reservoir_off >= needed)
return &reservoir[reservoir_off];
if (random_fd < 0) {