From 90b66638060639d863e34d1ea8fd321b93d4912a Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 17 Sep 2024 21:24:23 +0200 Subject: Print info about bad writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- TODO | 4 ++-- deadshred.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/TODO b/TODO index ff4552a..9a3b805 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ Add `-n iterations` +Add offset..length option Add shred map for continuing later (print to stdout on SIGTERM) Enhance progress printout with: - bad sections (count, bytes) - shredded bytes per seconds + shredded bytes per seconds (dont't forget machine and process suspension) diff --git a/deadshred.c b/deadshred.c index 84a5184..3321a4e 100644 --- a/deadshred.c +++ b/deadshred.c @@ -10,6 +10,7 @@ USAGE("device [< random-source]"); struct span { off_t start; off_t end; + off_t bad; size_t blocksize; }; @@ -28,6 +29,10 @@ static int use_stdin; static char total_size_1000[256]; static char total_size_1024[256]; +static uintmax_t bad_writes = 0; +static uintmax_t bad_sections = 0; +static off_t bad_bytes = 0; + static off_t filesize(int fd, const char *fname) @@ -99,8 +104,11 @@ add_span(off_t off, off_t max_end, size_t blocksize) spans[nspans].start = off; spans[nspans].end = end; + spans[nspans].bad = end - off; spans[nspans].blocksize = (size_t)blocksize; nspans++; + + return end - off; } @@ -136,12 +144,12 @@ humansize1024(off_t s, char *buf) s /= 1024; unit++; } - sprintf(buf, "%lu.%u %ciB", (unsigned long int)s / 1024U, (unsigned long int)((s * 10 % 10240) / 1024U), units[unit]); + sprintf(buf, "%lu.%lu %ciB", (unsigned long int)s / 1024UL, (unsigned long int)(s * 10 % 10240) / 1024UL, units[unit]); return buf; } -static int +static void print_progress(int done) { static char buf1[1024] = {0}; @@ -150,16 +158,23 @@ print_progress(int done) char subbuf1[256]; char subbuf2[256]; + char subbuf3[256]; + char subbuf4[256]; sprintf(i == 0 ? buf1 : buf2, - "%ji bytes (%s, %s, %.2lf %%) of %s (%s) shredded\033[K\n%s", + "%ji bytes (%s, %s, %.2lf %%) of %s (%s) shredded\033[K\n" + "failed writes: %ju; bad sections: %ju (%s, %s)\033[K\n%s", (intmax_t)shredded, humansize1000(shredded, subbuf1), humansize1024(shredded, subbuf2), - 100. * (double)shredded / (double)total_size, + 100 * (double)shredded / (double)total_size, total_size_1000, total_size_1024, - done ? "" : "\033[A"); + bad_writes, + bad_sections, + humansize1000(bad_bytes, subbuf3), + humansize1024(bad_bytes, subbuf4), + done ? "" : "\033[A\033[A"); if (strcmp(buf1, buf2)) { fprintf(stderr, "%s", i == 0 ? buf1 : buf2); @@ -171,15 +186,28 @@ print_progress(int done) static void -shredspan(int fd, const struct span *span, const char *fname) +shredspan(int fd, struct span *span, const char *fname) { - off_t off; + off_t off, n; ssize_t r; - int update_progress_delay = 0; + clockid_t clck = CLOCK_MONOTONIC_COARSE; + const char *clkcstr = "CLOCK_MONOTONIC_COARSE"; + struct timespec now, when = {0, 0}; + int bad = span->bad > 0; + + if (clock_gettime(clck, &now)) { + clck = CLOCK_MONOTONIC; + clkcstr = "CLOCK_MONOTONIC"; + } for (off = span->start; off < span->end;) { - if (!update_progress_delay--) { - update_progress_delay = 1000; /* TOOD use half a second instead */ + if (clock_gettime(clck, &now)) + eprintf("clock_gettime %s:", clkcstr); + if (now.tv_sec > when.tv_sec || (now.tv_sec == when.tv_sec && now.tv_nsec >= when.tv_nsec)) { + when = now; + when.tv_nsec += 500000000L; + when.tv_sec += when.tv_nsec / 1000000000L; + when.tv_nsec = when.tv_nsec % 1000000000L; print_progress(0); } if (lseek(fd, off, SEEK_SET) < 0) @@ -187,23 +215,37 @@ shredspan(int fd, const struct span *span, const char *fname) ensure_random(span->blocksize); r = write(fd, &reservoir[reservoir_off], (size_t)MIN((off_t)span->blocksize, span->end - off)); if (r < 0) { - if (errno != EINTR) - off = add_span(off, span->end, span->blocksize == 1U ? 1U : span->blocksize); - update_progress_delay = 0; + if (errno != EINTR) { + off += n = add_span(off, span->end, span->blocksize == 1U ? 1U : span->blocksize); + if (!span->bad) + bad_bytes += n; + if (bad) + bad = 0; + else + bad_sections += 1U; + } + when.tv_sec = 0; + when.tv_nsec = 0; + bad_writes += 1U; continue; } off += (off_t)r; shredded += (off_t)r; reservoir_off += (size_t)r; + if (span->bad) { + bad_bytes -= (off_t)r; + span->bad -= (off_t)r; + } } + + if (bad && !span->bad) + bad_sections -= 1U; } int main(int argc, char *argv[]) { - char buf1[256]; - char buf2[256]; size_t i; int fd; @@ -227,6 +269,7 @@ main(int argc, char *argv[]) spans = emalloc(sizeof(*spans)); spans[0].start = 0; spans[0].end = total_size = filesize(fd, argv[0]); + spans[0].bad = 0; spans[0].blocksize = 8192U; nspans = 1U; spans_size = 1U; -- cgit v1.2.3-70-g09d2