コード例 #1
0
ファイル: icount.c プロジェクト: alhashemi/e2fsprogs
static errcode_t alloc_icount(ext2_filsys fs, int flags, ext2_icount_t *ret)
{
	ext2_icount_t	icount;
	errcode_t	retval;

	*ret = 0;

	retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
	if (retval)
		return retval;
	memset(icount, 0, sizeof(struct ext2_icount));

	retval = ext2fs_allocate_inode_bitmap(fs, 0, &icount->single);
	if (retval)
		goto errout;

	if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
		retval = ext2fs_allocate_inode_bitmap(fs, 0,
						      &icount->multiple);
		if (retval)
			goto errout;
	} else
		icount->multiple = 0;

	icount->magic = EXT2_ET_MAGIC_ICOUNT;
	icount->num_inodes = fs->super->s_inodes_count;

	*ret = icount;
	return 0;

errout:
	ext2fs_free_icount(icount);
	return(retval);
}
コード例 #2
0
ファイル: icount.c プロジェクト: alhashemi/e2fsprogs
errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
				   int flags, ext2_icount_t *ret)
{
	ext2_icount_t	icount;
	errcode_t	retval;
	char 		*fn, uuid[40];
	int		fd;

	retval = alloc_icount(fs, flags,  &icount);
	if (retval)
		return retval;

	retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &fn);
	if (retval)
		goto errout;
	uuid_unparse(fs->super->s_uuid, uuid);
	sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
	fd = mkstemp(fn);

	icount->tdb_fn = fn;
	icount->tdb = tdb_open(fn, 0, TDB_CLEAR_IF_FIRST,
			       O_RDWR | O_CREAT | O_TRUNC, 0600);
	if (icount->tdb) {
		close(fd);
		*ret = icount;
		return 0;
	}

	retval = errno;
	close(fd);

errout:
	ext2fs_free_icount(icount);
	return(retval);
}
コード例 #3
0
ファイル: test_icount.c プロジェクト: ESOS-Lab/MOST
void do_free_icount(int argc, char **argv)
{
	if (check_icount(argv[0]))
		return;

	ext2fs_free_icount(test_icount);
	test_icount = 0;
}
コード例 #4
0
errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
				   int flags, ext2_icount_t *ret)
{
	ext2_icount_t	icount;
	errcode_t	retval;
	char 		*fn, uuid[40];
	ext2_ino_t	num_inodes;
	int		fd;

	retval = alloc_icount(fs, flags,  &icount);
	if (retval)
		return retval;

	retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &fn);
	if (retval)
		goto errout;
	uuid_unparse(fs->super->s_uuid, uuid);
	sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
	fd = mkstemp(fn);
	if (fd < 0)
		return fd;

	/*
	 * This is an overestimate of the size that we will need; the
	 * ideal value is the number of used inodes with a count
	 * greater than 1.  OTOH the times when we really need this is
	 * with the backup programs that use lots of hard links, in
	 * which case the number of inodes in use approaches the ideal
	 * value.
	 */
	num_inodes = fs->super->s_inodes_count - fs->super->s_free_inodes_count;

	icount->tdb_fn = fn;
	icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC,
			       O_RDWR | O_CREAT | O_TRUNC, 0600);
	if (icount->tdb) {
		close(fd);
		*ret = icount;
		return 0;
	}

	retval = errno;
	close(fd);

errout:
	ext2fs_free_icount(icount);
	return(retval);
}
コード例 #5
0
ファイル: e2fsck.c プロジェクト: TELE-TWIN/livebox2
/*
 * This function resets an e2fsck context; it is called when e2fsck
 * needs to be restarted.
 */
