Esempio n. 1
0
/*
 * This fuction deallocates an inode
 */
static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
{
	ext2_filsys fs = ctx->fs;
	struct ext2_inode	inode;
	struct problem_context	pctx;
	__u32			count;
	struct del_block	del_block;

	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
	e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
	clear_problem_context(&pctx);
	pctx.ino = ino;

	/*
	 * Fix up the bitmaps...
	 */
	e2fsck_read_bitmaps(ctx);
	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));

	if (ext2fs_file_acl_block(fs, &inode) &&
	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
		pctx.errcode = ext2fs_adjust_ea_refcount3(fs,
				ext2fs_file_acl_block(fs, &inode),
				block_buf, -1, &count, ino);
		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
			pctx.errcode = 0;
			count = 1;
		}
		if (pctx.errcode) {
			pctx.blk = ext2fs_file_acl_block(fs, &inode);
			fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
			ctx->flags |= E2F_FLAG_ABORT;
			return;
		}
		if (count == 0) {
			ext2fs_unmark_block_bitmap2(ctx->block_found_map,
					ext2fs_file_acl_block(fs, &inode));
			ext2fs_block_alloc_stats2(fs,
				  ext2fs_file_acl_block(fs, &inode), -1);
		}
		ext2fs_file_acl_block_set(fs, &inode, 0);
	}

	if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
		return;

	if (LINUX_S_ISREG(inode.i_mode) && EXT2_I_SIZE(&inode) >= 0x80000000UL)
		ctx->large_files--;

	del_block.ctx = ctx;
	del_block.num = 0;
	pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
					     deallocate_inode_block,
					     &del_block);
	if (pctx.errcode) {
		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
		ctx->flags |= E2F_FLAG_ABORT;
		return;
	}
}
Esempio n. 2
0
/*
 * Helper function which writes out a directory block.
 */
static int write_dir_block(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 write_dir_struct	*wd = (struct write_dir_struct *) priv_data;
	blk_t	blk;
	char	*dir;

	if (*block_nr == 0)
		return 0;
	if (blockcnt >= wd->outdir->num) {
		e2fsck_read_bitmaps(wd->ctx);
		blk = *block_nr;
		ext2fs_unmark_block_bitmap2(wd->ctx->block_found_map, blk);
		ext2fs_block_alloc_stats(fs, blk, -1);
		*block_nr = 0;
		wd->cleared++;
		return BLOCK_CHANGED;
	}
	if (blockcnt < 0)
		return 0;

	dir = wd->outdir->buf + (blockcnt * fs->blocksize);
	wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
	if (wd->err)
		return BLOCK_ABORT;
	return 0;
}
Esempio n. 3
0
/*
 * This function is called to deallocate a block, and is an interator
 * functioned called by deallocate inode via ext2fs_iterate_block().
 */
static int deallocate_inode_block(ext2_filsys fs,
				  blk64_t	*block_nr,
				  e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
				  blk64_t ref_block EXT2FS_ATTR((unused)),
				  int ref_offset EXT2FS_ATTR((unused)),
				  void *priv_data)
{
	struct del_block *p = priv_data;

	if (HOLE_BLKADDR(*block_nr))
		return 0;
	if ((*block_nr < fs->super->s_first_data_block) ||
	    (*block_nr >= ext2fs_blocks_count(fs->super)))
		return 0;
	ext2fs_unmark_block_bitmap2(p->ctx->block_found_map, *block_nr);
	ext2fs_block_alloc_stats2(fs, *block_nr, -1);
	p->num++;
	return 0;
}
Esempio n. 4
0
/*
 * Helper function which writes out a directory block.
 */
static int write_dir_block(ext2_filsys fs,
                           blk64_t *block_nr,
                           e2_blkcnt_t blockcnt,
                           blk64_t ref_block EXT2FS_ATTR((unused)),
                           int ref_offset EXT2FS_ATTR((unused)),
                           void *priv_data)
{
    struct write_dir_struct	*wd = (struct write_dir_struct *) priv_data;
    blk64_t	blk;
    char	*dir;

    if (*block_nr == 0)
        return 0;
    if (blockcnt >= wd->outdir->num) {
        e2fsck_read_bitmaps(wd->ctx);
        blk = *block_nr;
        /*
         * In theory, we only release blocks from the end of the
         * directory file, so it's fine to clobber a whole cluster at
         * once.
         */
        if (blk % EXT2FS_CLUSTER_RATIO(fs) == 0) {
            ext2fs_unmark_block_bitmap2(wd->ctx->block_found_map,
                                        blk);
            ext2fs_block_alloc_stats2(fs, blk, -1);
            wd->cleared++;
        }
        *block_nr = 0;
        return BLOCK_CHANGED;
    }
    if (blockcnt < 0)
        return 0;

    dir = wd->outdir->buf + (blockcnt * fs->blocksize);
    wd->err = ext2fs_write_dir_block3(fs, *block_nr, dir, 0);
    if (wd->err)
        return BLOCK_ABORT;
    return 0;
}
Esempio n. 5
0
void do_clearb(int argc, char *argv[])
{
	unsigned int block, num;
	int err;
	int test_result, op_result;

	if (check_fs_open(argv[0]))
		return;

	if (argc != 2 && argc != 3) {
		com_err(argv[0], 0, "Usage: clearb <block> [num]");
		return;
	}

	block = parse_ulong(argv[1], argv[0], "block", &err);
	if (err)
		return;

	if (argc == 3) {
		num = parse_ulong(argv[2], argv[0], "num", &err);
		if (err)
			return;

		ext2fs_unmark_block_bitmap_range2(test_fs->block_map,
						block, num);
		printf("Clearing blocks %u to %u\n", block, block + num - 1);
		return;
	}

	test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block);
	op_result = ext2fs_unmark_block_bitmap2(test_fs->block_map, block);
	printf("Clearing block %u, was %s before\n", block, op_result ?
	       "set" : "clear");
	if (!test_result != !op_result)
		com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)",
			test_result, op_result);
}
Esempio n. 6
0
void e2fsck_pass3(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	struct dir_info_iter *iter = NULL;
#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;
	}

	/*
	 * Force the creation of /lost+found if not present
	 */
	if ((ctx->options & 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:
	if (iter)
		e2fsck_dir_info_iter_end(ctx, iter);
	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;
	}

	if (ctx->lnf_repair_block) {
		ext2fs_unmark_block_bitmap2(ctx->block_found_map,
					    ctx->lnf_repair_block);
		ctx->lnf_repair_block = 0;
	}
	if (ctx->root_repair_block) {
		ext2fs_unmark_block_bitmap2(ctx->block_found_map,
					    ctx->root_repair_block);
		ctx->root_repair_block = 0;
	}

	print_resource_track(ctx, _("Pass 3"), &rtrack, ctx->fs->io);
}