pass2.c revision 36769c606c270094df0431cbcab9932905adcedc
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() */
45d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
4648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#include <string.h>
4748e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o
483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h"
4921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h"
500926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o#include "dict.h"
513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
52aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#ifdef NO_INLINE_FUNCS
53aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_
54aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#else
55aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ inline
56aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#endif
57aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
58ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o/* #define DX_DEBUG */
598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Keeps track of how many times an inode is referenced.
623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
634035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs,
656dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			   struct ext2_db_entry2 *dir_blocks_info,
6654dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o			   void *priv_data);
671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx,
686dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			      struct ext2_db_entry2 *dir_blocks_info,
6921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			      char *buf, struct problem_context *pctx);
708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
71ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir,
72ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		       struct dx_dirblock_info *dx_db);
73ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
7521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostruct check_dir_struct {
7621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	char *buf;
7721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct problem_context	pctx;
78f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	int	count, max;
791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	e2fsck_t ctx;
80efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o};
8121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
8208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass2(e2fsck_t ctx)
833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
84a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	struct ext2_super_block *sb = ctx->fs->super;
85a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	struct problem_context	pctx;
86a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	ext2_filsys 		fs = ctx->fs;
87a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	char			*buf;
888bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK
893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct resource_track	rtrack;
908bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif
9121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct check_dir_struct cd;
928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dir_info	*dx_dir;
938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dirblock_info	*dx_db, *dx_parent;
94830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o	unsigned int		save_type;
95544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	int			b;
96ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	int			i, depth;
978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	problem_t		code;
988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	int			bad_dir;
998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
1006d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	init_resource_track(&rtrack, ctx->fs->io);
1011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	clear_problem_context(&cd.pctx);
1021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE
1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	mtrace_print("Pass 2");
1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (!(ctx->options & E2F_OPT_PREEN))
1081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
1091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
110efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT,
11134b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o				&ctx->inode_count);
11234b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o	if (ctx->inode_count)
11334b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o		cd.pctx.errcode = 0;
114830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o	else {
115830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o		e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE,
116830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o				       "inode_count", &save_type);
117efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		cd.pctx.errcode = ext2fs_create_icount2(fs,
11834b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o						EXT2_ICOUNT_OPT_INCREMENT,
1191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						0, ctx->inode_link_info,
1201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						&ctx->inode_count);
121830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o		fs->default_bitmap_type = save_type;
122830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o	}
1231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (cd.pctx.errcode) {
1241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
12508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
12608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
12721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
128bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o	buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
12954dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o					      "directory scan buffer");
1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
13121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	/*
13221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 * Set up the parent pointer for the root directory, if
13321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 * present.  (If the root directory is not present, we will
13421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 * create it in pass 3.)
13521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	 */
13628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	(void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
13721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
13821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd.buf = buf;
1391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	cd.ctx = ctx;
140f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o	cd.count = 1;
1416dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	cd.max = ext2fs_dblist_count2(fs->dblist);
142f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o
143f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o	if (ctx->progress)
144f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o		(void) (ctx->progress)(ctx, 2, 0, cd.max);
145ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
146ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
1476dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp);
148efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1496dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block,
1506dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson						 &cd);
15149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
15208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
1536267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger
1546267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger	if (ctx->flags & E2F_FLAG_RESTART_LATER) {
1556267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger		ctx->flags |= E2F_FLAG_RESTART;
1566267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger		return;
1576267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger	}
1586267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger
1591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (cd.pctx.errcode) {
1601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
16108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
16208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
1637ac02a5ebddcc6187c893eedc80d92777b399575Theodore Ts'o	}
1648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
1658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
1668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
1674cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
1684cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o			return;
16962acaa1de132a808949d71264731bba7fe095705Theodore Ts'o		if (dx_dir->numblocks == 0)
1708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			continue;
1718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		clear_problem_context(&pctx);
1728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		bad_dir = 0;
1738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		pctx.dir = dx_dir->ino;
1748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db = dx_dir->dx_block;
1758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (dx_db->flags & DX_FLAG_REFERENCED)
1768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_DUP_REF;
1778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		else
1788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_REFERENCED;
1798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		/*
1808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		 * Find all of the first and last leaf blocks, and
1818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		 * update their parent's min and max hash values
1828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		 */
1838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		for (b=0, dx_db = dx_dir->dx_block;
1848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b < dx_dir->numblocks;
1858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b++, dx_db++) {
1868fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
1878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			    !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
1888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				continue;
1898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_parent = &dx_dir->dx_block[dx_db->parent];
1908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			/*
1918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
1928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 */
1938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (dx_db->flags & DX_FLAG_FIRST)
1948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				dx_parent->min_hash = dx_db->min_hash;
1958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			/*
1968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
1978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 */
1988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (dx_db->flags & DX_FLAG_LAST)
1998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				dx_parent->max_hash = dx_db->max_hash;
2008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
201efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
2028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		for (b=0, dx_db = dx_dir->dx_block;
2038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b < dx_dir->numblocks;
2048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		     b++, dx_db++) {
2058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			pctx.blkcount = b;
2068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			pctx.group = dx_db->parent;
2078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			code = 0;
2088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (!(dx_db->flags & DX_FLAG_FIRST) &&
2098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			    (dx_db->min_hash < dx_db->node_min_hash)) {
2108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk = dx_db->min_hash;
2118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk2 = dx_db->node_min_hash;
2128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_MIN_HASH;
2138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
2148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				bad_dir++;
2158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			}
216ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			if (dx_db->type == DX_DIRBLOCK_LEAF) {
217ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				depth = htree_depth(dx_dir, dx_db);
218ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				if (depth != dx_dir->depth) {
219e5e12db959d3c18f6cf4ac938a14f68be0a89accAndreas Dilger					pctx.num = dx_dir->depth;
220ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					code = PR_2_HTREE_BAD_DEPTH;
221ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					fix_problem(ctx, code, &pctx);
222ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					bad_dir++;
223ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				}
224ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			}
2258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			/*
226efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			 * This test doesn't apply for the root block
2278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 * at block #0
2288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			 */
2298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (b &&
2308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			    (dx_db->max_hash > dx_db->node_max_hash)) {
2318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk = dx_db->max_hash;
2328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				pctx.blk2 = dx_db->node_max_hash;
2338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_MAX_HASH;
2348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
235503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o				bad_dir++;
2368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			}
2378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
2388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_NOTREF;
2398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
2408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				bad_dir++;
2418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			} else if (dx_db->flags & DX_FLAG_DUP_REF) {
2428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				code = PR_2_HTREE_DUPREF;
2438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				fix_problem(ctx, code, &pctx);
2448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o				bad_dir++;
2458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			}
2468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
2478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
2488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			clear_htree(ctx, dx_dir->ino);
24962acaa1de132a808949d71264731bba7fe095705Theodore Ts'o			dx_dir->numblocks = 0;
2508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
2518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
25223f75f6efaac6b756e0f3e4e1d33b6798347f66aTheodore Ts'o	e2fsck_free_dx_dir_info(ctx);
2538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
254c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&buf);
25521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	ext2fs_free_dblist(fs->dblist);
25621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
2571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->inode_bad_map) {
2581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ctx->inode_bad_map = 0;
2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
261aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (ctx->inode_reg_map) {
262aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
263aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		ctx->inode_reg_map = 0;
264aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	}
265a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o
266a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	clear_problem_context(&pctx);
267a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	if (ctx->large_files) {
268a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		if (!(sb->s_feature_ro_compat &
269a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		      EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
270a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		    fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
271a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			sb->s_feature_ro_compat |=
272a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o				EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
2730cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
274a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			ext2fs_mark_super_dirty(fs);
275a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		}
276a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
277a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		    fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
278a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			ext2fs_update_dynamic_rev(fs);
279a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o			ext2fs_mark_super_dirty(fs);
280a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		}
281a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o	}
282efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
2839facd076ae8af6e908e228392cea866ce0faf1bcKen Chen	print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io);
2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
286ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o#define MAX_DEPTH 32000
287ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir,
288ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		       struct dx_dirblock_info *dx_db)
289ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o{
290ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	int	depth = 0;
291ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
292ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
293ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		dx_db = &dx_dir->dx_block[dx_db->parent];
294ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		depth++;
295ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
296ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	return depth;
297ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o}
298ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
2990926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'ostatic int dict_de_cmp(const void *a, const void *b)
3000926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o{
301520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o	const struct ext2_dir_entry *de_a, *de_b;
3020926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	int	a_len, b_len;
3030926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
304520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o	de_a = (const struct ext2_dir_entry *) a;
3050926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	a_len = de_a->name_len & 0xFF;
306520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o	de_b = (const struct ext2_dir_entry *) b;
3070926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	b_len = de_b->name_len & 0xFF;
3080926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
3090926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	if (a_len != b_len)
3100926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		return (a_len - b_len);
3110926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
3120926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	return strncmp(de_a->name, de_b->name, a_len);
3130926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o}
314ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
3153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
316ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This is special sort function that makes sure that directory blocks
317ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * with a dirblock of zero are sorted to the beginning of the list.
318ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This guarantees that the root node of the htree directories are
319ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * processed first, so we know what hash version to use.
320ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o */
321ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
322ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{
3236dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	const struct ext2_db_entry2 *db_a =
3246dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		(const struct ext2_db_entry2 *) a;
3256dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	const struct ext2_db_entry2 *db_b =
3266dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson		(const struct ext2_db_entry2 *) b;
327ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
328ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (db_a->blockcnt && !db_b->blockcnt)
329ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return 1;
330ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
331ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (!db_a->blockcnt && db_b->blockcnt)
332ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return -1;
333efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
334ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (db_a->blk != db_b->blk)
335ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return (int) (db_a->blk - db_b->blk);
336efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
337ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	if (db_a->ino != db_b->ino)
338ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o		return (int) (db_a->ino - db_b->ino);
339ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
340ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	return (int) (db_a->blockcnt - db_b->blockcnt);
341ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o}
342ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
343ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o
344ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o/*
3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the first entry in the directory is '.', and that the
3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane.
3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
3481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dot(e2fsck_t ctx,
3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		     struct ext2_dir_entry *dirent,
35086c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o		     ext2_ino_t ino, struct problem_context *pctx)
3513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
3523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct ext2_dir_entry *nextdir;
3538a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	unsigned int	rec_len, new_len;
3543c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o	int		status = 0;
3553c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o	int		created = 0;
3563c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o	problem_t	problem = 0;
357efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
35821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (!dirent->inode)
35921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_MISSING_DOT;
360b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o	else if (((dirent->name_len & 0xFF) != 1) ||
36121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		 (dirent->name[0] != '.'))
36221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_1ST_NOT_DOT;
36321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	else if (dirent->name[1] != '\0')
36421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_DOT_NULL_TERM;
3655dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o
3668a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
36721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (problem) {
3681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, problem, pctx)) {
3695dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o			if (rec_len < 12)
3705dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o				rec_len = dirent->rec_len = 12;
3713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->inode = ino;
3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name_len = 1;
3733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name[0] = '.';
37421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			dirent->name[1] = '\0';
3753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			status = 1;
3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			created = 1;
3773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (dirent->inode != ino) {
3801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->inode = ino;
3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			status = 1;
38321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		}
3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3855dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	if (rec_len > 12) {
3865dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		new_len = rec_len - 12;
3873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (new_len > 12) {
3883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (created ||
389f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o			    fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
3903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				nextdir = (struct ext2_dir_entry *)
3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					((char *) dirent + 12);
3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dirent->rec_len = 12;
3938a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o				(void) ext2fs_set_rec_len(ctx->fs, new_len,
3948a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o							  nextdir);
3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				nextdir->inode = 0;
3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				nextdir->name_len = 0;
3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				status = 1;
3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
3993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return status;
4023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
4053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the second entry in the directory is '..', and that the
4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane.  We do not check the inode number of '..'
4073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * here; this gets done in pass 3.
4083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
4091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dotdot(e2fsck_t ctx,
4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			struct ext2_dir_entry *dirent,
41128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o			ext2_ino_t ino, struct problem_context *pctx)
4123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
4133c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o	problem_t	problem = 0;
414cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger	unsigned int	rec_len;
415efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
41621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (!dirent->inode)
41721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_MISSING_DOT_DOT;
418b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o	else if (((dirent->name_len & 0xFF) != 2) ||
41921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		 (dirent->name[0] != '.') ||
42021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		 (dirent->name[1] != '.'))
42121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_2ND_NOT_DOT_DOT;
42221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	else if (dirent->name[2] != '\0')
42321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		problem = PR_2_DOT_DOT_NULL_TERM;
42421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
4258a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
42621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (problem) {
4271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, problem, pctx)) {
4285dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o			if (rec_len < 12)
42921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				dirent->rec_len = 12;
4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			/*
4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 * Note: we don't have the parent inode just
4323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 * yet, so we will fill it in with the root
4333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 * inode.  This will get fixed in pass 3.
4343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 */
4353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->inode = EXT2_ROOT_INO;
4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name_len = 2;
4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name[0] = '.';
4383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			dirent->name[1] = '.';
43921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			dirent->name[2] = '\0';
4403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			return 1;
441efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		}
4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
44428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) {
44528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o		fix_problem(ctx, PR_2_NO_DIRINFO, pctx);
44628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o		return -1;
44728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	}
4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
4493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Check to make sure a directory entry doesn't contain any illegal
4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * characters.
4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
4551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_name(e2fsck_t ctx,
4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		      struct ext2_dir_entry *dirent,
457efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
458544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		      struct problem_context *pctx)
4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	i;
4613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	fixup = -1;
4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int	ret = 0;
463efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
464b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o	for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
4663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fixup < 0) {
4671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
4693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fixup) {
4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dirent->name[i] = '.';
4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				ret = 1;
47221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			}
4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
4743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return ret;
4763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
478aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o/*
479aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * Check the directory filetype (if present)
480aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o */
481aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'ostatic _INLINE_ int check_filetype(e2fsck_t ctx,
482544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   struct ext2_dir_entry *dirent,
483544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
484544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   struct problem_context *pctx)
485aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o{
486aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	int	filetype = dirent->name_len >> 8;
487aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	int	should_be = EXT2_FT_UNKNOWN;
488aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	struct ext2_inode	inode;
489aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
490aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (!(ctx->fs->super->s_feature_incompat &
4917847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o	      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
4927847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		if (filetype == 0 ||
4937847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
4947847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o			return 0;
4957847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		dirent->name_len = dirent->name_len & 0xFF;
4967847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o		return 1;
4977847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o	}
498aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
499c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
500aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		should_be = EXT2_FT_DIR;
501c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	} else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
502aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o					    dirent->inode)) {
503aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		should_be = EXT2_FT_REG_FILE;
504aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	} else if (ctx->inode_bad_map &&
505c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson		   ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
506aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o					    dirent->inode))
507aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		should_be = 0;
508aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	else {
509aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		e2fsck_read_inode(ctx, dirent->inode, &inode,
510aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o				  "check_filetype");
5116fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		should_be = ext2_file_type(inode.i_mode);
512aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	}
513aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (filetype == should_be)
514aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		return 0;
515aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	pctx->num = should_be;
516aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
517aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
518aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o			pctx) == 0)
519aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		return 0;
520efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
521aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
522aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o	return 1;
523aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o}
524aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
5258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
5268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void parse_int_node(ext2_filsys fs,
5276dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			   struct ext2_db_entry2 *db,
5288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			   struct check_dir_struct *cd,
5298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			   struct dx_dir_info	*dx_dir,
5308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			   char *block_buf)
5318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{
5328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct 		ext2_dx_root_info  *root;
5338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct 		ext2_dx_entry *ent;
5348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct		ext2_dx_countlimit *limit;
5358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dirblock_info	*dx_db;
536ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	int		i, expect_limit, count;
5378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	blk_t		blk;
5388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	ext2_dirhash_t	min_hash = 0xffffffff;
5398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	ext2_dirhash_t	max_hash = 0;
540ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	ext2_dirhash_t	hash = 0, prev_hash;
5418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	if (db->blockcnt == 0) {
5438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		root = (struct ext2_dx_root_info *) (block_buf + 24);
544efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
5468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("Root node dump:\n");
5478deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato		printf("\t Reserved zero: %u\n", root->reserved_zero);
5488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Hash Version: %d\n", root->hash_version);
5498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Info length: %d\n", root->info_length);
5508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Indirect levels: %d\n", root->indirect_levels);
5518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		printf("\t Flags: %d\n", root->unused_flags);
5528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
5538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	} else {
5568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		ent = (struct ext2_dx_entry *) (block_buf+8);
5578fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
5588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	limit = (struct ext2_dx_countlimit *) ent;
5598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
561efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	printf("Number of entries (count): %d\n",
5628132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	       ext2fs_le16_to_cpu(limit->count));
563efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	printf("Number of entries (limit): %d\n",
5648132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	       ext2fs_le16_to_cpu(limit->limit));
5658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
5668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
5678132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	count = ext2fs_le16_to_cpu(limit->count);
568ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
569ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		sizeof(struct ext2_dx_entry);
5708132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5718132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
572ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
573ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			goto clear_and_exit;
574ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
5758132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o	if (count > expect_limit) {
5768132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		cd->pctx.num = count;
577ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
578ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			goto clear_and_exit;
579ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		count = expect_limit;
580ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
581efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
582ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	for (i=0; i < count; i++) {
583ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		prev_hash = hash;
5848132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
5868deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato		printf("Entry #%d: Hash 0x%08x, block %u\n", i,
5878132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		       hash, ext2fs_le32_to_cpu(ent[i].block));
5888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
5898132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		/* Check to make sure the block is valid */
591977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o		if (blk >= (blk_t) dx_dir->numblocks) {
592b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o			cd->pctx.blk = blk;
5938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
594ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o					&cd->pctx))
595ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				goto clear_and_exit;
596977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o			continue;
5978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
598ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		if (hash < prev_hash &&
599ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		    fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
600ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			goto clear_and_exit;
6018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db = &dx_dir->dx_block[blk];
6028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (dx_db->flags & DX_FLAG_REFERENCED) {
6038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_DUP_REF;
6048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		} else {
6058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_REFERENCED;
6068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->parent = db->blockcnt;
6078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
6088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (hash < min_hash)
6098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			min_hash = hash;
6108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (hash > max_hash)
6118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			max_hash = hash;
6128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->node_min_hash = hash;
6138132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o		if ((i+1) < count)
614efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			dx_db->node_max_hash =
6158132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o			  ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
6168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		else {
6178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->node_max_hash = 0xfffffffe;
6188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_LAST;
6198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
6208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (i == 0)
6218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_FIRST;
6228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
6238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG
6248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
6258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	       db->blockcnt, min_hash, max_hash);
6268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif
6278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_db = &dx_dir->dx_block[db->blockcnt];
6288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_db->min_hash = min_hash;
6298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_db->max_hash = max_hash;
630ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	return;
631ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o
632ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'oclear_and_exit:
633ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	clear_htree(cd->ctx, cd->pctx.ino);
634ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	dx_dir->numblocks = 0;
6358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o}
6368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
637aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o
638e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o/*
639e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Given a busted directory, try to salvage it somehow.
640efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
641e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */
642ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic void salvage_directory(ext2_filsys fs,
643e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o			      struct ext2_dir_entry *dirent,
644e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o			      struct ext2_dir_entry *prev,
645544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			      unsigned int *offset)
646e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o{
647e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	char	*cp = (char *) dirent;
6488a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	int left;
6498a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	unsigned int rec_len, prev_rec_len;
650642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o	unsigned int name_len = dirent->name_len & 0xFF;
651e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o
6528a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
6535dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	left = fs->blocksize - *offset - rec_len;
6545dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o
655e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	/*
656e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * Special case of directory entry of size 8: copy what's left
657e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * of the directory block up to cover up the invalid hole.
658e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 */
6595dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	if ((left >= 12) && (rec_len == 8)) {
660e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		memmove(cp, cp+8, left);
661e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		memset(cp + left, 0, 8);
662ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		return;
663ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	}
664ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	/*
665ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 * If the directory entry overruns the end of the directory
666ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 * block, and the name is small enough to fit, then adjust the
667ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 * record length.
668ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	 */
669ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	if ((left < 0) &&
6708a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	    ((int) rec_len + left > 8) &&
67168477355a9f3b4ca46dfa6c34d05105dcc6682adTheodore Ts'o	    ((int) name_len + 8 <= (int) rec_len + left) &&
672ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	    dirent->inode <= fs->super->s_inodes_count &&
673ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o	    strnlen(dirent->name, name_len) == name_len) {
6748a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent);
675ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		return;
676e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	}
677e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	/*
678575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah	 * If the record length of the directory entry is a multiple
679575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah	 * of four, and not too big, such that it is valid, let the
680575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah	 * previous directory entry absorb the invalid one.
681e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 */
6825dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	if (prev && rec_len && (rec_len % 4) == 0 &&
6835dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o	    (*offset + rec_len <= fs->blocksize)) {
6848a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
6858a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		prev_rec_len += rec_len;
6868a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
6875dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		*offset += rec_len;
688ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		return;
689e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	}
690e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	/*
691e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * Default salvage method --- kill all of the directory
692e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * entries for the rest of the block.  We will either try to
693e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * absorb it into the previous directory entry, or create a
694e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 * new empty directory entry the rest of the directory block.
695e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	 */
696e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	if (prev) {
6978a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
6988a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		prev_rec_len += fs->blocksize - *offset;
6998a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
700ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o		*offset = fs->blocksize;
701e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	} else {
7028a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		rec_len = fs->blocksize - *offset;
7038a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_set_rec_len(fs, rec_len, dirent);
704e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		dirent->name_len = 0;
705e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o		dirent->inode = 0;
706e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	}
707e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o}
708e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o
7093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs,
7106dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			   struct ext2_db_entry2 *db,
71154dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o			   void *priv_data)
7123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
7138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 	struct dx_dir_info	*dx_dir;
7148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
7158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct dx_dirblock_info	*dx_db = 0;
7168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
717e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	struct ext2_dir_entry 	*dirent, *prev;
7188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	ext2_dirhash_t		hash;
719544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int		offset = 0;
7203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int			dir_modified = 0;
72121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	int			dot_state;
72203fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o	unsigned int		rec_len;
7236dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	blk64_t			block_nr = db->blk;
72486c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o	ext2_ino_t 		ino = db->ino;
72528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	ext2_ino_t 		subdir_parent;
72621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	__u16			links;
72754dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	struct check_dir_struct	*cd;
7281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	char 			*buf;
7291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	e2fsck_t		ctx;
7303c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o	problem_t		problem;
731ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o	struct ext2_dx_root_info *root;
732e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o	struct ext2_dx_countlimit *limit;
7330926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	static dict_t de_dict;
7340926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	struct problem_context	pctx;
7350926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	int	dups_found = 0;
73628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o	int	ret;
7371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
73854dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	cd = (struct check_dir_struct *) priv_data;
7391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	buf = cd->buf;
7401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ctx = cd->ctx;
741f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o
74249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
7434cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		return DIRENT_ABORT;
744efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
7454cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o	if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7464cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		return DIRENT_ABORT;
747efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
7483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	/*
749efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 * Make sure the inode is still in use (could have been
7503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * deleted in the duplicate/bad blocks pass.
7513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 */
752c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino)))
7533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
75450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
75521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.ino = ino;
75621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.blk = block_nr;
75721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.blkcount = db->blockcnt;
75821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.ino2 = 0;
75921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.dirent = 0;
76021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	cd->pctx.num = 0;
76121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
76250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (db->blk == 0) {
7631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (allocate_dir_block(ctx, db, buf, &cd->pctx))
76450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			return 0;
76550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		block_nr = db->blk;
76650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
767efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
7683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (db->blockcnt)
7693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		dot_state = 2;
7703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else
7713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		dot_state = 0;
7723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
7730926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	if (ctx->dirs_to_hash &&
7740926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	    ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7750926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o		dups_found++;
7760926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o
7773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0
778f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	       db->blockcnt, ino);
7803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
781efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
782f85a9ae6397ff074193322a12ed721dbf5751e41Eric Sandeen	ehandler_operation(_("reading directory block"));
7836dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	cd->pctx.errcode = ext2fs_read_dir_block3(fs, block_nr, buf, 0);
784e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	ehandler_operation(0);
785b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o	if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
786b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o		cd->pctx.errcode = 0; /* We'll handle this ourselves */
7871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (cd->pctx.errcode) {
78808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
78908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			ctx->flags |= E2F_FLAG_ABORT;
79008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			return DIRENT_ABORT;
79108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		}
7921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		memset(buf, 0, fs->blocksize);
7933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
7948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE
7958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
79662acaa1de132a808949d71264731bba7fe095705Theodore Ts'o	if (dx_dir && dx_dir->numblocks) {
7978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (db->blockcnt >= dx_dir->numblocks) {
798ea9085c711e92c3727538a0637bc805141333d83Darrick J. Wong			pctx.dir = ino;
799efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK,
800d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o					&pctx)) {
801d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				clear_htree(ctx, ino);
802d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				dx_dir->numblocks = 0;
803d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				dx_db = 0;
804d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o				goto out_htree;
805d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o			}
806d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o			fatal_error(ctx, _("Can not continue."));
8078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		}
8088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db = &dx_dir->dx_block[db->blockcnt];
8098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->type = DX_DIRBLOCK_LEAF;
8108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->phys = block_nr;
8118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->min_hash = ~0;
8128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dx_db->max_hash = 0;
813efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
8148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		dirent = (struct ext2_dir_entry *) buf;
8158a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
816e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o		limit = (struct ext2_dx_countlimit *) (buf+8);
8178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		if (db->blockcnt == 0) {
818ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			root = (struct ext2_dx_root_info *) (buf + 24);
8198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->type = DX_DIRBLOCK_ROOT;
8208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
821ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			if ((root->reserved_zero ||
822ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			     root->info_length < 8 ||
823ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			     root->indirect_levels > 1) &&
824ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			    fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
825ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o				clear_htree(ctx, ino);
826ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o				dx_dir->numblocks = 0;
827ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o				dx_db = 0;
828f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			}
829ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o			dx_dir->hashversion = root->hash_version;
830f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			if ((dx_dir->hashversion <= EXT2_HASH_TEA) &&
831f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			    (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
832f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o				dx_dir->hashversion += 3;
833ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o			dx_dir->depth = root->indirect_levels + 1;
8348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o		} else if ((dirent->inode == 0) &&
8355dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o			   (rec_len == fs->blocksize) &&
836e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o			   (dirent->name_len == 0) &&
837efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   (ext2fs_le16_to_cpu(limit->limit) ==
838efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			    ((fs->blocksize-8) /
8398132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o			     sizeof(struct ext2_dx_entry))))
8408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o			dx_db->type = DX_DIRBLOCK_NODE;
8418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	}
842d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'oout_htree:
8438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */
8443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
8450926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o	dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
846e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o	prev = 0;
8473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	do {
8483971bfe878d6c30f9b5be3a2c0310943982a4775Theodore Ts'o		dgrp_t group;
84949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		ext2_ino_t first_unused_inode;
85049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
8511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		problem = 0;
8523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		dirent = (struct ext2_dir_entry *) (buf + offset);
8538a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
85421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		cd->pctx.dirent = dirent;
85521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		cd->pctx.num = offset;
8565dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		if (((offset + rec_len) > fs->blocksize) ||
8575dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		    (rec_len < 12) ||
8585dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		    ((rec_len % 4) != 0) ||
85903fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o		    (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) {
8601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
861ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o				salvage_directory(fs, dirent, prev, &offset);
8623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				dir_modified++;
863e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o				continue;
86421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			} else
8650926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o				goto abort_free_dict;
8663839e65723771b85975f4263102dd3ceec4523cTheodore 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) {
11367bef6d52125ef3f1ef07d9da71a13546f6843c56Kit Westneat		cd->pctx.errcode = ext2fs_write_dir_block3(fs, block_nr, buf, 0);
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
1152624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kalistruct del_block {
1153624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	e2fsck_t	ctx;
1154624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	e2_blkcnt_t	num;
1155624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali};
1156624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali
11573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
11583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This function is called to deallocate a block, and is an interator
11593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * functioned called by deallocate inode via ext2fs_iterate_block().
11603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
11613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int deallocate_inode_block(ext2_filsys fs,
11626dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson				  blk64_t	*block_nr,
1163544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				  e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
11646dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson				  blk64_t ref_block EXT2FS_ATTR((unused)),
1165544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				  int ref_offset EXT2FS_ATTR((unused)),
1166133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o				  void *priv_data)
11673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1168624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	struct del_block *p = priv_data;
1169efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
11701917875fcd16428d14eb5a86acf414472bc216f1Theodore Ts'o	if (HOLE_BLKADDR(*block_nr))
11713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
11721ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o	if ((*block_nr < fs->super->s_first_data_block) ||
11734efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson	    (*block_nr >= ext2fs_blocks_count(fs->super)))
11741ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o		return 0;
11758dd650ab9ac394c6d6d19b02e8bb22d5a1e5da0dDarrick J. Wong	if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0)
11768dd650ab9ac394c6d6d19b02e8bb22d5a1e5da0dDarrick J. Wong		ext2fs_block_alloc_stats2(fs, *block_nr, -1);
1177624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	p->num++;
11783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
11793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1180efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
11813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
11823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This fuction deallocates an inode
11833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
11844035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
11853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
11861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
11873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct ext2_inode	inode;
11881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	struct problem_context	pctx;
11890684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	__u32			count;
1190624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	struct del_block	del_block;
1191efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
119208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
11931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	clear_problem_context(&pctx);
11941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	pctx.ino = ino;
1195f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
11963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	/*
11973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * Fix up the bitmaps...
11983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 */
1199f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	e2fsck_read_bitmaps(ctx);
12000684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
12010684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o
12020c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o	if (ext2fs_file_acl_block(fs, &inode) &&
12030684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
12040c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o		pctx.errcode = ext2fs_adjust_ea_refcount2(fs,
12050c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o					ext2fs_file_acl_block(fs, &inode),
12060c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o					block_buf, -1, &count);
12070684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
12080684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			pctx.errcode = 0;
12090684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			count = 1;
12100684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
12110684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (pctx.errcode) {
12120c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o			pctx.blk = ext2fs_file_acl_block(fs, &inode);
12130684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
12140684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			ctx->flags |= E2F_FLAG_ABORT;
12150684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			return;
12160684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
12170684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (count == 0) {
121848f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson			ext2fs_block_alloc_stats2(fs,
12190c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o				  ext2fs_file_acl_block(fs, &inode), -1);
12200684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
12210c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o		ext2fs_file_acl_block_set(fs, &inode, 0);
12220684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	}
12233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
12240c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o	if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
1225c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o		goto clear_inode;
1226a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o
12273b6c0938ec5aa401c7ae6c95e94e5ad30a7b8562Darrick J. Wong	if (LINUX_S_ISREG(inode.i_mode) &&
12283b6c0938ec5aa401c7ae6c95e94e5ad30a7b8562Darrick J. Wong	    ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode)))
1229a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o		ctx->large_files--;
1230a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o
1231624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	del_block.ctx = ctx;
1232624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali	del_block.num = 0;
12336dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson	pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
1234624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali					     deallocate_inode_block,
1235624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali					     &del_block);
12361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx.errcode) {
12371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
123808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
123908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
12401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
1241c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'oclear_inode:
1242c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o	/* Inode may have changed by block_iterate, so reread it */
1243c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
1244c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o	e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
12453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
12463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
12478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o/*
12488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This fuction clears the htree flag on an inode
12498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */
12508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
12518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{
12528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	struct ext2_inode	inode;
1253efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
12548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
12558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
12568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o	e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
1257b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o	if (ctx->dirs_to_hash)
1258b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o		ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
12598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o}
12608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
12618fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o
1262f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'oint e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
1263f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'o			     ext2_ino_t ino, char *buf)
12643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
12651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
12663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct ext2_inode	inode;
12673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int			inode_modified = 0;
12686c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o	int			not_fixed = 0;
12691e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	unsigned char		*frag, *fsize;
127021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct problem_context	pctx;
12713c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o	problem_t		problem = 0;
12723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
127308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
127421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
127521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	clear_problem_context(&pctx);
127621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.ino = ino;
127721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.dir = dir;
127821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.inode = &inode;
127921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
12800c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o	if (ext2fs_file_acl_block(fs, &inode) &&
1281f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
1282f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o		if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
12830c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o			ext2fs_file_acl_block_set(fs, &inode, 0);
1284f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o			inode_modified++;
1285f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o		} else
1286f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o			not_fixed++;
1287f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o	}
12886c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o
128950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
129050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	    !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
129150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	    !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
129208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	    !(LINUX_S_ISSOCK(inode.i_mode)))
129308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = PR_2_BAD_MODE;
1294fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISCHR(inode.i_mode)
12950684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
129608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = PR_2_BAD_CHAR_DEV;
1297fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISBLK(inode.i_mode)
12980684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
129908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = PR_2_BAD_BLOCK_DEV;
1300fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISFIFO(inode.i_mode)
13010684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
13021dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		problem = PR_2_BAD_FIFO;
1303fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISSOCK(inode.i_mode)
13040684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		 && !e2fsck_pass1_check_device_inode(fs, &inode))
13051dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		problem = PR_2_BAD_SOCKET;
1306fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o	else if (LINUX_S_ISLNK(inode.i_mode)
13077cadc57780f3e3e8e644e8976e11a336902d4a25Theodore Ts'o		 && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
1308bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o		problem = PR_2_INVALID_SYMLINK;
130967052a8aeeca8cd80d1dd33c2792f917573accc8Andreas Dilger	}
13101dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o
131108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	if (problem) {
131208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		if (fix_problem(ctx, problem, &pctx)) {
13131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			deallocate_inode(ctx, ino, 0);
1314a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
131508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o				return 0;
13167cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o			return 1;
13176c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13186c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
131908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		problem = 0;
13207cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o	}
1321efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
13226c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o	if (inode.i_faddr) {
13236c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
13246c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode.i_faddr = 0;
13256c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode_modified++;
13266c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13276c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
13283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
13291e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o
13301e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	switch (fs->super->s_creator_os) {
13311e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	    case EXT2_OS_HURD:
13321e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		frag = &inode.osd2.hurd2.h_i_frag;
13331e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		fsize = &inode.osd2.hurd2.h_i_fsize;
13341e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		break;
13351e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	    default:
13361e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		frag = fsize = 0;
13371e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	}
133821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (frag && *frag) {
133921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = *frag;
13401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
134121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			*frag = 0;
134221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			inode_modified++;
13437e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o		} else
13447e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o			not_fixed++;
134521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = 0;
134621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
134721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (fsize && *fsize) {
134821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = *fsize;
13491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
135021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			*fsize = 0;
135121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			inode_modified++;
13526c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13536c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
135421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		pctx.num = 0;
135521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
135621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
13575d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
1358efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	    !(fs->super->s_feature_ro_compat &
13595d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
13605d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	    (inode.osd2.linux2.l_i_blocks_hi != 0)) {
13615d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o		pctx.num = inode.osd2.linux2.l_i_blocks_hi;
13625d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o		if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
13635d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o			inode.osd2.linux2.l_i_blocks_hi = 0;
13645d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o			inode_modified++;
13655d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o		}
13665d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o	}
13675d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o
136836769c606c270094df0431cbcab9932905adcedcJustus Winter	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
136936769c606c270094df0431cbcab9932905adcedcJustus Winter	    !(fs->super->s_feature_incompat &
1370911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	     EXT4_FEATURE_INCOMPAT_64BIT) &&
1371911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	    inode.osd2.linux2.l_i_file_acl_high != 0) {
1372911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o		pctx.num = inode.osd2.linux2.l_i_file_acl_high;
1373911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o		if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
1374911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o			inode.osd2.linux2.l_i_file_acl_high = 0;
1375911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o			inode_modified++;
1376911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o		} else
1377911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o			not_fixed++;
1378911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o	}
1379911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o
13800c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o	if (ext2fs_file_acl_block(fs, &inode) &&
13810c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o	    ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) ||
13820c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o	     (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) {
13836c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
13840c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o			ext2fs_file_acl_block_set(fs, &inode, 0);
13856c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode_modified++;
13866c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13876c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
1388342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o	}
138921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	if (inode.i_dir_acl &&
13906c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o	    LINUX_S_ISDIR(inode.i_mode)) {
13916c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
13926c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode.i_dir_acl = 0;
13936c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			inode_modified++;
13946c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o		} else
13956c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o			not_fixed++;
139621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
13976c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o
1398f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (inode_modified)
139908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
1400f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o	if (!not_fixed && ctx->inode_bad_map)
1401c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson		ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
14023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
14033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
14043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
140550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
140650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
140750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * allocate_dir_block --- this function allocates a new directory
140850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * 	block for a particular inode; this is done if a directory has
140950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * 	a "hole" in it, or if a directory has a illegal block number
141050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * 	that was zeroed out and now needs to be replaced.
141150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
14121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx,
14136dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson			      struct ext2_db_entry2 *db,
1414efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			      char *buf EXT2FS_ATTR((unused)),
1415544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			      struct problem_context *pctx)
141650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
14171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
1418ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong	blk64_t			blk = 0;
141950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char			*block;
142050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct ext2_inode	inode;
142150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
14221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
142350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
142450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
142550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
142650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Read the inode and block bitmaps in; we'll be messing with
142750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * them.
142850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
1429f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	e2fsck_read_bitmaps(ctx);
1430efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
143150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
143250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * First, find a free block
143350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
1434ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong	e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
1435ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong	pctx->errcode = ext2fs_map_cluster_block(fs, db->ino, &inode,
1436ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong						 db->blockcnt, &blk);
1437ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong	if (pctx->errcode || blk == 0) {
1438ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong		pctx->errcode = ext2fs_new_block2(fs, 0,
1439ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong						  ctx->block_found_map, &blk);
1440ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong		if (pctx->errcode) {
1441ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong			pctx->str = "ext2fs_new_block";
1442ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong			fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
1443ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong			return 1;
1444ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong		}
144550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
1446c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
1447c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson	ext2fs_mark_block_bitmap2(fs->block_map, blk);
144850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	ext2fs_mark_bb_dirty(fs);
144950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
145050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
145150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Now let's create the actual data block for the inode
145250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
145350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (db->blockcnt)
14541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
145550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	else
14561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
14571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o						     EXT2_ROOT_INO, &block);
145850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
14591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_new_dir_block";
14611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
146250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
146350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
146450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
14657bef6d52125ef3f1ef07d9da71a13546f6843c56Kit Westneat	pctx->errcode = ext2fs_write_dir_block3(fs, blk, block, 0);
1466c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&block);
14671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_write_dir_block";
14691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
147050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
147150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
147250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
147350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
147450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Update the inode block count
147550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
14761ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o	ext2fs_iblk_add_blocks(fs, &inode, 1);
147797c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong	if (EXT2_I_SIZE(&inode) < (db->blockcnt+1) * fs->blocksize) {
147897c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong		pctx->errcode = ext2fs_inode_size_set(fs, &inode,
147997c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong					(db->blockcnt+1) * fs->blocksize);
148097c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong		if (pctx->errcode) {
148197c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong			pctx->str = "ext2fs_inode_size_set";
148297c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong			fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
148397c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong			return 1;
148497c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong		}
148597c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong	}
148608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
148750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
148850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
148950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Finally, update the block pointers for the inode
149050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
149150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	db->blk = blk;
14922d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o	pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET,
14932d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o				     db->blockcnt, 0, &blk);
14941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (pctx->errcode) {
14951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx->str = "ext2fs_block_iterate";
14961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
149750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 1;
149850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
149950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
150050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return 0;
150150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
1502