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);
}
Exemple #2
0
/*
 * 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;
}