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++; } } }
/* * This routine reports a new bad block. If the bad block has already * been seen before, then it returns 0; otherwise it returns 1. */ static int bb_output (blk_t bad, enum error_types error_type) { errcode_t errcode; if (ext2fs_badblocks_list_test(bb_list, bad)) return 0; fprintf(out, "%lu\n", (unsigned long) bad); fflush(out); errcode = ext2fs_badblocks_list_add (bb_list, bad); if (errcode) { com_err (program_name, errcode, "adding to in-memory bad block list"); exit (1); } /* kludge: increment the iteration through the bb_list if an element was just added before the current iteration position. This should not cause next_bad to change. */ if (bb_iter && bad < next_bad) ext2fs_badblocks_list_iterate (bb_iter, &next_bad); if (error_type == READ_ERROR) { num_read_errors++; } else if (error_type == WRITE_ERROR) { num_write_errors++; } else if (error_type == CORRUPTION_ERROR) { num_corruption_errors++; } return 1; }
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt, blk_t ref_block EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), void *priv_data) { struct set_badblock_record *rec = (struct set_badblock_record *) priv_data; errcode_t retval; blk_t blk; if (blockcnt >= 0) { /* * Get the next bad block. */ if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk)) return BLOCK_ABORT; rec->bad_block_count++; } else { /* * An indirect block; fetch a block from the * previously used indirect block list. The block * most be not marked as used; if so, get another one. * If we run out of reserved indirect blocks, allocate * a new one. */ retry: if (rec->ind_blocks_ptr < rec->ind_blocks_size) { blk = rec->ind_blocks[rec->ind_blocks_ptr++]; if (ext2fs_test_block_bitmap(fs->block_map, blk)) goto retry; } else { retval = ext2fs_new_block(fs, 0, 0, &blk); if (retval) { rec->err = retval; return BLOCK_ABORT; } } retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf); if (retval) { rec->err = retval; return BLOCK_ABORT; } } /* * Update block counts */ ext2fs_block_alloc_stats(fs, blk, +1); *block_nr = blk; return BLOCK_CHANGED; }
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; }
/* * This routine reports a new bad block. If the bad block has already * been seen before, then it returns 0; otherwise it returns 1. */ static int bb_output (unsigned long bad) { errcode_t errcode; if (ext2fs_badblocks_list_test(bb_list, bad)) return 0; fprintf (out, "%lu\n", bad); errcode = ext2fs_badblocks_list_add (bb_list, bad); if (errcode) { com_err (program_name, errcode, "adding to in-memory bad block list"); exit (1); } /* kludge: increment the iteration through the bb_list if an element was just added before the current iteration position. This should not cause next_bad to change. */ if (bb_iter && bad < next_bad) ext2fs_badblocks_list_iterate (bb_iter, &next_bad); return 1; }
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); }
int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk) { return ext2fs_badblocks_list_iterate(iter, blk); }