13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass4.c -- pass #4 of e2fsck: Check reference counts
33839e65723771b85975f4263102dd3ceec4523cTheodore 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%
1021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *
1121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Pass 4 frees the following data structures:
1221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 	- A bitmap of which inodes are in bad blocks.	(inode_bb_map)
13aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * 	- A bitmap of which inodes are imagic inodes.	(inode_imagic_map)
143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h"
1721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h"
18fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger#include <ext2fs/ext2_ext_attr.h>
193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
205c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o/*
215c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * This routine is called when an inode is not connected to the
225c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * directory tree.
23efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
245c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * This subroutine returns 1 then the caller shouldn't bother with the
255c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o * rest of the pass 4 tests.
265c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o */
27fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilgerstatic int disconnect_inode(e2fsck_t ctx, ext2_ino_t i,
28fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger			    struct ext2_inode *inode)
295c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o{
301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
3121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct problem_context	pctx;
32fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	__u32 eamagic = 0;
33fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	int extra_size = 0;
345c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o
35fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) {
36fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger		e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super),
37fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger				       "pass4: disconnect_inode");
38fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger		extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize;
39fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	} else {
40fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger		e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode");
41fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	}
4221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	clear_problem_context(&pctx);
4321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	pctx.ino = i;
44fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	pctx.inode = inode;
45efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
46fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0)
47fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger		eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE +
48fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger				     extra_size);
490684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	/*
500684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	 * Offer to delete any zero-length files that does not have
510684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	 * blocks.  If there is an EA block, it might have useful
520684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	 * information, so we won't prompt to delete it, but let it be
530684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	 * reconnected to lost+found.
540684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	 */
55fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC &&
56fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	    (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) {
571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
58efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			e2fsck_clear_inode(ctx, i, inode, 0,
595c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o					   "disconnect_inode");
605c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			/*
615c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			 * Fix up the bitmaps...
625c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			 */
63f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o			e2fsck_read_bitmaps(ctx);
640684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			ext2fs_inode_alloc_stats2(fs, i, -1,
65fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger						  LINUX_S_ISDIR(inode->i_mode));
66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			quota_data_inodes(ctx->qctx, inode, i, -1);
675c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			return 0;
685c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		}
695c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	}
70efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
715c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	/*
725c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	 * Prompt to reconnect.
735c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	 */
741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		if (e2fsck_reconnect_file(ctx, i))
765c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			ext2fs_unmark_valid(fs);
775c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	} else {
785c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		/*
795c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		 * If we don't attach the inode, then skip the
805c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		 * i_links_test since there's no point in trying to
815c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		 * force i_links_count to zero.
825c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		 */
835c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		ext2fs_unmark_valid(fs);
845c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o		return 1;
855c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	}
865c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o	return 0;
875c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o}
885c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o
895c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o
9008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass4(e2fsck_t ctx)
913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
9386c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o	ext2_ino_t	i;
94fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	struct ext2_inode	*inode;
958bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK
963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct resource_track	rtrack;
978bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif
9821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	struct problem_context	pctx;
9921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	__u16	link_count, link_counted;
100bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o	char	*buf = 0;
101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	dgrp_t	group, maxgroup;
102efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1036d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	init_resource_track(&rtrack, ctx->fs->io);
1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE
1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	mtrace_print("Pass 4");
1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
10921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	clear_problem_context(&pctx);
1101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
1111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (!(ctx->options & E2F_OPT_PREEN))
1121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
1131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
114f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	group = 0;
1157f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o	maxgroup = fs->group_desc_count;
116f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	if (ctx->progress)
1177f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o		if ((ctx->progress)(ctx, 4, 0, maxgroup))
118a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o			return;
1195830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen
120fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super),
121fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger				       "scratch inode");
122fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger
1235830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen	/* Protect loop from wrap-around if s_inodes_count maxed */
1245830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		int isdir;
126992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o
1274cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12806c9c6ffc16cbf4c9513ddea3c73328f2a937eb7Brian Behlendorf			goto errout;
129f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		if ((i % fs->super->s_inodes_per_group) == 0) {
130f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o			group++;
131f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o			if (ctx->progress)
1327f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o				if ((ctx->progress)(ctx, 4, group, maxgroup))
13306c9c6ffc16cbf4c9513ddea3c73328f2a937eb7Brian Behlendorf					goto errout;
134f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		}
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (i == EXT2_BAD_INO ||
1367f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			continue;
138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, i)) ||
139aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o		    (ctx->inode_imagic_map &&
140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     ext2fs_test_inode_bitmap2(ctx->inode_imagic_map, i)) ||
1411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		    (ctx->inode_bb_map &&
142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     ext2fs_test_inode_bitmap2(ctx->inode_bb_map, i)))
1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			continue;
1441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
1451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
14621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		if (link_counted == 0) {
147bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o			if (!buf)
148bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o				buf = e2fsck_allocate_memory(ctx,
149bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o				     fs->blocksize, "bad_inode buffer");
150bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
151e72a9ba39471364ad2f9397f645ca547090e3485Theodore Ts'o				continue;
152fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger			if (disconnect_inode(ctx, i, inode))
1531e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o				continue;
1541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			ext2fs_icount_fetch(ctx->inode_link_info, i,
1551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o					    &link_count);
1561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			ext2fs_icount_fetch(ctx->inode_count, i,
1571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o					    &link_counted);
1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i);
160992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o		if (isdir && (link_counted > EXT2_LINK_MAX))
161a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger			link_counted = 1;
16221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		if (link_counted != link_count) {
163fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger			e2fsck_read_inode(ctx, i, inode, "pass4");
16421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			pctx.ino = i;
165fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger			pctx.inode = inode;
166992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o			if ((link_count != inode->i_links_count) && !isdir &&
167992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o			    (inode->i_links_count <= EXT2_LINK_MAX)) {
1681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				pctx.num = link_count;
1691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o				fix_problem(ctx,
1701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o					    PR_4_INCONSISTENT_COUNT, &pctx);
1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
17221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			pctx.num = link_counted;
173a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger			/* i_link_count was previously exceeded, but no longer
174a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger			 * is, fix this but don't consider it an error */
175992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o			if ((isdir && link_counted > 1 &&
176a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger			     (inode->i_flags & EXT2_INDEX_FL) &&
177a7c9cb7d0dc464eda26958595b728a6c3a4cacbcAndreas Dilger			     link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
178992016c5afde0f77a9ff10c4fc5be02f83eb055cTheodore Ts'o			    fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
179fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger				inode->i_links_count = link_counted;
180fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger				e2fsck_write_inode(ctx, i, inode, "pass4");
18121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			}
1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
1851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
1861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
1871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ctx->inode_bb_map = 0;
1887142db08c4e54a863fea2e757c6d3afa42ba2290Theodore Ts'o	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
1897142db08c4e54a863fea2e757c6d3afa42ba2290Theodore Ts'o	ctx->inode_imagic_map = 0;
19006c9c6ffc16cbf4c9513ddea3c73328f2a937eb7Brian Behlendorferrout:
191bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o	if (buf)
192c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&buf);
193fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger
194fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	ext2fs_free_mem(&inode);
1959facd076ae8af6e908e228392cea866ce0faf1bcKen Chen	print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io);
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
198