badblocks.c revision 45ff69ffeb700012a7c052f5e45882557a40be7e
153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* 253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * badblocks.c - Bad blocks checker 353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> 553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Laboratoire MASI, Institut Blaise Pascal 653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Universite Pierre et Marie Curie (Paris VI) 753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o 953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright 1999 by David Beattie 1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This file is based on the minix file system programs fsck and mkfs 1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi> 1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 1453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * %Begin-Header% 1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This file may be redistributed under the terms of the GNU Public 1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * License. 1753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * %End-Header% 1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */ 1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* 2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * History: 2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 93/05/26 - Creation from e2fsck 2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 94/02/27 - Made a separate bad blocks checker 2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 99/06/30...99/07/26 - Added non-destructive write-testing, 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * configurable blocks-at-once parameter, 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * loading of badblocks list to avoid testing 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * blocks known to be bad, multiple passes to 28a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * make sure that no new blocks are added to the 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * list. (Work done by David Beattie) 301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) */ 311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#ifndef _GNU_SOURCE 3319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#define _GNU_SOURCE /* for O_DIRECT */ 34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#endif 35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#ifndef O_LARGEFILE 37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#define O_LARGEFILE 0 3851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#endif 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "config.h" 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <errno.h> 4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <fcntl.h> 4319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#ifdef HAVE_GETOPT_H 44591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include <getopt.h> 4593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#else 46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)extern char *optarg; 4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)extern int optind; 48591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif 491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <signal.h> 50a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <stdio.h> 51a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <stdlib.h> 52521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <string.h> 53521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <unistd.h> 5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <setjmp.h> 558abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include <time.h> 5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <limits.h> 5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <sys/time.h> 5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <sys/ioctl.h> 60a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <sys/types.h> 6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "et/com_err.h" 6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "ext2fs/ext2_io.h" 64a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "ext2fs/ext2_fs.h" 65a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "ext2fs/ext2fs.h" 66a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "nls-enable.h" 67a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 68a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)const char * program_name = "badblocks"; 69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)const char * done_string = N_("done \n"); 70a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static int v_flag; /* verbose */ 72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int w_flag; /* do r/w test: 0=no, 1=yes, 73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * 2=non-destructive */ 74a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int s_flag; /* show progress of test */ 75a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int force; /* force check of mounted device */ 76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static int t_flag; /* number of test patterns */ 77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static int t_max; /* allocated test patterns */ 78d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static unsigned int *t_patts; /* test patterns */ 79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int use_buffered_io; 80a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int exclusive_ok; 81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static unsigned int max_bb; /* Abort test if more than this number of bad blocks has been encountered */ 82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static unsigned int d_flag; /* delay factor between reads */ 83a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static struct timeval time_start; 84a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 85a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#define T_INC 32 86a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 87a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)unsigned int sys_page_size = 4096; 88a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 89a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static void usage(void) 90d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 91a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) fprintf(stderr, _( 92a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n" 93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)" [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n" 94a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)" [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n" 9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)" device [last_block [first_block]]\n"), 9607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch program_name); 9707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch exit (1); 9881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)} 9907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 10081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)static void exclusive_usage(void) 10181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles){ 10281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) fprintf(stderr, 10319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) _("%s: The -n and -w options are mutually exclusive.\n\n"), 10451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) program_name); 10551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) exit(1); 10619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 10751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 10819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t currently_testing = 0; 10919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_blocks = 0; 11019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_read_errors = 0; 11119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_write_errors = 0; 11219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_corruption_errors = 0; 11351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static ext2_badblocks_list bb_list = NULL; 11419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static FILE *out; 11519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t next_bad = 0; 11653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static ext2_badblocks_iterate bb_iter = NULL; 11781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) 11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR }; 11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 12007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic void *allocate_buffer(size_t size) 1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 12281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) void *ret = 0; 1235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 124c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#ifdef HAVE_POSIX_MEMALIGN 12581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) if (posix_memalign(&ret, sys_page_size, size) < 0) 12653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ret = 0; 12793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#else 12853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#ifdef HAVE_MEMALIGN 12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ret = memalign(sys_page_size, size); 13053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#else 13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#ifdef HAVE_VALLOC 13253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ret = valloc(size); 133aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#endif /* HAVE_VALLOC */ 13453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif /* HAVE_MEMALIGN */ 13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif /* HAVE_POSIX_MEMALIGN */ 13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!ret) 13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ret = malloc(size); 13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 14053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return ret; 14153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/* 144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * This routine reports a new bad block. If the bad block has already 1455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * been seen before, then it returns 0; otherwise it returns 1. 146c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) */ 14719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static int bb_output (blk_t bad, enum error_types error_type) 14853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 14953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode_t errcode; 15053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (ext2fs_badblocks_list_test(bb_list, bad)) 15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return 0; 15353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 15453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(out, "%lu\n", (unsigned long) bad); 155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) fflush(out); 15681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) 15707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch errcode = ext2fs_badblocks_list_add (bb_list, bad); 15807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch if (errcode) { 15953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, errcode, "adding to in-memory bad block list"); 16053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 16153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 16253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* kludge: 16453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) increment the iteration through the bb_list if 16553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) an element was just added before the current iteration 166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) position. This should not cause next_bad to change. */ 167a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (bb_iter && bad < next_bad) 16853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 16953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 17053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (error_type == READ_ERROR) { 171d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) num_read_errors++; 172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else if (error_type == WRITE_ERROR) { 17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) num_write_errors++; 17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } else if (error_type == CORRUPTION_ERROR) { 17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) num_corruption_errors++; 17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 17781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) return 1; 17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 18007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic char *time_diff_format(struct timeval *tv1, 18181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) struct timeval *tv2, char *buf) 18253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 18353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) time_t diff = (tv1->tv_sec - tv2->tv_sec); 18407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch int hr,min,sec; 18553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 186e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) sec = diff % 60; 187e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) diff /= 60; 188e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) min = diff % 60; 18907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch hr = diff / 60; 19053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 19107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch if (hr) 19253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) sprintf(buf, "%d:%02d:%02d", hr, min, sec); 19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else 19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) sprintf(buf, "%d:%02d", min, sec); 19553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return buf; 19653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 198e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)static float calc_percent(unsigned long current, unsigned long total) { 199e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) float percent = 0.0; 200e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (total <= 0) 20181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) return percent; 20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (current >= total) { 20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) percent = 100.0; 20453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 20553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) percent=(100.0*(float)current/(float)total); 206a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) } 207a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return percent; 2085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 2095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void print_status(void) 2115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 2125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) struct timeval time_end; 2135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) char diff_buf[32], line_buf[128]; 214a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) int len; 2155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) gettimeofday(&time_end, 0); 2175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) len = snprintf(line_buf, sizeof(line_buf), 2185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) _("%6.2f%% done, %s elapsed. " 2195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) "(%d/%d/%d errors)"), 2205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) calc_percent((unsigned long) currently_testing, 2215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) (unsigned long) num_blocks), 2225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) time_diff_format(&time_end, &time_start, diff_buf), 2235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) num_read_errors, 2245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) num_write_errors, 2255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) num_corruption_errors); 2265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef HAVE_MBSTOWCS 2275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) len = mbstowcs(NULL, line_buf, sizeof(line_buf)); 2285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#endif 2295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) fputs(line_buf, stderr); 2305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) memset(line_buf, '\b', len); 2315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) line_buf[len] = 0; 2325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) fputs(line_buf, stderr); 2335267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) fflush (stderr); 2345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 2355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void alarm_intr(int alnum EXT2FS_ATTR((unused))) 2375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 2385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) signal (SIGALRM, alarm_intr); 2395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) alarm(1); 24093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!num_blocks) 24153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return; 24253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) print_status(); 24353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 24453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 24593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void *terminate_addr = NULL; 24693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void terminate_intr(int signo EXT2FS_ATTR((unused))) 24853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 24953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fflush(out); 250d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) fprintf(stderr, "\n\nInterrupted at block %llu\n", 25153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (unsigned long long) currently_testing); 25253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fflush(stderr); 25393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (terminate_addr) 25453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) longjmp(terminate_addr,1); 25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit(1); 25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 257e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 25893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void capture_terminate(jmp_buf term_addr) 25993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 2605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) terminate_addr = term_addr; 26193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) signal (SIGHUP, terminate_intr); 26293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) signal (SIGINT, terminate_intr); 263d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) signal (SIGPIPE, terminate_intr); 26453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal (SIGTERM, terminate_intr); 26553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal (SIGUSR1, terminate_intr); 26653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal (SIGUSR2, terminate_intr); 26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 268e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 269e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)static void uncapture_terminate(void) 270e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){ 27153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) terminate_addr = NULL; 27253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal (SIGHUP, SIG_DFL); 2735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) signal (SIGINT, SIG_DFL); 27453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal (SIGPIPE, SIG_DFL); 27553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) signal (SIGTERM, SIG_DFL); 27609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) signal (SIGUSR1, SIG_DFL); 277d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) signal (SIGUSR2, SIG_DFL); 27853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 27953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 28053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* Linux requires that O_DIRECT I/Os be 512-byte sector aligned */ 28153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 282e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#define O_DIRECT_SIZE 512 283e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 284e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)static void set_o_direct(int dev, unsigned char *buffer, size_t size, 28553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ext2_loff_t offset) 28653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 2875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef O_DIRECT 28853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) static int current_O_DIRECT; /* Current status of O_DIRECT flag */ 28953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int new_flag = O_DIRECT; 29009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int flag; 291d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 29253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if ((use_buffered_io != 0) || 29353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (((unsigned long) buffer & (sys_page_size - 1)) != 0) || 294591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ((size & (sys_page_size - 1)) != 0) || 295d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ((offset & (O_DIRECT_SIZE - 1)) != 0)) 296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) new_flag = 0; 29753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 29853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (new_flag != current_O_DIRECT) { 29953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */ 300e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) flag = fcntl(dev, F_GETFL); 30109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (flag > 0) { 30293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) flag = (flag & ~O_DIRECT) | new_flag; 30353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fcntl(dev, F_SETFL, flag); 30453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 30553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) current_O_DIRECT = new_flag; 306d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 307d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif 308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 31053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 31153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static void pattern_fill(unsigned char *buffer, unsigned int pattern, 312d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) size_t n) 31353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 31453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int i, nb; 31553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned char bpattern[sizeof(pattern)], *ptr; 316e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 317d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (pattern == (unsigned int) ~0) { 31853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (ptr = buffer; ptr < buffer + n; ptr++) { 31953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (*ptr) = random() % (1 << (8 * sizeof(char))); 32093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 32153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag | v_flag) 32253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("Testing with random pattern: "), stderr); 32353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 324e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) bpattern[0] = 0; 325d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for (i = 0; i < sizeof(bpattern); i++) { 32653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (pattern == 0) 32753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 32893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bpattern[i] = pattern & 0xFF; 32953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pattern = pattern >> 8; 330d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 331e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) nb = i ? (i-1) : 0; 332e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) { 33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) *ptr = bpattern[i]; 334e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (i == 0) 335e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) i = nb; 33609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else 33709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) i--; 33809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 33909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (s_flag | v_flag) { 34009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) fputs(_("Testing with pattern 0x"), stderr); 341e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) for (i = 0; i <= nb; i++) 342e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) fprintf(stderr, "%02x", buffer[i]); 34306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) fputs(": ", stderr); 34406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } 34506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } 34606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)} 34706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 34806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)/* 34906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) * Perform a read of a sequence of blocks; return the number of blocks 35006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) * successfully sequentially read. 35106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) */ 35206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)static int do_read (int dev, unsigned char * buffer, int try, int block_size, 35306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) blk_t current_block) 35406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){ 35551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) long got; 356e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) struct timeval tv1, tv2; 35793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#define NANOSEC (1000000000L) 35893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#define MILISEC (1000L) 35951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 36051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#if 0 36151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) printf("do_read: block %d, try %d\n", current_block, try); 36251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#endif 36351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) set_o_direct(dev, buffer, try * block_size, 36451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) ((ext2_loff_t) current_block) * block_size); 36551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 36651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (v_flag > 1) 36751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) print_status(); 368e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 369e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) /* Seek to the correct loc. */ 37093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 371e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) SEEK_SET) != (ext2_loff_t) current_block * block_size) 372e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) com_err (program_name, errno, "%s", _("during seek")); 373e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 374e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) /* Try the read */ 37593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (d_flag) 37693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) gettimeofday(&tv1, NULL); 37793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) got = read (dev, buffer, try * block_size); 37893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (d_flag) 379e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) gettimeofday(&tv2, NULL); 380e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (got < 0) 38193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) got = 0; 382e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (got & 511) 38393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 38493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) got /= block_size; 38593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (d_flag && got == try) { 38693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#ifdef HAVE_NANOSLEEP 387591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch struct timespec ts; 38893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ts.tv_sec = tv2.tv_sec - tv1.tv_sec; 389e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC; 39093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (ts.tv_nsec < 0) { 391e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) ts.tv_nsec += NANOSEC; 392e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) ts.tv_sec -= 1; 393a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) } 394e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) /* increase/decrease the sleep time based on d_flag value */ 39507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch ts.tv_sec = ts.tv_sec * d_flag / 100; 39607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch ts.tv_nsec = ts.tv_nsec * d_flag / 100; 397d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (ts.tv_nsec > NANOSEC) { 398e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) ts.tv_sec += ts.tv_nsec / NANOSEC; 399e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) ts.tv_nsec %= NANOSEC; 4001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 401c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if (ts.tv_sec || ts.tv_nsec) 402d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) nanosleep(&ts, NULL); 4031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#else 4041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#ifdef HAVE_USLEEP 4051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) struct timeval tv; 4061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) tv.tv_sec = tv2.tv_sec - tv1.tv_sec; 40709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) tv.tv_usec = tv2.tv_usec - tv1.tv_usec; 40809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) tv.tv_sec = tv.tv_sec * d_flag / 100; 4091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) tv.tv_usec = tv.tv_usec * d_flag / 100; 4101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (tv.tv_usec > 1000000) { 411d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) tv.tv_sec += tv.tv_usec / 1000000; 412d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) tv.tv_usec %= 1000000; 413c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) } 414c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if (tv.tv_sec) 41507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch sleep(tv.tv_sec); 416e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (tv.tv_usec) 41793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) usleep(tv.tv_usec); 41893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif 41993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif 42007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 421e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) return got; 422e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)} 42393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 424e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)/* 42593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * Perform a write of a sequence of blocks; return the number of blocks 42693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * successfully sequentially written. 42793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) */ 42807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic int do_write(int dev, unsigned char * buffer, int try, int block_size, 42993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) unsigned long current_block) 43093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 431e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) long got; 432e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 433d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#if 0 434e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) printf("do_write: block %lu, try %d\n", current_block, try); 43593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif 436d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) set_o_direct(dev, buffer, try * block_size, 43709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ((ext2_loff_t) current_block) * block_size); 43809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 439d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (v_flag > 1) 44009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) print_status(); 44107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 44293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) /* Seek to the correct loc. */ 443d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 44453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) SEEK_SET) != (ext2_loff_t) current_block * block_size) 44553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, errno, "%s", _("during seek")); 446c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) 44753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* Try the write */ 448d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) got = write (dev, buffer, try * block_size); 4498abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (got < 0) 4508abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) got = 0; 45109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (got & 511) 4528abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) fprintf(stderr, "Weird value (%ld) in do_write\n", got); 45353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) got /= block_size; 45453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return got; 45553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 45653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 45753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static int host_dev; 458d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 4591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static void flush_bufs(void) 46009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 46153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode_t retval; 462c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) 463c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#ifdef O_DIRECT 46407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch if (!use_buffered_io) 465c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) return; 46607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#endif 467c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) retval = ext2fs_sync_device(host_dev, 1); 468c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if (retval) 46981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) com_err(program_name, retval, "%s", 470c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) _("during ext2fs_sync_device")); 47181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)} 47253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 47353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static unsigned int test_ro (int dev, blk_t last_block, 474c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) int block_size, blk_t first_block, 47553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int blocks_at_once) 476e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){ 477e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) unsigned char * blkbuf; 478e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) int try; 479c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) int got; 48053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int bb_count = 0; 481c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) errcode_t errcode; 482c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) blk_t recover_block = ~0; 483c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) 484c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) /* set up abend handler */ 48553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) capture_terminate(NULL); 48653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 48719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 48819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (errcode) { 48919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) com_err(program_name, errcode, "%s", 49019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) _("while beginning bad block list iteration")); 49151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) exit (1); 49251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 49351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) do { 49407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 49507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } while (next_bad && next_bad < first_block); 49607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 49707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch if (t_flag) { 49807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch blkbuf = allocate_buffer((blocks_at_once + 1) * block_size); 49907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } else { 50007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch blkbuf = allocate_buffer(blocks_at_once * block_size); 50107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 50207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch if (!blkbuf) 50307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch { 50407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch com_err(program_name, ENOMEM, "%s", 50507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch _("while allocating buffers")); 50651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) exit (1); 50751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 50851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (v_flag) { 50919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) fprintf(stderr, _("Checking blocks %lu to %lu\n"), 51019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) (unsigned long)first_block, 51119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) (unsigned long)last_block - 1); 51219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 51319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (t_flag) { 51419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) fputs(_("Checking for bad blocks in read-only mode\n"), stderr); 51519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) pattern_fill(blkbuf + blocks_at_once * block_size, 51607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch t_patts[0], block_size); 51707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 51807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch flush_bufs(); 51907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch try = blocks_at_once; 52019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) currently_testing = first_block; 52119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) num_blocks = last_block - 1; 52219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (!t_flag && (s_flag || v_flag)) 52319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) fputs(_("Checking for bad blocks (read-only test): "), stderr); 52419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (s_flag && v_flag <= 1) 52519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) alarm_intr(SIGALRM); 52619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) while (currently_testing < last_block) 52751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) { 52851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (max_bb && bb_count >= max_bb) { 52951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (s_flag || v_flag) { 53051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) fputs(_("Too many bad blocks, aborting test\n"), stderr); 53151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 53219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) break; 53319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 53409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (next_bad) { 53519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (currently_testing == next_bad) { 53619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) /* fprintf (out, "%lu\n", nextbad); */ 53709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 53819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) currently_testing++; 53919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) continue; 54007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 54119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) else if (currently_testing + try > next_bad) 54219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) try = next_bad - currently_testing; 54319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 54419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (currently_testing + try > last_block) 54519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) try = last_block - currently_testing; 54619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) got = do_read (dev, blkbuf, try, block_size, currently_testing); 54719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (t_flag) { 54819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) /* test the comparison between all the 54919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) blocks successfully read */ 55019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) int i; 55119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) for (i = 0; i < got; ++i) 55281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) if (memcmp (blkbuf+i*block_size, 55381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) blkbuf+blocks_at_once*block_size, 554e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) block_size)) 555e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR); 556e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 557d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (got == 0 && try == 1) 55881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) bb_count += bb_output(currently_testing++, READ_ERROR); 55981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) currently_testing += got; 560d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (got != try) { 56181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) try = 1; 562e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (recover_block == ~0U) 563d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) recover_block = currently_testing - got + 56481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) blocks_at_once; 565d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) continue; 56653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else if (currently_testing == recover_block) { 56753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) try = blocks_at_once; 56853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) recover_block = ~0; 56953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 57053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 57153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_blocks = 0; 57253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) alarm(0); 57353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag || v_flag) 57453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_(done_string), stderr); 57553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 57653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fflush (stderr); 57753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) free (blkbuf); 57853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 579d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ext2fs_badblocks_list_iterate_end(bb_iter); 58053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 58153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) uncapture_terminate(); 58253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 583d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return bb_count; 584d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 58553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 58653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static unsigned int test_rw (int dev, blk_t last_block, 58753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int block_size, blk_t first_block, 58853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int blocks_at_once) 58953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 59053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned char *buffer, *read_buffer; 59153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00}; 59253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const unsigned int *pattern; 59353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int i, try, got, nr_pattern, pat_idx; 594d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) unsigned int bb_count = 0; 59553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blk_t recover_block = ~0; 596d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 597d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) /* set up abend handler */ 59853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) capture_terminate(NULL); 59953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 600591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch buffer = allocate_buffer(2 * blocks_at_once * block_size); 60153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) read_buffer = buffer + blocks_at_once * block_size; 602591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 603591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!buffer) { 604591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch com_err(program_name, ENOMEM, "%s", 605591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch _("while allocating buffers")); 606591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch exit (1); 607591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 608591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 609591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch flush_bufs(); 610591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 611591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (v_flag) { 612591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch fputs(_("Checking for bad blocks in read-write mode\n"), 61353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) stderr); 61453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(stderr, _("From block %lu to %lu\n"), 61553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (unsigned long) first_block, 61653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (unsigned long) last_block - 1); 61753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 61853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (t_flag) { 61953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pattern = t_patts; 62053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) nr_pattern = t_flag; 62153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 62253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pattern = patterns; 62353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 62453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 62553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 62653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pattern_fill(buffer, pattern[pat_idx], 62753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blocks_at_once * block_size); 62853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_blocks = last_block - 1; 62953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) currently_testing = first_block; 63053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag && v_flag <= 1) 63153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) alarm_intr(SIGALRM); 63253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 63353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) try = blocks_at_once; 63453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while (currently_testing < last_block) { 63553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (max_bb && bb_count >= max_bb) { 63653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag || v_flag) { 63753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("Too many bad blocks, aborting test\n"), stderr); 63853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 63953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 64053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 64153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (currently_testing + try > last_block) 64253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) try = last_block - currently_testing; 643591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch got = do_write(dev, buffer, try, block_size, 644591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch currently_testing); 645591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (v_flag > 1) 646591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch print_status(); 647591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 648591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (got == 0 && try == 1) 649591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch bb_count += bb_output(currently_testing++, WRITE_ERROR); 650591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch currently_testing += got; 651591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (got != try) { 652591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try = 1; 653591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (recover_block == ~0U) 654591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch recover_block = currently_testing - 655591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch got + blocks_at_once; 656591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch continue; 657591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else if (currently_testing == recover_block) { 658591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try = blocks_at_once; 65907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch recover_block = ~0; 66007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 66107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 662591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 663591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch num_blocks = 0; 664591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch alarm (0); 665591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (s_flag | v_flag) 666591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch fputs(_(done_string), stderr); 667591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch flush_bufs(); 668591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (s_flag | v_flag) 669591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch fputs(_("Reading and comparing: "), stderr); 670591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch num_blocks = last_block; 671591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch currently_testing = first_block; 672591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (s_flag && v_flag <= 1) 673591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch alarm_intr(SIGALRM); 674591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 675591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try = blocks_at_once; 676591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch while (currently_testing < last_block) { 677591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (max_bb && bb_count >= max_bb) { 678591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (s_flag || v_flag) { 679591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch fputs(_("Too many bad blocks, aborting test\n"), stderr); 680591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 681591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch break; 682591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 683591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (currently_testing + try > last_block) 684591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try = last_block - currently_testing; 685591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch got = do_read (dev, read_buffer, try, block_size, 686591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch currently_testing); 687591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (got == 0 && try == 1) 688591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch bb_count += bb_output(currently_testing++, READ_ERROR); 689591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch currently_testing += got; 690591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (got != try) { 691591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try = 1; 692591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (recover_block == ~0U) 693591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch recover_block = currently_testing - 694591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch got + blocks_at_once; 695591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch continue; 696591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else if (currently_testing == recover_block) { 697591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch try = blocks_at_once; 698591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch recover_block = ~0U; 699591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 700591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch for (i=0; i < got; i++) { 701d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (memcmp(read_buffer + i * block_size, 702d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) buffer + i * block_size, 703d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) block_size)) 704d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bb_count += bb_output(currently_testing+i, CORRUPTION_ERROR); 705591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 706591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (v_flag > 1) 707591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch print_status(); 708591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 709591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 71053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_blocks = 0; 71153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) alarm (0); 71253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag | v_flag) 71353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_(done_string), stderr); 71453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) flush_bufs(); 71553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 71653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) uncapture_terminate(); 71753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) free(buffer); 71853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return bb_count; 71953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 72053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 72153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)struct saved_blk_record { 72253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blk_t block; 72353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int num; 72453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}; 72553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 72653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static unsigned int test_nd (int dev, blk_t last_block, 72753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int block_size, blk_t first_block, 72809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) unsigned int blocks_at_once) 729d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 73053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 73153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned char *test_base, *save_base, *read_base; 73253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int try, i; 73353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const unsigned int patterns[] = { ~0 }; 73453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const unsigned int *pattern; 73553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int nr_pattern, pat_idx; 73653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int got, used2, written; 73753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blk_t save_currently_testing; 73853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) struct saved_blk_record *test_record; 73953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* This is static to prevent being clobbered by the longjmp */ 74053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) static int num_saved; 74153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) jmp_buf terminate_env; 74253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode_t errcode; 74353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned long buf_used; 74453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) static unsigned int bb_count; 74553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int granularity = blocks_at_once; 74653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blk_t recover_block = ~0U; 74753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 74853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) bb_count = 0; 74953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 75053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (errcode) { 75153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err(program_name, errcode, "%s", 752a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch _("while beginning bad block list iteration")); 75353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 75481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) } 75553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) do { 75653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 75753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } while (next_bad && next_bad < first_block); 75853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 75953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blkbuf = allocate_buffer(3 * blocks_at_once * block_size); 76053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_record = malloc(blocks_at_once * sizeof(struct saved_blk_record)); 76153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!blkbuf || !test_record) { 76253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err(program_name, ENOMEM, "%s", 76353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("while allocating buffers")); 76453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 76553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 76653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 76753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) save_base = blkbuf; 76853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_base = blkbuf + (blocks_at_once * block_size); 76953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) read_base = blkbuf + (2 * blocks_at_once * block_size); 77053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 77153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_saved = 0; 77253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 7738abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) flush_bufs(); 77453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (v_flag) { 77553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr); 77653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf (stderr, _("From block %lu to %lu\n"), 77743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) (unsigned long) first_block, 77843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) (unsigned long) last_block - 1); 77943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) } 78053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag || v_flag > 1) { 78143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr); 78253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 78353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (setjmp(terminate_env)) { 78453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* 78553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Abnormal termination by a signal is handled here. 786521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) */ 787521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) signal (SIGALRM, SIG_IGN); 78853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("\nInterrupt caught, cleaning up\n"), stderr); 78953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 79053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) save_ptr = save_base; 79153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (i=0; i < num_saved; i++) { 79253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) do_write(dev, save_ptr, test_record[i].num, 79353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) block_size, test_record[i].block); 79443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) save_ptr += test_record[i].num * block_size; 79553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 79653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fflush (out); 79753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit(1); 79853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 79953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 80053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* set up abend handler */ 80153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) capture_terminate(terminate_env); 80253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 80353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (t_flag) { 804521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) pattern = t_patts; 805521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) nr_pattern = t_flag; 80653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 80753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pattern = patterns; 80853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 80953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 81053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 81153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) pattern_fill(test_base, pattern[pat_idx], 81253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blocks_at_once * block_size); 81353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 81453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) buf_used = 0; 81543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) bb_count = 0; 81653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) save_ptr = save_base; 81753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_ptr = test_base; 81853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) currently_testing = first_block; 81953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_blocks = last_block - 1; 82053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag && v_flag <= 1) 82153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) alarm_intr(SIGALRM); 82253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 82353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while (currently_testing < last_block) { 82453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (max_bb && bb_count >= max_bb) { 82553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag || v_flag) { 82653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("Too many bad blocks, aborting test\n"), stderr); 82743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) } 82843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) break; 82953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 83053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) got = try = granularity - buf_used; 83153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (next_bad) { 83253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (currently_testing == next_bad) { 83353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* fprintf (out, "%lu\n", nextbad); */ 83453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 83543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) currently_testing++; 83643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) goto check_for_more; 83743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) } 83853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else if (currently_testing + try > next_bad) 83943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) try = next_bad - currently_testing; 84053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 84143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) if (currently_testing + try > last_block) 84253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) try = last_block - currently_testing; 84343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) got = do_read (dev, save_ptr, try, block_size, 84453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) currently_testing); 84553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (got == 0) { 84643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) if (recover_block == ~0U) 84743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) recover_block = currently_testing + 84853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blocks_at_once; 84953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (granularity != 1) { 85053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) granularity = 1; 8518abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) continue; 85253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 85353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* First block must have been bad. */ 85453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) bb_count += bb_output(currently_testing++, READ_ERROR); 85553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) goto check_for_more; 85653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 85753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 85853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* 85953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Note the fact that we've saved this much data 86053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * *before* we overwrite it with test data 86153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */ 86253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_record[num_saved].block = currently_testing; 86353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_record[num_saved].num = got; 86453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_saved++; 86553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 86653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* Write the test data */ 86753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) written = do_write (dev, test_ptr, got, block_size, 86853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) currently_testing); 8697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (written != got) 8707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch com_err (program_name, errno, 87153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("during test data write, block %lu"), 87253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (unsigned long) currently_testing + 87353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) written); 87453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 87553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) buf_used += got; 8767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch save_ptr += got * block_size; 87753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_ptr += got * block_size; 87853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) currently_testing += got; 87953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (got != try) { 88053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) try = 1; 88153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (recover_block == ~0U) 88281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) recover_block = currently_testing - 88381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) got + blocks_at_once; 88453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) continue; 88553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 88653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 88781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) check_for_more: 88853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* 88953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * If there's room for more blocks to be tested this 89053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * around, and we're not done yet testing the disk, go 89153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * back and get some more blocks. 89253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */ 89353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if ((buf_used != granularity) && 89453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (currently_testing < last_block)) 89553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) continue; 89653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 89753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (currently_testing >= recover_block) { 89853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) granularity = blocks_at_once; 89993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) recover_block = ~0; 90093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 90193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 90293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) flush_bufs(); 903d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) save_currently_testing = currently_testing; 904d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 905d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) /* 906d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * for each contiguous block that we read into the 907d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * buffer (and wrote test data into afterwards), read 908d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * it back (looping if necessary, to get past newly 909d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * discovered unreadable blocks, of which there should 910d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * be none, but with a hard drive which is unreliable, 911d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * it has happened), and compare with the test data 912d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * that was written; output to the bad block list if 913d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * it doesn't match. 914d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) */ 915d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) used2 = 0; 916d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) save_ptr = save_base; 917d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) test_ptr = test_base; 91893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) read_ptr = read_base; 919d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) try = 0; 920d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 921d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) while (1) { 922d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (try == 0) { 923d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (used2 >= num_saved) 92493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 92593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) currently_testing = test_record[used2].block; 926d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) try = test_record[used2].num; 92753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) used2++; 92853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 92953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 93053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) got = do_read (dev, read_ptr, try, 93153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) block_size, currently_testing); 93253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 93353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* test the comparison between all the 93453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blocks successfully read */ 93553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (i = 0; i < got; ++i) 93653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (memcmp (test_ptr+i*block_size, 93753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) read_ptr+i*block_size, block_size)) 93853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR); 93981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) if (got < try) { 940d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bb_count += bb_output(currently_testing + got, READ_ERROR); 941d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) got++; 942d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 943d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 944d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) /* write back original data */ 945d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) do_write (dev, save_ptr, got, 946d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) block_size, currently_testing); 947d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) save_ptr += got * block_size; 948d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 949d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) currently_testing += got; 950d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) test_ptr += got * block_size; 951d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) read_ptr += got * block_size; 952d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) try -= got; 95381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) } 95481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) 95553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* empty the buffer so it can be reused */ 95653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_saved = 0; 95793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) buf_used = 0; 95853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) save_ptr = save_base; 95953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_ptr = test_base; 96053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) currently_testing = save_currently_testing; 96153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 96293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) num_blocks = 0; 96353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) alarm(0); 96453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (s_flag || v_flag > 1) 96593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fputs(_(done_string), stderr); 96653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 96753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) flush_bufs(); 96853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 96953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) uncapture_terminate(); 97093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fflush(stderr); 97153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) free(blkbuf); 97253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) free(test_record); 97393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 97453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ext2fs_badblocks_list_iterate_end(bb_iter); 97553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 97653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return bb_count; 97753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 97893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 97993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void check_mount(char *device_name) 98093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 98153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode_t retval; 98253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int mount_flags; 98353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 98453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) retval = ext2fs_check_if_mounted(device_name, &mount_flags); 98553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (retval) { 98653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err("ext2fs_check_if_mount", retval, 98753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("while determining whether %s is mounted."), 98853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) device_name); 98953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return; 99053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 99153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (mount_flags & EXT2_MF_MOUNTED) { 99253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(stderr, _("%s is mounted; "), device_name); 99353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (force) { 99453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("badblocks forced anyway. " 99553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) "Hope /etc/mtab is incorrect.\n"), stderr); 99653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return; 99753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 99853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) abort_badblocks: 99953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("it's not safe to run badblocks!\n"), stderr); 100093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) exit(1); 100193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 100293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 100353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) { 100453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(stderr, _("%s is apparently in use by the system; "), 100553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) device_name); 100653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (force) 100753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fputs(_("badblocks forced anyway.\n"), stderr); 100853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else 100953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) goto abort_badblocks; 101053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 101153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 101253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 10135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 101453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* 101553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This function will convert a string to an unsigned long, printing 101653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * an error message if it fails, and returning success or failure in err. 101753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */ 10185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static unsigned int parse_uint(const char *str, const char *descr) 101953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 102053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) char *tmp; 10215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) unsigned long ret; 102253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 102353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errno = 0; 102453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ret = strtoul(str, &tmp, 0); 10255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (*tmp || errno || (ret > UINT_MAX) || 102653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) (ret == ULONG_MAX && errno == ERANGE)) { 102753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, 0, _("invalid %s - %s"), descr, str); 102843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) exit (1); 102953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 103053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return ret; 103153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 103243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) 103353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)int main (int argc, char ** argv) 103453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 103543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) int c; 103653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) char * device_name; 103743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) char * host_device_name = NULL; 103853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) char * input_file = NULL; 103953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) char * output_file = NULL; 10405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) FILE * in = NULL; 104153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int block_size = 1024; 104253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int blocks_at_once = 64; 104353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blk64_t last_block, first_block; 10445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) int num_passes = 0; 104553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int passes_clean = 0; 104653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int dev; 104743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) errcode_t errcode; 104843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) unsigned int pattern; 104943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) unsigned int (*test_func)(int, blk_t, 105053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int, blk_t, 10515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) unsigned int); 105253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int open_flag; 105353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) long sysval; 105443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) blk64_t inblk; 105553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 105653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) setbuf(stdout, NULL); 105753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) setbuf(stderr, NULL); 105843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)#ifdef ENABLE_NLS 105953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) setlocale(LC_MESSAGES, ""); 106053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) setlocale(LC_CTYPE, ""); 10615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 106243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) textdomain(NLS_CAT_NAME); 106353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) set_com_err_gettext(gettext); 106453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif 106553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) srandom((unsigned int)time(NULL)); /* simple randomness is enough */ 106653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_func = test_ro; 106753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 106853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) /* Determine the system page size if possible */ 10695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef HAVE_SYSCONF 107053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) 107153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define _SC_PAGESIZE _SC_PAGE_SIZE 107253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif 107343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)#ifdef _SC_PAGESIZE 107453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) sysval = sysconf(_SC_PAGESIZE); 107553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (sysval > 0) 1076a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) sys_page_size = sysval; 107753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif /* _SC_PAGESIZE */ 107853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif /* HAVE_SYSCONF */ 107953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1080a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (argc && *argv) 108153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) program_name = *argv; 108253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while ((c = getopt (argc, argv, "b:d:e:fi:o:svwnc:p:h:t:BX")) != EOF) { 108343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) switch (c) { 108453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'b': 108553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) block_size = parse_uint(optarg, "block size"); 108653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 108743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) case 'f': 108853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) force++; 108953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 1090a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) case 'i': 109153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) input_file = optarg; 10925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) break; 109353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'o': 109453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) output_file = optarg; 109543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) break; 109653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 's': 109743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) s_flag = 1; 109853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 109953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'v': 11005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) v_flag++; 110153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 110253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'w': 110353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (w_flag) 1104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) exclusive_usage(); 110553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) test_func = test_rw; 110653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) w_flag = 1; 110743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) break; 110853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'n': 110953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (w_flag) 111053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exclusive_usage(); 111143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) test_func = test_nd; 111253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) w_flag = 2; 111353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 1114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) case 'c': 111553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) blocks_at_once = parse_uint(optarg, "blocks at once"); 1116e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) break; 1117e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) case 'e': 1118e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) max_bb = parse_uint(optarg, "max bad block count"); 1119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) break; 112053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'd': 112153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) d_flag = parse_uint(optarg, "read delay factor"); 1122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) break; 112353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'p': 112453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) num_passes = parse_uint(optarg, 112553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) "number of clean passes"); 1126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) break; 1127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) case 'h': 1128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_device_name = optarg; 1129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) break; 1130d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) case 't': 1131d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (t_flag + 1 > t_max) { 1132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) unsigned int *t_patts_new; 1133d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1134d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) t_patts_new = realloc(t_patts, sizeof(int) * 1135d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) (t_max + T_INC)); 1136d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!t_patts_new) { 113707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch com_err(program_name, ENOMEM, 113807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch _("can't allocate memory for " 113907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch "test_pattern - %s"), 1140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) optarg); 1141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) exit(1); 1142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 1143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) t_patts = t_patts_new; 114453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) t_max += T_INC; 114553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 114653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) { 1147e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) t_patts[t_flag++] = ~0; 114853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 1149e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) pattern = parse_uint(optarg, "test pattern"); 1150e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (pattern == (unsigned int) ~0) 1151e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) pattern = 0xffff; 115281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) t_patts[t_flag++] = pattern; 115353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 115453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 115553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'B': 115653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) use_buffered_io = 1; 115753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 115853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) case 'X': 115953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exclusive_ok++; 11605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) break; 116153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) default: 116253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) usage(); 1163e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 1164e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 1165e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (!w_flag) { 1166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (t_flag > 1) { 1167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) com_err(program_name, 0, "%s", 11689bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles) _("Maximum of one test_pattern may be " 11699bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles) "specified in read-only mode")); 117053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit(1); 117153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 117253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (t_patts && (t_patts[0] == (unsigned int) ~0)) { 117353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err(program_name, 0, "%s", 117453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("Random test_pattern is not allowed " 117553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) "in read-only mode")); 117653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit(1); 1177e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 1178e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 1179e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (optind > argc - 1) 118081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) usage(); 118153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) device_name = argv[optind++]; 118253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (optind > argc - 1) { 118353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode = ext2fs_get_device_size2(device_name, 118453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) block_size, 118553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) &last_block); 118653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (errcode == EXT2_ET_UNIMPLEMENTED) { 118753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err(program_name, 0, "%s", 1188e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) _("Couldn't determine device size; you " 1189e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) "must specify\nthe size manually\n")); 1190e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) exit(1); 119181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) } 119253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (errcode) { 119353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err(program_name, errcode, "%s", 119453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("while trying to determine device size")); 119553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit(1); 119653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 119753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else { 119853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errno = 0; 1199e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) last_block = parse_uint(argv[optind], _("last block")); 1200e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) last_block++; 1201e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) optind++; 120281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) } 120353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (optind <= argc-1) { 120453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errno = 0; 120553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) first_block = parse_uint(argv[optind], _("first block")); 120653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else first_block = 0; 120753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (first_block >= last_block) { 120853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, 0, _("invalid starting block (%llu): must be less than %llu"), 120953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) first_block, last_block); 121007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch exit (1); 121107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 121207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch /* ext2 badblocks file can't handle large values */ 121353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (last_block >> 32) { 121453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err(program_name, EOVERFLOW, 121553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("invalid end block (%llu): must be 32-bit value"), 121653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) last_block); 121753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit(1); 121893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 121953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (w_flag) 1220e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) check_mount(device_name); 1221e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 1222e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) gettimeofday(&time_start, 0); 122381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) open_flag = O_LARGEFILE | (w_flag ? O_RDWR : O_RDONLY); 122493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) dev = open (device_name, open_flag); 122553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (dev == -1) { 122653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, errno, _("while trying to open %s"), 122753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) device_name); 122853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 122953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 123053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (host_device_name) { 123153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) host_dev = open (host_device_name, open_flag); 123253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (host_dev == -1) { 123353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, errno, 123453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("while trying to open %s"), 123553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) host_device_name); 123653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 123753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 123853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else 123953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) host_dev = dev; 1240d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (input_file) { 1241d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (strcmp (input_file, "-") == 0) 124253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) in = stdin; 124353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else { 1244d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) in = fopen (input_file, "r"); 124553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (in == NULL) 124653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 124753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) com_err (program_name, errno, 124853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("while trying to open %s"), 124953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) input_file); 125053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 125153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 125253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 125353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 125453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (output_file && strcmp (output_file, "-") != 0) 125553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 1256d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) out = fopen (output_file, "w"); 125753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (out == NULL) 125853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 12595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) com_err (program_name, errno, 126053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("while trying to open %s"), 126153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) output_file); 126253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) exit (1); 126353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 126453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 1265d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) else 126653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) out = stdout; 126753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 126853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) errcode = ext2fs_badblocks_list_create(&bb_list,0); 126953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (errcode) { 1270d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) com_err(program_name, errcode, "%s", 1271d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) _("while creating in-memory bad blocks list")); 1272d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) exit (1); 1273d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 1274d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1275d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (in) { 1276d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for(;;) { 1277d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) switch (fscanf(in, "%llu\n", &inblk)) { 1278d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) case 0: 1279d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) com_err(program_name, 0, "%s", 1280d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) _("input file - bad format")); 1281d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) exit (1); 1282d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) case EOF: 1283d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) break; 1284d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) default: 1285d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (inblk >> 32) { 1286d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) com_err(program_name, 1287d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EOVERFLOW, "%s", 1288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) _("while adding to in-memory " 1289d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) "bad block list")); 1290d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) exit(1); 1291d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 1292d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) next_bad = inblk; 1293d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 1294d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (errcode) { 1295d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) com_err(program_name, errcode, 1296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) "%s", 1297d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) _("while adding to in-memory " 1298d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) "bad block list")); 1299d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) exit (1); 1300e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 13015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) continue; 130253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 130353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) break; 130453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 130553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 130653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (in != stdin) 130753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fclose (in); 130853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 130953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 131053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) do { 131153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) unsigned int bb_count; 131253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 13135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) bb_count = test_func(dev, last_block, block_size, 131453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) first_block, blocks_at_once); 131553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (bb_count) 131653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) passes_clean = 0; 131753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else 131853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ++passes_clean; 131953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 132053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (v_flag) 132153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(stderr, 132253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) _("Pass completed, %u bad blocks found. (%d/%d/%d errors)\n"), 1323d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bb_count, num_read_errors, num_write_errors, num_corruption_errors); 132453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 132553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } while (passes_clean < num_passes); 132681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) 132753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) close (dev); 132853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (out != stdout) 132953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fclose (out); 133053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) free(t_patts); 133153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return 0; 133253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 133353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)