badblocks.c revision f8188fff23dc2d9c9f858fb21264e46b17672825
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c --- replace/append bad blocks to the bad block inode 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * redistributed under the terms of the GNU Public License. 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 83839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H 1050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 1150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <et/com_err.h> 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 16f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 17f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o void *private); 18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 19f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void invalid_block(ext2_filsys fs, blk_t blk) 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o printf("Bad block %u out of range; ignored.\n", blk); 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ovoid read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int replace_bad_blocks) 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list bb_list = 0; 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o FILE *f; 3374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o char buf[1024]; 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 35f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * Make sure the bad block inode is sane. If there are any 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * illegal blocks, clear them. 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, 42f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o check_bb_inode_blocks, 0); 43f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 44f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ext2fs_block_iterate", retval, 45f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while sanity checking the bad blocks inode"); 46f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 47f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If we're appending to the bad blocks inode, read in the 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * current bad blocks. 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!replace_bad_blocks) { 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_inode(fs, &bb_list); 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_read_bb_inode", retval, 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while reading the bad blocks inode"); 58f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 6374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o * Now read in the bad blocks from the file; if 6474becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o * bad_blocks_file is null, then try to run the badblocks 6574becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o * command. 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 6774becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (bad_blocks_file) { 6874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o f = fopen(bad_blocks_file, "r"); 6974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (!f) { 7074becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o com_err("read_bad_blocks_file", errno, 7174becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o "while trying to open %s", bad_blocks_file); 72f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 7374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o } 7474becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o } else { 75f635d7f65bd002984ce9a202d491d4f187b996b2Theodore Ts'o sprintf(buf, "badblocks -b %d %s%s %d", fs->blocksize, 761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (ctx->options & E2F_OPT_PREEN) ? "" : "-s ", 771b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fs->device_name, fs->super->s_blocks_count); 7874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o f = popen(buf, "r"); 7974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (!f) { 8074becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o com_err("read_bad_blocks_file", errno, 8174becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o "while trying popen '%s'", buf); 82f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 8374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o } 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); 8674becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (bad_blocks_file) 8774becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o fclose(f); 8874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o else 8974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o pclose(f); 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_read_bb_FILE", retval, 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while reading in list of bad blocks from file"); 93f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Finally, update the bad blocks from the bad_block_map 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_update_bb_inode(fs, bb_list); 1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_update_bb_inode", retval, 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while updating bad block inode"); 103f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list_free(bb_list); 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 108f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 109f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'ofatal: 110f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 111f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o return; 112f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ovoid test_disk(e2fsck_t ctx) 11674becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o{ 1171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o read_bad_blocks_file(ctx, 0, 1); 11874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o} 11974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o 120f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 121f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o void *private) 122f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 123f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!*block_nr) 124f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 125f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 126f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 127f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * If the block number is outrageous, clear it and ignore it. 128f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 129f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (*block_nr >= fs->super->s_blocks_count || 130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *block_nr < fs->super->s_first_data_block) { 13150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o printf("Warning illegal block %u found in bad block inode. Cleared.\n", *block_nr); 132f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *block_nr = 0; 133f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return BLOCK_CHANGED; 134f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 135f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 136f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 138f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 139