void do_zeroi(int argc, char *argv[]) { if (check_fs_open(argv[0])) return; printf("Clearing inode bitmap.\n"); ext2fs_clear_inode_bitmap(test_fs->inode_map); }
/* * This subroutine is responsible for making sure that a particular * directory is connected to the root; if it isn't we trace it up as * far as we can go, and then offer to connect the resulting parent to * the lost+found. We have to do loop detection; if we ever discover * a loop, we treat that as a disconnected directory and offer to * reparent it to lost+found. * * However, loop detection is expensive, because for very large * filesystems, the inode_loop_detect bitmap is huge, and clearing it * is non-trivial. Loops in filesystems are also a rare error case, * and we shouldn't optimize for error cases. So we try two passes of * the algorithm. The first time, we ignore loop detection and merely * increment a counter; if the counter exceeds some extreme threshold, * then we try again with the loop detection bitmap enabled. */ static int check_directory(e2fsck_t ctx, ext2_ino_t dir, struct problem_context *pctx) { ext2_filsys fs = ctx->fs; ext2_ino_t ino = dir, parent; int loop_pass = 0, parent_count = 0; while (1) { /* * Mark this inode as being "done"; by the time we * return from this function, the inode we either be * verified as being connected to the directory tree, * or we will have offered to reconnect this to * lost+found. * * If it was marked done already, then we've reached a * parent we've already checked. */ if (ext2fs_mark_inode_bitmap2(inode_done_map, ino)) break; if (e2fsck_dir_info_get_parent(ctx, ino, &parent)) { fix_problem(ctx, PR_3_NO_DIRINFO, pctx); return 0; } /* * If this directory doesn't have a parent, or we've * seen the parent once already, then offer to * reparent it to lost+found */ if (!parent || (loop_pass && (ext2fs_test_inode_bitmap2(inode_loop_detect, parent)))) { pctx->ino = ino; if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) { if (e2fsck_reconnect_file(ctx, pctx->ino)) ext2fs_unmark_valid(fs); else { fix_dotdot(ctx, pctx->ino, ctx->lost_and_found); parent = ctx->lost_and_found; } } break; } ino = parent; if (loop_pass) { ext2fs_mark_inode_bitmap2(inode_loop_detect, ino); } else if (parent_count++ > 2048) { /* * If we've run into a path depth that's * greater than 2048, try again with the inode * loop bitmap turned on and start from the * top. */ loop_pass = 1; if (inode_loop_detect) ext2fs_clear_inode_bitmap(inode_loop_detect); else { pctx->errcode = e2fsck_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), EXT2FS_BMAP64_AUTODIR, "inode_loop_detect", &inode_loop_detect); if (pctx->errcode) { pctx->num = 1; fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, pctx); ctx->flags |= E2F_FLAG_ABORT; return -1; } } ino = dir; } } /* * Make sure that .. and the parent directory are the same; * offer to fix it if not. */ pctx->ino = dir; if (e2fsck_dir_info_get_dotdot(ctx, dir, &pctx->ino2) || e2fsck_dir_info_get_parent(ctx, dir, &pctx->dir)) { fix_problem(ctx, PR_3_NO_DIRINFO, pctx); return 0; } if (pctx->ino2 != pctx->dir) { if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx)) fix_dotdot(ctx, dir, pctx->dir); } return 0; }