badblocks.c revision cbbf031b6edf9bdf5511af2193e44cff7fdaa66a
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, 1754dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data); 18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 19f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void invalid_block(ext2_filsys fs, blk_t blk) 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 220c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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, 450c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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, 570c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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, 710c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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, 810c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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, 920c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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, 1020c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while updating bad block inode")); 103f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 106cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o ext2fs_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{ 1171fad9048b51f66df8813022f33a48fbf7a0a26b7Theodore Ts'o read_bad_blocks_file(ctx, 0, 0); 11874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o} 11974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o 120f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 12154dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 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) { 1310c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore 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