badblocks.c revision f56f32b0a505e34712c8b8fb908dffb616743726
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> 495267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o#include <limits.h> 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 51edf261f6f859ed0ff3c16803ab61a78373089ad8Iustin Pop#include <sys/time.h> 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 53f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 5479e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen#include <sys/time.h> 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 57d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 5854c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h" 59879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 60d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h" 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 63f63978aff759325b542de7134ab659c79dc47496Theodore Ts'oconst char * done_string = N_("done \n"); 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int v_flag = 0; /* verbose */ 664d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int w_flag = 0; /* do r/w test: 0=no, 1=yes, 674d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * 2=non-destructive */ 684d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int s_flag = 0; /* show progress of test */ 69981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic int force = 0; /* force check of mounted device */ 70849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'ostatic int t_flag = 0; /* number of test patterns */ 71849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'ostatic int t_max = 0; /* allocated test patterns */ 72e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'ostatic unsigned int *t_patts = NULL; /* test patterns */ 731c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'ostatic int current_O_DIRECT = 0; /* Current status of O_DIRECT flag */ 74f63978aff759325b542de7134ab659c79dc47496Theodore Ts'ostatic int exclusive_ok = 0; 75931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Popstatic unsigned int max_bb = 0; /* Abort test if more than this number of bad blocks has been encountered */ 76264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Popstatic unsigned int d_flag = 0; /* delay factor between reads */ 771c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 78849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o#define T_INC 32 794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 80acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ounsigned int sys_page_size = 4096; 811c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 828820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void usage(void) 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 84f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] [-e max_bad_blocks] [-d delay_factor_between_reads] [-t test_pattern [-t test_pattern [...]]]\n device [last_block [first_block]]\n"), 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 89d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'ostatic void exclusive_usage(void) 90d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o{ 91d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o fprintf(stderr, 92017a76ee39356ecb13911d666a152f2a4856cbbbTheodore Ts'o _("%s: The -n and -w options are mutually exclusive.\n\n"), 93017a76ee39356ecb13911d666a152f2a4856cbbbTheodore Ts'o program_name); 94017a76ee39356ecb13911d666a152f2a4856cbbbTheodore Ts'o exit(1); 95d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o} 96d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o 97acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic blk_t currently_testing = 0; 98acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic blk_t num_blocks = 0; 99879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 100879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 101879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 102879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 10319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1041c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'ostatic void *allocate_buffer(size_t size) 1051c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o{ 1061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o void *ret = 0; 1071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_POSIX_MEMALIGN 1091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (posix_memalign(&ret, sys_page_size, size) < 0) 1101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = 0; 1111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#else 1121c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_MEMALIGN 1131c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = memalign(sys_page_size, size); 1141c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#else 1151c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_VALLOC 1161c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = valloc(size); 1171c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_VALLOC */ 1181c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_MEMALIGN */ 1191c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_POSIX_MEMALIGN */ 1201c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1211c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (!ret) 1221c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = malloc(size); 1231c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1241c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o return ret; 1251c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o} 1261c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 127dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o/* 128dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * This routine reports a new bad block. If the bad block has already 129dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * been seen before, then it returns 0; otherwise it returns 1. 130dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o */ 131acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic int bb_output (blk_t bad) 132879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 134879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 135dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if (ext2fs_badblocks_list_test(bb_list, bad)) 136dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 0; 137dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o 138acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o fprintf(out, "%lu\n", (unsigned long) bad); 139cc4f98ed2deeaca33244fd77386e7d76917a3d30Theodore Ts'o fflush(out); 140879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 141879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 142879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 143879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 144879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 145879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 146879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 147879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 148879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o increment the iteration through the bb_list if 149879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 150879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 151879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 152879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 153dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 1; 154879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 155879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1568820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void print_status(void) 15719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 158acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o fprintf(stderr, "%15lu/%15lu", (unsigned long) currently_testing, 159acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o (unsigned long) num_blocks); 160c76564a8784c3c44a6a0516e0fc40f10ec6221edTheodore 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); 16119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 16219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 16319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 164544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void alarm_intr(int alnum EXT2FS_ATTR((unused))) 16519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 16619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 16719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 16819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 16919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 170c76564a8784c3c44a6a0516e0fc40f10ec6221edTheodore Ts'o print_status(); 17119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 17219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 173879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 174879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 175544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void terminate_intr(int signo EXT2FS_ATTR((unused))) 176879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 177879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 178879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 179879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 180879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 181879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 182981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void capture_terminate(jmp_buf term_addr) 183879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 184879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 185879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 186879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 187879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 188879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 189879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 190879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 191879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 192879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1938820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void uncapture_terminate(void) 1944d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o{ 1954d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o terminate_addr = NULL; 1964d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGHUP, SIG_DFL); 1974d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGINT, SIG_DFL); 1984d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGPIPE, SIG_DFL); 1994d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGTERM, SIG_DFL); 2004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR1, SIG_DFL); 2014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR2, SIG_DFL); 2024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o} 2034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 2041f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'ostatic void set_o_direct(int dev, unsigned char *buffer, size_t size, 205acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o blk_t current_block) 2061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o{ 2071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef O_DIRECT 2081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int new_flag = O_DIRECT; 2091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int flag; 2101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 2111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if ((((unsigned long) buffer & (sys_page_size - 1)) != 0) || 2121f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o ((size & (sys_page_size - 1)) != 0) || 2131f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o ((current_block & ((sys_page_size >> 9)-1)) != 0)) 2141c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o new_flag = 0; 2151c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 2161c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (new_flag != current_O_DIRECT) { 217dc058719dfca9b35baec3208932702d39a502d3aTheodore Ts'o /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */ 2181c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o flag = fcntl(dev, F_GETFL); 2191c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (flag > 0) { 2201c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o flag = (flag & ~O_DIRECT) | new_flag; 2211c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o fcntl(dev, F_SETFL, flag); 2221c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 2231c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o current_O_DIRECT = new_flag; 2241c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 2251c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif 2261c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o} 2271c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 2281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 229e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'ostatic void pattern_fill(unsigned char *buffer, unsigned int pattern, 23084c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o size_t n) 231849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o{ 232544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int i, nb; 23384c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o unsigned char bpattern[sizeof(pattern)], *ptr; 234849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 235e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o if (pattern == (unsigned int) ~0) { 236849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (ptr = buffer; ptr < buffer + n; ptr++) { 237849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o (*ptr) = random() % (1 << (8 * sizeof(char))); 238849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 239849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag | v_flag) 240544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Testing with random pattern: "), stderr); 241849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 242849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bpattern[0] = 0; 243849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < sizeof(bpattern); i++) { 244849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (pattern == 0) 245849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 246849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bpattern[i] = pattern & 0xFF; 247849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = pattern >> 8; 248849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 249849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nb = i ? (i-1) : 0; 250849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) { 251544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o *ptr = bpattern[i]; 252544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if (i == 0) 253849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o i = nb; 254544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o else 255544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o i--; 256849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 25784c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (s_flag | v_flag) { 258544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Testing with pattern 0x"), stderr); 25984c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o for (i = 0; i <= nb; i++) 26084c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o fprintf(stderr, "%02x", buffer[i]); 261544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(": ", stderr); 26284c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } 263849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 264849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o} 265849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 267879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 268879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 270acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic int do_read (int dev, unsigned char * buffer, int try, int block_size, 271acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o blk_t current_block) 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 274264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop struct timeval tv1, tv2; 275264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop#define NANOSEC (1000000000L) 276264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop#define MILISEC (1000L) 2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2781f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o set_o_direct(dev, buffer, try * block_size, current_block); 2791c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 28019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 28119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 28219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 28419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 285f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 286d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 289264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (d_flag) 290edf261f6f859ed0ff3c16803ab61a78373089ad8Iustin Pop gettimeofday(&tv1, NULL); 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 292264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (d_flag) 293edf261f6f859ed0ff3c16803ab61a78373089ad8Iustin Pop gettimeofday(&tv2, NULL); 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 2969f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 297d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 298879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 299264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (d_flag && got == try) { 300264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop struct timespec ts; 301264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec = tv2.tv_sec - tv1.tv_sec; 302264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC; 303264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (ts.tv_nsec < 0) { 304264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec += NANOSEC; 305264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec -= 1; 306264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop } 307264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop /* increase/decrease the sleep time based on d_flag value */ 308264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec = ts.tv_sec * d_flag / 100; 309264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec = ts.tv_nsec * d_flag / 100; 310264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (ts.tv_nsec > NANOSEC) { 311264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec += ts.tv_nsec / NANOSEC; 312264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec %= NANOSEC; 313264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop } 314264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (ts.tv_sec || ts.tv_nsec) 315264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop nanosleep(&ts, NULL); 316264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop } 317879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 318879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 319879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 320879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 321879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 322879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 323879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 324acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic int do_write(int dev, unsigned char * buffer, int try, int block_size, 325acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned long current_block) 326879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 327879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 328879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 3291f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o set_o_direct(dev, buffer, try * block_size, current_block); 3301c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 331879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 332879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 333879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 334879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 335879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 336879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 337d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 338879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 339879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 340879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 341879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 342879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = 0; 343879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 344544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fprintf(stderr, "Weird value (%ld) in do_write\n", got); 3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 349879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 350879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 3514d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'ostatic void flush_bufs(void) 352a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 3534d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o errcode_t retval; 354a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 3554d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o retval = ext2fs_sync_device(host_dev, 1); 3564d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o if (retval) 3574d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o com_err(program_name, retval, _("during ext2fs_sync_device")); 358a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 359a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 360acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic unsigned int test_ro (int dev, blk_t last_block, 361f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o int block_size, blk_t first_block, 362acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once) 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 36448e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned char * blkbuf; 3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 366acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o int got; 367879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 368879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 3693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 370879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 371879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 372d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 373d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 374879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 375879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 376879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 377879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 378f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o } while (next_bad && next_bad < first_block); 379879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 380849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 3811c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer((blocks_at_once + 1) * block_size); 382849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 3831c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer(blocks_at_once * block_size); 384849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 3853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 387d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 3883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 390f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 391acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o fprintf (stderr, _("Checking blocks %lu to %lu\n"), 392f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) first_block, 393acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o (unsigned long) last_block - 1); 394f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 395849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 396544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in read-only mode\n"), stderr); 397849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern_fill(blkbuf + blocks_at_once * block_size, 398849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts[0], block_size); 399849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 400849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 401879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 402f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 4038938ce64dca50d7d0f47f45fdc886de4f0939f0bTheodore Ts'o num_blocks = last_block - 1; 404849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!t_flag && (s_flag || v_flag)) { 405544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks (read-only test): "), stderr); 40619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 40719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 4083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 409cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o while (currently_testing < last_block) 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 411931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 412931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 413931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 414931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 415931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 416931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 417879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 418879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 419879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 420879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 421879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 422879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 423879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 424879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 425879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 426879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 427cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (currently_testing + try > last_block) 428cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o try = last_block - currently_testing; 429879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 430849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 431849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* test the comparison between all the 432849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blocks successfully read */ 433849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o int i; 434849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < got; ++i) 435849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (memcmp (blkbuf+i*block_size, 436849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blkbuf+blocks_at_once*block_size, 437849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o block_size)) 438849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing + i); 439849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 4403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 4413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 442879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 4431f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o /* recover page-aligned offset for O_DIRECT */ 444acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o if ( (blocks_at_once >= sys_page_size >> 9) 4451f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o && (currently_testing % (sys_page_size >> 9)!= 0)) 4461f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try -= (sys_page_size >> 9) 4471f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o - (currently_testing 4481f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o % (sys_page_size >> 9)); 4493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 453879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got == 0) { 454dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o bb_count += bb_output(currently_testing++); 455879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 4583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 459849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag || v_flag) 4603ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 461879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 462f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 464879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 465879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 466879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 467879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 470acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic unsigned int test_rw (int dev, blk_t last_block, 471f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o int block_size, blk_t first_block, 472acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once) 4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4741c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o unsigned char *buffer, *read_buffer; 475e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00}; 476e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int *pattern; 4771c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int i, try, got, nr_pattern, pat_idx; 478879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 4793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4801c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o buffer = allocate_buffer(2 * blocks_at_once * block_size); 4811c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_buffer = buffer + blocks_at_once * block_size; 4821c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 4831c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (!buffer) { 484d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 4853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 4863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4884d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 489a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 49019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 491544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in read-write mode\n"), 492544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o stderr); 493d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("From block %lu to %lu\n"), 494f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) first_block, 495f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) last_block - 1); 49619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 497849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 498849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = t_patts; 499849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = t_flag; 500849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 501849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = patterns; 502849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 503849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 504849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 5051c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o pattern_fill(buffer, pattern[pat_idx], 5061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blocks_at_once * block_size); 5078938ce64dca50d7d0f47f45fdc886de4f0939f0bTheodore Ts'o num_blocks = last_block - 1; 508f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 50919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 510f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 5111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 5121c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 5131c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o while (currently_testing < last_block) { 514931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 515931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 516931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 517931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 518931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 519931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 5201c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (currently_testing + try > last_block) 5211c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = last_block - currently_testing; 5221c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = do_write(dev, buffer, try, block_size, 5231c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing); 52419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 52519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 5261c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 5271c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing += got; 5281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (got == try) { 5291c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 5301f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o /* recover page-aligned offset for O_DIRECT */ 531acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o if ( (blocks_at_once >= sys_page_size >> 9) 5321f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o && (currently_testing % 5331f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o (sys_page_size >> 9)!= 0)) 5341f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try -= (sys_page_size >> 9) 5351f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o - (currently_testing 5361f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o % (sys_page_size >> 9)); 5371c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o continue; 5381c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } else 5391c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = 1; 5401c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (got == 0) { 5411c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o bb_count += bb_output(currently_testing++); 5421c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 5433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5441c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 545f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 546f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 547f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 5483ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 5494d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 550f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 551544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Reading and comparing: "), stderr); 552cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 553f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 55419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 555f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 5561c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 5571c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 5581c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o while (currently_testing < last_block) { 559931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 560931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 561931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 562931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 563931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 564931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 5651c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (currently_testing + try > last_block) 5661c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = last_block - currently_testing; 5671c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = do_read (dev, read_buffer, try, block_size, 5681c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing); 5691c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (got == 0) { 5701c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o bb_count += bb_output(currently_testing++); 5711c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o continue; 5721c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 5731c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o for (i=0; i < got; i++) { 5741c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (memcmp(read_buffer + i * block_size, 5751c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o buffer + i * block_size, 5761c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o block_size)) 5771c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o bb_count += bb_output(currently_testing+i); 5781c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 5791c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing += got; 5801f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o /* recover page-aligned offset for O_DIRECT */ 581acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o if ( (blocks_at_once >= sys_page_size >> 9) 5821f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o && (currently_testing % (sys_page_size >> 9)!= 0)) 5831f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try = blocks_at_once - (sys_page_size >> 9) 5841f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o - (currently_testing 5851f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o % (sys_page_size >> 9)); 5861f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o else 5871f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o try = blocks_at_once; 58819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 58919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 5903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5911c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 592f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 593f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 594f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 5953ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 5964d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 5973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 598849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o uncapture_terminate(); 5996d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o free(buffer); 600879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 601879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 602879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 603d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostruct saved_blk_record { 604d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o blk_t block; 605d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num; 606d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o}; 607d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 608acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic unsigned int test_nd (int dev, blk_t last_block, 609f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o int block_size, blk_t first_block, 610acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once) 611879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 61248e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 6131c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o unsigned char *test_base, *save_base, *read_base; 614dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int try, i; 615e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int patterns[] = { ~0 }; 616e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int *pattern; 617849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o int nr_pattern, pat_idx; 618acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o int got, used2, written; 619acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o blk_t save_currently_testing; 620d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o struct saved_blk_record *test_record; 621a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o /* This is static to prevent being clobbered by the longjmp */ 622a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o static int num_saved; 623879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 624879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 625544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned long buf_used; 626544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o static unsigned int bb_count; 627879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 628544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o bb_count = 0; 629879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 630879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 631dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o com_err (program_name, errcode, 632d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 633879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 634879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 635879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 636879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 637f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o } while (next_bad && next_bad < first_block); 638879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 6391c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer(3 * blocks_at_once * block_size); 640d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record)); 641d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (!blkbuf || !test_record) { 642d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err(program_name, ENOMEM, _("while allocating buffers")); 643879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 644879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 6451c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 6461c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_base = blkbuf; 6471c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_base = blkbuf + (blocks_at_once * block_size); 6481c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_base = blkbuf + (2 * blocks_at_once * block_size); 6491c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 650d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 651879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 6524d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 653879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 654544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr); 655acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), 656f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) first_block, 657f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) last_block - 1); 658879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 659879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 660544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr); 661879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 6624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (setjmp(terminate_env)) { 6634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 6644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * Abnormal termination by a signal is handled here. 6654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 666a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o signal (SIGALRM, SIG_IGN); 667544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("\nInterrupt caught, cleaning up\n"), stderr); 668879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 6691c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 670d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o for (i=0; i < num_saved; i++) { 671d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o do_write(dev, save_ptr, test_record[i].num, 672d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o block_size, test_record[i].block); 673d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr += test_record[i].num * block_size; 674d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 675879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 676dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o exit(1); 677879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 6784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 6794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* set up abend handler */ 6804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o capture_terminate(terminate_env); 6814d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 682849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 683849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = t_patts; 684849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = t_flag; 685849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 686849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = patterns; 687849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 688849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 689849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 6901c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o pattern_fill(test_base, pattern[pat_idx], 6911c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blocks_at_once * block_size); 6924d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 693849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used = 0; 694849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count = 0; 6951c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 6961c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 697f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 6988938ce64dca50d7d0f47f45fdc886de4f0939f0bTheodore Ts'o num_blocks = last_block - 1; 699849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag && v_flag <= 1) 700849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o alarm_intr(SIGALRM); 7014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 702849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o while (currently_testing < last_block) { 703931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 704931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 705931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 706931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 707931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 708931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 7091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = try = blocks_at_once - buf_used; 710849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (next_bad) { 711849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (currently_testing == next_bad) { 712849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 713849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 714849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing++; 715849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o goto check_for_more; 716849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 717849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o else if (currently_testing + try > next_bad) 718849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = next_bad - currently_testing; 719d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 720849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (currently_testing + try > last_block) 721849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = last_block - currently_testing; 722849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got = do_read (dev, save_ptr, try, block_size, 723849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing); 724849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got == 0) { 725849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* First block must have been bad. */ 726849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing++); 727849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o goto check_for_more; 7284d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 7294d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 730849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 731849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * Note the fact that we've saved this much data 732849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * *before* we overwrite it with test data 733849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 734849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_record[num_saved].block = currently_testing; 735849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_record[num_saved].num = got; 736849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_saved++; 737849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 738849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* Write the test data */ 739849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o written = do_write (dev, test_ptr, got, block_size, 740849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing); 741849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (written != got) 742849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err (program_name, errno, 743849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("during test data write, block %lu"), 744acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o (unsigned long) currently_testing + 745acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o written); 746849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 747849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used += got; 7484d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 7494d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 750849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing += got; 751849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got != try) 752849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing++); 753849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 754849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o check_for_more: 755849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 756849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * If there's room for more blocks to be tested this 757849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * around, and we're not done yet testing the disk, go 758849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * back and get some more blocks. 759849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 760849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if ((buf_used != blocks_at_once) && 761849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o (currently_testing < last_block)) 762849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o continue; 763849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 764849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 765849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o save_currently_testing = currently_testing; 766849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 767849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 768849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * for each contiguous block that we read into the 769849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * buffer (and wrote test data into afterwards), read 770849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it back (looping if necessary, to get past newly 771849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * discovered unreadable blocks, of which there should 772849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * be none, but with a hard drive which is unreliable, 773849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it has happened), and compare with the test data 774849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * that was written; output to the bad block list if 775849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it doesn't match. 776849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 777849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o used2 = 0; 7781c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 7791c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 7801c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_ptr = read_base; 781849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = 0; 782849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 783849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o while (1) { 784849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (try == 0) { 785849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (used2 >= num_saved) 786849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 787849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = test_record[used2].block; 788849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = test_record[used2].num; 789849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o used2++; 790849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 791849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 792849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got = do_read (dev, read_ptr, try, 793849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o block_size, currently_testing); 794849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 795849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* test the comparison between all the 796849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blocks successfully read */ 797849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < got; ++i) 798849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (memcmp (test_ptr+i*block_size, 799849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o read_ptr+i*block_size, block_size)) 800849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing + i); 801849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got < try) { 802849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count += bb_output(currently_testing + got); 803849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got++; 804849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 805849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 8061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o /* write back original data */ 8071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o do_write (dev, save_ptr, got, 8081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o block_size, currently_testing); 8091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr += got * block_size; 810849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 811849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing += got; 812849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_ptr += got * block_size; 813849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o read_ptr += got * block_size; 814849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try -= got; 815849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 816849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 817849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* empty the buffer so it can be reused */ 818849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_saved = 0; 819849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used = 0; 8201c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 8211c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 822849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = save_currently_testing; 8234d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 824849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_blocks = 0; 825849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o alarm(0); 826849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag || v_flag > 1) 8273ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 8284d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 829849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 8304d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 8314d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o uncapture_terminate(); 832dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o fflush(stderr); 833dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o free(blkbuf); 834d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o free(test_record); 835879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 836879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 837879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 838879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 8393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 8403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 841981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void check_mount(char *device_name) 842981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o{ 843981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o errcode_t retval; 844981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o int mount_flags; 845981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 846981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o retval = ext2fs_check_if_mounted(device_name, &mount_flags); 847981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (retval) { 848981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o com_err("ext2fs_check_if_mount", retval, 849981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o _("while determining whether %s is mounted."), 850981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o device_name); 851981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 852981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 8532fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (mount_flags & EXT2_MF_MOUNTED) { 8542fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fprintf(stderr, _("%s is mounted; "), device_name); 8552fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (force) { 8562fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("badblocks forced anyway. " 8572fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o "Hope /etc/mtab is incorrect.\n"), stderr); 8582fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o return; 8592fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o } 8602fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o abort_badblocks: 8612fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("it's not safe to run badblocks!\n"), stderr); 8622fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o exit(1); 8632fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o } 864981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 865f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) { 8662fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fprintf(stderr, _("%s is apparently in use by the system; "), 8672fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o device_name); 8682fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (force) 8692fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("badblocks forced anyway.\n"), stderr); 8702fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o else 8712fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o goto abort_badblocks; 872981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 8732fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o 874981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o} 875981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 876d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o/* 877d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o * This function will convert a string to an unsigned long, printing 878d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o * an error message if it fails, and returning success or failure in err. 879d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o */ 880d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'ostatic unsigned int parse_uint(const char *str, const char *descr) 881d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o{ 882d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o char *tmp; 883d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o unsigned long ret; 884d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o 885eb594251b6d1a06d2acbb281b3816c017d7066ebIustin Pop errno = 0; 886d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o ret = strtoul(str, &tmp, 0); 887d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o if (*tmp || errno || (ret > UINT_MAX) || 888d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o (ret == ULONG_MAX && errno == ERANGE)) { 889d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o com_err (program_name, 0, _("invalid %s - %s"), descr, str); 890d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o exit (1); 891d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o } 892d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o return ret; 893d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o} 894981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 89500e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 8963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 897519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 8983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 899879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 900879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 9013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 902879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 903dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size = 1024; 904acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once = 64; 905f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o blk_t last_block, first_block; 906879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 907879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 9083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 909879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 910e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o unsigned int pattern; 911acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int (*test_func)(int, blk_t, 912acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o int, blk_t, 913acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int); 9141c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int open_flag = 0; 9151c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o long sysval; 9163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 9183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 919d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS 920d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o setlocale(LC_MESSAGES, ""); 92114308a5398984842e808faa3ff2dd6a1c52d90bdTheodore Ts'o setlocale(LC_CTYPE, ""); 922d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 923d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o textdomain(NLS_CAT_NAME); 924d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif 9256d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o srandom((unsigned int)time(NULL)); /* simple randomness is enough */ 9264d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_ro; 9274d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o 9281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o /* Determine the system page size if possible */ 9291c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_SYSCONF 9301c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) 9311c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#define _SC_PAGESIZE _SC_PAGE_SIZE 9321c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif 9331c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef _SC_PAGESIZE 9341c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o sysval = sysconf(_SC_PAGESIZE); 9351c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (sysval > 0) 9361c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o sys_page_size = sysval; 9371c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* _SC_PAGESIZE */ 9381c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_SYSCONF */ 9391c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 9403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 9413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 942264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop while ((c = getopt (argc, argv, "b:d:e:fi:o:svwnc:p:h:t:X")) != EOF) { 9433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 9443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 945d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o block_size = parse_uint(optarg, "block size"); 946d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o if (block_size > 4096) { 9473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 948d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("bad block size - %s"), optarg); 9493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 9503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 9513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 952981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o case 'f': 953981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o force++; 954981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o break; 955879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 956879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 957879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 9583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 9593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 9603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 9613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 9623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 9633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 9643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 96519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 9663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 9673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 9684d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 969d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o exclusive_usage(); 9704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_rw; 9714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o w_flag = 1; 972879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 973879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 9744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 975d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o exclusive_usage(); 9764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_nd; 977879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 978879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 979879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 980d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o blocks_at_once = parse_uint(optarg, "blocks at once"); 981879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 982931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop case 'e': 983931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop max_bb = parse_uint(optarg, "max bad block count"); 984931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 985264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop case 'd': 986264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop d_flag = parse_uint(optarg, "read delay factor"); 987264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop break; 988879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 989d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o num_passes = parse_uint(optarg, 990d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o "number of clean passes"); 991879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 992879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 993879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 9943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 995849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o case 't': 996849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag + 1 > t_max) { 997e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o unsigned int *t_patts_new; 998849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 99969d813520cf14f5700c38c82b5c147aa3756bbd9Theodore Ts'o t_patts_new = realloc(t_patts, sizeof(int) * 100069d813520cf14f5700c38c82b5c147aa3756bbd9Theodore Ts'o (t_max + T_INC)); 1001849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!t_patts_new) { 1002849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, ENOMEM, 1003849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("can't allocate memory for " 1004849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "test_pattern - %s"), 1005849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o optarg); 1006849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 1007849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1008849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts = t_patts_new; 1009849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_max += T_INC; 1010849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 101184c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) { 101284c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o t_patts[t_flag++] = ~0; 101384c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } else { 1014d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o pattern = parse_uint(optarg, "test pattern"); 1015e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o if (pattern == (unsigned int) ~0) 101684c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o pattern = 0xffff; 101784c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o t_patts[t_flag++] = pattern; 1018849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1019849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 1020f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o case 'X': 1021f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o exclusive_ok++; 1022f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o break; 10233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 1024818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 10253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1027849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!w_flag) { 1028849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag > 1) { 1029849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, 0, 1030849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("Maximum of one test_pattern may be specified " 1031849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "in read-only mode")); 1032849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 1033849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1034e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o if (t_patts && (t_patts[0] == (unsigned int) ~0)) { 1035849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, 0, 1036849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("Random test_pattern is not allowed " 1037849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "in read-only mode")); 1038849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 1039849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1040849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 10413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 1042818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 10433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 104435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind > argc - 1) { 104535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o errcode = ext2fs_get_device_size(device_name, 104635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o block_size, 1047cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o &last_block); 104835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode == EXT2_ET_UNIMPLEMENTED) { 104935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, 0, 105035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("Couldn't determine device size; you " 105135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o "must specify\nthe size manually\n")); 105235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 105335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 105435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode) { 105535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, errcode, 105635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("while trying to determine device size")); 105735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 105835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 105935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } else { 10605267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o errno = 0; 1061f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o last_block = parse_uint(argv[optind], _("last block")); 10625267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o last_block++; 106335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o optind++; 10643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 106535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind <= argc-1) { 10665267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o errno = 0; 1067f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o first_block = parse_uint(argv[optind], _("first block")); 1068f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o } else first_block = 0; 1069f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o if (first_block >= last_block) { 1070d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o com_err (program_name, 0, _("invalid starting block (%lu): must be less than %lu"), 1071f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) first_block, (unsigned long) last_block); 1072f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 1073f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1074981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (w_flag) 1075981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o check_mount(device_name); 1076981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 10771c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o open_flag = w_flag ? O_RDWR : O_RDONLY; 10781c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o dev = open (device_name, open_flag); 10795493a27dc1138d2e30193b80217a0127d247af1eTheodore Ts'o if (dev == -1) { 1080d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("while trying to open %s"), 10813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 10823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 10833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1084879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 10851c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o host_dev = open (host_device_name, open_flag); 10865493a27dc1138d2e30193b80217a0127d247af1eTheodore Ts'o if (host_dev == -1) { 1087d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1088d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1089d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o host_device_name); 1090879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1091879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1092879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 1093879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 10943e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o if (input_file) { 1095879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 1096879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 1097879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 1098879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 1099879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 1100879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 1101d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1102d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1103879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 1104879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1105879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1106879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 11073e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o } 11083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 11093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 11103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 11113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 11123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 1113d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1114d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1115879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 11163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 11173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 11183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 11193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 11203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 1121879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1122879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 1123879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 1124d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 1125bb145b01cf5fd27d9afe03c3262d0e1a326e7ec1Theodore Ts'o _("while creating in-memory bad blocks list")); 1126879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1127879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1128879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1129879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 1130879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 1131a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o switch(fscanf (in, "%u\n", &next_bad)) { 1132879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 1133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, "input file - bad format"); 1134879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1135879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 1136879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1137879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 1138879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 1139879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 1140bb145b01cf5fd27d9afe03c3262d0e1a326e7ec1Theodore Ts'o com_err (program_name, errcode, _("while adding to in-memory bad block list")); 1141879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1142879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1143879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 1144879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1145879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1146879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1147879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1148879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 1149879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 1150879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1151879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1152879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 1153879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 1154879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1155cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o bb_count = test_func(dev, last_block, block_size, 1156f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o first_block, blocks_at_once); 11574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (bb_count) 11584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o passes_clean = 0; 11594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else 11604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ++passes_clean; 11614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 1162879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 1163d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 1164d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Pass completed, %u bad blocks found.\n"), 1165d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bb_count); 1166879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1167879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 1168879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 11693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 11703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 11713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 1172849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_patts) 1173849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o free(t_patts); 1174879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 11753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1176d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o 1177