void e2fsck_rehash_directories(e2fsck_t ctx) { struct problem_context pctx; #ifdef RESOURCE_TRACK struct resource_track rtrack; #endif struct dir_info *dir; ext2_u32_iterate iter; struct dir_info_iter * dirinfo_iter = 0; ext2_ino_t ino; errcode_t retval; int cur, max, all_dirs, first = 1; init_resource_track(&rtrack, ctx->fs->io); all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS; if (!ctx->dirs_to_hash && !all_dirs) return; (void) e2fsck_get_lost_and_found(ctx, 0); clear_problem_context(&pctx); cur = 0; if (all_dirs) { dirinfo_iter = e2fsck_dir_info_iter_begin(ctx); max = e2fsck_get_num_dirinfo(ctx); } else { retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash, &iter); if (retval) { pctx.errcode = retval; fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx); return; } max = ext2fs_u32_list_count(ctx->dirs_to_hash); } while (1) { if (all_dirs) { if ((dir = e2fsck_dir_info_iter(ctx, dirinfo_iter)) == 0) break; ino = dir->ino; } else { if (!ext2fs_u32_list_iterate(iter, &ino)) break; } pctx.dir = ino; if (first) { fix_problem(ctx, PR_3A_PASS_HEADER, &pctx); first = 0; } #if 0 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx); #endif pctx.errcode = e2fsck_rehash_dir(ctx, ino, &pctx); if (pctx.errcode) { end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR); fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx); } if (ctx->progress && !ctx->progress_fd) e2fsck_simple_progress(ctx, "Rebuilding directory", 100.0 * (float) (++cur) / (float) max, ino); } end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR); if (all_dirs) e2fsck_dir_info_iter_end(ctx, dirinfo_iter); else ext2fs_u32_list_iterate_end(iter); if (ctx->dirs_to_hash) ext2fs_u32_list_free(ctx->dirs_to_hash); ctx->dirs_to_hash = 0; print_resource_track(ctx, "Pass 3A", &rtrack, ctx->fs->io); }
void e2fsck_pass3(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; struct dir_info_iter *iter; #ifdef RESOURCE_TRACK struct resource_track rtrack; #endif struct problem_context pctx; struct dir_info *dir; unsigned long maxdirs, count; init_resource_track(&rtrack, ctx->fs->io); clear_problem_context(&pctx); #ifdef MTRACE mtrace_print("Pass 3"); #endif if (!(ctx->options & E2F_OPT_PREEN)) fix_problem(ctx, PR_3_PASS_HEADER, &pctx); /* * Allocate some bitmaps to do loop detection. */ pctx.errcode = e2fsck_allocate_inode_bitmap(fs, _("inode done bitmap"), EXT2FS_BMAP64_AUTODIR, "inode_done_map", &inode_done_map); if (pctx.errcode) { pctx.num = 2; fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); ctx->flags |= E2F_FLAG_ABORT; goto abort_exit; } print_resource_track(ctx, _("Peak memory"), &ctx->global_rtrack, NULL); check_root(ctx); if (ctx->flags & E2F_FLAG_SIGNAL_MASK) goto abort_exit; ext2fs_mark_inode_bitmap2(inode_done_map, EXT2_ROOT_INO); maxdirs = e2fsck_get_num_dirinfo(ctx); count = 1; if (ctx->progress) if ((ctx->progress)(ctx, 3, 0, maxdirs)) goto abort_exit; iter = e2fsck_dir_info_iter_begin(ctx); while ((dir = e2fsck_dir_info_iter(ctx, iter)) != 0) { if (ctx->flags & E2F_FLAG_SIGNAL_MASK) goto abort_exit; if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs)) goto abort_exit; if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dir->ino)) if (check_directory(ctx, dir->ino, &pctx)) goto abort_exit; } e2fsck_dir_info_iter_end(ctx, iter); /* * Force the creation of /lost+found if not present */ if ((ctx->flags & E2F_OPT_READONLY) == 0) e2fsck_get_lost_and_found(ctx, 1); /* * If there are any directories that need to be indexed or * optimized, do it here. */ e2fsck_rehash_directories(ctx); abort_exit: e2fsck_free_dir_info(ctx); if (inode_loop_detect) { ext2fs_free_inode_bitmap(inode_loop_detect); inode_loop_detect = 0; } if (inode_done_map) { ext2fs_free_inode_bitmap(inode_done_map); inode_done_map = 0; } print_resource_track(ctx, _("Pass 3"), &rtrack, ctx->fs->io); }