static void list_bad_blocks(ext2_filsys fs, int dump) { badblocks_list bb_list = 0; badblocks_iterate bb_iter; blk_t blk; errcode_t retval; const char *header, *fmt; retval = ext2fs_read_bb_inode(fs, &bb_list); if (retval) { com_err("ext2fs_read_bb_inode", retval, 0); return; } retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); if (retval) { com_err("ext2fs_badblocks_list_iterate_begin", retval, "%s", _("while printing bad block list")); return; } if (dump) { header = fmt = "%u\n"; } else { header = _("Bad blocks: %u"); fmt = ", %u"; } while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { printf(header ? header : fmt, blk); header = 0; } ext2fs_badblocks_list_iterate_end(bb_iter); if (!dump) fputc('\n', stdout); ext2fs_badblocks_list_free(bb_list); }
static void print_list(badblocks_list bb, int verify) { errcode_t retval; badblocks_iterate iter; blk_t blk; int i, ok; retval = ext2fs_badblocks_list_iterate_begin(bb, &iter); if (retval) { com_err("print_list", retval, "while setting up iterator"); return; } ok = i = 1; while (ext2fs_badblocks_list_iterate(iter, &blk)) { printf("%d ", blk); if (i++ != blk) ok = 0; } ext2fs_badblocks_list_iterate_end(iter); if (verify) { if (ok) printf("--- OK"); else { printf("--- NOT OK"); test_fail++; } } }
errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, unsigned int flags EXT2FS_ATTR((unused)), FILE *f) { badblocks_iterate bb_iter; blk_t blk; errcode_t retval; retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); if (retval) return retval; while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { fprintf(f, "%u\n", blk); } ext2fs_badblocks_list_iterate_end(bb_iter); return 0; }
/* * Given a bad blocks bitmap, update the bad blocks inode to reflect * the map. */ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) { errcode_t retval; struct set_badblock_record rec; struct ext2_inode inode; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (!fs->block_map) return EXT2_ET_NO_BLOCK_BITMAP; rec.bad_block_count = 0; rec.ind_blocks_size = rec.ind_blocks_ptr = 0; rec.max_ind_blocks = 10; retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t), &rec.ind_blocks); if (retval) return retval; memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); if (retval) goto cleanup; memset(rec.block_buf, 0, fs->blocksize); rec.err = 0; /* * First clear the old bad blocks (while saving the indirect blocks) */ retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_DEPTH_TRAVERSE, 0, clear_bad_block_proc, &rec); if (retval) goto cleanup; if (rec.err) { retval = rec.err; goto cleanup; } /* * Now set the bad blocks! * * First, mark the bad blocks as used. This prevents a bad * block from being used as an indirecto block for the bad * block inode (!). */ if (bb_list) { retval = ext2fs_badblocks_list_iterate_begin(bb_list, &rec.bb_iter); if (retval) goto cleanup; retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_APPEND, 0, set_bad_block_proc, &rec); ext2fs_badblocks_list_iterate_end(rec.bb_iter); if (retval) goto cleanup; if (rec.err) { retval = rec.err; goto cleanup; } } /* * Update the bad block inode's mod time and block count * field. */ retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); if (retval) goto cleanup; inode.i_atime = inode.i_mtime = time(NULL); if (!inode.i_ctime) inode.i_ctime = time(NULL); inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512); inode.i_size = rec.bad_block_count * fs->blocksize; retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode); if (retval) goto cleanup; cleanup: ext2fs_free_mem(&rec.ind_blocks); ext2fs_free_mem(&rec.block_buf); return retval; }
static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list) { dgrp_t i; blk_t j; unsigned must_be_good; blk_t blk; badblocks_iterate bb_iter; errcode_t retval; blk_t group_block; int group; int group_bad; if (!bb_list) return; /* * The primary superblock and group descriptors *must* be * good; if not, abort. */ must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks; for (i = fs->super->s_first_data_block; i <= must_be_good; i++) { if (ext2fs_badblocks_list_test(bb_list, i)) { fprintf(stderr, _("Block %d in primary " "superblock/group descriptor area bad.\n"), i); fprintf(stderr, _("Blocks %u through %d must be good " "in order to build a filesystem.\n"), fs->super->s_first_data_block, must_be_good); fputs(_("Aborting....\n"), stderr); exit(1); } } /* * See if any of the bad blocks are showing up in the backup * superblocks and/or group descriptors. If so, issue a * warning and adjust the block counts appropriately. */ group_block = fs->super->s_first_data_block + fs->super->s_blocks_per_group; for (i = 1; i < fs->group_desc_count; i++) { group_bad = 0; for (j=0; j < fs->desc_blocks+1; j++) { if (ext2fs_badblocks_list_test(bb_list, group_block + j)) { if (!group_bad) fprintf(stderr, _("Warning: the backup superblock/group descriptors at block %u contain\n" " bad blocks.\n\n"), group_block); group_bad++; group = ext2fs_group_of_blk(fs, group_block+j); fs->group_desc[group].bg_free_blocks_count++; fs->super->s_free_blocks_count++; } } group_block += fs->super->s_blocks_per_group; } /* * Mark all the bad blocks as used... */ retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); if (retval) { com_err("ext2fs_badblocks_list_iterate_begin", retval, _("while marking bad blocks as used")); exit(1); } while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) ext2fs_mark_block_bitmap(fs->block_map, blk); ext2fs_badblocks_list_iterate_end(bb_iter); }
errcode_t badblocks_list_iterate_begin(badblocks_list bb, badblocks_iterate *ret) { return ext2fs_badblocks_list_iterate_begin(bb, ret); }