badblocks.c revision 50e1e10fa0ac12a3e2a9d20a75ee9041873cda96
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 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ovoid read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file, 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int replace_bad_blocks) 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list bb_list = 0; 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o FILE *f; 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o read_bitmaps(fs); 34f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 35f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * Make sure the bad block inode is sane. If there are any 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * illegal blocks, clear them. 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o check_bb_inode_blocks, 0); 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 42f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ext2fs_block_iterate", retval, 43f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while sanity checking the bad blocks inode"); 44f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fatal_error(0); 45f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 46f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If we're appending to the bad blocks inode, read in the 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * current bad blocks. 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!replace_bad_blocks) { 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_inode(fs, &bb_list); 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_read_bb_inode", retval, 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while reading the bad blocks inode"); 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Now read in the bad blocks from the file. 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o f = fopen(bad_blocks_file, "r"); 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!f) { 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("read_bad_blocks_file", errno, 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while trying to open %s", bad_blocks_file); 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (f); 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_read_bb_FILE", retval, 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while reading in list of bad blocks from file"); 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Finally, update the bad blocks from the bad_block_map 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_update_bb_inode(fs, bb_list); 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_update_bb_inode", retval, 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while updating bad block inode"); 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list_free(bb_list); 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 92f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 93f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o void *private) 94f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 95f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!*block_nr) 96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 97f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 98f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 99f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * If the block number is outrageous, clear it and ignore it. 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (*block_nr >= fs->super->s_blocks_count || 102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *block_nr < fs->super->s_first_data_block) { 10350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o printf("Warning illegal block %u found in bad block inode. Cleared.\n", *block_nr); 104f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *block_nr = 0; 105f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return BLOCK_CHANGED; 106f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 107f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 108f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 109f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ovoid test_disk(ext2_filsys fs) 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list bb_list = 0; 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o FILE *f; 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char buf[1024]; 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o read_bitmaps(fs); 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Always read in the current list of bad blocks. 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_inode(fs, &bb_list); 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_read_bb_inode", retval, 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while reading the bad blocks inode"); 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Now run the bad blocks program 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 13350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o sprintf(buf, "badblocks %s%s %d", preen ? "" : "-s ", 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->device_name, 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->super->s_blocks_count); 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (verbose) 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o printf("Running command: %s\n", buf); 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o f = popen(buf, "r"); 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!f) { 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("popen", errno, 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while trying to run %s", buf); 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); 1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (f); 1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_read_bb_FILE", retval, 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while processing list of bad blocks from program"); 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Finally, update the bad blocks from the bad_block_map 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_update_bb_inode(fs, bb_list); 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("ext2fs_update_bb_inode", retval, 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while updating bad block inode"); 1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fatal_error(0); 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list_free(bb_list); 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 166