Home | History | Annotate | Download | only in e2fsck
      1 /*
      2  * pass4.c -- pass #4 of e2fsck: Check reference counts
      3  *
      4  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
      5  *
      6  * %Begin-Header%
      7  * This file may be redistributed under the terms of the GNU Public
      8  * License.
      9  * %End-Header%
     10  *
     11  * Pass 4 frees the following data structures:
     12  * 	- A bitmap of which inodes are in bad blocks.	(inode_bb_map)
     13  * 	- A bitmap of which inodes are imagic inodes.	(inode_imagic_map)
     14  */
     15 
     16 #include "e2fsck.h"
     17 #include "problem.h"
     18 
     19 /*
     20  * This routine is called when an inode is not connected to the
     21  * directory tree.
     22  *
     23  * This subroutine returns 1 then the caller shouldn't bother with the
     24  * rest of the pass 4 tests.
     25  */
     26 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
     27 {
     28 	ext2_filsys fs = ctx->fs;
     29 	struct ext2_inode	inode;
     30 	struct problem_context	pctx;
     31 
     32 	e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
     33 	clear_problem_context(&pctx);
     34 	pctx.ino = i;
     35 	pctx.inode = &inode;
     36 
     37 	/*
     38 	 * Offer to delete any zero-length files that does not have
     39 	 * blocks.  If there is an EA block, it might have useful
     40 	 * information, so we won't prompt to delete it, but let it be
     41 	 * reconnected to lost+found.
     42 	 */
     43 	if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
     44 				LINUX_S_ISDIR(inode.i_mode))) {
     45 		if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
     46 			ext2fs_icount_store(ctx->inode_link_info, i, 0);
     47 			inode.i_links_count = 0;
     48 			inode.i_dtime = ctx->now;
     49 			e2fsck_write_inode(ctx, i, &inode,
     50 					   "disconnect_inode");
     51 			/*
     52 			 * Fix up the bitmaps...
     53 			 */
     54 			e2fsck_read_bitmaps(ctx);
     55 			ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
     56 			ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
     57 			ext2fs_inode_alloc_stats2(fs, i, -1,
     58 						  LINUX_S_ISDIR(inode.i_mode));
     59 			return 0;
     60 		}
     61 	}
     62 
     63 	/*
     64 	 * Prompt to reconnect.
     65 	 */
     66 	if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
     67 		if (e2fsck_reconnect_file(ctx, i))
     68 			ext2fs_unmark_valid(fs);
     69 	} else {
     70 		/*
     71 		 * If we don't attach the inode, then skip the
     72 		 * i_links_test since there's no point in trying to
     73 		 * force i_links_count to zero.
     74 		 */
     75 		ext2fs_unmark_valid(fs);
     76 		return 1;
     77 	}
     78 	return 0;
     79 }
     80 
     81 
     82 void e2fsck_pass4(e2fsck_t ctx)
     83 {
     84 	ext2_filsys fs = ctx->fs;
     85 	ext2_ino_t	i;
     86 	struct ext2_inode	inode;
     87 #ifdef RESOURCE_TRACK
     88 	struct resource_track	rtrack;
     89 #endif
     90 	struct problem_context	pctx;
     91 	__u16	link_count, link_counted;
     92 	char	*buf = 0;
     93 	int	group, maxgroup;
     94 
     95 #ifdef RESOURCE_TRACK
     96 	init_resource_track(&rtrack);
     97 #endif
     98 
     99 #ifdef MTRACE
    100 	mtrace_print("Pass 4");
    101 #endif
    102 
    103 	clear_problem_context(&pctx);
    104 
    105 	if (!(ctx->options & E2F_OPT_PREEN))
    106 		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
    107 
    108 	group = 0;
    109 	maxgroup = fs->group_desc_count;
    110 	if (ctx->progress)
    111 		if ((ctx->progress)(ctx, 4, 0, maxgroup))
    112 			return;
    113 
    114 	/* Protect loop from wrap-around if s_inodes_count maxed */
    115 	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
    116 		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
    117 			goto errout;
    118 		if ((i % fs->super->s_inodes_per_group) == 0) {
    119 			group++;
    120 			if (ctx->progress)
    121 				if ((ctx->progress)(ctx, 4, group, maxgroup))
    122 					goto errout;
    123 		}
    124 		if (i == EXT2_BAD_INO ||
    125 		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
    126 			continue;
    127 		if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
    128 		    (ctx->inode_imagic_map &&
    129 		     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
    130 		    (ctx->inode_bb_map &&
    131 		     ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
    132 			continue;
    133 		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
    134 		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
    135 		if (link_counted == 0) {
    136 			if (!buf)
    137 				buf = e2fsck_allocate_memory(ctx,
    138 				     fs->blocksize, "bad_inode buffer");
    139 			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
    140 				continue;
    141 			if (disconnect_inode(ctx, i))
    142 				continue;
    143 			ext2fs_icount_fetch(ctx->inode_link_info, i,
    144 					    &link_count);
    145 			ext2fs_icount_fetch(ctx->inode_count, i,
    146 					    &link_counted);
    147 		}
    148 		if (link_counted != link_count) {
    149 			e2fsck_read_inode(ctx, i, &inode, "pass4");
    150 			pctx.ino = i;
    151 			pctx.inode = &inode;
    152 			if (link_count != inode.i_links_count) {
    153 				pctx.num = link_count;
    154 				fix_problem(ctx,
    155 					    PR_4_INCONSISTENT_COUNT, &pctx);
    156 			}
    157 			pctx.num = link_counted;
    158 			if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
    159 				inode.i_links_count = link_counted;
    160 				e2fsck_write_inode(ctx, i, &inode, "pass4");
    161 			}
    162 		}
    163 	}
    164 	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
    165 	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
    166 	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
    167 	ctx->inode_bb_map = 0;
    168 	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
    169 	ctx->inode_imagic_map = 0;
    170 errout:
    171 	if (buf)
    172 		ext2fs_free_mem(&buf);
    173 #ifdef RESOURCE_TRACK
    174 	if (ctx->options & E2F_OPT_TIME2) {
    175 		e2fsck_clear_progbar(ctx);
    176 		print_resource_track(_("Pass 4"), &rtrack);
    177 	}
    178 #endif
    179 }
    180 
    181