xref: /aosp_15_r20/external/e2fsprogs/e2fsck/pass4.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * pass4.c -- pass #4 of e2fsck: Check reference counts
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5*6a54128fSAndroid Build Coastguard Worker  *
6*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Public
8*6a54128fSAndroid Build Coastguard Worker  * License.
9*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker  *
11*6a54128fSAndroid Build Coastguard Worker  * Pass 4 frees the following data structures:
12*6a54128fSAndroid Build Coastguard Worker  * 	- A bitmap of which inodes are in bad blocks.	(inode_bb_map)
13*6a54128fSAndroid Build Coastguard Worker  * 	- A bitmap of which inodes are imagic inodes.	(inode_imagic_map)
14*6a54128fSAndroid Build Coastguard Worker  *	- Ref counts for ea_inodes.			(ea_inode_refs)
15*6a54128fSAndroid Build Coastguard Worker  */
16*6a54128fSAndroid Build Coastguard Worker 
17*6a54128fSAndroid Build Coastguard Worker #include "config.h"
18*6a54128fSAndroid Build Coastguard Worker #include "e2fsck.h"
19*6a54128fSAndroid Build Coastguard Worker #include "problem.h"
20*6a54128fSAndroid Build Coastguard Worker #include <ext2fs/ext2_ext_attr.h>
21*6a54128fSAndroid Build Coastguard Worker 
22*6a54128fSAndroid Build Coastguard Worker /*
23*6a54128fSAndroid Build Coastguard Worker  * This routine is called when an inode is not connected to the
24*6a54128fSAndroid Build Coastguard Worker  * directory tree.
25*6a54128fSAndroid Build Coastguard Worker  *
26*6a54128fSAndroid Build Coastguard Worker  * This subroutine returns 1 then the caller shouldn't bother with the
27*6a54128fSAndroid Build Coastguard Worker  * rest of the pass 4 tests.
28*6a54128fSAndroid Build Coastguard Worker  */
disconnect_inode(e2fsck_t ctx,ext2_ino_t i,struct ext2_inode_large * inode)29*6a54128fSAndroid Build Coastguard Worker static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i,
30*6a54128fSAndroid Build Coastguard Worker 			    struct ext2_inode_large *inode)
31*6a54128fSAndroid Build Coastguard Worker {
32*6a54128fSAndroid Build Coastguard Worker 	ext2_filsys fs = ctx->fs;
33*6a54128fSAndroid Build Coastguard Worker 	struct problem_context	pctx;
34*6a54128fSAndroid Build Coastguard Worker 	__u32 eamagic = 0;
35*6a54128fSAndroid Build Coastguard Worker 	int extra_size = 0;
36*6a54128fSAndroid Build Coastguard Worker 
37*6a54128fSAndroid Build Coastguard Worker 	e2fsck_read_inode_full(ctx, i, EXT2_INODE(inode),
38*6a54128fSAndroid Build Coastguard Worker 			       EXT2_INODE_SIZE(fs->super),
39*6a54128fSAndroid Build Coastguard Worker 			       "pass4: disconnect_inode");
40*6a54128fSAndroid Build Coastguard Worker 	if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
41*6a54128fSAndroid Build Coastguard Worker 		extra_size = inode->i_extra_isize;
42*6a54128fSAndroid Build Coastguard Worker 
43*6a54128fSAndroid Build Coastguard Worker 	clear_problem_context(&pctx);
44*6a54128fSAndroid Build Coastguard Worker 	pctx.ino = i;
45*6a54128fSAndroid Build Coastguard Worker 	pctx.inode = EXT2_INODE(inode);
46*6a54128fSAndroid Build Coastguard Worker 
47*6a54128fSAndroid Build Coastguard Worker 	if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0)
48*6a54128fSAndroid Build Coastguard Worker 		eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE +
49*6a54128fSAndroid Build Coastguard Worker 				     extra_size);
50*6a54128fSAndroid Build Coastguard Worker 	/*
51*6a54128fSAndroid Build Coastguard Worker 	 * Offer to delete any zero-length files that does not have
52*6a54128fSAndroid Build Coastguard Worker 	 * blocks.  If there is an EA block, it might have useful
53*6a54128fSAndroid Build Coastguard Worker 	 * information, so we won't prompt to delete it, but let it be
54*6a54128fSAndroid Build Coastguard Worker 	 * reconnected to lost+found.
55*6a54128fSAndroid Build Coastguard Worker 	 */
56*6a54128fSAndroid Build Coastguard Worker 	if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC &&
57*6a54128fSAndroid Build Coastguard Worker 	    (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) {
58*6a54128fSAndroid Build Coastguard Worker 		if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
59*6a54128fSAndroid Build Coastguard Worker 			e2fsck_clear_inode(ctx, i, EXT2_INODE(inode), 0,
60*6a54128fSAndroid Build Coastguard Worker 					   "disconnect_inode");
61*6a54128fSAndroid Build Coastguard Worker 			/*
62*6a54128fSAndroid Build Coastguard Worker 			 * Fix up the bitmaps...
63*6a54128fSAndroid Build Coastguard Worker 			 */
64*6a54128fSAndroid Build Coastguard Worker 			e2fsck_read_bitmaps(ctx);
65*6a54128fSAndroid Build Coastguard Worker 			ext2fs_inode_alloc_stats2(fs, i, -1,
66*6a54128fSAndroid Build Coastguard Worker 						  LINUX_S_ISDIR(inode->i_mode));
67*6a54128fSAndroid Build Coastguard Worker 			quota_data_inodes(ctx->qctx, inode, i, -1);
68*6a54128fSAndroid Build Coastguard Worker 			return 0;
69*6a54128fSAndroid Build Coastguard Worker 		}
70*6a54128fSAndroid Build Coastguard Worker 	}
71*6a54128fSAndroid Build Coastguard Worker 
72*6a54128fSAndroid Build Coastguard Worker 	/*
73*6a54128fSAndroid Build Coastguard Worker 	 * Prompt to reconnect.
74*6a54128fSAndroid Build Coastguard Worker 	 */
75*6a54128fSAndroid Build Coastguard Worker 	if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
76*6a54128fSAndroid Build Coastguard Worker 		if (e2fsck_reconnect_file(ctx, i))
77*6a54128fSAndroid Build Coastguard Worker 			ext2fs_unmark_valid(fs);
78*6a54128fSAndroid Build Coastguard Worker 	} else {
79*6a54128fSAndroid Build Coastguard Worker 		/*
80*6a54128fSAndroid Build Coastguard Worker 		 * If we don't attach the inode, then skip the
81*6a54128fSAndroid Build Coastguard Worker 		 * i_links_test since there's no point in trying to
82*6a54128fSAndroid Build Coastguard Worker 		 * force i_links_count to zero.
83*6a54128fSAndroid Build Coastguard Worker 		 */
84*6a54128fSAndroid Build Coastguard Worker 		ext2fs_unmark_valid(fs);
85*6a54128fSAndroid Build Coastguard Worker 		return 1;
86*6a54128fSAndroid Build Coastguard Worker 	}
87*6a54128fSAndroid Build Coastguard Worker 	return 0;
88*6a54128fSAndroid Build Coastguard Worker }
89*6a54128fSAndroid Build Coastguard Worker 
check_ea_inode(e2fsck_t ctx,ext2_ino_t i,struct ext2_inode_large * inode,__u16 * link_counted)90*6a54128fSAndroid Build Coastguard Worker static void check_ea_inode(e2fsck_t ctx, ext2_ino_t i,
91*6a54128fSAndroid Build Coastguard Worker 			   struct ext2_inode_large *inode, __u16 *link_counted)
92*6a54128fSAndroid Build Coastguard Worker {
93*6a54128fSAndroid Build Coastguard Worker 	__u64 actual_refs = 0;
94*6a54128fSAndroid Build Coastguard Worker 	__u64 ref_count;
95*6a54128fSAndroid Build Coastguard Worker 
96*6a54128fSAndroid Build Coastguard Worker 	/*
97*6a54128fSAndroid Build Coastguard Worker 	 * This function is called when link_counted is zero. So this may not
98*6a54128fSAndroid Build Coastguard Worker 	 * be an xattr inode at all. Return immediately if EA_INODE flag is not
99*6a54128fSAndroid Build Coastguard Worker 	 * set.
100*6a54128fSAndroid Build Coastguard Worker 	 */
101*6a54128fSAndroid Build Coastguard Worker 	e2fsck_read_inode_full(ctx, i, EXT2_INODE(inode),
102*6a54128fSAndroid Build Coastguard Worker 			       EXT2_INODE_SIZE(ctx->fs->super),
103*6a54128fSAndroid Build Coastguard Worker 			       "pass4: check_ea_inode");
104*6a54128fSAndroid Build Coastguard Worker 	if (!(inode->i_flags & EXT4_EA_INODE_FL))
105*6a54128fSAndroid Build Coastguard Worker 		return;
106*6a54128fSAndroid Build Coastguard Worker 
107*6a54128fSAndroid Build Coastguard Worker 	if (ctx->ea_inode_refs)
108*6a54128fSAndroid Build Coastguard Worker 		ea_refcount_fetch(ctx->ea_inode_refs, i, &actual_refs);
109*6a54128fSAndroid Build Coastguard Worker 	if (!actual_refs)
110*6a54128fSAndroid Build Coastguard Worker 		return;
111*6a54128fSAndroid Build Coastguard Worker 
112*6a54128fSAndroid Build Coastguard Worker 	/*
113*6a54128fSAndroid Build Coastguard Worker 	 * There are some attribute references, link_counted is now considered
114*6a54128fSAndroid Build Coastguard Worker 	 * to be 1.
115*6a54128fSAndroid Build Coastguard Worker 	 */
116*6a54128fSAndroid Build Coastguard Worker 	*link_counted = 1;
117*6a54128fSAndroid Build Coastguard Worker 
118*6a54128fSAndroid Build Coastguard Worker 	ref_count = ext2fs_get_ea_inode_ref(EXT2_INODE(inode));
119*6a54128fSAndroid Build Coastguard Worker 
120*6a54128fSAndroid Build Coastguard Worker 	/* Old Lustre-style xattr inodes do not have a stored refcount.
121*6a54128fSAndroid Build Coastguard Worker 	 * However, their i_ctime and i_atime should be the same.
122*6a54128fSAndroid Build Coastguard Worker 	 */
123*6a54128fSAndroid Build Coastguard Worker 	if (ref_count != actual_refs && inode->i_ctime != inode->i_atime) {
124*6a54128fSAndroid Build Coastguard Worker 		struct problem_context pctx;
125*6a54128fSAndroid Build Coastguard Worker 
126*6a54128fSAndroid Build Coastguard Worker 		clear_problem_context(&pctx);
127*6a54128fSAndroid Build Coastguard Worker 		pctx.ino = i;
128*6a54128fSAndroid Build Coastguard Worker 		pctx.num = ref_count;
129*6a54128fSAndroid Build Coastguard Worker 		pctx.num2 = actual_refs;
130*6a54128fSAndroid Build Coastguard Worker 		if (fix_problem(ctx, PR_4_EA_INODE_REF_COUNT, &pctx)) {
131*6a54128fSAndroid Build Coastguard Worker 			ext2fs_set_ea_inode_ref(EXT2_INODE(inode), actual_refs);
132*6a54128fSAndroid Build Coastguard Worker 			e2fsck_write_inode(ctx, i, EXT2_INODE(inode), "pass4");
133*6a54128fSAndroid Build Coastguard Worker 		}
134*6a54128fSAndroid Build Coastguard Worker 	}
135*6a54128fSAndroid Build Coastguard Worker }
136*6a54128fSAndroid Build Coastguard Worker 
e2fsck_pass4(e2fsck_t ctx)137*6a54128fSAndroid Build Coastguard Worker void e2fsck_pass4(e2fsck_t ctx)
138*6a54128fSAndroid Build Coastguard Worker {
139*6a54128fSAndroid Build Coastguard Worker 	ext2_filsys fs = ctx->fs;
140*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t	i;
141*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode_large	*inode;
142*6a54128fSAndroid Build Coastguard Worker 	int inode_size = EXT2_INODE_SIZE(fs->super);
143*6a54128fSAndroid Build Coastguard Worker #ifdef RESOURCE_TRACK
144*6a54128fSAndroid Build Coastguard Worker 	struct resource_track	rtrack;
145*6a54128fSAndroid Build Coastguard Worker #endif
146*6a54128fSAndroid Build Coastguard Worker 	struct problem_context	pctx;
147*6a54128fSAndroid Build Coastguard Worker 	__u16	link_count, link_counted;
148*6a54128fSAndroid Build Coastguard Worker 	int dir_nlink_fs;
149*6a54128fSAndroid Build Coastguard Worker 	char	*buf = 0;
150*6a54128fSAndroid Build Coastguard Worker 	dgrp_t	group, maxgroup;
151*6a54128fSAndroid Build Coastguard Worker 
152*6a54128fSAndroid Build Coastguard Worker 	init_resource_track(&rtrack, ctx->fs->io);
153*6a54128fSAndroid Build Coastguard Worker 
154*6a54128fSAndroid Build Coastguard Worker #ifdef MTRACE
155*6a54128fSAndroid Build Coastguard Worker 	mtrace_print("Pass 4");
156*6a54128fSAndroid Build Coastguard Worker #endif
157*6a54128fSAndroid Build Coastguard Worker 	/*
158*6a54128fSAndroid Build Coastguard Worker 	 * Since pass4 is mostly CPU bound, start readahead of bitmaps
159*6a54128fSAndroid Build Coastguard Worker 	 * ahead of pass 5 if we haven't already loaded them.
160*6a54128fSAndroid Build Coastguard Worker 	 */
161*6a54128fSAndroid Build Coastguard Worker 	if (ctx->readahead_kb &&
162*6a54128fSAndroid Build Coastguard Worker 	    (fs->block_map == NULL || fs->inode_map == NULL))
163*6a54128fSAndroid Build Coastguard Worker 		e2fsck_readahead(fs, E2FSCK_READA_BBITMAP |
164*6a54128fSAndroid Build Coastguard Worker 				     E2FSCK_READA_IBITMAP,
165*6a54128fSAndroid Build Coastguard Worker 				 0, fs->group_desc_count);
166*6a54128fSAndroid Build Coastguard Worker 
167*6a54128fSAndroid Build Coastguard Worker 	clear_problem_context(&pctx);
168*6a54128fSAndroid Build Coastguard Worker 
169*6a54128fSAndroid Build Coastguard Worker 	if (!(ctx->options & E2F_OPT_PREEN))
170*6a54128fSAndroid Build Coastguard Worker 		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
171*6a54128fSAndroid Build Coastguard Worker 
172*6a54128fSAndroid Build Coastguard Worker 	dir_nlink_fs = ext2fs_has_feature_dir_nlink(fs->super);
173*6a54128fSAndroid Build Coastguard Worker 
174*6a54128fSAndroid Build Coastguard Worker 	group = 0;
175*6a54128fSAndroid Build Coastguard Worker 	maxgroup = fs->group_desc_count;
176*6a54128fSAndroid Build Coastguard Worker 	if (ctx->progress)
177*6a54128fSAndroid Build Coastguard Worker 		if ((ctx->progress)(ctx, 4, 0, maxgroup))
178*6a54128fSAndroid Build Coastguard Worker 			return;
179*6a54128fSAndroid Build Coastguard Worker 
180*6a54128fSAndroid Build Coastguard Worker 	inode = e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
181*6a54128fSAndroid Build Coastguard Worker 
182*6a54128fSAndroid Build Coastguard Worker 	/* Protect loop from wrap-around if s_inodes_count maxed */
183*6a54128fSAndroid Build Coastguard Worker 	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
184*6a54128fSAndroid Build Coastguard Worker 		int isdir;
185*6a54128fSAndroid Build Coastguard Worker 
186*6a54128fSAndroid Build Coastguard Worker 		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
187*6a54128fSAndroid Build Coastguard Worker 			goto errout;
188*6a54128fSAndroid Build Coastguard Worker 		if ((i % fs->super->s_inodes_per_group) == 0) {
189*6a54128fSAndroid Build Coastguard Worker 			group++;
190*6a54128fSAndroid Build Coastguard Worker 			if (ctx->progress)
191*6a54128fSAndroid Build Coastguard Worker 				if ((ctx->progress)(ctx, 4, group, maxgroup))
192*6a54128fSAndroid Build Coastguard Worker 					goto errout;
193*6a54128fSAndroid Build Coastguard Worker 		}
194*6a54128fSAndroid Build Coastguard Worker 		if (i == quota_type2inum(PRJQUOTA, ctx->fs->super) ||
195*6a54128fSAndroid Build Coastguard Worker 		    i == EXT2_BAD_INO ||
196*6a54128fSAndroid Build Coastguard Worker 		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
197*6a54128fSAndroid Build Coastguard Worker 			continue;
198*6a54128fSAndroid Build Coastguard Worker 		if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, i)) ||
199*6a54128fSAndroid Build Coastguard Worker 		    (ctx->inode_imagic_map &&
200*6a54128fSAndroid Build Coastguard Worker 		     ext2fs_test_inode_bitmap2(ctx->inode_imagic_map, i)) ||
201*6a54128fSAndroid Build Coastguard Worker 		    (ctx->inode_bb_map &&
202*6a54128fSAndroid Build Coastguard Worker 		     ext2fs_test_inode_bitmap2(ctx->inode_bb_map, i)))
203*6a54128fSAndroid Build Coastguard Worker 			continue;
204*6a54128fSAndroid Build Coastguard Worker 		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
205*6a54128fSAndroid Build Coastguard Worker 		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
206*6a54128fSAndroid Build Coastguard Worker 
207*6a54128fSAndroid Build Coastguard Worker 		if (link_counted == 0) {
208*6a54128fSAndroid Build Coastguard Worker 			/*
209*6a54128fSAndroid Build Coastguard Worker 			 * link_counted is expected to be 0 for an ea_inode.
210*6a54128fSAndroid Build Coastguard Worker 			 * check_ea_inode() will update link_counted if
211*6a54128fSAndroid Build Coastguard Worker 			 * necessary.
212*6a54128fSAndroid Build Coastguard Worker 			 */
213*6a54128fSAndroid Build Coastguard Worker 			check_ea_inode(ctx, i, inode, &link_counted);
214*6a54128fSAndroid Build Coastguard Worker 		}
215*6a54128fSAndroid Build Coastguard Worker 
216*6a54128fSAndroid Build Coastguard Worker 		if (link_counted == 0) {
217*6a54128fSAndroid Build Coastguard Worker 			if (!buf)
218*6a54128fSAndroid Build Coastguard Worker 				buf = e2fsck_allocate_memory(ctx,
219*6a54128fSAndroid Build Coastguard Worker 				     fs->blocksize, "bad_inode buffer");
220*6a54128fSAndroid Build Coastguard Worker 			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
221*6a54128fSAndroid Build Coastguard Worker 				continue;
222*6a54128fSAndroid Build Coastguard Worker 			if (disconnect_inode(ctx, i, inode))
223*6a54128fSAndroid Build Coastguard Worker 				continue;
224*6a54128fSAndroid Build Coastguard Worker 			ext2fs_icount_fetch(ctx->inode_link_info, i,
225*6a54128fSAndroid Build Coastguard Worker 					    &link_count);
226*6a54128fSAndroid Build Coastguard Worker 			ext2fs_icount_fetch(ctx->inode_count, i,
227*6a54128fSAndroid Build Coastguard Worker 					    &link_counted);
228*6a54128fSAndroid Build Coastguard Worker 		}
229*6a54128fSAndroid Build Coastguard Worker 		isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i);
230*6a54128fSAndroid Build Coastguard Worker 		if (isdir && (link_counted > EXT2_LINK_MAX)) {
231*6a54128fSAndroid Build Coastguard Worker 			if (!dir_nlink_fs &&
232*6a54128fSAndroid Build Coastguard Worker 			    fix_problem(ctx, PR_4_DIR_NLINK_FEATURE, &pctx)) {
233*6a54128fSAndroid Build Coastguard Worker 				ext2fs_set_feature_dir_nlink(fs->super);
234*6a54128fSAndroid Build Coastguard Worker 				ext2fs_mark_super_dirty(fs);
235*6a54128fSAndroid Build Coastguard Worker 				dir_nlink_fs = 1;
236*6a54128fSAndroid Build Coastguard Worker 			}
237*6a54128fSAndroid Build Coastguard Worker 			link_counted = 1;
238*6a54128fSAndroid Build Coastguard Worker 		}
239*6a54128fSAndroid Build Coastguard Worker 		if (link_counted != link_count) {
240*6a54128fSAndroid Build Coastguard Worker 			int fix_nlink = 0;
241*6a54128fSAndroid Build Coastguard Worker 
242*6a54128fSAndroid Build Coastguard Worker 			e2fsck_read_inode_full(ctx, i, EXT2_INODE(inode),
243*6a54128fSAndroid Build Coastguard Worker 					       inode_size, "pass4");
244*6a54128fSAndroid Build Coastguard Worker 			pctx.ino = i;
245*6a54128fSAndroid Build Coastguard Worker 			pctx.inode = EXT2_INODE(inode);
246*6a54128fSAndroid Build Coastguard Worker 			if ((link_count != inode->i_links_count) && !isdir &&
247*6a54128fSAndroid Build Coastguard Worker 			    (inode->i_links_count <= EXT2_LINK_MAX)) {
248*6a54128fSAndroid Build Coastguard Worker 				pctx.num = link_count;
249*6a54128fSAndroid Build Coastguard Worker 				fix_problem(ctx,
250*6a54128fSAndroid Build Coastguard Worker 					    PR_4_INCONSISTENT_COUNT, &pctx);
251*6a54128fSAndroid Build Coastguard Worker 			}
252*6a54128fSAndroid Build Coastguard Worker 			pctx.num = link_counted;
253*6a54128fSAndroid Build Coastguard Worker 			/* i_link_count was previously exceeded, but no longer
254*6a54128fSAndroid Build Coastguard Worker 			 * is, fix this but don't consider it an error */
255*6a54128fSAndroid Build Coastguard Worker 			if (isdir && link_counted > 1 &&
256*6a54128fSAndroid Build Coastguard Worker 			    (inode->i_flags & EXT2_INDEX_FL) &&
257*6a54128fSAndroid Build Coastguard Worker 			    link_count == 1) {
258*6a54128fSAndroid Build Coastguard Worker 				if ((ctx->options & E2F_OPT_READONLY) == 0) {
259*6a54128fSAndroid Build Coastguard Worker 					fix_nlink =
260*6a54128fSAndroid Build Coastguard Worker 						fix_problem(ctx,
261*6a54128fSAndroid Build Coastguard Worker 							PR_4_DIR_OVERFLOW_REF_COUNT,
262*6a54128fSAndroid Build Coastguard Worker 							&pctx);
263*6a54128fSAndroid Build Coastguard Worker 				}
264*6a54128fSAndroid Build Coastguard Worker 			} else {
265*6a54128fSAndroid Build Coastguard Worker 				fix_nlink = fix_problem(ctx, PR_4_BAD_REF_COUNT,
266*6a54128fSAndroid Build Coastguard Worker 						&pctx);
267*6a54128fSAndroid Build Coastguard Worker 			}
268*6a54128fSAndroid Build Coastguard Worker 			if (fix_nlink) {
269*6a54128fSAndroid Build Coastguard Worker 				inode->i_links_count = link_counted;
270*6a54128fSAndroid Build Coastguard Worker 				e2fsck_write_inode_full(ctx, i,
271*6a54128fSAndroid Build Coastguard Worker 							EXT2_INODE(inode),
272*6a54128fSAndroid Build Coastguard Worker 							inode_size, "pass4");
273*6a54128fSAndroid Build Coastguard Worker 			}
274*6a54128fSAndroid Build Coastguard Worker 		}
275*6a54128fSAndroid Build Coastguard Worker 	}
276*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
277*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
278*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
279*6a54128fSAndroid Build Coastguard Worker 	ctx->inode_bb_map = 0;
280*6a54128fSAndroid Build Coastguard Worker 	ea_refcount_free(ctx->ea_inode_refs);
281*6a54128fSAndroid Build Coastguard Worker 	ctx->ea_inode_refs = 0;
282*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
283*6a54128fSAndroid Build Coastguard Worker 	ctx->inode_imagic_map = 0;
284*6a54128fSAndroid Build Coastguard Worker errout:
285*6a54128fSAndroid Build Coastguard Worker 	if (buf)
286*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&buf);
287*6a54128fSAndroid Build Coastguard Worker 
288*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&inode);
289*6a54128fSAndroid Build Coastguard Worker 	print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io);
290*6a54128fSAndroid Build Coastguard Worker }
291*6a54128fSAndroid Build Coastguard Worker 
292