Whamcloud - gitweb
badblocks: add a max bad blocks count option
authorIustin Pop <iustin@google.com>
Wed, 11 Jun 2008 11:12:17 +0000 (13:12 +0200)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 17 Jun 2008 11:33:29 +0000 (07:33 -0400)
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 <iustin@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/badblocks.8.in
misc/badblocks.c

index 4748810..b83b598 100644 (file)
@@ -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 <Remy.Card@linux.org>.  Current maintainer is
index 709effe..d2992e3 100644 (file)
@@ -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");