errcode_t e2fsck_reset_context(e2fsck_t ctx)
{
	ctx->flags = 0;
	ctx->lost_and_found = 0;
	ctx->bad_lost_and_found = 0;
	if (ctx->inode_used_map) {
		ext2fs_free_inode_bitmap(ctx->inode_used_map);
		ctx->inode_used_map = 0;
	}
	if (ctx->inode_dir_map) {
		ext2fs_free_inode_bitmap(ctx->inode_dir_map);
		ctx->inode_dir_map = 0;
	}
	if (ctx->inode_reg_map) {
		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
		ctx->inode_reg_map = 0;
	}
	if (ctx->block_found_map) {
		ext2fs_free_block_bitmap(ctx->block_found_map);
		ctx->block_found_map = 0;
	}
	if (ctx->inode_link_info) {
		ext2fs_free_icount(ctx->inode_link_info);
		ctx->inode_link_info = 0;
	}
	if (ctx->journal_io) {
		if (ctx->fs && ctx->fs->io != ctx->journal_io)
			io_channel_close(ctx->journal_io);
		ctx->journal_io = 0;
	}
	if (ctx->fs && ctx->fs->dblist) {
		ext2fs_free_dblist(ctx->fs->dblist);
		ctx->fs->dblist = 0;
	}
	e2fsck_free_dir_info(ctx);
#ifdef ENABLE_HTREE
	e2fsck_free_dx_dir_info(ctx);
#endif
	if (ctx->refcount) {
		ea_refcount_free(ctx->refcount);
		ctx->refcount = 0;
	}
	if (ctx->refcount_extra) {
		ea_refcount_free(ctx->refcount_extra);
		ctx->refcount_extra = 0;
	}
	if (ctx->block_dup_map) {
		ext2fs_free_block_bitmap(ctx->block_dup_map);
		ctx->block_dup_map = 0;
	}
	if (ctx->block_ea_map) {
		ext2fs_free_block_bitmap(ctx->block_ea_map);
		ctx->block_ea_map = 0;
	}
	if (ctx->inode_bb_map) {
		ext2fs_free_inode_bitmap(ctx->inode_bb_map);
		ctx->inode_bb_map = 0;
	}
	if (ctx->inode_bad_map) {
		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
		ctx->inode_bad_map = 0;
	}
	if (ctx->inode_imagic_map) {
		ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
		ctx->inode_imagic_map = 0;
	}
	if (ctx->dirs_to_hash) {
		ext2fs_u32_list_free(ctx->dirs_to_hash);
		ctx->dirs_to_hash = 0;
	}

	/*
	 * Clear the array of invalid meta-data flags
	 */
	if (ctx->invalid_inode_bitmap_flag) {
		ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
		ctx->invalid_inode_bitmap_flag = 0;
	}
	if (ctx->invalid_block_bitmap_flag) {
		ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
		ctx->invalid_block_bitmap_flag = 0;
	}
	if (ctx->invalid_inode_table_flag) {
		ext2fs_free_mem(&ctx->invalid_inode_table_flag);
		ctx->invalid_inode_table_flag = 0;
	}

	/* Clear statistic counters */
	ctx->fs_directory_count = 0;
	ctx->fs_regular_count = 0;
	ctx->fs_blockdev_count = 0;
	ctx->fs_chardev_count = 0;
	ctx->fs_links_count = 0;
	ctx->fs_symlinks_count = 0;
	ctx->fs_fast_symlinks_count = 0;
	ctx->fs_fifo_count = 0;
	ctx->fs_total_count = 0;
	ctx->fs_badblocks_count = 0;
	ctx->fs_sockets_count = 0;
	ctx->fs_ind_count = 0;
	ctx->fs_dind_count = 0;
	ctx->fs_tind_count = 0;
	ctx->fs_fragmented = 0;
	ctx->large_files = 0;

	/* Reset the superblock to the user's requested value */
	ctx->superblock = ctx->use_superblock;
	
	return 0;
}
コード例 #6
0
ファイル: icount.c プロジェクト: alhashemi/e2fsprogs
int run_test(int flags, int size, char *dir, struct test_program *prog)
{
	errcode_t	retval;
	ext2_icount_t	icount;
	struct test_program *pc;
	__u16		result;
	int		problem = 0;

	if (dir) {
		retval = ext2fs_create_icount_tdb(test_fs, dir,
						  flags, &icount);
		if (retval) {
			com_err("run_test", retval,
				"while creating icount using tdb");
			exit(1);
		}
	} else {
		retval = ext2fs_create_icount2(test_fs, flags, size, 0,
					       &icount);
		if (retval) {
			com_err("run_test", retval, "while creating icount");
			exit(1);
		}
	}
	for (pc = prog; pc->cmd != EXIT; pc++) {
		switch (pc->cmd) {
		case FETCH:
			printf("icount_fetch(%u) = ", pc->ino);
			break;
		case STORE:
			retval = ext2fs_icount_store(icount, pc->ino, pc->arg);
			if (retval) {
				com_err("run_test", retval,
					"while calling icount_store");
				exit(1);
			}
			printf("icount_store(%u, %u) = ", pc->ino, pc->arg);
			break;
		case INCREMENT:
			retval = ext2fs_icount_increment(icount, pc->ino, 0);
			if (retval) {
				com_err("run_test", retval,
					"while calling icount_increment");
				exit(1);
			}
			printf("icount_increment(%u) = ", pc->ino);
			break;
		case DECREMENT:
			retval = ext2fs_icount_decrement(icount, pc->ino, 0);
			if (retval) {
				com_err("run_test", retval,
					"while calling icount_decrement");
				exit(1);
			}
			printf("icount_decrement(%u) = ", pc->ino);
			break;
		}
		retval = ext2fs_icount_fetch(icount, pc->ino, &result);
		if (retval) {
			com_err("run_test", retval,
				"while calling icount_fetch");
			exit(1);
		}
		printf("%u (%s)\n", result, (result == pc->expected) ?
		       "OK" : "NOT OK");
		if (result != pc->expected)
			problem++;
	}
	printf("icount size is %u\n", ext2fs_get_icount_size(icount));
	retval = ext2fs_icount_validate(icount, stdout);
	if (retval) {
		com_err("run_test", retval, "while calling icount_validate");
		exit(1);
	}
	ext2fs_free_icount(icount);
	return problem;
}
コード例 #7
0
ファイル: icount.c プロジェクト: alhashemi/e2fsprogs
errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
				ext2_icount_t hint, ext2_icount_t *ret)
{
	ext2_icount_t	icount;
	errcode_t	retval;
	size_t		bytes;
	ext2_ino_t	i;

	if (hint) {
		EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
		if (hint->size > size)
			size = (size_t) hint->size;
	}

	retval = alloc_icount(fs, flags, &icount);
	if (retval)
		return retval;

	if (size) {
		icount->size = size;
	} else {
		/*
		 * Figure out how many special case inode counts we will
		 * have.  We know we will need one for each directory;
		 * we also need to reserve some extra room for file links
		 */
		retval = ext2fs_get_num_dirs(fs, &icount->size);
		if (retval)
			goto errout;
		icount->size += fs->super->s_inodes_count / 50;
	}

	bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
#if 0
	printf("Icount allocated %u entries, %d bytes.\n",
	       icount->size, bytes);
#endif
	retval = ext2fs_get_array(icount->size, sizeof(struct ext2_icount_el),
			 &icount->list);
	if (retval)
		goto errout;
	memset(icount->list, 0, bytes);

	icount->count = 0;
	icount->cursor = 0;

	/*
	 * Populate the sorted list with those entries which were
	 * found in the hint icount (since those are ones which will
	 * likely need to be in the sorted list this time around).
	 */
	if (hint) {
		for (i=0; i < hint->count; i++)
			icount->list[i].ino = hint->list[i].ino;
		icount->count = hint->count;
	}

	*ret = icount;
	return 0;

errout:
	ext2fs_free_icount(icount);
	return(retval);
}
コード例 #8
0
ファイル: pass4.c プロジェクト: Gwinel/e2fsprogs
void e2fsck_pass4(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	ext2_ino_t	i;
	struct ext2_inode	*inode;
#ifdef RESOURCE_TRACK
	struct resource_track	rtrack;
#endif
	struct problem_context	pctx;
	__u16	link_count, link_counted;
	char	*buf = 0;
	dgrp_t	group, maxgroup;

	init_resource_track(&rtrack, ctx->fs->io);

#ifdef MTRACE
	mtrace_print("Pass 4");
#endif

	clear_problem_context(&pctx);

	if (!(ctx->options & E2F_OPT_PREEN))
		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);

	group = 0;
	maxgroup = fs->group_desc_count;
	if (ctx->progress)
		if ((ctx->progress)(ctx, 4, 0, maxgroup))
			return;

	inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super),
				       "scratch inode");

	/* Protect loop from wrap-around if s_inodes_count maxed */
	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
		int isdir;

		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
			goto errout;
		if ((i % fs->super->s_inodes_per_group) == 0) {
			group++;
			if (ctx->progress)
				if ((ctx->progress)(ctx, 4, group, maxgroup))
					goto errout;
		}
		if (i == EXT2_BAD_INO ||
		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
			continue;
		if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, i)) ||
		    (ctx->inode_imagic_map &&
		     ext2fs_test_inode_bitmap2(ctx->inode_imagic_map, i)) ||
		    (ctx->inode_bb_map &&
		     ext2fs_test_inode_bitmap2(ctx->inode_bb_map, i)))
			continue;
		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
		if (link_counted == 0) {
			if (!buf)
				buf = e2fsck_allocate_memory(ctx,
				     fs->blocksize, "bad_inode buffer");
			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
				continue;
			if (disconnect_inode(ctx, i, inode))
				continue;
			ext2fs_icount_fetch(ctx->inode_link_info, i,
					    &link_count);
			ext2fs_icount_fetch(ctx->inode_count, i,
					    &link_counted);
		}
		isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i);
		if (isdir && (link_counted > EXT2_LINK_MAX))
			link_counted = 1;
		if (link_counted != link_count) {
			e2fsck_read_inode(ctx, i, inode, "pass4");
			pctx.ino = i;
			pctx.inode = inode;
			if ((link_count != inode->i_links_count) && !isdir &&
			    (inode->i_links_count <= EXT2_LINK_MAX)) {
				pctx.num = link_count;
				fix_problem(ctx,
					    PR_4_INCONSISTENT_COUNT, &pctx);
			}
			pctx.num = link_counted;
			/* i_link_count was previously exceeded, but no longer
			 * is, fix this but don't consider it an error */
			if ((isdir && link_counted > 1 &&
			     (inode->i_flags & EXT2_INDEX_FL) &&
			     link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
			    fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
				inode->i_links_count = link_counted;
				e2fsck_write_inode(ctx, i, inode, "pass4");
			}
		}
	}
	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
	ctx->inode_bb_map = 0;
	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
	ctx->inode_imagic_map = 0;
