From 931b0289eee5d83bff7e80c7420bda0a5bb078da Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Wed, 11 Jun 2008 13:12:17 +0200 Subject: [PATCH] badblocks: add a max bad blocks count option Currently, badblocks will continue scanning the device until it reaches last_block, even though it might be that the drive is not responding at all anymore. This patch introduces a new parameter ('-e') that allows one to specify the maximum bad block count; if badblocks sees more than this number, it will abort the test. While this is not useful for testing a device that will need to be used as a filesystem (because we don't get an exhaustive list of bad blocks), it is useful for testing if a device has bad blocks at all: for example, with a count of 1, it will finish after the first error thus not needing to test the whole device if the only purpose of the test is to check for any bad blocks. Signed-off-by: Iustin Pop Signed-off-by: Theodore Ts'o --- misc/badblocks.8.in | 16 ++++++++++++++++ misc/badblocks.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/misc/badblocks.8.in b/misc/badblocks.8.in index 4748810..b83b598 100644 --- a/misc/badblocks.8.in +++ b/misc/badblocks.8.in @@ -16,6 +16,10 @@ badblocks \- search a device for bad blocks .I blocks_at_once ] [ +.B \-e +.I max_bad_blocks +] +[ .B \-i .I input_file ] @@ -81,6 +85,11 @@ Specify the size of blocks in bytes. The default is 1024. .BI \-c " number of blocks" is the number of blocks which are tested at a time. The default is 64. .TP +.BI \-e " max bad block count" +Specify a maximum number of bad blocks before aborting the test. The +default is 0, meaning the test will continue until the end of the test +range is reached. +.TP .B \-f Normally, badblocks will refuse to do a read/write or a non-destructive test on a device which is mounted, since either can cause the system to @@ -183,6 +192,13 @@ This option erases data! If you want to do write-mode testing on an existing file system, use the .B \-n option instead. It is slower, but it will preserve your data. +.PP +The +.B \-e +option will cause badblocks to output a possibly incomplete list of +bad blocks. Therefore it is recommended to use it only when one wants +to know if there are any bad blocks at all on the device, and not when +the list of bad blocks is wanted. .SH AUTHOR .B badblocks was written by Remy Card . Current maintainer is diff --git a/misc/badblocks.c b/misc/badblocks.c index 709effe..d2992e3 100644 --- a/misc/badblocks.c +++ b/misc/badblocks.c @@ -70,6 +70,7 @@ static int t_max = 0; /* allocated test patterns */ static unsigned int *t_patts = NULL; /* test patterns */ static int current_O_DIRECT = 0; /* Current status of O_DIRECT flag */ static int exclusive_ok = 0; +static unsigned int max_bb = 0; /* Abort test if more than this number of bad blocks has been encountered */ #define T_INC 32 @@ -77,7 +78,7 @@ unsigned int sys_page_size = 4096; static void usage(void) { - fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n device [last_block [start_block]]\n"), + fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] [-e max_bad_blocks] [-t test_pattern [-t test_pattern [...]]]\n device [last_block [start_block]]\n"), program_name); exit (1); } @@ -379,6 +380,12 @@ static unsigned int test_ro (int dev, blk_t last_block, } while (currently_testing < last_block) { + if (max_bb && bb_count >= max_bb) { + if (s_flag || v_flag) { + fputs(_("Too many bad blocks, aborting test\n"), stderr); + } + break; + } if (next_bad) { if (currently_testing == next_bad) { /* fprintf (out, "%lu\n", nextbad); */ @@ -476,6 +483,12 @@ static unsigned int test_rw (int dev, blk_t last_block, try = blocks_at_once; while (currently_testing < last_block) { + if (max_bb && bb_count >= max_bb) { + if (s_flag || v_flag) { + fputs(_("Too many bad blocks, aborting test\n"), stderr); + } + break; + } if (currently_testing + try > last_block) try = last_block - currently_testing; got = do_write(dev, buffer, try, block_size, @@ -515,6 +528,12 @@ static unsigned int test_rw (int dev, blk_t last_block, try = blocks_at_once; while (currently_testing < last_block) { + if (max_bb && bb_count >= max_bb) { + if (s_flag || v_flag) { + fputs(_("Too many bad blocks, aborting test\n"), stderr); + } + break; + } if (currently_testing + try > last_block) try = last_block - currently_testing; got = do_read (dev, read_buffer, try, block_size, @@ -652,6 +671,12 @@ static unsigned int test_nd (int dev, blk_t last_block, alarm_intr(SIGALRM); while (currently_testing < last_block) { + if (max_bb && bb_count >= max_bb) { + if (s_flag || v_flag) { + fputs(_("Too many bad blocks, aborting test\n"), stderr); + } + break; + } got = try = blocks_at_once - buf_used; if (next_bad) { if (currently_testing == next_bad) { @@ -884,7 +909,7 @@ int main (int argc, char ** argv) if (argc && *argv) program_name = *argv; - while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:t:X")) != EOF) { + while ((c = getopt (argc, argv, "b:e:fi:o:svwnc:p:h:t:X")) != EOF) { switch (c) { case 'b': block_size = parse_uint(optarg, "block size"); @@ -924,6 +949,9 @@ int main (int argc, char ** argv) case 'c': blocks_at_once = parse_uint(optarg, "blocks at once"); break; + case 'e': + max_bb = parse_uint(optarg, "max bad block count"); + break; case 'p': num_passes = parse_uint(optarg, "number of clean passes"); -- 1.8.3.1