pass2.c revision cf5301d7f2c3bbed3d26600335102414cbf0c4ba
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass2.c --- check directory structure
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *
621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header%
721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public
821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License.
921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header%
10efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 of e2fsck iterates through all active directory inodes, and
123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * applies to following tests to each directory entry in the directory
133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * blocks in the inodes:
143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *	- The length of the directory entry (rec_len) should be at
163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 		least 8 bytes, and no more than the remaining space
173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 		left in the directory block.
183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The length of the name in the directory entry (name_len)
19efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 		should be less than (rec_len - 8).
203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *	- The inode number in the directory entry should be within
213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 		legal bounds.
223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The inode number should refer to a in-use inode.
233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *	- The first entry should be '.', and its inode should be
243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 		the inode of the directory.
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The second entry should be '..'.
263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * To minimize disk seek time, the directory blocks are processed in
283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * sorted order of block numbers.
293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 also collects the following information:
313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The inode numbers of the subdirectories for each directory.
323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 relies on the following information from previous passes:
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The directory information collected in pass 1.
353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The inode_used_map bitmap
363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The inode_bad_map bitmap
373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The inode_dir_map bitmap
383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 frees the following data structures
403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 	- The inode_bad_map bitmap
41aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * 	- The inode_reg_map bitmap
423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
44b969b1b8a5c13992cadb026114731958644540d8Matthias Andree#define _GNU_SOURCE 1 /* get strnlen() */
4548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#include <string.h>
4648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o
473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h"
4821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h"
490926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o#include "dict.h"
503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
51aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#ifdef NO_INLINE_FUNCS
52aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_
53aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#else
54aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ inline
55aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#endif
56aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
57ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o/* #define DX_DEBUG */
588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Keeps track of how many times an inode is referenced.
613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
624035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs,
646dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			   struct ext2_db_entry2 *dir_blocks_info,
6554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o			   void *priv_data);
661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx,
676dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			      struct ext2_db_entry2 *dir_blocks_info,
6821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			      char *buf, struct problem_context *pctx);
698fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
70ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir,
71ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		       struct dx_dirblock_info *dx_db);
72ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
7421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostruct check_dir_struct {
7521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	char *buf;
7621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct problem_context	pctx;
77f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	int	count, max;
781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	e2fsck_t ctx;
79efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o};
8021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
8108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass2(e2fsck_t ctx)
823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
83a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	struct ext2_super_block *sb = ctx->fs->super;
84a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	struct problem_context	pctx;
85a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	ext2_filsys 		fs = ctx->fs;
86a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	char			*buf;
878bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK
883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct resource_track	rtrack;
898bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif
9021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct check_dir_struct cd;
918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dir_info	*dx_dir;
928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dirblock_info	*dx_db, *dx_parent;
93544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	int			b;
94ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	int			i, depth;
958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	problem_t		code;
968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	int			bad_dir;
978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
986d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	init_resource_track(&rtrack, ctx->fs->io);
991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	clear_problem_context(&cd.pctx);
1001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE
1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	mtrace_print("Pass 2");
1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (!(ctx->options & E2F_OPT_PREEN))
1061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
1071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
108efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT,
10934b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o				&ctx->inode_count);
11034b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o	if (ctx->inode_count)
11134b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o		cd.pctx.errcode = 0;
112efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	else
113efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		cd.pctx.errcode = ext2fs_create_icount2(fs,
11434b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o						EXT2_ICOUNT_OPT_INCREMENT,
1151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						0, ctx->inode_link_info,
1161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						&ctx->inode_count);
1171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (cd.pctx.errcode) {
1181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
11908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
12008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
12121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
122bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o	buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
12354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o					      "directory scan buffer");
1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
12521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	/*
12621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 * Set up the parent pointer for the root directory, if
12721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 * present.  (If the root directory is not present, we will
12821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 * create it in pass 3.)
12921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 */
13028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	(void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
13121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
13221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd.buf = buf;
1331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	cd.ctx = ctx;
134f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o	cd.count = 1;
1356dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	cd.max = ext2fs_dblist_count2(fs->dblist);
136f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o
137f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o	if (ctx->progress)
138f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o		(void) (ctx->progress)(ctx, 2, 0, cd.max);
139ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
140ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
1416dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp);
142efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1436dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block,
1446dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson						 &cd);
14549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
14608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
1476267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger
1486267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger	if (ctx->flags & E2F_FLAG_RESTART_LATER) {
1496267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger		ctx->flags |= E2F_FLAG_RESTART;
1506267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger		return;
1516267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger	}
1526267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger
1531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (cd.pctx.errcode) {
1541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
15508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
15608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
1577ac02a5ebddcc6187c893eedc80d92777b399575Theodore Ts'o	}
1588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
1598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
1608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
1614cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
1624cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o			return;
16362acaa1de132a808949d71264731bba7fe095705Theodore Ts'o		if (dx_dir->numblocks == 0)
1648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			continue;
1658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		clear_problem_context(&pctx);
1668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		bad_dir = 0;
1678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		pctx.dir = dx_dir->ino;
1688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db = dx_dir->dx_block;
1698fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (dx_db->flags & DX_FLAG_REFERENCED)
1708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_DUP_REF;
1718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		else
1728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_REFERENCED;
1738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		/*
1748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		 * Find all of the first and last leaf blocks, and
1758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		 * update their parent's min and max hash values
1768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		 */
1778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		for (b=0, dx_db = dx_dir->dx_block;
1788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b < dx_dir->numblocks;
1798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b++, dx_db++) {
1808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
1818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			    !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
1828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				continue;
1838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_parent = &dx_dir->dx_block[dx_db->parent];
1848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			/*
1858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
1868fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 */
1878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (dx_db->flags & DX_FLAG_FIRST)
1888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				dx_parent->min_hash = dx_db->min_hash;
1898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			/*
1908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
1918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 */
1928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (dx_db->flags & DX_FLAG_LAST)
1938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				dx_parent->max_hash = dx_db->max_hash;
1948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
195efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		for (b=0, dx_db = dx_dir->dx_block;
1978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b < dx_dir->numblocks;
1988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b++, dx_db++) {
1998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			pctx.blkcount = b;
2008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			pctx.group = dx_db->parent;
2018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			code = 0;
2028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (!(dx_db->flags & DX_FLAG_FIRST) &&
2038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			    (dx_db->min_hash < dx_db->node_min_hash)) {
2048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk = dx_db->min_hash;
2058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk2 = dx_db->node_min_hash;
2068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_MIN_HASH;
2078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
2088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				bad_dir++;
2098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			}
210ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			if (dx_db->type == DX_DIRBLOCK_LEAF) {
211ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				depth = htree_depth(dx_dir, dx_db);
212ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				if (depth != dx_dir->depth) {
213e5e12db959d3c18f6cf4ac938a14f68be0a89accAndreas Dilger					pctx.num = dx_dir->depth;
214ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					code = PR_2_HTREE_BAD_DEPTH;
215ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					fix_problem(ctx, code, &pctx);
216ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					bad_dir++;
217ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				}
218ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			}
2198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			/*
220efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			 * This test doesn't apply for the root block
2218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 * at block #0
2228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 */
2238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (b &&
2248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			    (dx_db->max_hash > dx_db->node_max_hash)) {
2258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk = dx_db->max_hash;
2268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk2 = dx_db->node_max_hash;
2278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_MAX_HASH;
2288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
229503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o				bad_dir++;
2308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			}
2318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
2328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_NOTREF;
2338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
2348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				bad_dir++;
2358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			} else if (dx_db->flags & DX_FLAG_DUP_REF) {
2368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_DUPREF;
2378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
2388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				bad_dir++;
2398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			}
2408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
2418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
2428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			clear_htree(ctx, dx_dir->ino);
24362acaa1de132a808949d71264731bba7fe095705Theodore Ts'o			dx_dir->numblocks = 0;
2448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
2458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
24623f75f6efaac6b756e0f3e4e1d33b6798347f66aTheodore Ts'o	e2fsck_free_dx_dir_info(ctx);
2478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
248c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&buf);
24921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	ext2fs_free_dblist(fs->dblist);
25021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
2511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->inode_bad_map) {
2521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ctx->inode_bad_map = 0;
2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
255aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (ctx->inode_reg_map) {
256aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
257aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		ctx->inode_reg_map = 0;
258aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	}
259a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o
260a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	clear_problem_context(&pctx);
261a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	if (ctx->large_files) {
262a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		if (!(sb->s_feature_ro_compat &
263a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		      EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
264a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		    fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
265a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			sb->s_feature_ro_compat |=
266a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o				EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
2670cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
268a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			ext2fs_mark_super_dirty(fs);
269a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		}
270a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
271a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		    fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
272a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			ext2fs_update_dynamic_rev(fs);
273a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			ext2fs_mark_super_dirty(fs);
274a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		}
275a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	}
276efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
2779facd076ae8af6e908e228392cea866ce0faf1bcKen Chen	print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io);
2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
280ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o#define MAX_DEPTH 32000
281ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir,
282ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		       struct dx_dirblock_info *dx_db)
283ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o{
284ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	int	depth = 0;
285ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
286ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
287ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		dx_db = &dx_dir->dx_block[dx_db->parent];
288ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		depth++;
289ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
290ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	return depth;
291ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o}
292ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
2930926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'ostatic int dict_de_cmp(const void *a, const void *b)
2940926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o{
295520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o	const struct ext2_dir_entry *de_a, *de_b;
2960926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	int	a_len, b_len;
2970926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
298520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o	de_a = (const struct ext2_dir_entry *) a;
2990926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	a_len = de_a->name_len & 0xFF;
300520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o	de_b = (const struct ext2_dir_entry *) b;
3010926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	b_len = de_b->name_len & 0xFF;
3020926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
3030926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	if (a_len != b_len)
3040926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		return (a_len - b_len);
3050926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
3060926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	return strncmp(de_a->name, de_b->name, a_len);
3070926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o}
308ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
3093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
310ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This is special sort function that makes sure that directory blocks
311ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * with a dirblock of zero are sorted to the beginning of the list.
312ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This guarantees that the root node of the htree directories are
313ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * processed first, so we know what hash version to use.
314ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o */
315ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
316ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{
3176dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	const struct ext2_db_entry2 *db_a =
3186dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		(const struct ext2_db_entry2 *) a;
3196dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	const struct ext2_db_entry2 *db_b =
3206dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		(const struct ext2_db_entry2 *) b;
321ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
322ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (db_a->blockcnt && !db_b->blockcnt)
323ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return 1;
324ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
325ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (!db_a->blockcnt && db_b->blockcnt)
326ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return -1;
327efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
328ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (db_a->blk != db_b->blk)
329ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return (int) (db_a->blk - db_b->blk);
330efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
331ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (db_a->ino != db_b->ino)
332ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return (int) (db_a->ino - db_b->ino);
333ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
334ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	return (int) (db_a->blockcnt - db_b->blockcnt);
335ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o}
336ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
337ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
338ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o/*
3393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the first entry in the directory is '.', and that the
3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane.
3413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
3421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dot(e2fsck_t ctx,
3433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		     struct ext2_dir_entry *dirent,
34486c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o		     ext2_ino_t ino, struct problem_context *pctx)
3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct ext2_dir_entry *nextdir;
3478a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	unsigned int	rec_len, new_len;
3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	status = 0;
3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	created = 0;
35021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	int	problem = 0;
351efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
35221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (!dirent->inode)
35321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_MISSING_DOT;
354b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o	else if (((dirent->name_len & 0xFF) != 1) ||
35521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		 (dirent->name[0] != '.'))
35621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_1ST_NOT_DOT;
35721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	else if (dirent->name[1] != '\0')
35821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_DOT_NULL_TERM;
3595dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o
3608a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
36121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (problem) {
3621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, problem, pctx)) {
3635dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o			if (rec_len < 12)
3645dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o				rec_len = dirent->rec_len = 12;
3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->inode = ino;
3663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name_len = 1;
3673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name[0] = '.';
36821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			dirent->name[1] = '\0';
3693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			status = 1;
3703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			created = 1;
3713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (dirent->inode != ino) {
3741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
3753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->inode = ino;
3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			status = 1;
37721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		}
3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3795dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	if (rec_len > 12) {
3805dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		new_len = rec_len - 12;
3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (new_len > 12) {
3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (created ||
383f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o			    fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				nextdir = (struct ext2_dir_entry *)
3853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					((char *) dirent + 12);
3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dirent->rec_len = 12;
3878a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o				(void) ext2fs_set_rec_len(ctx->fs, new_len,
3888a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o							  nextdir);
3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				nextdir->inode = 0;
3903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				nextdir->name_len = 0;
3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				status = 1;
3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
3933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
3943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return status;
3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
3993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the second entry in the directory is '..', and that the
4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane.  We do not check the inode number of '..'
4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * here; this gets done in pass 3.
4023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
4031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dotdot(e2fsck_t ctx,
4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			struct ext2_dir_entry *dirent,
40528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			ext2_ino_t ino, struct problem_context *pctx)
4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
407cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger	int		problem = 0;
408cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger	unsigned int	rec_len;
409efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
41021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (!dirent->inode)
41121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_MISSING_DOT_DOT;
412b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o	else if (((dirent->name_len & 0xFF) != 2) ||
41321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		 (dirent->name[0] != '.') ||
41421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		 (dirent->name[1] != '.'))
41521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_2ND_NOT_DOT_DOT;
41621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	else if (dirent->name[2] != '\0')
41721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_DOT_DOT_NULL_TERM;
41821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
4198a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
42021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (problem) {
4211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, problem, pctx)) {
4225dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o			if (rec_len < 12)
42321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				dirent->rec_len = 12;
4243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			/*
4253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 * Note: we don't have the parent inode just
4263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 * yet, so we will fill it in with the root
4273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 * inode.  This will get fixed in pass 3.
4283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 */
4293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->inode = EXT2_ROOT_INO;
4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name_len = 2;
4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name[0] = '.';
4323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name[1] = '.';
43321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			dirent->name[2] = '\0';
4343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			return 1;
435efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		}
4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
43828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) {
43928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o		fix_problem(ctx, PR_2_NO_DIRINFO, pctx);
44028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o		return -1;
44128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	}
4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
4453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
4463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Check to make sure a directory entry doesn't contain any illegal
4473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * characters.
4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
4491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_name(e2fsck_t ctx,
4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		      struct ext2_dir_entry *dirent,
451efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
452544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		      struct problem_context *pctx)
4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	i;
4553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	fixup = -1;
4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	ret = 0;
457efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
458b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o	for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fixup < 0) {
4611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fixup) {
4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dirent->name[i] = '.';
4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				ret = 1;
46621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			}
4673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
4693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return ret;
4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
472aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o/*
473aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * Check the directory filetype (if present)
474aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o */
475aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'ostatic _INLINE_ int check_filetype(e2fsck_t ctx,
476544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   struct ext2_dir_entry *dirent,
477544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
478544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   struct problem_context *pctx)
479aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o{
480aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	int	filetype = dirent->name_len >> 8;
481aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	int	should_be = EXT2_FT_UNKNOWN;
482aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	struct ext2_inode	inode;
483aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
484aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (!(ctx->fs->super->s_feature_incompat &
4857847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o	      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
4867847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		if (filetype == 0 ||
4877847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
4887847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o			return 0;
4897847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		dirent->name_len = dirent->name_len & 0xFF;
4907847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		return 1;
4917847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o	}
492aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
493c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
494aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		should_be = EXT2_FT_DIR;
495c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	} else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
496aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o					    dirent->inode)) {
497aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		should_be = EXT2_FT_REG_FILE;
498aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	} else if (ctx->inode_bad_map &&
499c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson		   ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
500aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o					    dirent->inode))
501aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		should_be = 0;
502aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	else {
503aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		e2fsck_read_inode(ctx, dirent->inode, &inode,
504aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o				  "check_filetype");
5056fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		should_be = ext2_file_type(inode.i_mode);
506aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	}
507aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (filetype == should_be)
508aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		return 0;
509aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	pctx->num = should_be;
510aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
511aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
512aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o			pctx) == 0)
513aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		return 0;
514efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
515aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
516aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	return 1;
517aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o}
518aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
5198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
5208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void parse_int_node(ext2_filsys fs,
5216dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			   struct ext2_db_entry2 *db,
5228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			   struct check_dir_struct *cd,
5238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			   struct dx_dir_info	*dx_dir,
5248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			   char *block_buf)
5258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{
5268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct 		ext2_dx_root_info  *root;
5278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct 		ext2_dx_entry *ent;
5288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct		ext2_dx_countlimit *limit;
5298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dirblock_info	*dx_db;
530ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	int		i, expect_limit, count;
5318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	blk_t		blk;
5328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	ext2_dirhash_t	min_hash = 0xffffffff;
5338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	ext2_dirhash_t	max_hash = 0;
534ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	ext2_dirhash_t	hash = 0, prev_hash;
5358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	if (db->blockcnt == 0) {
5378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		root = (struct ext2_dx_root_info *) (block_buf + 24);
538efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
5408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("Root node dump:\n");
5418deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato		printf("\t Reserved zero: %u\n", root->reserved_zero);
5428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Hash Version: %d\n", root->hash_version);
5438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Info length: %d\n", root->info_length);
5448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Indirect levels: %d\n", root->indirect_levels);
5458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Flags: %d\n", root->unused_flags);
5468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
5478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	} else {
5508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		ent = (struct ext2_dx_entry *) (block_buf+8);
5518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
5528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	limit = (struct ext2_dx_countlimit *) ent;
5538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
555efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	printf("Number of entries (count): %d\n",
5568132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	       ext2fs_le16_to_cpu(limit->count));
557efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	printf("Number of entries (limit): %d\n",
5588132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	       ext2fs_le16_to_cpu(limit->limit));
5598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
5608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5618132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	count = ext2fs_le16_to_cpu(limit->count);
562ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
563ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		sizeof(struct ext2_dx_entry);
5648132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5658132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
566ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
567ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			goto clear_and_exit;
568ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
5698132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	if (count > expect_limit) {
5708132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		cd->pctx.num = count;
571ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
572ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			goto clear_and_exit;
573ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		count = expect_limit;
574ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
575efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
576ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	for (i=0; i < count; i++) {
577ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		prev_hash = hash;
5788132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
5808deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato		printf("Entry #%d: Hash 0x%08x, block %u\n", i,
5818132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		       hash, ext2fs_le32_to_cpu(ent[i].block));
5828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
5838132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		/* Check to make sure the block is valid */
585977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o		if (blk >= (blk_t) dx_dir->numblocks) {
586b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o			cd->pctx.blk = blk;
5878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
588ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					&cd->pctx))
589ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				goto clear_and_exit;
590977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o			continue;
5918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
592ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		if (hash < prev_hash &&
593ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		    fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
594ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			goto clear_and_exit;
5958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db = &dx_dir->dx_block[blk];
5968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (dx_db->flags & DX_FLAG_REFERENCED) {
5978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_DUP_REF;
5988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		} else {
5998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_REFERENCED;
6008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->parent = db->blockcnt;
6018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
6028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (hash < min_hash)
6038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			min_hash = hash;
6048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (hash > max_hash)
6058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			max_hash = hash;
6068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->node_min_hash = hash;
6078132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		if ((i+1) < count)
608efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			dx_db->node_max_hash =
6098132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o			  ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
6108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		else {
6118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->node_max_hash = 0xfffffffe;
6128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_LAST;
6138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
6148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (i == 0)
6158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_FIRST;
6168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
6178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
6188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
6198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	       db->blockcnt, min_hash, max_hash);
6208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
6218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_db = &dx_dir->dx_block[db->blockcnt];
6228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_db->min_hash = min_hash;
6238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_db->max_hash = max_hash;
624ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	return;
625ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
626ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'oclear_and_exit:
627ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	clear_htree(cd->ctx, cd->pctx.ino);
628ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	dx_dir->numblocks = 0;
6298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o}
6308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
631aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
632e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o/*
633e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Given a busted directory, try to salvage it somehow.
634efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
635e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */
636ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic void salvage_directory(ext2_filsys fs,
637e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o			      struct ext2_dir_entry *dirent,
638e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o			      struct ext2_dir_entry *prev,
639544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			      unsigned int *offset)
640e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o{
641e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	char	*cp = (char *) dirent;
6428a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	int left;
6438a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	unsigned int rec_len, prev_rec_len;
644642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o	unsigned int name_len = dirent->name_len & 0xFF;
645e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o
6468a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
6475dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	left = fs->blocksize - *offset - rec_len;
6485dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o
649e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	/*
650e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * Special case of directory entry of size 8: copy what's left
651e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * of the directory block up to cover up the invalid hole.
652e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 */
6535dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	if ((left >= 12) && (rec_len == 8)) {
654e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		memmove(cp, cp+8, left);
655e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		memset(cp + left, 0, 8);
656ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		return;
657ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
658ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	/*
659ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 * If the directory entry overruns the end of the directory
660ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 * block, and the name is small enough to fit, then adjust the
661ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 * record length.
662ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 */
663ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	if ((left < 0) &&
6648a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	    ((int) rec_len + left > 8) &&
6658a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	    (name_len + 8 <= (int) rec_len + left) &&
666ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	    dirent->inode <= fs->super->s_inodes_count &&
667ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	    strnlen(dirent->name, name_len) == name_len) {
6688a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent);
669ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		return;
670e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	}
671e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	/*
672575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah	 * If the record length of the directory entry is a multiple
673575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah	 * of four, and not too big, such that it is valid, let the
674575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah	 * previous directory entry absorb the invalid one.
675e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 */
6765dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	if (prev && rec_len && (rec_len % 4) == 0 &&
6775dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	    (*offset + rec_len <= fs->blocksize)) {
6788a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
6798a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		prev_rec_len += rec_len;
6808a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
6815dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		*offset += rec_len;
682ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		return;
683e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	}
684e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	/*
685e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * Default salvage method --- kill all of the directory
686e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * entries for the rest of the block.  We will either try to
687e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * absorb it into the previous directory entry, or create a
688e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * new empty directory entry the rest of the directory block.
689e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 */
690e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	if (prev) {
6918a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
6928a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		prev_rec_len += fs->blocksize - *offset;
6938a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
694ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		*offset = fs->blocksize;
695e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	} else {
6968a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		rec_len = fs->blocksize - *offset;
6978a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, rec_len, dirent);
698e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		dirent->name_len = 0;
699e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		dirent->inode = 0;
700e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	}
701e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o}
702e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o
7033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs,
7046dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			   struct ext2_db_entry2 *db,
70554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o			   void *priv_data)
7063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
7078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 	struct dx_dir_info	*dx_dir;
7088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
7098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dirblock_info	*dx_db = 0;
7108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
711e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	struct ext2_dir_entry 	*dirent, *prev;
7128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	ext2_dirhash_t		hash;
713544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int		offset = 0;
714e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	const char *		old_op;
7153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int			dir_modified = 0;
71621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	int			dot_state;
71703fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o	unsigned int		rec_len;
7186dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	blk64_t			block_nr = db->blk;
71986c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o	ext2_ino_t 		ino = db->ino;
72028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	ext2_ino_t 		subdir_parent;
72121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	__u16			links;
72254dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	struct check_dir_struct	*cd;
7231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	char 			*buf;
7241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	e2fsck_t		ctx;
7251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	int			problem;
726ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	struct ext2_dx_root_info *root;
727e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o	struct ext2_dx_countlimit *limit;
7280926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	static dict_t de_dict;
7290926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	struct problem_context	pctx;
7300926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	int	dups_found = 0;
73128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	int	ret;
7321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
73354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	cd = (struct check_dir_struct *) priv_data;
7341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	buf = cd->buf;
7351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ctx = cd->ctx;
736f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o
73749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
7384cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		return DIRENT_ABORT;
739efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
7404cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o	if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7414cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		return DIRENT_ABORT;
742efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
7433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	/*
744efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 * Make sure the inode is still in use (could have been
7453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * deleted in the duplicate/bad blocks pass.
7463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 */
747c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino)))
7483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
74950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
75021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.ino = ino;
75121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.blk = block_nr;
75221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.blkcount = db->blockcnt;
75321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.ino2 = 0;
75421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.dirent = 0;
75521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.num = 0;
75621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
75750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (db->blk == 0) {
7581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (allocate_dir_block(ctx, db, buf, &cd->pctx))
75950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			return 0;
76050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		block_nr = db->blk;
76150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
762efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
7633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (db->blockcnt)
7643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		dot_state = 2;
7653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else
7663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		dot_state = 0;
7673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
7680926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	if (ctx->dirs_to_hash &&
7690926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	    ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7700926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		dups_found++;
7710926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
7723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0
773f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	       db->blockcnt, ino);
7753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
776efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
777e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	old_op = ehandler_operation(_("reading directory block"));
7786dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	cd->pctx.errcode = ext2fs_read_dir_block3(fs, block_nr, buf, 0);
779e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	ehandler_operation(0);
780b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o	if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
781b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o		cd->pctx.errcode = 0; /* We'll handle this ourselves */
7821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (cd->pctx.errcode) {
78308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
78408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			ctx->flags |= E2F_FLAG_ABORT;
78508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			return DIRENT_ABORT;
78608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		}
7871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		memset(buf, 0, fs->blocksize);
7883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
7898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
7908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
79162acaa1de132a808949d71264731bba7fe095705Theodore Ts'o	if (dx_dir && dx_dir->numblocks) {
7928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (db->blockcnt >= dx_dir->numblocks) {
793efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK,
794d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o					&pctx)) {
795d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				clear_htree(ctx, ino);
796d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				dx_dir->numblocks = 0;
797d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				dx_db = 0;
798d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				goto out_htree;
799d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o			}
800d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o			fatal_error(ctx, _("Can not continue."));
8018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
8028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db = &dx_dir->dx_block[db->blockcnt];
8038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->type = DX_DIRBLOCK_LEAF;
8048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->phys = block_nr;
8058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->min_hash = ~0;
8068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->max_hash = 0;
807efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
8088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dirent = (struct ext2_dir_entry *) buf;
8098a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
810e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o		limit = (struct ext2_dx_countlimit *) (buf+8);
8118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (db->blockcnt == 0) {
812ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			root = (struct ext2_dx_root_info *) (buf + 24);
8138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->type = DX_DIRBLOCK_ROOT;
8148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
815ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			if ((root->reserved_zero ||
816ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			     root->info_length < 8 ||
817ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			     root->indirect_levels > 1) &&
818ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			    fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
819ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o				clear_htree(ctx, ino);
820ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o				dx_dir->numblocks = 0;
821ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o				dx_db = 0;
822f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			}
823ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			dx_dir->hashversion = root->hash_version;
824f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			if ((dx_dir->hashversion <= EXT2_HASH_TEA) &&
825f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			    (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
826f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o				dx_dir->hashversion += 3;
827ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			dx_dir->depth = root->indirect_levels + 1;
8288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		} else if ((dirent->inode == 0) &&
8295dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o			   (rec_len == fs->blocksize) &&
830e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o			   (dirent->name_len == 0) &&
831efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   (ext2fs_le16_to_cpu(limit->limit) ==
832efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			    ((fs->blocksize-8) /
8338132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o			     sizeof(struct ext2_dx_entry))))
8348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->type = DX_DIRBLOCK_NODE;
8358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
836d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'oout_htree:
8378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
8383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
8390926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
840e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	prev = 0;
8413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	do {
84249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		int group;
84349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		ext2_ino_t first_unused_inode;
84449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
8451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		problem = 0;
8463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		dirent = (struct ext2_dir_entry *) (buf + offset);
8478a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
84821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		cd->pctx.dirent = dirent;
84921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		cd->pctx.num = offset;
8505dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		if (((offset + rec_len) > fs->blocksize) ||
8515dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		    (rec_len < 12) ||
8525dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		    ((rec_len % 4) != 0) ||
85303fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o		    (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) {
8541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
855ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				salvage_directory(fs, dirent, prev, &offset);
8563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dir_modified++;
857e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o				continue;
85821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			} else
8590926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				goto abort_free_dict;
8603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
861b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o		if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
8621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
86350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				dirent->name_len = EXT2_NAME_LEN;
86450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				dir_modified++;
86550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			}
86650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		}
86750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
868e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		if (dot_state == 0) {
8691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			if (check_dot(ctx, dirent, ino, &cd->pctx))
8703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dir_modified++;
871e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		} else if (dot_state == 1) {
87228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			ret = check_dotdot(ctx, dirent, ino, &cd->pctx);
87328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			if (ret < 0)
8740926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				goto abort_free_dict;
87528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			if (ret)
8763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dir_modified++;
8773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		} else if (dirent->inode == ino) {
8781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			problem = PR_2_LINK_DOT;
8791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
8803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dirent->inode = 0;
8813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dir_modified++;
88221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				goto next;
8833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
8843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
885efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (!dirent->inode)
8863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			goto next;
887efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
8883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		/*
8893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * Make sure the inode listed is a legal one.
890efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		 */
8913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (((dirent->inode != EXT2_ROOT_INO) &&
8927f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o		     (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
8933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		    (dirent->inode > fs->super->s_inodes_count)) {
8941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			problem = PR_2_BAD_INO;
8951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		} else if (ctx->inode_bb_map &&
896c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson			   (ext2fs_test_inode_bitmap2(ctx->inode_bb_map,
8971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						     dirent->inode))) {
8981b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			/*
8991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * If the inode is in a bad block, offer to
9001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * clear it.
9011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 */
9021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			problem = PR_2_BB_INODE;
903e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		} else if ((dot_state > 1) &&
904b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o			   ((dirent->name_len & 0xFF) == 1) &&
9051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			   (dirent->name[0] == '.')) {
9061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			/*
9071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * If there's a '.' entry in anything other
9081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * than the first directory entry, it's a
9091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * duplicate entry that should be removed.
9101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 */
9111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			problem = PR_2_DUP_DOT;
912e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		} else if ((dot_state > 1) &&
913b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o			   ((dirent->name_len & 0xFF) == 2) &&
914efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   (dirent->name[0] == '.') &&
9151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			   (dirent->name[1] == '.')) {
9161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			/*
9171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * If there's a '..' entry in anything other
9181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * than the second directory entry, it's a
9191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * duplicate entry that should be removed.
9201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 */
9211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			problem = PR_2_DUP_DOT_DOT;
922e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		} else if ((dot_state > 1) &&
9231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			   (dirent->inode == EXT2_ROOT_INO)) {
9241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			/*
9251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * Don't allow links to the root directory.
9261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * We check this specially to make sure we
9271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * catch this error case even if the root
9281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 * directory hasn't been created yet.
9291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			 */
9301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			problem = PR_2_LINK_ROOT;
931e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		} else if ((dot_state > 1) &&
932c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o			   (dirent->name_len & 0xFF) == 0) {
933c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o			/*
934c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o			 * Don't allow zero-length directory names.
935c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o			 */
936c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o			problem = PR_2_NULL_NAME;
93721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		}
93821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
9391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (problem) {
9401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			if (fix_problem(ctx, problem, &cd->pctx)) {
94121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				dirent->inode = 0;
94221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				dir_modified++;
94321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				goto next;
9441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			} else {
9451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				ext2fs_unmark_valid(fs);
9461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				if (problem == PR_2_BAD_INO)
9471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o					goto next;
94821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			}
9493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
9503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
9513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		/*
9523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * If the inode was marked as having bad fields in
9533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * pass1, process it and offer to fix/clear it.
9543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * (We wait until now so that we can display the
9553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * pathname to the user.)
9563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 */
9571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (ctx->inode_bad_map &&
958c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson		    ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
9593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					     dirent->inode)) {
960e72a9ba39471364ad2f9397f645ca547090e3485Theodore Ts'o			if (e2fsck_process_bad_inode(ctx, ino,
961bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o						     dirent->inode,
962bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o						     buf + fs->blocksize)) {
9633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dirent->inode = 0;
9643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dir_modified++;
9653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				goto next;
9663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
967a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
96808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o				return DIRENT_ABORT;
9693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
9703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
97149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		group = ext2fs_group_of_ino(fs, dirent->inode);
97249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		first_unused_inode = group * fs->super->s_inodes_per_group +
97349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos					1 + fs->super->s_inodes_per_group -
974d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson					ext2fs_bg_itable_unused(fs, group);
97549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		cd->pctx.group = group;
97649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
97749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		/*
97842e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o		 * Check if the inode was missed out because
97942e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o		 * _INODE_UNINIT flag was set or bg_itable_unused was
98042e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o		 * incorrect.  If so, clear the _INODE_UNINIT flag and
98142e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o		 * restart e2fsck.  In the future it would be nice if
98242e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o		 * we could call a function in pass1.c that checks the
98342e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o		 * newly visible inodes.
98449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		 */
985cd65a24e756b8f6770a5961fd94c67eb00dd7baaTheodore Ts'o		if (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)) {
9866267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger			pctx.num = dirent->inode;
98749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT,
98849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos					&cd->pctx)){
989e633b58ac75f2f544b7d6572e37d4b63da31e59cEric Sandeen				ext2fs_bg_flags_clear(fs, group,
990732c8cd58ff30ffae0d3276c411a08920717a46cTheodore Ts'o						      EXT2_BG_INODE_UNINIT);
99142e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o				ext2fs_mark_super_dirty(fs);
9926267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger				ctx->flags |= E2F_FLAG_RESTART_LATER;
99349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			} else {
99449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				ext2fs_unmark_valid(fs);
99549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				if (problem == PR_2_BAD_INO)
99649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos					goto next;
99749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			}
99849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		} else if (dirent->inode >= first_unused_inode) {
9996267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger			pctx.num = dirent->inode;
100049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){
1001d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson				ext2fs_bg_itable_unused_set(fs, group, 0);
100249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				ext2fs_mark_super_dirty(fs);
10036267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger				ctx->flags |= E2F_FLAG_RESTART_LATER;
100449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			} else {
100549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				ext2fs_unmark_valid(fs);
100649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				if (problem == PR_2_BAD_INO)
100749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos					goto next;
100849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			}
100949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
101049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
10110433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		/*
10120433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 * Offer to clear unused inodes; if we are going to be
10130433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 * restarting the scan due to bg_itable_unused being
10140433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 * wrong, then don't clear any inodes to avoid zapping
10150433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 * inodes that were skipped during pass1 due to an
10160433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 * incorrect bg_itable_unused; we'll get any real
10170433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 * problems after we restart.
10180433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		 */
10190433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o		if (!(ctx->flags & E2F_FLAG_RESTART_LATER) &&
102097d26ce9e3589e9f5fa17014467a9730a884d158Theodore Ts'o		    !(ext2fs_test_inode_bitmap2(ctx->inode_used_map,
102197d26ce9e3589e9f5fa17014467a9730a884d158Theodore Ts'o						dirent->inode)))
102249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			problem = PR_2_UNUSED_INODE;
102349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
102449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (problem) {
102549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (fix_problem(ctx, problem, &cd->pctx)) {
102649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				dirent->inode = 0;
102749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				dir_modified++;
102849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				goto next;
102949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			} else {
103049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				ext2fs_unmark_valid(fs);
103149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				if (problem == PR_2_BAD_INO)
103249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos					goto next;
103349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			}
103449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
103549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
10361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (check_name(ctx, dirent, ino, &cd->pctx))
10371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			dir_modified++;
10381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
1039aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		if (check_filetype(ctx, dirent, ino, &cd->pctx))
1040aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o			dir_modified++;
1041aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
10428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
10438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (dx_db) {
10448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			ext2fs_dirhash(dx_dir->hashversion, dirent->name,
1045503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o				       (dirent->name_len & 0xFF),
1046503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o				       fs->super->s_hash_seed, &hash, 0);
10478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (hash < dx_db->min_hash)
10488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				dx_db->min_hash = hash;
10498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (hash > dx_db->max_hash)
10508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				dx_db->max_hash = hash;
10518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
10528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
10538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
105421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		/*
10553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * If this is a directory, then mark its parent in its
10563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * dir_info structure.  If the parent field is already
10573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * filled in, then this directory has more than one
10583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * hard link.  We assume the first link is correct,
10593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 * and ask the user if he/she wants to clear this one.
10603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 */
1061e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		if ((dot_state > 1) &&
1062c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson		    (ext2fs_test_inode_bitmap2(ctx->inode_dir_map,
10633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					      dirent->inode))) {
106428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			if (e2fsck_dir_info_get_parent(ctx, dirent->inode,
106528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o						       &subdir_parent)) {
10661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				cd->pctx.ino = dirent->inode;
10671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
10680926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				goto abort_free_dict;
10693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
107028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			if (subdir_parent) {
107128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o				cd->pctx.ino2 = subdir_parent;
10721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				if (fix_problem(ctx, PR_2_LINK_DIR,
107321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o						&cd->pctx)) {
10743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					dirent->inode = 0;
10753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					dir_modified++;
10763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					goto next;
107721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				}
107821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				cd->pctx.ino2 = 0;
107928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			} else {
1080efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o				(void) e2fsck_dir_info_set_parent(ctx,
108128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o						  dirent->inode, ino);
108228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			}
10833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
10840926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
10850926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		if (dups_found) {
10860926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			;
10870926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		} else if (dict_lookup(&de_dict, dirent)) {
10880926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			clear_problem_context(&pctx);
10890926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			pctx.ino = ino;
10900926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			pctx.dirent = dirent;
10910926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
10920926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			if (!ctx->dirs_to_hash)
10930926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
10940926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			if (ctx->dirs_to_hash)
10950926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
10960926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			dups_found++;
10970926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		} else
10980926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o			dict_alloc_insert(&de_dict, dirent, dirent);
1099efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
11001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ext2fs_icount_increment(ctx->inode_count, dirent->inode,
11011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o					&links);
110221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		if (links > 1)
11031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			ctx->fs_links_count++;
11041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ctx->fs_total_count++;
11053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	next:
1106e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		prev = dirent;
11075dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		if (dir_modified)
11088a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o			(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
11095dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		offset += rec_len;
1110e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		dot_state++;
11113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	} while (offset < fs->blocksize);
11123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0
11133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	printf("\n");
11143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
11158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
11168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	if (dx_db) {
11178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
11188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
11198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		       db->blockcnt, dx_db->type,
11208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		       dx_db->min_hash, dx_db->max_hash);
11218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
1122b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o		cd->pctx.dir = cd->pctx.ino;
11238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
11248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		    (dx_db->type == DX_DIRBLOCK_NODE))
11258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			parse_int_node(fs, db, cd, dx_dir, buf);
11268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
11278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
11283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (offset != fs->blocksize) {
11295dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		cd->pctx.num = rec_len - fs->blocksize + offset;
11301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
11311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			dirent->rec_len = cd->pctx.num;
11321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			dir_modified++;
11331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		}
11343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
11353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (dir_modified) {
11361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
11371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (cd->pctx.errcode) {
113808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
11390926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o					 &cd->pctx))
11400926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				goto abort_free_dict;
11413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
11423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		ext2fs_mark_changed(fs);
11433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
11440926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	dict_free_nodes(&de_dict);
11453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
11460926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'oabort_free_dict:
11470926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	ctx->flags |= E2F_FLAG_ABORT;
114849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	dict_free_nodes(&de_dict);
11490926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	return DIRENT_ABORT;
11503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
11513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
11523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
11533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This function is called to deallocate a block, and is an interator
11543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * functioned called by deallocate inode via ext2fs_iterate_block().
11553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
11563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int deallocate_inode_block(ext2_filsys fs,
11576dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson				  blk64_t	*block_nr,
1158544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				  e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
11596dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson				  blk64_t ref_block EXT2FS_ATTR((unused)),
1160544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				  int ref_offset EXT2FS_ATTR((unused)),
1161133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o				  void *priv_data)
11623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
116354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	e2fsck_t	ctx = (e2fsck_t) priv_data;
1164efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
11651917875fcd16428d14eb5a86acf414472bc216f1Theodore Ts'o	if (HOLE_BLKADDR(*block_nr))
11663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
11671ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o	if ((*block_nr < fs->super->s_first_data_block) ||
11684efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson	    (*block_nr >= ext2fs_blocks_count(fs->super)))
11691ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o		return 0;
1170c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	ext2fs_unmark_block_bitmap2(ctx->block_found_map, *block_nr);
117148f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson	ext2fs_block_alloc_stats2(fs, *block_nr, -1);
11723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
11733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1174efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
11753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
11763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This fuction deallocates an inode
11773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
11784035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
11793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
11801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
11813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct ext2_inode	inode;
11821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	struct problem_context	pctx;
11830684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	__u32			count;
1184efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
118508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
1186e3df15abdb288c3519000c639ed40429a82b63cdTheodore Ts'o	e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
11871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	clear_problem_context(&pctx);
11881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	pctx.ino = ino;
1189f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
11903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	/*
11913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * Fix up the bitmaps...
11923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 */
1193f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	e2fsck_read_bitmaps(ctx);
11940684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
11950684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o
1196a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson	if (ext2fs_file_acl_block(&inode) &&
11970684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
11986dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		pctx.errcode = ext2fs_adjust_ea_refcount2(fs, ext2fs_file_acl_block(&inode),
11990684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o						   block_buf, -1, &count);
12000684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
12010684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			pctx.errcode = 0;
12020684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			count = 1;
12030684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
12040684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (pctx.errcode) {
1205a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson			pctx.blk = ext2fs_file_acl_block(&inode);
12060684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
12070684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			ctx->flags |= E2F_FLAG_ABORT;
12080684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			return;
12090684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
12100684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (count == 0) {
1211c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson			ext2fs_unmark_block_bitmap2(ctx->block_found_map,
121248f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson						ext2fs_file_acl_block(&inode));
121348f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson			ext2fs_block_alloc_stats2(fs,
121448f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson					        ext2fs_file_acl_block(&inode),
121548f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson					        -1);
12160684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
1217a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson		ext2fs_file_acl_block_set(&inode, 0);
12180684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	}
12193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
122021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (!ext2fs_inode_has_valid_blocks(&inode))
12213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return;
1222a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o
1223b94a052a25d0c524209782e408c31d8ff25a6fe1Andreas Dilger	if (LINUX_S_ISREG(inode.i_mode) &&
1224a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	    (inode.i_size_high || inode.i_size & 0x80000000UL))
1225a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		ctx->large_files--;
1226a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o
12276dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
12286dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson					     deallocate_inode_block, ctx);
12291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx.errcode) {
12301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
123108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
123208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
12331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
12343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
12353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
12368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o/*
12378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This fuction clears the htree flag on an inode
12388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */
12398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
12408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{
12418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct ext2_inode	inode;
1242efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
12438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
12448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
12458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
1246b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o	if (ctx->dirs_to_hash)
1247b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o		ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
12488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o}
12498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
12508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
125186c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'oextern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
1252bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o				    ext2_ino_t ino, char *buf)
12533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
12541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
12553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct ext2_inode	inode;
12563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int			inode_modified = 0;
12576c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o	int			not_fixed = 0;
12581e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	unsigned char		*frag, *fsize;
125921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct problem_context	pctx;
126008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	int	problem = 0;
12613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
126208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
126321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
126421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	clear_problem_context(&pctx);
126521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.ino = ino;
126621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.dir = dir;
126721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.inode = &inode;
126821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
1269a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson	if (ext2fs_file_acl_block(&inode) &&
1270f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
1271f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o		if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
1272a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson			ext2fs_file_acl_block_set(&inode, 0);
1273f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o			inode_modified++;
1274f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o		} else
1275f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o			not_fixed++;
1276f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o	}
12776c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o
127850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
127950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	    !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
128050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	    !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
128108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	    !(LINUX_S_ISSOCK(inode.i_mode)))
128208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = PR_2_BAD_MODE;
1283fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISCHR(inode.i_mode)
12840684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
128508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = PR_2_BAD_CHAR_DEV;
1286fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISBLK(inode.i_mode)
12870684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
128808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = PR_2_BAD_BLOCK_DEV;
1289fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISFIFO(inode.i_mode)
12900684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
12911dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		problem = PR_2_BAD_FIFO;
1292fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISSOCK(inode.i_mode)
12930684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
12941dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		problem = PR_2_BAD_SOCKET;
1295fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISLNK(inode.i_mode)
12967cadc57780f3e3e8e644e8976e11a336902d4a25Theodore Ts'o		 && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
1297bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o		problem = PR_2_INVALID_SYMLINK;
129867052a8aeeca8cd80d1dd33c2792f917573accc8Andreas Dilger	}
12991dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o
130008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	if (problem) {
130108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		if (fix_problem(ctx, problem, &pctx)) {
13021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			deallocate_inode(ctx, ino, 0);
1303a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
130408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o				return 0;
13057cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o			return 1;
13066c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13076c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
130808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = 0;
13097cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o	}
1310efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
13116c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o	if (inode.i_faddr) {
13126c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
13136c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode.i_faddr = 0;
13146c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode_modified++;
13156c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13166c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
13173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
13181e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o
13191e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	switch (fs->super->s_creator_os) {
13201e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	    case EXT2_OS_HURD:
13211e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		frag = &inode.osd2.hurd2.h_i_frag;
13221e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		fsize = &inode.osd2.hurd2.h_i_fsize;
13231e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		break;
13241e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	    default:
13251e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		frag = fsize = 0;
13261e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	}
132721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (frag && *frag) {
132821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = *frag;
13291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
133021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			*frag = 0;
133121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			inode_modified++;
13327e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o		} else
13337e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o			not_fixed++;
133421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = 0;
133521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
133621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (fsize && *fsize) {
133721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = *fsize;
13381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
133921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			*fsize = 0;
134021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			inode_modified++;
13416c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13426c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
134321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = 0;
134421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
134521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
13465d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
1347efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	    !(fs->super->s_feature_ro_compat &
13485d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
13495d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	    (inode.osd2.linux2.l_i_blocks_hi != 0)) {
13505d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o		pctx.num = inode.osd2.linux2.l_i_blocks_hi;
13515d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o		if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
13525d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o			inode.osd2.linux2.l_i_blocks_hi = 0;
13535d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o			inode_modified++;
13545d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o		}
13555d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	}
13565d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o
1357911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	if (!(fs->super->s_feature_incompat &
1358911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	     EXT4_FEATURE_INCOMPAT_64BIT) &&
1359911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	    inode.osd2.linux2.l_i_file_acl_high != 0) {
1360911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o		pctx.num = inode.osd2.linux2.l_i_file_acl_high;
1361911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o		if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
1362911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o			inode.osd2.linux2.l_i_file_acl_high = 0;
1363911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o			inode_modified++;
1364911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o		} else
1365911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o			not_fixed++;
1366911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	}
1367911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o
1368a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson	if (ext2fs_file_acl_block(&inode) &&
1369a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson	    ((ext2fs_file_acl_block(&inode) < fs->super->s_first_data_block) ||
13704efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson	     (ext2fs_file_acl_block(&inode) >= ext2fs_blocks_count(fs->super)))) {
13716c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
1372a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson			ext2fs_file_acl_block_set(&inode, 0);
13736c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode_modified++;
13746c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13756c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
1376342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o	}
137721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (inode.i_dir_acl &&
13786c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o	    LINUX_S_ISDIR(inode.i_mode)) {
13796c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
13806c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode.i_dir_acl = 0;
13816c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode_modified++;
13826c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13836c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
138421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
13856c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o
1386f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (inode_modified)
138708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
1388f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o	if (!not_fixed && ctx->inode_bad_map)
1389c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson		ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
13903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
13913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
13923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
139350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
139450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
139550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * allocate_dir_block --- this function allocates a new directory
139650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * 	block for a particular inode; this is done if a directory has
139750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * 	a "hole" in it, or if a directory has a illegal block number
139850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * 	that was zeroed out and now needs to be replaced.
139950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
14001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx,
14016dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			      struct ext2_db_entry2 *db,
1402efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			      char *buf EXT2FS_ATTR((unused)),
1403544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			      struct problem_context *pctx)
140450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
14051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
1406c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	blk64_t			blk;
140750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char			*block;
140850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct ext2_inode	inode;
140950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
14101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
141150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
141250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
141350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
141450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Read the inode and block bitmaps in; we'll be messing with
141550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * them.
141650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
1417f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	e2fsck_read_bitmaps(ctx);
1418efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
141950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
142050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * First, find a free block
142150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
1422c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	pctx->errcode = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
14231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_new_block";
14251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
142650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
142750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
1428c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
1429c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	ext2fs_mark_block_bitmap2(fs->block_map, blk);
143050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	ext2fs_mark_bb_dirty(fs);
143150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
143250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
143350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Now let's create the actual data block for the inode
143450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
143550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (db->blockcnt)
14361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
143750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	else
14381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
14391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						     EXT2_ROOT_INO, &block);
144050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
14411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_new_dir_block";
14431b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
144450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
144550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
144650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
14471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
1448c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&block);
14491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_write_dir_block";
14511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
145250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
145350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
145450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
145550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
145650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Update the inode block count
145750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
145808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
14591ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o	ext2fs_iblk_add_blocks(fs, &inode, 1);
146050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
146150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		inode.i_size = (db->blockcnt+1) * fs->blocksize;
146208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
146350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
146450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
146550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Finally, update the block pointers for the inode
146650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
146750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	db->blk = blk;
14682d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o	pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET,
14692d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o				     db->blockcnt, 0, &blk);
14701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_block_iterate";
14721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
147350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
147450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
147550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
147650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return 0;
147750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
1478