badblocks.c revision f63978aff759325b542de7134ab659c79dc47496
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c - Bad blocks checker 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Laboratoire MASI, Institut Blaise Pascal 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Universite Pierre et Marie Curie (Paris VI) 73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 8dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o 9879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Copyright 1999 by David Beattie 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file is based on the minix file system programs fsck and mkfs 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi> 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 1519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * History: 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/05/26 - Creation from e2fsck 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27 - Made a separate bad blocks checker 24879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * 99/06/30...99/07/26 - Added non-destructive write-testing, 25dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * configurable blocks-at-once parameter, 26dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * loading of badblocks list to avoid testing 27dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * blocks known to be bad, multiple passes to 28dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * make sure that no new blocks are added to the 29dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * list. (Work done by David Beattie) 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 321c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#define _GNU_SOURCE /* for O_DIRECT */ 331c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h> 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 36a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h> 38373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o#else 39373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern char *optarg; 40373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern int optind; 41a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h> 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 47879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <setjmp.h> 486d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o#include <time.h> 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 51f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 54d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 5554c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h" 56879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 57d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h" 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 60f63978aff759325b542de7134ab659c79dc47496Theodore Ts'oconst char * done_string = N_("done \n"); 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int v_flag = 0; /* verbose */ 634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int w_flag = 0; /* do r/w test: 0=no, 1=yes, 644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * 2=non-destructive */ 654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int s_flag = 0; /* show progress of test */ 66981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic int force = 0; /* force check of mounted device */ 67849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'ostatic int t_flag = 0; /* number of test patterns */ 68849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'ostatic int t_max = 0; /* allocated test patterns */ 6984c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'ostatic unsigned long *t_patts = NULL; /* test patterns */ 701c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'ostatic int current_O_DIRECT = 0; /* Current status of O_DIRECT flag */ 71f63978aff759325b542de7134ab659c79dc47496Theodore Ts'ostatic int exclusive_ok = 0; 721c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 73849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o#define T_INC 32 744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 751c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'oint sys_page_size = 4096; 761c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 778820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void usage(void) 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 79849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n device [last_block [start_block]]\n"), 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long currently_testing = 0; 8519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long num_blocks = 0; 86879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 87879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 88879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 89879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 9019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 911c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'ostatic void *allocate_buffer(size_t size) 921c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o{ 931c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o void *ret = 0; 941c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 951c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_POSIX_MEMALIGN 961c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (posix_memalign(&ret, sys_page_size, size) < 0) 971c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = 0; 981c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#else 991c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_MEMALIGN 1001c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = memalign(sys_page_size, size); 1011c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#else 1021c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_VALLOC 1031c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = valloc(size); 1041c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_VALLOC */ 1051c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_MEMALIGN */ 1061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_POSIX_MEMALIGN */ 1071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (!ret) 1091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = malloc(size); 1101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o return ret; 1121c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o} 1131c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 114dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o/* 115dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * This routine reports a new bad block. If the bad block has already 116dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * been seen before, then it returns 0; otherwise it returns 1. 117dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o */ 118dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic int bb_output (unsigned long bad) 119879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 120879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 121879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 122dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if (ext2fs_badblocks_list_test(bb_list, bad)) 123dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 0; 124dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o 125cc4f98ed2deeaca33244fd77386e7d76917a3d30Theodore Ts'o fprintf(out, "%lu\n", bad); 126cc4f98ed2deeaca33244fd77386e7d76917a3d30Theodore Ts'o fflush(out); 127879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 128879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 129879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 130879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 131879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 132879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 134879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 135879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o increment the iteration through the bb_list if 136879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 137879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 138879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 139879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 140dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 1; 141879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 142879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1438820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void print_status(void) 14419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 145c76564a8784c3c44a6a0516e0fc40f10ec6221edTheodore Ts'o fprintf(stderr, "%15ld/%15ld", currently_testing, num_blocks); 146c76564a8784c3c44a6a0516e0fc40f10ec6221edTheodore Ts'o fputs("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", stderr); 14719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 14819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 14919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 150544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void alarm_intr(int alnum EXT2FS_ATTR((unused))) 15119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 15219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 15319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 15419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 15519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 156c76564a8784c3c44a6a0516e0fc40f10ec6221edTheodore Ts'o print_status(); 15719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 15819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 159879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 160879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 161544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void terminate_intr(int signo EXT2FS_ATTR((unused))) 162879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 163879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 164879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 165879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 166879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 167879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 168981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void capture_terminate(jmp_buf term_addr) 169879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 170879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 171879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 172879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 173879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 174879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 175879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 176879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 177879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 178879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1798820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void uncapture_terminate(void) 1804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o{ 1814d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o terminate_addr = NULL; 1824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGHUP, SIG_DFL); 1834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGINT, SIG_DFL); 1844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGPIPE, SIG_DFL); 1854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGTERM, SIG_DFL); 1864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR1, SIG_DFL); 1874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR2, SIG_DFL); 1884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o} 1894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 1901f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'ostatic void set_o_direct(int dev, unsigned char *buffer, size_t size, 1911f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o unsigned long current_block) 1921c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o{ 1931c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef O_DIRECT 1941c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int new_flag = O_DIRECT; 1951c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int flag; 1961c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1971c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if ((((unsigned long) buffer & (sys_page_size - 1)) != 0) || 1981f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o ((size & (sys_page_size - 1)) != 0) || 1991f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o ((current_block & ((sys_page_size >> 9)-1)) != 0)) 2001c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o new_flag = 0; 2011c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 2021c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (new_flag != current_O_DIRECT) { 203dc058719dfca9b35baec3208932702d39a502d3aTheodore Ts'o /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */ 2041c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o flag = fcntl(dev, F_GETFL); 2051c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (flag > 0) { 2061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o flag = (flag & ~O_DIRECT) | new_flag; 2071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o fcntl(dev, F_SETFL, flag); 2081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 2091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o current_O_DIRECT = new_flag; 2101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 2111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif 2121c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o} 2131c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 2141c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 21584c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'ostatic void pattern_fill(unsigned char *buffer, unsigned long pattern, 21684c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o size_t n) 217849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o{ 218544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int i, nb; 21984c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o unsigned char bpattern[sizeof(pattern)], *ptr; 220849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 221023cbb302963a93d0247e95a02591cb304bf152cTheodore Ts'o if (pattern == (unsigned long) ~0) { 222849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (ptr = buffer; ptr < buffer + n; ptr++) { 223849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o (*ptr) = random() % (1 << (8 * sizeof(char))); 224849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 225849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag | v_flag) 226544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Testing with random pattern: "), stderr); 227849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 228849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bpattern[0] = 0; 229849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < sizeof(bpattern); i++) { 230849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (pattern == 0) 231849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 232849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bpattern[i] = pattern & 0xFF; 233849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = pattern >> 8; 234849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 235849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nb = i ? (i-1) : 0; 236849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) { 237544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o *ptr = bpattern[i]; 238544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if (i == 0) 239849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o i = nb; 240544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o else 241544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o i--; 242849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 24384c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (s_flag | v_flag) { 244544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Testing with pattern 0x"), stderr); 24584c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o for (i = 0; i <= nb; i++) 24684c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o fprintf(stderr, "%02x", buffer[i]); 247544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(": ", stderr); 24884c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } 249849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 250849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o} 251849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 253879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 254879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 25648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'ostatic long do_read (int dev, unsigned char * buffer, int try, int block_size, 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long current_block) 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2611f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o set_o_direct(dev, buffer, try * block_size, current_block); 2621c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 26319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 26419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 26519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 26719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 268f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 269d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 2743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 2759f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 276d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 277879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 278879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 279879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 280879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 281879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 282879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 283879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 284879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 28548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'ostatic long do_write (int dev, unsigned char * buffer, int try, int block_size, 286879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long current_block) 287879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 288879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 289879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 2901f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o set_o_direct(dev, buffer, try * block_size, current_block); 2911c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 292879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 293879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 294879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 295879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 296879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 297879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 298d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 299879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 300879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 301879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 302879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 303879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = 0; 304879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 305544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fprintf(stderr, "Weird value (%ld) in do_write\n", got); 3063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 3083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 310879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 311879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 3124d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'ostatic void flush_bufs(void) 313a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 3144d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o errcode_t retval; 315a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 3164d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o retval = ext2fs_sync_device(host_dev, 1); 3174d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o if (retval) 3184d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o com_err(program_name, retval, _("during ext2fs_sync_device")); 319a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 320a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 321cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'ostatic unsigned int test_ro (int dev, unsigned long last_block, 322dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 323dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 32548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned char * blkbuf; 3263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 3273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 328879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 329879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 331879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 332879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 333d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 334d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 335879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 336879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 337879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 338879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 339879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 340879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 341849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 3421c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer((blocks_at_once + 1) * block_size); 343849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 3441c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer(blocks_at_once * block_size); 345849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 348d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 351f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 352849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o fprintf (stderr, _("Checking blocks %lu to %lu\n"), from_count, 353cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o last_block); 354f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 355849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 356544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in read-only mode\n"), stderr); 357849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern_fill(blkbuf + blocks_at_once * block_size, 358849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts[0], block_size); 359849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 360849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 361879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 362f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 363cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 364849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!t_flag && (s_flag || v_flag)) { 365544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks (read-only test): "), stderr); 36619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 36719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 3683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 369cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o while (currently_testing < last_block) 3703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 371879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 372879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 373879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 374879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 375879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 376879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 377879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 378879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 379879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 380879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 381cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (currently_testing + try > last_block) 382cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o try = last_block - currently_testing; 383879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 384849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 385849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* test the comparison between all the 386849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blocks successfully read */ 387849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o int i; 388849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < got; ++i) 389849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (memcmp (blkbuf+i*block_size, 390849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blkbuf+blocks_at_once*block_size, 391849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o block_size)) 392849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing + i); 393849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 3943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 396879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 3971f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o /* recover page-aligned offset for O_DIRECT */ 398544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9) 3991f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o && (currently_testing % (sys_page_size >> 9)!= 0)) 4001f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try -= (sys_page_size >> 9) 4011f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o - (currently_testing 4021f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o % (sys_page_size >> 9)); 4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 407879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got == 0) { 408dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o bb_count += bb_output(currently_testing++); 409879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 4123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 413849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag || v_flag) 4143ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 415879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 416f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 4173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 418879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 419879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 420879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 421879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 4223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 424cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'ostatic unsigned int test_rw (int dev, unsigned long last_block, 425dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 426dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 4273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o unsigned char *buffer, *read_buffer; 42984c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o const unsigned long patterns[] = {0xaa, 0x55, 0xff, 0x00}; 43084c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o const unsigned long *pattern; 4311c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int i, try, got, nr_pattern, pat_idx; 432879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 4333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4341c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o buffer = allocate_buffer(2 * blocks_at_once * block_size); 4351c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_buffer = buffer + blocks_at_once * block_size; 4361c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 4371c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (!buffer) { 438d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 4393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 4403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4424d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 443a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 44419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 445544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in read-write mode\n"), 446544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o stderr); 447d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("From block %lu to %lu\n"), 448cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o from_count, last_block); 44919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 450849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 451849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = t_patts; 452849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = t_flag; 453849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 454849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = patterns; 455849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 456849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 457849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 4581c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o pattern_fill(buffer, pattern[pat_idx], 4591c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blocks_at_once * block_size); 460cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 461f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 46219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 463f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 4641c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 4651c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 4661c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o while (currently_testing < last_block) { 4671c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (currently_testing + try > last_block) 4681c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = last_block - currently_testing; 4691c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = do_write(dev, buffer, try, block_size, 4701c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing); 47119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 47219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 4731c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 4741c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing += got; 4751c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (got == try) { 4761c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 4771f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o /* recover page-aligned offset for O_DIRECT */ 478544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9) 4791f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o && (currently_testing % 4801f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o (sys_page_size >> 9)!= 0)) 4811f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try -= (sys_page_size >> 9) 4821f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o - (currently_testing 4831f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o % (sys_page_size >> 9)); 4841c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o continue; 4851c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } else 4861c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = 1; 4871c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (got == 0) { 4881c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o bb_count += bb_output(currently_testing++); 4891c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 4903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4911c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 492f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 493f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 494f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 4953ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 4964d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 497f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 498544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Reading and comparing: "), stderr); 499cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 500f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 50119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 502f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 5031c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 5041c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 5051c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o while (currently_testing < last_block) { 5061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (currently_testing + try > last_block) 5071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = last_block - currently_testing; 5081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = do_read (dev, read_buffer, try, block_size, 5091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing); 5101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (got == 0) { 5111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o bb_count += bb_output(currently_testing++); 5121c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o continue; 5131c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 5141c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o for (i=0; i < got; i++) { 5151c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (memcmp(read_buffer + i * block_size, 5161c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o buffer + i * block_size, 5171c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o block_size)) 5181c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o bb_count += bb_output(currently_testing+i); 5191c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 5201c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing += got; 5211f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o /* recover page-aligned offset for O_DIRECT */ 522544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9) 5231f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o && (currently_testing % (sys_page_size >> 9)!= 0)) 5241f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try = blocks_at_once - (sys_page_size >> 9) 5251f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o - (currently_testing 5261f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o % (sys_page_size >> 9)); 5271f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o else 5281f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try = blocks_at_once; 52919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 53019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 5313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5321c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 533f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 534f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 535f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 5363ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 5374d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 5383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 539849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o uncapture_terminate(); 5406d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o free(buffer); 541879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 542879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 543879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 544d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostruct saved_blk_record { 545d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o blk_t block; 546d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num; 547d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o}; 548d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 549cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'ostatic unsigned int test_nd (int dev, unsigned long last_block, 550dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 551dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 552879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 55348e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 5541c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o unsigned char *test_base, *save_base, *read_base; 555dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int try, i; 55684c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o const unsigned long patterns[] = { ~0 }; 55784c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o const unsigned long *pattern; 558849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o int nr_pattern, pat_idx; 559a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o long got, used2, written, save_currently_testing; 560d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o struct saved_blk_record *test_record; 561a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o /* This is static to prevent being clobbered by the longjmp */ 562a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o static int num_saved; 563879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 564879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 565544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned long buf_used; 566544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o static unsigned int bb_count; 567879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 568544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o bb_count = 0; 569879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 570879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 571dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o com_err (program_name, errcode, 572d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 573879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 574879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 575879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 576879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 577879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 578879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 5791c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer(3 * blocks_at_once * block_size); 580d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record)); 581d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (!blkbuf || !test_record) { 582d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err(program_name, ENOMEM, _("while allocating buffers")); 583879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 584879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 5851c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 5861c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_base = blkbuf; 5871c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_base = blkbuf + (blocks_at_once * block_size); 5881c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_base = blkbuf + (2 * blocks_at_once * block_size); 5891c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 590d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 591879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 5924d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 593879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 594544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr); 595cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, last_block); 596879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 597879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 598544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr); 599879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 6004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (setjmp(terminate_env)) { 6014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 6024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * Abnormal termination by a signal is handled here. 6034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 604a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o signal (SIGALRM, SIG_IGN); 605544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("\nInterrupt caught, cleaning up\n"), stderr); 606879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 6071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 608d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o for (i=0; i < num_saved; i++) { 609d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o do_write(dev, save_ptr, test_record[i].num, 610d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o block_size, test_record[i].block); 611d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr += test_record[i].num * block_size; 612d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 613879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 614dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o exit(1); 615879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 6164d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 6174d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* set up abend handler */ 6184d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o capture_terminate(terminate_env); 6194d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 620849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 621849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = t_patts; 622849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = t_flag; 623849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 624849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = patterns; 625849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 626849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 627849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 6281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o pattern_fill(test_base, pattern[pat_idx], 6291c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blocks_at_once * block_size); 6304d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 631849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used = 0; 632849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count = 0; 6331c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 6341c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 635849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = from_count; 636849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_blocks = last_block; 637849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag && v_flag <= 1) 638849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o alarm_intr(SIGALRM); 6394d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 640849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o while (currently_testing < last_block) { 6411c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = try = blocks_at_once - buf_used; 642849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (next_bad) { 643849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (currently_testing == next_bad) { 644849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 645849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 646849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing++; 647849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o goto check_for_more; 648849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 649849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o else if (currently_testing + try > next_bad) 650849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = next_bad - currently_testing; 651d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 652849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (currently_testing + try > last_block) 653849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = last_block - currently_testing; 654849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got = do_read (dev, save_ptr, try, block_size, 655849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing); 656849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got == 0) { 657849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* First block must have been bad. */ 658849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing++); 659849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o goto check_for_more; 6604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 6614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 662849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 663849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * Note the fact that we've saved this much data 664849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * *before* we overwrite it with test data 665849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 666849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_record[num_saved].block = currently_testing; 667849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_record[num_saved].num = got; 668849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_saved++; 669849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 670849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* Write the test data */ 671849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o written = do_write (dev, test_ptr, got, block_size, 672849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing); 673849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (written != got) 674849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err (program_name, errno, 675849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("during test data write, block %lu"), 676849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing + written); 677849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 678849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used += got; 6794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 6804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 681849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing += got; 682849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got != try) 683849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing++); 684849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 685849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o check_for_more: 686849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 687849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * If there's room for more blocks to be tested this 688849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * around, and we're not done yet testing the disk, go 689849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * back and get some more blocks. 690849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 691849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if ((buf_used != blocks_at_once) && 692849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o (currently_testing < last_block)) 693849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o continue; 694849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 695849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 696849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o save_currently_testing = currently_testing; 697849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 698849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 699849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * for each contiguous block that we read into the 700849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * buffer (and wrote test data into afterwards), read 701849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it back (looping if necessary, to get past newly 702849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * discovered unreadable blocks, of which there should 703849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * be none, but with a hard drive which is unreliable, 704849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it has happened), and compare with the test data 705849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * that was written; output to the bad block list if 706849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it doesn't match. 707849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 708849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o used2 = 0; 7091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 7101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 7111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_ptr = read_base; 712849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = 0; 713849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 714849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o while (1) { 715849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (try == 0) { 716849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (used2 >= num_saved) 717849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 718849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = test_record[used2].block; 719849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = test_record[used2].num; 720849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o used2++; 721849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 722849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 723849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got = do_read (dev, read_ptr, try, 724849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o block_size, currently_testing); 725849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 726849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* test the comparison between all the 727849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blocks successfully read */ 728849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < got; ++i) 729849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (memcmp (test_ptr+i*block_size, 730849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o read_ptr+i*block_size, block_size)) 731849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing + i); 732849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got < try) { 733849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing + got); 734849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got++; 735849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 736849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 7371c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o /* write back original data */ 7381c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o do_write (dev, save_ptr, got, 7391c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o block_size, currently_testing); 7401c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr += got * block_size; 741849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 742849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing += got; 743849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_ptr += got * block_size; 744849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o read_ptr += got * block_size; 745849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try -= got; 746849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 747849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 748849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* empty the buffer so it can be reused */ 749849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_saved = 0; 750849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used = 0; 7511c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 7521c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 753849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = save_currently_testing; 7544d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 755849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_blocks = 0; 756849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o alarm(0); 757849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag || v_flag > 1) 7583ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 7594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 760849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 7614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 7624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o uncapture_terminate(); 763dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o fflush(stderr); 764dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o free(blkbuf); 765d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o free(test_record); 766879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 767879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 768879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 769879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 7703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 7713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 772981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void check_mount(char *device_name) 773981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o{ 774981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o errcode_t retval; 775981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o int mount_flags; 776981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 777981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o retval = ext2fs_check_if_mounted(device_name, &mount_flags); 778981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (retval) { 779981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o com_err("ext2fs_check_if_mount", retval, 780981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o _("while determining whether %s is mounted."), 781981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o device_name); 782981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 783981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 7842fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (mount_flags & EXT2_MF_MOUNTED) { 7852fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fprintf(stderr, _("%s is mounted; "), device_name); 7862fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (force) { 7872fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("badblocks forced anyway. " 7882fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o "Hope /etc/mtab is incorrect.\n"), stderr); 7892fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o return; 7902fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o } 7912fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o abort_badblocks: 7922fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("it's not safe to run badblocks!\n"), stderr); 7932fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o exit(1); 7942fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o } 795981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 796f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) { 7972fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fprintf(stderr, _("%s is apparently in use by the system; "), 7982fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o device_name); 7992fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (force) 8002fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("badblocks forced anyway.\n"), stderr); 8012fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o else 8022fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o goto abort_badblocks; 803981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 8042fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o 805981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o} 806981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 807981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 80800e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 8093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 810519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 8113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * tmp; 8123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 813879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 814879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 8153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 816879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 817dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size = 1024; 818167af997e3a8fb36cb9fc8db9c40fb62a7f9464bTheodore Ts'o unsigned long blocks_at_once = 64; 819cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o blk_t last_block, from_count; 820879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 821879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 8223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 823879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 82484c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o unsigned long pattern; 8258820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o unsigned int (*test_func)(int, unsigned long, 8268820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o int, unsigned long, 8278820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o unsigned long); 8281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int open_flag = 0; 8291c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o long sysval; 8303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 8323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 833d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS 834d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o setlocale(LC_MESSAGES, ""); 83514308a5398984842e808faa3ff2dd6a1c52d90bdTheodore Ts'o setlocale(LC_CTYPE, ""); 836d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 837d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o textdomain(NLS_CAT_NAME); 838d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif 8396d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o srandom((unsigned int)time(NULL)); /* simple randomness is enough */ 8404d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_ro; 8414d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o 8421c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o /* Determine the system page size if possible */ 8431c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_SYSCONF 8441c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) 8451c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#define _SC_PAGESIZE _SC_PAGE_SIZE 8461c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif 8471c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef _SC_PAGESIZE 8481c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o sysval = sysconf(_SC_PAGESIZE); 8491c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (sysval > 0) 8501c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o sys_page_size = sysval; 8511c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* _SC_PAGESIZE */ 8521c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_SYSCONF */ 8531c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 8543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 8553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 856f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:t:X")) != EOF) { 8573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 8583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 8593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o block_size = strtoul (optarg, &tmp, 0); 8603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp || block_size > 4096) { 8613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 862d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("bad block size - %s"), optarg); 8633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 8643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 866981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o case 'f': 867981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o force++; 868981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o break; 869879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 870879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 871879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 8723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 8733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 8743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 8753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 8763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 8773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 8783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 87919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 8803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 8813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 8824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 8834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 8844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_rw; 8854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o w_flag = 1; 886879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 887879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 8884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 8894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 8904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_nd; 891879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 892879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 893879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 894879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blocks_at_once = strtoul (optarg, &tmp, 0); 895879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 896879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 897879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad simultaneous block count - %s", optarg); 898879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 899879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 900879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 901879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 902879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_passes = strtoul (optarg, &tmp, 0); 903879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 904879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 905879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad number of clean passes - %s", optarg); 906879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 907879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 908879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 909879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 910879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 9113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 912849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o case 't': 913849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag + 1 > t_max) { 91448e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned long *t_patts_new; 915849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 916849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts_new = realloc(t_patts, t_max + T_INC); 917849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!t_patts_new) { 918849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, ENOMEM, 919849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("can't allocate memory for " 920849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "test_pattern - %s"), 921849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o optarg); 922849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 923849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 924849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts = t_patts_new; 925849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_max += T_INC; 926849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 92784c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) { 92884c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o t_patts[t_flag++] = ~0; 92984c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } else { 93084c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o pattern = strtoul(optarg, &tmp, 0); 93184c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (*tmp) { 93284c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o com_err(program_name, 0, 933849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("invalid test_pattern: %s\n"), 93484c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o optarg); 93584c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o exit(1); 93684c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } 937544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if (pattern == (unsigned long) ~0) 93884c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o pattern = 0xffff; 93984c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o t_patts[t_flag++] = pattern; 940849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 941849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 942f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o case 'X': 943f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o exclusive_ok++; 944f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o break; 9453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 946818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 9473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 9483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 949849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!w_flag) { 950849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag > 1) { 951849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, 0, 952849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("Maximum of one test_pattern may be specified " 953849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "in read-only mode")); 954849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 955849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 956544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if (t_patts && (t_patts[0] == (unsigned long) ~0)) { 957849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, 0, 958849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("Random test_pattern is not allowed " 959849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "in read-only mode")); 960849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 961849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 962849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 9633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 964818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 9653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 96635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind > argc - 1) { 96735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o errcode = ext2fs_get_device_size(device_name, 96835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o block_size, 969cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o &last_block); 97035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode == EXT2_ET_UNIMPLEMENTED) { 97135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, 0, 97235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("Couldn't determine device size; you " 97335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o "must specify\nthe size manually\n")); 97435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 97535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 97635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode) { 97735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, errcode, 97835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("while trying to determine device size")); 97935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 98035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 98135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } else { 982cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o last_block = strtoul (argv[optind], &tmp, 0); 98335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (*tmp) { 984f37ab68a26bacf4f5cc7643b8373e40292b7682aTheodore Ts'o com_err (program_name, 0, _("invalid blocks count - %s"), 98535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o argv[optind]); 98635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit (1); 98735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 98835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o optind++; 9893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 99035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind <= argc-1) { 991f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count = strtoul (argv[optind], &tmp, 0); 992a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o if (*tmp) { 993f37ab68a26bacf4f5cc7643b8373e40292b7682aTheodore Ts'o com_err (program_name, 0, _("invalid starting block - %s"), 994a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o argv[optind]); 995a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o exit (1); 996a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o } 997f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else from_count = 0; 998cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (from_count >= last_block) { 999f37ab68a26bacf4f5cc7643b8373e40292b7682aTheodore Ts'o com_err (program_name, 0, _("invalid blocks range: %lu-%lu"), 1000544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o (unsigned long) from_count, (unsigned long) last_block); 1001f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 1002f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1003981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (w_flag) 1004981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o check_mount(device_name); 1005981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 10061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o open_flag = w_flag ? O_RDWR : O_RDONLY; 10071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o dev = open (device_name, open_flag); 10085493a27dc1138d2e30193b80217a0127d247af1eTheodore Ts'o if (dev == -1) { 1009d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("while trying to open %s"), 10103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 10113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 10123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1013879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 10141c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o host_dev = open (host_device_name, open_flag); 10155493a27dc1138d2e30193b80217a0127d247af1eTheodore Ts'o if (host_dev == -1) { 1016d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1017d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1018d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o host_device_name); 1019879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1020879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1021879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 1022879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 10233e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o if (input_file) { 1024879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 1025879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 1026879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 1027879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 1028879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 1029879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 1030d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1031d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1032879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 1033879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1034879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1035879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 10363e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o } 10373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 10383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 10393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 10403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 10413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 1042d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1043d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1044879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 10453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 10463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 10493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 1050879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1051879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 1052879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 1053d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 1054bb145b01cf5fd27d9afe03c3262d0e1a326e7ec1Theodore Ts'o _("while creating in-memory bad blocks list")); 1055879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1056879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1057879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1058879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 1059879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 1060a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o switch(fscanf (in, "%u\n", &next_bad)) { 1061879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 1062879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, "input file - bad format"); 1063879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1064879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 1065879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1066879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 1067879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 1068879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 1069bb145b01cf5fd27d9afe03c3262d0e1a326e7ec1Theodore Ts'o com_err (program_name, errcode, _("while adding to in-memory bad block list")); 1070879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1071879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1072879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 1073879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1074879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1075879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1076879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1077879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 1078879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 1079879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1080879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1081879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 1082879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 1083879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1084cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o bb_count = test_func(dev, last_block, block_size, 10854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o from_count, blocks_at_once); 10864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (bb_count) 10874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o passes_clean = 0; 10884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else 10894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ++passes_clean; 10904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 1091879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 1092d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 1093d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Pass completed, %u bad blocks found.\n"), 1094d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bb_count); 1095879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1096879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 1097879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 10983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 10993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 11003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 1101849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_patts) 1102849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o free(t_patts); 1103879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 11043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1105d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o 1106