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> 13efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore 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 27efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore 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 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef _GNU_SOURCE 331c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#define _GNU_SOURCE /* for O_DIRECT */ 34cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger#endif 351c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h> 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 38a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h> 40373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o#else 41373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern char *optarg; 42373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern int optind; 43a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h> 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 49879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <setjmp.h> 506d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o#include <time.h> 515267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o#include <limits.h> 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 53edf261f6f859ed0ff3c16803ab61a78373089ad8Iustin Pop#include <sys/time.h> 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 55f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 58d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 5954c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h" 60879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 61d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h" 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef O_LARGEFILE 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define O_LARGEFILE 0 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic const char * program_name = "badblocks"; 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic const char * done_string = N_("done \n"); 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int v_flag; /* verbose */ 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int w_flag; /* do r/w test: 0=no, 1=yes, 724d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * 2=non-destructive */ 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int s_flag; /* show progress of test */ 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int force; /* force check of mounted device */ 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int t_flag; /* number of test patterns */ 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int t_max; /* allocated test patterns */ 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int *t_patts; /* test patterns */ 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int use_buffered_io; 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int exclusive_ok; 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int max_bb; /* Abort test if more than this number of bad blocks has been encountered */ 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int d_flag; /* delay factor between reads */ 82504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyarstatic struct timeval time_start; 831c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 84849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o#define T_INC 32 854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int sys_page_size = 4096; 871c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 888820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void usage(void) 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 90ad39bcd9e3b0fe98c33825db6dfdf343463e388cBenno Schulenberg fprintf(stderr, _( 91ad39bcd9e3b0fe98c33825db6dfdf343463e388cBenno Schulenberg"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n" 92ad39bcd9e3b0fe98c33825db6dfdf343463e388cBenno Schulenberg" [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n" 93ad39bcd9e3b0fe98c33825db6dfdf343463e388cBenno Schulenberg" [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n" 94ad39bcd9e3b0fe98c33825db6dfdf343463e388cBenno Schulenberg" device [last_block [first_block]]\n"), 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 99d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'ostatic void exclusive_usage(void) 100d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o{ 101efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fprintf(stderr, 102efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o _("%s: The -n and -w options are mutually exclusive.\n\n"), 103017a76ee39356ecb13911d666a152f2a4856cbbbTheodore Ts'o program_name); 104017a76ee39356ecb13911d666a152f2a4856cbbbTheodore Ts'o exit(1); 105d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o} 106d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o 107acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic blk_t currently_testing = 0; 108acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic blk_t num_blocks = 0; 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic blk_t num_read_errors = 0; 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic blk_t num_write_errors = 0; 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic blk_t num_corruption_errors = 0; 112879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 113879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 114879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 115879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 11619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallenum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR }; 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1191c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'ostatic void *allocate_buffer(size_t size) 1201c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o{ 1211c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o void *ret = 0; 122efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1231c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_POSIX_MEMALIGN 1241c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (posix_memalign(&ret, sys_page_size, size) < 0) 1251c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = 0; 1261c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#else 1271c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_MEMALIGN 1281c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = memalign(sys_page_size, size); 1291c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#else 1301c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_VALLOC 1311c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = valloc(size); 1321c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_VALLOC */ 133efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#endif /* HAVE_MEMALIGN */ 1341c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_POSIX_MEMALIGN */ 1351c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1361c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (!ret) 1371c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o ret = malloc(size); 1381c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 1391c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o return ret; 1401c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o} 1411c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 142dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o/* 143dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * This routine reports a new bad block. If the bad block has already 144dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * been seen before, then it returns 0; otherwise it returns 1. 145dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o */ 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int bb_output (blk_t bad, enum error_types error_type) 147879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 148879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 149879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 150dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if (ext2fs_badblocks_list_test(bb_list, bad)) 151dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 0; 152dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o 153acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o fprintf(out, "%lu\n", (unsigned long) bad); 154cc4f98ed2deeaca33244fd77386e7d76917a3d30Theodore Ts'o fflush(out); 155879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 156879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 157879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 158879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 159879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 160879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 161879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 162879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 163efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o increment the iteration through the bb_list if 164879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 165879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 166879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 167879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (error_type == READ_ERROR) { 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_read_errors++; 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (error_type == WRITE_ERROR) { 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_write_errors++; 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (error_type == CORRUPTION_ERROR) { 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_corruption_errors++; 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 176dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 1; 177879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 178879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 179504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyarstatic char *time_diff_format(struct timeval *tv1, 180504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar struct timeval *tv2, char *buf) 181504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar{ 182504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar time_t diff = (tv1->tv_sec - tv2->tv_sec); 183504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar int hr,min,sec; 184504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar 185504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar sec = diff % 60; 186504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar diff /= 60; 187504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar min = diff % 60; 188504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar hr = diff / 60; 189504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar 190504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar if (hr) 191504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar sprintf(buf, "%d:%02d:%02d", hr, min, sec); 192504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar else 193504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar sprintf(buf, "%d:%02d", min, sec); 194504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar return buf; 195504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar} 196504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar 197504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyarstatic float calc_percent(unsigned long current, unsigned long total) { 198504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar float percent = 0.0; 199504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar if (total <= 0) 200504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar return percent; 201504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar if (current >= total) { 202504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar percent = 100.0; 203504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar } else { 204504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar percent=(100.0*(float)current/(float)total); 205504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar } 206504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar return percent; 207504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar} 208504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar 2098820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void print_status(void) 21019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 211504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar struct timeval time_end; 212504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar char diff_buf[32], line_buf[128]; 213504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar int len; 214504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar 215504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar gettimeofday(&time_end, 0); 216504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar len = snprintf(line_buf, sizeof(line_buf), 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("%6.2f%% done, %s elapsed. " 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "(%d/%d/%d errors)"), 219504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar calc_percent((unsigned long) currently_testing, 220504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar (unsigned long) num_blocks), 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall time_diff_format(&time_end, &time_start, diff_buf), 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_read_errors, 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_write_errors, 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_corruption_errors); 22561ef2474c24c80a5bf0e24ba85a7506fd7651a5cTheodore Ts'o#ifdef HAVE_MBSTOWCS 22661ef2474c24c80a5bf0e24ba85a7506fd7651a5cTheodore Ts'o len = mbstowcs(NULL, line_buf, sizeof(line_buf)); 22761ef2474c24c80a5bf0e24ba85a7506fd7651a5cTheodore Ts'o#endif 228504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar fputs(line_buf, stderr); 229504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar memset(line_buf, '\b', len); 230504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar line_buf[len] = 0; 231504f7a2981306032fff7084c0d90beaa45872ee0Manish Katiyar fputs(line_buf, stderr); 23219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 23319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 23419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 235544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void alarm_intr(int alnum EXT2FS_ATTR((unused))) 23619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 23719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 23819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 23919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 24019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 241c76564a8784c3c44a6a0516e0fc40f10ec6221edTheodore Ts'o print_status(); 24219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 24319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 244879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 245879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 246544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void terminate_intr(int signo EXT2FS_ATTR((unused))) 247879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 248c510d6f2684f2e2fa05c0de7bdaee954743546f8Theodore Ts'o fflush(out); 24983bfa27d3272631ef26f569471845c3755428134Theodore Ts'o fprintf(stderr, "\n\nInterrupted at block %llu\n", 25083bfa27d3272631ef26f569471845c3755428134Theodore Ts'o (unsigned long long) currently_testing); 25183bfa27d3272631ef26f569471845c3755428134Theodore Ts'o fflush(stderr); 252879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 253879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 254879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 255879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 256879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 257981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void capture_terminate(jmp_buf term_addr) 258879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 259879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 260879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 261879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 262879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 263879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 264879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 265879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 266879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 267879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 2688820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void uncapture_terminate(void) 2694d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o{ 2704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o terminate_addr = NULL; 2714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGHUP, SIG_DFL); 2724d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGINT, SIG_DFL); 2734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGPIPE, SIG_DFL); 2744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGTERM, SIG_DFL); 2754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR1, SIG_DFL); 2764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR2, SIG_DFL); 2774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o} 2784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Linux requires that O_DIRECT I/Os be 512-byte sector aligned */ 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define O_DIRECT_SIZE 512 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2831f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'ostatic void set_o_direct(int dev, unsigned char *buffer, size_t size, 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_loff_t offset) 2851c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o{ 2861c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef O_DIRECT 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static int current_O_DIRECT; /* Current status of O_DIRECT flag */ 2881c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int new_flag = O_DIRECT; 2891c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int flag; 290efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((use_buffered_io != 0) || 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (((unsigned long) buffer & (sys_page_size - 1)) != 0) || 2931f9a60c251261f8c10d29da4e6202fe530b4684dTheodore Ts'o ((size & (sys_page_size - 1)) != 0) || 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((offset & (O_DIRECT_SIZE - 1)) != 0)) 2951c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o new_flag = 0; 2961c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 2971c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (new_flag != current_O_DIRECT) { 298dc058719dfca9b35baec3208932702d39a502d3aTheodore Ts'o /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */ 2991c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o flag = fcntl(dev, F_GETFL); 3001c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (flag > 0) { 3011c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o flag = (flag & ~O_DIRECT) | new_flag; 3021c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o fcntl(dev, F_SETFL, flag); 3031c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 3041c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o current_O_DIRECT = new_flag; 3051c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 3061c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif 3071c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o} 3081c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 3091c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 310e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'ostatic void pattern_fill(unsigned char *buffer, unsigned int pattern, 31184c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o size_t n) 312849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o{ 313544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int i, nb; 31484c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o unsigned char bpattern[sizeof(pattern)], *ptr; 315efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 316e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o if (pattern == (unsigned int) ~0) { 317849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (ptr = buffer; ptr < buffer + n; ptr++) { 318849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o (*ptr) = random() % (1 << (8 * sizeof(char))); 319849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 320849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag | v_flag) 321544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Testing with random pattern: "), stderr); 322849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 323849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bpattern[0] = 0; 324849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < sizeof(bpattern); i++) { 325849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (pattern == 0) 326849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 327849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bpattern[i] = pattern & 0xFF; 328849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = pattern >> 8; 329849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 330849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nb = i ? (i-1) : 0; 331849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) { 332544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o *ptr = bpattern[i]; 333544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if (i == 0) 334849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o i = nb; 335544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o else 336544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o i--; 337849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 33884c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (s_flag | v_flag) { 339544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Testing with pattern 0x"), stderr); 34084c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o for (i = 0; i <= nb; i++) 34184c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o fprintf(stderr, "%02x", buffer[i]); 342544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(": ", stderr); 34384c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } 344849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 345849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o} 346849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 348879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 349879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 3503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 351acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic int do_read (int dev, unsigned char * buffer, int try, int block_size, 352acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o blk_t current_block) 3533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 355264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop struct timeval tv1, tv2; 356264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop#define NANOSEC (1000000000L) 357264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop#define MILISEC (1000L) 3583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if 0 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("do_read: block %d, try %d\n", current_block, try); 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall set_o_direct(dev, buffer, try * block_size, 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((ext2_loff_t) current_block) * block_size); 3641c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 36519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 36619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 36719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 3683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 36919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 370f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err (program_name, errno, "%s", _("during seek")); 3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 374264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (d_flag) 375edf261f6f859ed0ff3c16803ab61a78373089ad8Iustin Pop gettimeofday(&tv1, NULL); 3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 377264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (d_flag) 378edf261f6f859ed0ff3c16803ab61a78373089ad8Iustin Pop gettimeofday(&tv2, NULL); 3793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 380efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o got = 0; 3819f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 382d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 383879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 384264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (d_flag && got == try) { 385c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o#ifdef HAVE_NANOSLEEP 386264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop struct timespec ts; 387264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec = tv2.tv_sec - tv1.tv_sec; 388264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC; 389264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (ts.tv_nsec < 0) { 390264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec += NANOSEC; 391264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec -= 1; 392264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop } 393264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop /* increase/decrease the sleep time based on d_flag value */ 394264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec = ts.tv_sec * d_flag / 100; 395264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec = ts.tv_nsec * d_flag / 100; 396264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (ts.tv_nsec > NANOSEC) { 397264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_sec += ts.tv_nsec / NANOSEC; 398264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop ts.tv_nsec %= NANOSEC; 399264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop } 400264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop if (ts.tv_sec || ts.tv_nsec) 401264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop nanosleep(&ts, NULL); 402c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o#else 403c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o#ifdef HAVE_USLEEP 404c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o struct timeval tv; 405c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o tv.tv_sec = tv2.tv_sec - tv1.tv_sec; 406c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o tv.tv_usec = tv2.tv_usec - tv1.tv_usec; 407c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o tv.tv_sec = tv.tv_sec * d_flag / 100; 408c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o tv.tv_usec = tv.tv_usec * d_flag / 100; 409c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o if (tv.tv_usec > 1000000) { 410c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o tv.tv_sec += tv.tv_usec / 1000000; 411c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o tv.tv_usec %= 1000000; 412c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o } 413c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o if (tv.tv_sec) 414c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o sleep(tv.tv_sec); 415c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o if (tv.tv_usec) 416c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o usleep(tv.tv_usec); 417c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o#endif 418c13ab4fa7aa2ddd3daa66c353ad41422265de9c3Theodore Ts'o#endif 419264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop } 420879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 421879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 422879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 423879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 424879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 425879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 426879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 427acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic int do_write(int dev, unsigned char * buffer, int try, int block_size, 428acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned long current_block) 429879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 430879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 431879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 432e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if 0 433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("do_write: block %lu, try %d\n", current_block, try); 434e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 435e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall set_o_direct(dev, buffer, try * block_size, 436e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((ext2_loff_t) current_block) * block_size); 4371c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 438879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 439879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 440879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 441879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 442879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 443879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 444e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err (program_name, errno, "%s", _("during seek")); 445879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 446879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 447879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 448879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 449efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o got = 0; 450879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 451544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fprintf(stderr, "Weird value (%ld) in do_write\n", got); 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 456879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 457879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 4584d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'ostatic void flush_bufs(void) 459a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 4604d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o errcode_t retval; 461a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef O_DIRECT 463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!use_buffered_io) 464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 4664d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o retval = ext2fs_sync_device(host_dev, 1); 4674d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o if (retval) 468e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, retval, "%s", 469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("during ext2fs_sync_device")); 470a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 471a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 472acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic unsigned int test_ro (int dev, blk_t last_block, 473f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o int block_size, blk_t first_block, 474acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once) 4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 47648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned char * blkbuf; 4773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 478acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o int got; 479879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 480879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 481e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_t recover_block = ~0; 4823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 48383bfa27d3272631ef26f569471845c3755428134Theodore Ts'o /* set up abend handler */ 48483bfa27d3272631ef26f569471845c3755428134Theodore Ts'o capture_terminate(NULL); 48583bfa27d3272631ef26f569471845c3755428134Theodore Ts'o 486879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 487879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, errcode, "%s", 489e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while beginning bad block list iteration")); 490879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 491879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 492879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 493879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 494f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o } while (next_bad && next_bad < first_block); 495879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 496849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 4971c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer((blocks_at_once + 1) * block_size); 498849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 4991c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer(blocks_at_once * block_size); 500849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 5013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 5023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 503e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, ENOMEM, "%s", 504e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while allocating buffers")); 5053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 5063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 507f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 508e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, _("Checking blocks %lu to %lu\n"), 509e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned long)first_block, 510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned long)last_block - 1); 511f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 512849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 513544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in read-only mode\n"), stderr); 514849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern_fill(blkbuf + blocks_at_once * block_size, 515849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts[0], block_size); 516849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 517849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 518879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 519f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 5208938ce64dca50d7d0f47f45fdc886de4f0939f0bTheodore Ts'o num_blocks = last_block - 1; 521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!t_flag && (s_flag || v_flag)) 522544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks (read-only test): "), stderr); 523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (s_flag && v_flag <= 1) 524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall alarm_intr(SIGALRM); 525cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o while (currently_testing < last_block) 5263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 527931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 528931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 529931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 530931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 531931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 532931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 533879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 534879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 535879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 536879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 537879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 538879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 539879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 540879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 541879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 542879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 543cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (currently_testing + try > last_block) 544cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o try = last_block - currently_testing; 545879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 546849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 547849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* test the comparison between all the 548849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blocks successfully read */ 549849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o int i; 550849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < got; ++i) 551849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (memcmp (blkbuf+i*block_size, 552849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blkbuf+blocks_at_once*block_size, 553849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o block_size)) 554e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR); 555849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 556e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got == 0 && try == 1) 557e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing++, READ_ERROR); 5583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 559e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got != try) { 56065f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall try = 1; 561e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (recover_block == ~0U) 562e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = currently_testing - got + 563e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocks_at_once; 564e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 565e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (currently_testing == recover_block) { 566e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall try = blocks_at_once; 567e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = ~0; 568879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 5693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 5713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 572849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag || v_flag) 5733ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 574879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 575f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 5763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 577879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 578879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 579879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 58083bfa27d3272631ef26f569471845c3755428134Theodore Ts'o uncapture_terminate(); 58183bfa27d3272631ef26f569471845c3755428134Theodore Ts'o 582879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 5833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 585acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic unsigned int test_rw (int dev, blk_t last_block, 586f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o int block_size, blk_t first_block, 587acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once) 5883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5891c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o unsigned char *buffer, *read_buffer; 590e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00}; 591e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int *pattern; 5921c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o int i, try, got, nr_pattern, pat_idx; 593879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 594e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_t recover_block = ~0; 5953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 59683bfa27d3272631ef26f569471845c3755428134Theodore Ts'o /* set up abend handler */ 59783bfa27d3272631ef26f569471845c3755428134Theodore Ts'o capture_terminate(NULL); 59883bfa27d3272631ef26f569471845c3755428134Theodore Ts'o 5991c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o buffer = allocate_buffer(2 * blocks_at_once * block_size); 6001c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_buffer = buffer + blocks_at_once * block_size; 601efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 6021c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (!buffer) { 603e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, ENOMEM, "%s", 604e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while allocating buffers")); 6053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6084d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 609a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 61019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 611efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fputs(_("Checking for bad blocks in read-write mode\n"), 612544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o stderr); 613d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("From block %lu to %lu\n"), 614efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (unsigned long) first_block, 615f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) last_block - 1); 61619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 617849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 618849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = t_patts; 619849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = t_flag; 620849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 621849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = patterns; 622849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 623849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 624849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 6251c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o pattern_fill(buffer, pattern[pat_idx], 6261c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blocks_at_once * block_size); 6278938ce64dca50d7d0f47f45fdc886de4f0939f0bTheodore Ts'o num_blocks = last_block - 1; 628f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 62919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 630f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 6311c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 6321c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 6331c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o while (currently_testing < last_block) { 634931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 635931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 636931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 637931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 638931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 639931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 6401c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (currently_testing + try > last_block) 6411c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = last_block - currently_testing; 6421c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = do_write(dev, buffer, try, block_size, 6431c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing); 64419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 64519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 6461c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 647e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got == 0 && try == 1) 648e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing++, WRITE_ERROR); 6491c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing += got; 650e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got != try) { 65165f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall try = 1; 652e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (recover_block == ~0U) 653e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = currently_testing - 654e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall got + blocks_at_once; 655e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 656e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (currently_testing == recover_block) { 657e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall try = blocks_at_once; 658e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = ~0; 6591c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 6603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 661efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 662f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 663f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 664f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 6653ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 6664d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 667f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 668544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Reading and comparing: "), stderr); 669cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 670f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 67119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 672f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 6731c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 6741c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = blocks_at_once; 6751c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o while (currently_testing < last_block) { 676931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 677931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 678931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 679931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 680931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 681931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 6821c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (currently_testing + try > last_block) 6831c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o try = last_block - currently_testing; 6841c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o got = do_read (dev, read_buffer, try, block_size, 6851c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o currently_testing); 686e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got == 0 && try == 1) 687e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing++, READ_ERROR); 688e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall currently_testing += got; 689e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got != try) { 690e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall try = 1; 691e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (recover_block == ~0U) 692e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = currently_testing - 693e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall got + blocks_at_once; 6941c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o continue; 695e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (currently_testing == recover_block) { 696e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall try = blocks_at_once; 697e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = ~0U; 6981c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o } 6991c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o for (i=0; i < got; i++) { 7001c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (memcmp(read_buffer + i * block_size, 7011c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o buffer + i * block_size, 7021c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o block_size)) 703e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing+i, CORRUPTION_ERROR); 704468d82f430dfdf270b738e14345b879560c2cd9eTheodore Ts'o } 70519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 70619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 7073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 708efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 709f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 710f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 711f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 7123ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 7134d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 7143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 715849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o uncapture_terminate(); 7166d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o free(buffer); 717879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 718879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 719879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 720d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostruct saved_blk_record { 721d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o blk_t block; 722d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num; 723d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o}; 724d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 725acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'ostatic unsigned int test_nd (int dev, blk_t last_block, 726f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o int block_size, blk_t first_block, 727acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once) 728879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 72948e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 7301c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o unsigned char *test_base, *save_base, *read_base; 731dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int try, i; 732e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int patterns[] = { ~0 }; 733e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o const unsigned int *pattern; 734849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o int nr_pattern, pat_idx; 735acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o int got, used2, written; 736acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o blk_t save_currently_testing; 737d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o struct saved_blk_record *test_record; 738a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o /* This is static to prevent being clobbered by the longjmp */ 739a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o static int num_saved; 740879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 741879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 742544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned long buf_used; 743544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o static unsigned int bb_count; 744e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int granularity = blocks_at_once; 745e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_t recover_block = ~0U; 746879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 747544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o bb_count = 0; 748879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 749879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 750e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, errcode, "%s", 751e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while beginning bad block list iteration")); 752879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 753879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 754879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 755879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 756f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o } while (next_bad && next_bad < first_block); 757879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 7581c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blkbuf = allocate_buffer(3 * blocks_at_once * block_size); 759e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall test_record = malloc(blocks_at_once * sizeof(struct saved_blk_record)); 760d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (!blkbuf || !test_record) { 761e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, ENOMEM, "%s", 762e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while allocating buffers")); 763879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 764879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 7651c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o 7661c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_base = blkbuf; 7671c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_base = blkbuf + (blocks_at_once * block_size); 7681c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_base = blkbuf + (2 * blocks_at_once * block_size); 769efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 770d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 771879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 7724d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 773879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 774544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr); 775efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), 776f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) first_block, 777f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o (unsigned long) last_block - 1); 778879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 779879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 780544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr); 781879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 7824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (setjmp(terminate_env)) { 7834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 7844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * Abnormal termination by a signal is handled here. 7854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 786a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o signal (SIGALRM, SIG_IGN); 787544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o fputs(_("\nInterrupt caught, cleaning up\n"), stderr); 788879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 7891c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 790d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o for (i=0; i < num_saved; i++) { 791d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o do_write(dev, save_ptr, test_record[i].num, 792d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o block_size, test_record[i].block); 793d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr += test_record[i].num * block_size; 794d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 795879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 796dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o exit(1); 797879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 798efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7994d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* set up abend handler */ 8004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o capture_terminate(terminate_env); 8014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 802849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag) { 803849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = t_patts; 804849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = t_flag; 805849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } else { 806849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o pattern = patterns; 807849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o nr_pattern = sizeof(patterns) / sizeof(patterns[0]); 808849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 809849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { 8101c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o pattern_fill(test_base, pattern[pat_idx], 8111c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o blocks_at_once * block_size); 8124d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 813849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used = 0; 814849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o bb_count = 0; 8151c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 8161c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 817f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o currently_testing = first_block; 8188938ce64dca50d7d0f47f45fdc886de4f0939f0bTheodore Ts'o num_blocks = last_block - 1; 819849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag && v_flag <= 1) 820849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o alarm_intr(SIGALRM); 8214d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 822849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o while (currently_testing < last_block) { 823931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (max_bb && bb_count >= max_bb) { 824931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop if (s_flag || v_flag) { 825931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop fputs(_("Too many bad blocks, aborting test\n"), stderr); 826931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 827931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 828931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop } 829e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall got = try = granularity - buf_used; 830849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (next_bad) { 831849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (currently_testing == next_bad) { 832849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 833849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 834849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing++; 835849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o goto check_for_more; 836849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 837849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o else if (currently_testing + try > next_bad) 838849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = next_bad - currently_testing; 839d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 840849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (currently_testing + try > last_block) 841849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = last_block - currently_testing; 842849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got = do_read (dev, save_ptr, try, block_size, 843849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing); 844849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got == 0) { 845e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (recover_block == ~0U) 846e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = currently_testing + 847e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocks_at_once; 848e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (granularity != 1) { 849e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall granularity = 1; 850e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 851e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 852849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* First block must have been bad. */ 853e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing++, READ_ERROR); 854849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o goto check_for_more; 8554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 8564d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 857849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 858849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * Note the fact that we've saved this much data 859849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * *before* we overwrite it with test data 860849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 861849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_record[num_saved].block = currently_testing; 862849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_record[num_saved].num = got; 863849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_saved++; 864849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 865849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* Write the test data */ 866849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o written = do_write (dev, test_ptr, got, block_size, 867849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing); 868849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (written != got) 869849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err (program_name, errno, 870849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("during test data write, block %lu"), 871efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (unsigned long) currently_testing + 872acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o written); 873849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 874849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used += got; 8754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 8764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 877849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing += got; 878e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (got != try) { 879e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall try = 1; 880e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (recover_block == ~0U) 881e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = currently_testing - 882e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall got + blocks_at_once; 883e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 884e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 885849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 886849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o check_for_more: 887849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 888849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * If there's room for more blocks to be tested this 889849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * around, and we're not done yet testing the disk, go 890849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * back and get some more blocks. 891849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 892e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((buf_used != granularity) && 893849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o (currently_testing < last_block)) 894849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o continue; 895849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 896e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (currently_testing >= recover_block) { 897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall granularity = blocks_at_once; 898e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall recover_block = ~0; 899e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 900e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 901849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 902849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o save_currently_testing = currently_testing; 903849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 904849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* 905849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * for each contiguous block that we read into the 906849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * buffer (and wrote test data into afterwards), read 907849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it back (looping if necessary, to get past newly 908849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * discovered unreadable blocks, of which there should 909849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * be none, but with a hard drive which is unreliable, 910849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it has happened), and compare with the test data 911849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * that was written; output to the bad block list if 912849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o * it doesn't match. 913849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o */ 914849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o used2 = 0; 9151c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 9161c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 9171c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o read_ptr = read_base; 918849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = 0; 919849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 920849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o while (1) { 921849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (try == 0) { 922849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (used2 >= num_saved) 923849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 924849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = test_record[used2].block; 925849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try = test_record[used2].num; 926849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o used2++; 927849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 928efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 929849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got = do_read (dev, read_ptr, try, 930849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o block_size, currently_testing); 931849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 932849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* test the comparison between all the 933849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o blocks successfully read */ 934849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o for (i = 0; i < got; ++i) 935849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (memcmp (test_ptr+i*block_size, 936849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o read_ptr+i*block_size, block_size)) 937e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR); 938849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (got < try) { 939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count += bb_output(currently_testing + got, READ_ERROR); 940849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o got++; 941849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 942efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 9431c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o /* write back original data */ 9441c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o do_write (dev, save_ptr, got, 9451c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o block_size, currently_testing); 9461c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr += got * block_size; 947849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 948849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing += got; 949849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o test_ptr += got * block_size; 950849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o read_ptr += got * block_size; 951849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o try -= got; 952849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 953849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 954849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o /* empty the buffer so it can be reused */ 955849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_saved = 0; 956849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o buf_used = 0; 9571c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o save_ptr = save_base; 9581c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o test_ptr = test_base; 959849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o currently_testing = save_currently_testing; 9604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 961849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o num_blocks = 0; 962849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o alarm(0); 963849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (s_flag || v_flag > 1) 9643ef681c5dbaccd2d905026b964c580f2ce3466caTheodore Ts'o fputs(_(done_string), stderr); 9654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 966849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o flush_bufs(); 9674d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 9684d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o uncapture_terminate(); 969dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o fflush(stderr); 970dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o free(blkbuf); 971d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o free(test_record); 972879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 973879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 974879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 975879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 9763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 9773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 978981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void check_mount(char *device_name) 979981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o{ 980981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o errcode_t retval; 981981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o int mount_flags; 982981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 983981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o retval = ext2fs_check_if_mounted(device_name, &mount_flags); 984981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (retval) { 985981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o com_err("ext2fs_check_if_mount", retval, 986981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o _("while determining whether %s is mounted."), 987981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o device_name); 988981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 989981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 9902fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (mount_flags & EXT2_MF_MOUNTED) { 9912fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fprintf(stderr, _("%s is mounted; "), device_name); 9922fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (force) { 9932fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("badblocks forced anyway. " 9942fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o "Hope /etc/mtab is incorrect.\n"), stderr); 9952fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o return; 9962fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o } 9972fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o abort_badblocks: 9982fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("it's not safe to run badblocks!\n"), stderr); 9992fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o exit(1); 10002fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o } 1001981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 1002f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) { 10032fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fprintf(stderr, _("%s is apparently in use by the system; "), 10042fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o device_name); 10052fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o if (force) 10062fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o fputs(_("badblocks forced anyway.\n"), stderr); 10072fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o else 10082fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o goto abort_badblocks; 1009981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 10102fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o 1011981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o} 1012981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 1013d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o/* 1014d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o * This function will convert a string to an unsigned long, printing 1015d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o * an error message if it fails, and returning success or failure in err. 1016d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o */ 1017d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'ostatic unsigned int parse_uint(const char *str, const char *descr) 1018d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o{ 1019d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o char *tmp; 1020d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o unsigned long ret; 1021efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1022eb594251b6d1a06d2acbb281b3816c017d7066ebIustin Pop errno = 0; 1023d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o ret = strtoul(str, &tmp, 0); 1024d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o if (*tmp || errno || (ret > UINT_MAX) || 1025d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o (ret == ULONG_MAX && errno == ERANGE)) { 1026d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o com_err (program_name, 0, _("invalid %s - %s"), descr, str); 1027d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o exit (1); 1028d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o } 1029d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o return ret; 1030d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o} 1031981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 103200e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 10333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1034519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 10353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 1036879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 1037879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 10383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 1039879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 1040dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size = 1024; 1041acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int blocks_at_once = 64; 1042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t last_block, first_block; 1043879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 1044879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 10453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 1046879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 1047e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o unsigned int pattern; 1048acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int (*test_func)(int, blk_t, 1049acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o int, blk_t, 1050acd77415a9c0d6279f4effee2a5e59ededc7b2d2Theodore Ts'o unsigned int); 105122301afb01f3059a2b1baf68abff26aaf6db7c9eTheodore Ts'o int open_flag; 10521c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o long sysval; 1053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t inblk; 10543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 10553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 10563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 1057d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS 1058d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o setlocale(LC_MESSAGES, ""); 105914308a5398984842e808faa3ff2dd6a1c52d90bdTheodore Ts'o setlocale(LC_CTYPE, ""); 1060d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 1061d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o textdomain(NLS_CAT_NAME); 1062e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall set_com_err_gettext(gettext); 1063d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif 10646d40f568cdec7d654691e6eed61cf5a32e918c03Theodore Ts'o srandom((unsigned int)time(NULL)); /* simple randomness is enough */ 10654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_ro; 10664d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o 10671c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o /* Determine the system page size if possible */ 10681c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef HAVE_SYSCONF 10691c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) 10701c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#define _SC_PAGESIZE _SC_PAGE_SIZE 10711c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif 10721c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#ifdef _SC_PAGESIZE 10731c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o sysval = sysconf(_SC_PAGESIZE); 10741c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o if (sysval > 0) 10751c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o sys_page_size = sysval; 10761c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* _SC_PAGESIZE */ 10771c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o#endif /* HAVE_SYSCONF */ 1078efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 10793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 10803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 1081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((c = getopt (argc, argv, "b:d:e:fi:o:svwnc:p:h:t:BX")) != EOF) { 10823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 10833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 1084d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o block_size = parse_uint(optarg, "block size"); 10853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 1086981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o case 'f': 1087981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o force++; 1088981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o break; 1089879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 1090879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 1091879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 10923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 10933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 10943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 10953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 10963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 10973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 10983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 109919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 11003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 11013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 11024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 1103d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o exclusive_usage(); 11044d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_rw; 11054d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o w_flag = 1; 1106879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1107879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 11084d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 1109d8b5f777438445407f7cd408bd5fe301e4687271Theodore Ts'o exclusive_usage(); 11104d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_nd; 1111879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 1112879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1113879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 1114d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o blocks_at_once = parse_uint(optarg, "blocks at once"); 1115879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1116931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop case 'e': 1117931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop max_bb = parse_uint(optarg, "max bad block count"); 1118931b0289eee5d83bff7e80c7420bda0a5bb078daIustin Pop break; 1119264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop case 'd': 1120264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop d_flag = parse_uint(optarg, "read delay factor"); 1121264f64a5a8bb7225ab8513de6f1c6ac9e7448790Iustin Pop break; 1122879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 1123efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o num_passes = parse_uint(optarg, 1124d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o "number of clean passes"); 1125879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1126879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 1127879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 11283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 1129849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o case 't': 1130849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag + 1 > t_max) { 1131e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o unsigned int *t_patts_new; 1132849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o 1133efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o t_patts_new = realloc(t_patts, sizeof(int) * 113469d813520cf14f5700c38c82b5c147aa3756bbd9Theodore Ts'o (t_max + T_INC)); 1135849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!t_patts_new) { 1136849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o com_err(program_name, ENOMEM, 1137849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o _("can't allocate memory for " 1138849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o "test_pattern - %s"), 1139849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o optarg); 1140849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 1141849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1142849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_patts = t_patts_new; 1143849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o t_max += T_INC; 1144849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 114584c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) { 114684c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o t_patts[t_flag++] = ~0; 114784c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o } else { 1148d4be9fad6eb65752a623521f9b66b5c30831a3a1Theodore Ts'o pattern = parse_uint(optarg, "test pattern"); 1149e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o if (pattern == (unsigned int) ~0) 115084c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o pattern = 0xffff; 115184c054577fcc08cee6683fb1c8905711c5b985f3Theodore Ts'o t_patts[t_flag++] = pattern; 1152849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1153849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o break; 1154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case 'B': 1155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall use_buffered_io = 1; 1156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1157f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o case 'X': 1158f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o exclusive_ok++; 1159f63978aff759325b542de7134ab659c79dc47496Theodore Ts'o break; 11603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 1161818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 11623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 11633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1164849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (!w_flag) { 1165849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o if (t_flag > 1) { 1166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, 0, "%s", 1167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("Maximum of one test_pattern may be " 1168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "specified in read-only mode")); 1169849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 1170849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1171e9860ae966c71bca8af8013c7d3148b171c8491fTheodore Ts'o if (t_patts && (t_patts[0] == (unsigned int) ~0)) { 1172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, 0, "%s", 1173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("Random test_pattern is not allowed " 1174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "in read-only mode")); 1175849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o exit(1); 1176849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 1177849b6bc8ec0d4959913ea6f412ac5b6e9939e9ffTheodore Ts'o } 11783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 1179818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 11803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 118135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind > argc - 1) { 1182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = ext2fs_get_device_size2(device_name, 118335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o block_size, 1184cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o &last_block); 118535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode == EXT2_ET_UNIMPLEMENTED) { 1186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, 0, "%s", 118735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("Couldn't determine device size; you " 118835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o "must specify\nthe size manually\n")); 118935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 119035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 119135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode) { 1192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, errcode, "%s", 119335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("while trying to determine device size")); 119435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 119535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 119635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } else { 11975267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o errno = 0; 1198f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o last_block = parse_uint(argv[optind], _("last block")); 11995267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o last_block++; 120035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o optind++; 12013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 120235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind <= argc-1) { 12035267a520bb7887b146f05ffa8726664afbb6c3c2Theodore Ts'o errno = 0; 1204f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o first_block = parse_uint(argv[optind], _("first block")); 1205f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o } else first_block = 0; 1206f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o if (first_block >= last_block) { 1207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err (program_name, 0, _("invalid starting block (%llu): must be less than %llu"), 1208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall first_block, last_block); 1209f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 1210f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* ext2 badblocks file can't handle large values */ 1212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (last_block >> 32) { 1213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, EOVERFLOW, 1214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("invalid end block (%llu): must be 32-bit value"), 1215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall last_block); 1216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit(1); 1217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1218981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (w_flag) 1219981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o check_mount(device_name); 1220efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 122142e572b5b6aa71a567219265686c90eabff3fc31Theodore Ts'o gettimeofday(&time_start, 0); 122222301afb01f3059a2b1baf68abff26aaf6db7c9eTheodore Ts'o open_flag = O_LARGEFILE | (w_flag ? O_RDWR : O_RDONLY); 12231c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o dev = open (device_name, open_flag); 12245493a27dc1138d2e30193b80217a0127d247af1eTheodore Ts'o if (dev == -1) { 1225d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("while trying to open %s"), 12263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 12273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 12283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1229879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 12301c29b0979a7100a4fd254c006997a08b3bdd72dfTheodore Ts'o host_dev = open (host_device_name, open_flag); 12315493a27dc1138d2e30193b80217a0127d247af1eTheodore Ts'o if (host_dev == -1) { 1232d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1233d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1234d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o host_device_name); 1235879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1236879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1237879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 1238879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 12393e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o if (input_file) { 1240879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 1241879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 1242879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 1243879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 1244879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 1245879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 1246d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1247d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1248879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 1249879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1250879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1251879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 12523e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o } 12533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 12543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 12553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 12563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 12573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 1258d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 1259d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 1260879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 12613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 12623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 12633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 12643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 12653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 1266879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1267879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 1268879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 1269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, errcode, "%s", 1270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while creating in-memory bad blocks list")); 1271879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1272879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1273879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1274879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 1275879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 1276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall switch (fscanf(in, "%llu\n", &inblk)) { 1277879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 1278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, 0, "%s", 1279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("input file - bad format")); 1280879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1281879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 1282879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1283879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 1284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (inblk >> 32) { 1285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, 1286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EOVERFLOW, "%s", 1287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while adding to in-memory " 1288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "bad block list")); 1289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit(1); 1290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall next_bad = inblk; 1292879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 1293879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 1294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(program_name, errcode, 1295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%s", 1296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("while adding to in-memory " 1297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "bad block list")); 1298879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 1299879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1300879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 1301879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1302879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 1303879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1304879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1305879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 1306879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 1307879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 1308879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1309879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 1310879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 1311879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1312cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o bb_count = test_func(dev, last_block, block_size, 1313f56f32b0a505e34712c8b8fb908dffb616743726Theodore Ts'o first_block, blocks_at_once); 13144d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (bb_count) 13154d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o passes_clean = 0; 13164d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else 13174d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ++passes_clean; 1318efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1319879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 1320d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 1321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall _("Pass completed, %u bad blocks found. (%d/%d/%d errors)\n"), 1322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bb_count, num_read_errors, num_write_errors, num_corruption_errors); 1323879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1324879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 1325879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 13263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 13273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 13283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 132945e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(t_patts); 1330879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 13313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1332