errout:
	if (buf)
		ext2fs_free_mem(&buf);

	ext2fs_free_mem(&inode);
	print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io);
}
コード例 #9
0
/*
 * This function resets an e2fsck context; it is called when e2fsck
 * needs to be restarted.
 */
errcode_t e2fsck_reset_context(e2fsck_t ctx)
{
	int	i;

	ctx->flags &= E2F_RESET_FLAGS;
	ctx->lost_and_found = 0;
	ctx->bad_lost_and_found = 0;
	if (ctx->inode_used_map) {
		ext2fs_free_inode_bitmap(ctx->inode_used_map);
		ctx->inode_used_map = 0;
	}
	if (ctx->inode_dir_map) {
		ext2fs_free_inode_bitmap(ctx->inode_dir_map);
		ctx->inode_dir_map = 0;
	}
	if (ctx->inode_reg_map) {
		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
		ctx->inode_reg_map = 0;
	}
	if (ctx->block_found_map) {
		ext2fs_free_block_bitmap(ctx->block_found_map);
		ctx->block_found_map = 0;
	}
	if (ctx->inode_link_info) {
		ext2fs_free_icount(ctx->inode_link_info);
		ctx->inode_link_info = 0;
	}
	if (ctx->journal_io) {
		if (ctx->fs && ctx->fs->io != ctx->journal_io)
			io_channel_close(ctx->journal_io);
		ctx->journal_io = 0;
	}
	if (ctx->fs && ctx->fs->dblist) {
		ext2fs_free_dblist(ctx->fs->dblist);
		ctx->fs->dblist = 0;
	}
	e2fsck_free_dir_info(ctx);
	e2fsck_free_dx_dir_info(ctx);
	if (ctx->refcount) {
		ea_refcount_free(ctx->refcount);
		ctx->refcount = 0;
	}
	if (ctx->refcount_extra) {
		ea_refcount_free(ctx->refcount_extra);
		ctx->refcount_extra = 0;
	}
	if (ctx->block_dup_map) {
		ext2fs_free_block_bitmap(ctx->block_dup_map);
		ctx->block_dup_map = 0;
	}
	if (ctx->block_ea_map) {
		ext2fs_free_block_bitmap(ctx->block_ea_map);
		ctx->block_ea_map = 0;
	}
	if (ctx->block_metadata_map) {
		ext2fs_free_block_bitmap(ctx->block_metadata_map);
		ctx->block_metadata_map = 0;
	}
	if (ctx->inode_bb_map) {
		ext2fs_free_inode_bitmap(ctx->inode_bb_map);
		ctx->inode_bb_map = 0;
	}
	if (ctx->inode_bad_map) {
		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
		ctx->inode_bad_map = 0;
	}
	if (ctx->inode_imagic_map) {
		ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
		ctx->inode_imagic_map = 0;
	}
	if (ctx->dirs_to_hash) {
		ext2fs_u32_list_free(ctx->dirs_to_hash);
		ctx->dirs_to_hash = 0;
	}

	/*
	 * Clear the array of invalid meta-data flags
	 */
	if (ctx->invalid_inode_bitmap_flag) {
		ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
		ctx->invalid_inode_bitmap_flag = 0;
	}
	if (ctx->invalid_block_bitmap_flag) {
		ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
		ctx->invalid_block_bitmap_flag = 0;
	}
	if (ctx->invalid_inode_table_flag) {
		ext2fs_free_mem(&ctx->invalid_inode_table_flag);
		ctx->invalid_inode_table_flag = 0;
	}
	if (ctx->encrypted_dirs) {
		ext2fs_u32_list_free(ctx->encrypted_dirs);
		ctx->encrypted_dirs = 0;
	}
	if (ctx->inode_count) {
		ext2fs_free_icount(ctx->inode_count);
		ctx->inode_count = 0;
	}

	/* Clear statistic counters */
	ctx->fs_directory_count = 0;
	ctx->fs_regular_count = 0;
	ctx->fs_blockdev_count = 0;
	ctx->fs_chardev_count = 0;
	ctx->fs_links_count = 0;
	ctx->fs_symlinks_count = 0;
	ctx->fs_fast_symlinks_count = 0;
	ctx->fs_fifo_count = 0;
	ctx->fs_total_count = 0;
	ctx->fs_badblocks_count = 0;
	ctx->fs_sockets_count = 0;
	ctx->fs_ind_count = 0;
	ctx->fs_dind_count = 0;
	ctx->fs_tind_count = 0;
	ctx->fs_fragmented = 0;
	ctx->fs_fragmented_dir = 0;
	ctx->large_files = 0;

	for (i=0; i < MAX_EXTENT_DEPTH_COUNT; i++)
		ctx->extent_depth_count[i] = 0;

	/* Reset the superblock to the user's requested value */
	ctx->superblock = ctx->use_superblock;

	return 0;
}
コード例 #10
0
ファイル: pass4.c プロジェクト: 325116067/semc-qsd8x50
void e2fsck_pass4(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	ext2_ino_t	i;
	struct ext2_inode	inode;
#ifdef RESOURCE_TRACK
	struct resource_track	rtrack;
#endif
	struct problem_context	pctx;
	__u16	link_count, link_counted;
	char	*buf = 0;
	int	group, maxgroup;
	
#ifdef RESOURCE_TRACK
	init_resource_track(&rtrack);
#endif

#ifdef MTRACE
	mtrace_print("Pass 4");
#endif

	clear_problem_context(&pctx);

	if (!(ctx->options & E2F_OPT_PREEN))
		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);

	group = 0;
	maxgroup = fs->group_desc_count;
	if (ctx->progress)
		if ((ctx->progress)(ctx, 4, 0, maxgroup))
			return;

	/* Protect loop from wrap-around if s_inodes_count maxed */
	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
			goto errout;
		if ((i % fs->super->s_inodes_per_group) == 0) {
			group++;
			if (ctx->progress)
				if ((ctx->progress)(ctx, 4, group, maxgroup))
					goto errout;
		}
		if (i == EXT2_BAD_INO ||
		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
			continue;
		if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
		    (ctx->inode_imagic_map &&
		     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
		    (ctx->inode_bb_map &&
		     ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
			continue;
		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
		if (link_counted == 0) {
			if (!buf)
				buf = e2fsck_allocate_memory(ctx,
				     fs->blocksize, "bad_inode buffer");
			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
				continue;
			if (disconnect_inode(ctx, i))
				continue;
			ext2fs_icount_fetch(ctx->inode_link_info, i,
					    &link_count);
			ext2fs_icount_fetch(ctx->inode_count, i,
					    &link_counted);
		}
		if (link_counted != link_count) {
			e2fsck_read_inode(ctx, i, &inode, "pass4");
			pctx.ino = i;
			pctx.inode = &inode;
			if (link_count != inode.i_links_count) {
				pctx.num = link_count;
				fix_problem(ctx,
					    PR_4_INCONSISTENT_COUNT, &pctx);
			}
			pctx.num = link_counted;
			if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
				inode.i_links_count = link_counted;
				e2fsck_write_inode(ctx, i, &inode, "pass4");
			}
		}
	}
	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
	ctx->inode_bb_map = 0;
	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
	ctx->inode_imagic_map = 0;
errout:
	if (buf)
		ext2fs_free_mem(&buf);
#ifdef RESOURCE_TRACK
	if (ctx->options & E2F_OPT_TIME2) {
		e2fsck_clear_progbar(ctx);
		print_resource_track(_("Pass 4"), &rtrack);
	}
#endif
}