diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | common.h | 5 | ||||
-rw-r--r-- | deadshred.c | 70 | ||||
-rw-r--r-- | rnd.c | 44 |
4 files changed, 80 insertions, 40 deletions
@@ -1 +1,2 @@ Add shred map operand +Test direction alternation @@ -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) @@ -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) { |