Home | History | Annotate | Download | only in e2fsck
      1 /*
      2  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
      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  */
     12 
     13 #include "config.h"
     14 #include <stdint.h>
     15 #include <sys/types.h>
     16 #include <sys/stat.h>
     17 #include <sys/ioctl.h>
     18 #include <fcntl.h>
     19 #include <errno.h>
     20 
     21 #include "e2fsck.h"
     22 #include "problem.h"
     23 
     24 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
     25 
     26 static void check_block_bitmaps(e2fsck_t ctx);
     27 static void check_inode_bitmaps(e2fsck_t ctx);
     28 static void check_inode_end(e2fsck_t ctx);
     29 static void check_block_end(e2fsck_t ctx);
     30 static void check_inode_bitmap_checksum(e2fsck_t ctx);
     31 static void check_block_bitmap_checksum(e2fsck_t ctx);
     32 
     33 void e2fsck_pass5(e2fsck_t ctx)
     34 {
     35 #ifdef RESOURCE_TRACK
     36 	struct resource_track	rtrack;
     37 #endif
     38 	struct problem_context	pctx;
     39 
     40 #ifdef MTRACE
     41 	mtrace_print("Pass 5");
     42 #endif
     43 
     44 	init_resource_track(&rtrack, ctx->fs->io);
     45 	clear_problem_context(&pctx);
     46 
     47 	if (!(ctx->options & E2F_OPT_PREEN))
     48 		fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
     49 
     50 	if (ctx->progress)
     51 		if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
     52 			return;
     53 
     54 	e2fsck_read_bitmaps(ctx);
     55 
     56 	check_block_bitmaps(ctx);
     57 	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
     58 		return;
     59 	check_inode_bitmaps(ctx);
     60 	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
     61 		return;
     62 	check_inode_end(ctx);
     63 	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
     64 		return;
     65 	check_block_end(ctx);
     66 	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
     67 		return;
     68 
     69 	check_inode_bitmap_checksum(ctx);
     70 	check_block_bitmap_checksum(ctx);
     71 
     72 	ext2fs_free_inode_bitmap(ctx->inode_used_map);
     73 	ctx->inode_used_map = 0;
     74 	ext2fs_free_inode_bitmap(ctx->inode_dir_map);
     75 	ctx->inode_dir_map = 0;
     76 	ext2fs_free_block_bitmap(ctx->block_found_map);
     77 	ctx->block_found_map = 0;
     78 	ext2fs_free_block_bitmap(ctx->block_metadata_map);
     79 	ctx->block_metadata_map = 0;
     80 
     81 	print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
     82 }
     83 
     84 static void check_inode_bitmap_checksum(e2fsck_t ctx)
     85 {
     86 	struct problem_context	pctx;
     87 	char		*buf = NULL;
     88 	dgrp_t		i;
     89 	int		nbytes;
     90 	ext2_ino_t	ino_itr;
     91 	errcode_t	retval;
     92 
     93 	if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
     94 		return;
     95 
     96 	/* If bitmap is dirty from being fixed, checksum will be corrected */
     97 	if (ext2fs_test_ib_dirty(ctx->fs))
     98 		return;
     99 
    100 	nbytes = (size_t)(EXT2_INODES_PER_GROUP(ctx->fs->super) / 8);
    101 	retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
    102 	if (retval) {
    103 		com_err(ctx->program_name, 0, "%s",
    104 		    _("check_inode_bitmap_checksum: Memory allocation error"));
    105 		fatal_error(ctx, 0);
    106 	}
    107 
    108 	clear_problem_context(&pctx);
    109 	for (i = 0; i < ctx->fs->group_desc_count; i++) {
    110 		if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_INODE_UNINIT))
    111 			continue;
    112 
    113 		ino_itr = 1 + (i * (nbytes << 3));
    114 		retval = ext2fs_get_inode_bitmap_range2(ctx->fs->inode_map,
    115 							ino_itr, nbytes << 3,
    116 							buf);
    117 		if (retval)
    118 			break;
    119 
    120 		if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
    121 			continue;
    122 		pctx.group = i;
    123 		if (!fix_problem(ctx, PR_5_INODE_BITMAP_CSUM_INVALID, &pctx))
    124 			continue;
    125 
    126 		/*
    127 		 * Fixing one checksum will rewrite all of them.  The bitmap
    128 		 * will be checked against the one we made during pass1 for
    129 		 * discrepancies, and fixed if need be.
    130 		 */
    131 		ext2fs_mark_ib_dirty(ctx->fs);
    132 		break;
    133 	}
    134 
    135 	ext2fs_free_mem(&buf);
    136 }
    137 
    138 static void check_block_bitmap_checksum(e2fsck_t ctx)
    139 {
    140 	struct problem_context	pctx;
    141 	char		*buf = NULL;
    142 	dgrp_t		i;
    143 	int		nbytes;
    144 	blk64_t		blk_itr;
    145 	errcode_t	retval;
    146 
    147 	if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
    148 		return;
    149 
    150 	/* If bitmap is dirty from being fixed, checksum will be corrected */
    151 	if (ext2fs_test_bb_dirty(ctx->fs))
    152 		return;
    153 
    154 	nbytes = (size_t)(EXT2_CLUSTERS_PER_GROUP(ctx->fs->super) / 8);
    155 	retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
    156 	if (retval) {
    157 		com_err(ctx->program_name, 0, "%s",
    158 		    _("check_block_bitmap_checksum: Memory allocation error"));
    159 		fatal_error(ctx, 0);
    160 	}
    161 
    162 	clear_problem_context(&pctx);
    163 	for (i = 0; i < ctx->fs->group_desc_count; i++) {
    164 		if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_BLOCK_UNINIT))
    165 			continue;
    166 
    167 		blk_itr = EXT2FS_B2C(ctx->fs,
    168 				     ctx->fs->super->s_first_data_block) +
    169 			  ((blk64_t) i * (nbytes << 3));
    170 		retval = ext2fs_get_block_bitmap_range2(ctx->fs->block_map,
    171 							blk_itr, nbytes << 3,
    172 							buf);
    173 		if (retval)
    174 			break;
    175 
    176 		if (ext2fs_block_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
    177 			continue;
    178 		pctx.group = i;
    179 		if (!fix_problem(ctx, PR_5_BLOCK_BITMAP_CSUM_INVALID, &pctx))
    180 			continue;
    181 
    182 		/*
    183 		 * Fixing one checksum will rewrite all of them.  The bitmap
    184 		 * will be checked against the one we made during pass1 for
    185 		 * discrepancies, and fixed if need be.
    186 		 */
    187 		ext2fs_mark_bb_dirty(ctx->fs);
    188 		break;
    189 	}
    190 
    191 	ext2fs_free_mem(&buf);
    192 }
    193 
    194 static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start,
    195 				  blk64_t count)
    196 {
    197 	ext2_filsys fs = ctx->fs;
    198 
    199 	/*
    200 	 * If the filesystem has changed it means that there was an corruption
    201 	 * which should be repaired, but in some cases just one e2fsck run is
    202 	 * not enough to fix the problem, hence it is not safe to run discard
    203 	 * in this case.
    204 	 */
    205 	if (ext2fs_test_changed(fs))
    206 		ctx->options &= ~E2F_OPT_DISCARD;
    207 
    208 	if ((ctx->options & E2F_OPT_DISCARD) &&
    209 	    (io_channel_discard(fs->io, start, count)))
    210 		ctx->options &= ~E2F_OPT_DISCARD;
    211 }
    212 
    213 /*
    214  * This will try to discard number 'count' inodes starting at
    215  * inode number 'start' within the 'group'. Note that 'start'
    216  * is 1-based, it means that we need to adjust it by -1 in this
    217  * function to compute right offset in the particular inode table.
    218  */
    219 static void e2fsck_discard_inodes(e2fsck_t ctx, dgrp_t group,
    220 				  ext2_ino_t start, int count)
    221 {
    222 	ext2_filsys fs = ctx->fs;
    223 	blk64_t blk, num;
    224 
    225 	/*
    226 	 * Sanity check for 'start'
    227 	 */
    228 	if ((start < 1) || (start > EXT2_INODES_PER_GROUP(fs->super))) {
    229 		printf("PROGRAMMING ERROR: Got start %d outside of group %d!"
    230 		       " Disabling discard\n",
    231 			start, group);
    232 		ctx->options &= ~E2F_OPT_DISCARD;
    233 	}
    234 
    235 	/*
    236 	 * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also
    237 	 * skip the discard on this group if discard does not zero data.
    238 	 * The reason is that if the inode table is not zeroed discard would
    239 	 * no help us since we need to zero it anyway, or if the inode table
    240 	 * is zeroed then the read after discard would not be deterministic
    241 	 * anyway and we would not be able to assume that this inode table
    242 	 * was zeroed anymore so we would have to zero it again, which does
    243 	 * not really make sense.
    244 	 */
    245 	if (!(ctx->options & E2F_OPT_DISCARD) ||
    246 	    !io_channel_discard_zeroes_data(fs->io))
    247 		return;
    248 
    249 	/*
    250 	 * Start is inode number within the group which starts
    251 	 * counting from 1, so we need to adjust it.
    252 	 */
    253 	start -= 1;
    254 
    255 	/*
    256 	 * We can discard only blocks containing only unused
    257 	 * inodes in the table.
    258 	 */
    259 	blk = DIV_ROUND_UP(start,
    260 		EXT2_INODES_PER_BLOCK(fs->super));
    261 	count -= (blk * EXT2_INODES_PER_BLOCK(fs->super) - start);
    262 	blk += ext2fs_inode_table_loc(fs, group);
    263 	num = count / EXT2_INODES_PER_BLOCK(fs->super);
    264 
    265 	if (num > 0)
    266 		e2fsck_discard_blocks(ctx, blk, num);
    267 }
    268 
    269 #define NO_BLK ((blk64_t) -1)
    270 
    271 static void print_bitmap_problem(e2fsck_t ctx, problem_t problem,
    272 			    struct problem_context *pctx)
    273 {
    274 	switch (problem) {
    275 	case PR_5_BLOCK_UNUSED:
    276 		if (pctx->blk == pctx->blk2)
    277 			pctx->blk2 = 0;
    278 		else
    279 			problem = PR_5_BLOCK_RANGE_UNUSED;
    280 		break;
    281 	case PR_5_BLOCK_USED:
    282 		if (pctx->blk == pctx->blk2)
    283 			pctx->blk2 = 0;
    284 		else
    285 			problem = PR_5_BLOCK_RANGE_USED;
    286 		break;
    287 	case PR_5_INODE_UNUSED:
    288 		if (pctx->ino == pctx->ino2)
    289 			pctx->ino2 = 0;
    290 		else
    291 			problem = PR_5_INODE_RANGE_UNUSED;
    292 		break;
    293 	case PR_5_INODE_USED:
    294 		if (pctx->ino == pctx->ino2)
    295 			pctx->ino2 = 0;
    296 		else
    297 			problem = PR_5_INODE_RANGE_USED;
    298 		break;
    299 	}
    300 	fix_problem(ctx, problem, pctx);
    301 	pctx->blk = pctx->blk2 = NO_BLK;
    302 	pctx->ino = pctx->ino2 = 0;
    303 }
    304 
    305 /* Just to be more succint */
    306 #define B2C(x)	EXT2FS_B2C(fs, (x))
    307 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
    308 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
    309 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
    310 
    311 static void check_block_bitmaps(e2fsck_t ctx)
    312 {
    313 	ext2_filsys fs = ctx->fs;
    314 	blk64_t	i;
    315 	unsigned int	*free_array;
    316 	dgrp_t		g, group = 0;
    317 	unsigned int	blocks = 0;
    318 	blk64_t	free_blocks = 0;
    319 	blk64_t first_free = ext2fs_blocks_count(fs->super);
    320 	unsigned int	group_free = 0;
    321 	int	actual, bitmap;
    322 	struct problem_context	pctx;
    323 	problem_t	problem, save_problem;
    324 	int		fixit, had_problem;
    325 	errcode_t	retval;
    326 	int	redo_flag = 0;
    327 	char *actual_buf, *bitmap_buf;
    328 
    329 	actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
    330 						     "actual bitmap buffer");
    331 	bitmap_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
    332 						     "bitmap block buffer");
    333 
    334 	clear_problem_context(&pctx);
    335 	free_array = (unsigned int *) e2fsck_allocate_memory(ctx,
    336 	    fs->group_desc_count * sizeof(unsigned int), "free block count array");
    337 
    338 	if ((B2C(fs->super->s_first_data_block) <
    339 	     ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
    340 	    (B2C(ext2fs_blocks_count(fs->super)-1) >
    341 	     ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
    342 		pctx.num = 1;
    343 		pctx.blk = B2C(fs->super->s_first_data_block);
    344 		pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
    345 		pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
    346 		pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
    347 		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
    348 
    349 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    350 		goto errout;
    351 	}
    352 
    353 	if ((B2C(fs->super->s_first_data_block) <
    354 	     ext2fs_get_block_bitmap_start2(fs->block_map)) ||
    355 	    (B2C(ext2fs_blocks_count(fs->super)-1) >
    356 	     ext2fs_get_block_bitmap_end2(fs->block_map))) {
    357 		pctx.num = 2;
    358 		pctx.blk = B2C(fs->super->s_first_data_block);
    359 		pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
    360 		pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
    361 		pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
    362 		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
    363 
    364 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    365 		goto errout;
    366 	}
    367 
    368 redo_counts:
    369 	had_problem = 0;
    370 	save_problem = 0;
    371 	pctx.blk = pctx.blk2 = NO_BLK;
    372 	for (i = B2C(fs->super->s_first_data_block);
    373 	     i < ext2fs_blocks_count(fs->super);
    374 	     i += EXT2FS_CLUSTER_RATIO(fs)) {
    375 		int first_block_in_bg = (B2C(i) -
    376 					 B2C(fs->super->s_first_data_block)) %
    377 			fs->super->s_clusters_per_group == 0;
    378 		int n, nbytes = fs->super->s_clusters_per_group / 8;
    379 
    380 		actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
    381 
    382 		/*
    383 		 * Try to optimize pass5 by extracting a bitmap block
    384 		 * as expected from what we have on disk, and then
    385 		 * comparing the two.  If they are identical, then
    386 		 * update the free block counts and go on to the next
    387 		 * block group.  This is much faster than doing the
    388 		 * individual bit-by-bit comparison.  The one downside
    389 		 * is that this doesn't work if we are asking e2fsck
    390 		 * to do a discard operation.
    391 		 */
    392 		if (!first_block_in_bg ||
    393 		    (group == fs->group_desc_count - 1) ||
    394 		    (ctx->options & E2F_OPT_DISCARD))
    395 			goto no_optimize;
    396 
    397 		retval = ext2fs_get_block_bitmap_range2(ctx->block_found_map,
    398 				B2C(i), fs->super->s_clusters_per_group,
    399 				actual_buf);
    400 		if (retval)
    401 			goto no_optimize;
    402 		retval = ext2fs_get_block_bitmap_range2(fs->block_map,
    403 				B2C(i), fs->super->s_clusters_per_group,
    404 				bitmap_buf);
    405 		if (retval)
    406 			goto no_optimize;
    407 		if (memcmp(actual_buf, bitmap_buf, nbytes) != 0)
    408 			goto no_optimize;
    409 		n = ext2fs_bitcount(actual_buf, nbytes);
    410 		group_free = fs->super->s_clusters_per_group - n;
    411 		free_blocks += group_free;
    412 		i += EXT2FS_C2B(fs, fs->super->s_clusters_per_group - 1);
    413 		goto next_group;
    414 	no_optimize:
    415 
    416 		if (redo_flag)
    417 			bitmap = actual;
    418 		else
    419 			bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
    420 
    421 		if (!actual == !bitmap)
    422 			goto do_counts;
    423 
    424 		if (!actual && bitmap) {
    425 			/*
    426 			 * Block not used, but marked in use in the bitmap.
    427 			 */
    428 			problem = PR_5_BLOCK_UNUSED;
    429 		} else {
    430 			/*
    431 			 * Block used, but not marked in use in the bitmap.
    432 			 */
    433 			problem = PR_5_BLOCK_USED;
    434 
    435 			if (ext2fs_bg_flags_test(fs, group,
    436 						 EXT2_BG_BLOCK_UNINIT)) {
    437 				struct problem_context pctx2;
    438 				pctx2.blk = i;
    439 				pctx2.group = group;
    440 				if (fix_problem(ctx, PR_5_BLOCK_UNINIT,
    441 						&pctx2))
    442 					ext2fs_bg_flags_clear(fs, group,
    443 							EXT2_BG_BLOCK_UNINIT);
    444 			}
    445 		}
    446 		if (pctx.blk == NO_BLK) {
    447 			pctx.blk = pctx.blk2 = i;
    448 			save_problem = problem;
    449 		} else {
    450 			if ((problem == save_problem) &&
    451 			    (pctx.blk2 == i - EXT2FS_CLUSTER_RATIO(fs)))
    452 				pctx.blk2 += EXT2FS_CLUSTER_RATIO(fs);
    453 			else {
    454 				print_bitmap_problem(ctx, save_problem, &pctx);
    455 				pctx.blk = pctx.blk2 = i;
    456 				save_problem = problem;
    457 			}
    458 		}
    459 		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
    460 		had_problem++;
    461 
    462 		/*
    463 		 * If there a problem we should turn off the discard so we
    464 		 * do not compromise the filesystem.
    465 		 */
    466 		ctx->options &= ~E2F_OPT_DISCARD;
    467 
    468 	do_counts:
    469 		if (!bitmap) {
    470 			group_free++;
    471 			free_blocks++;
    472 			if (first_free > i)
    473 				first_free = i;
    474 		} else if (i > first_free) {
    475 			e2fsck_discard_blocks(ctx, first_free,
    476 					      (i - first_free));
    477 			first_free = ext2fs_blocks_count(fs->super);
    478 		}
    479 		blocks ++;
    480 		if ((blocks == fs->super->s_clusters_per_group) ||
    481 		    (EXT2FS_B2C(fs, i) ==
    482 		     EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) {
    483 			/*
    484 			 * If the last block of this group is free, then we can
    485 			 * discard it as well.
    486 			 */
    487 			if (!bitmap && i >= first_free)
    488 				e2fsck_discard_blocks(ctx, first_free,
    489 						      (i - first_free) + 1);
    490 		next_group:
    491 			first_free = ext2fs_blocks_count(fs->super);
    492 
    493 			free_array[group] = group_free;
    494 			group ++;
    495 			blocks = 0;
    496 			group_free = 0;
    497 			if (ctx->progress)
    498 				if ((ctx->progress)(ctx, 5, group,
    499 						    fs->group_desc_count*2))
    500 					goto errout;
    501 		}
    502 	}
    503 	if (pctx.blk != NO_BLK)
    504 		print_bitmap_problem(ctx, save_problem, &pctx);
    505 	if (had_problem)
    506 		fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
    507 	else
    508 		fixit = -1;
    509 	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
    510 
    511 	if (fixit == 1) {
    512 		ext2fs_free_block_bitmap(fs->block_map);
    513 		retval = ext2fs_copy_bitmap(ctx->block_found_map,
    514 						  &fs->block_map);
    515 		if (retval) {
    516 			clear_problem_context(&pctx);
    517 			fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
    518 			ctx->flags |= E2F_FLAG_ABORT;
    519 			goto errout;
    520 		}
    521 		ext2fs_set_bitmap_padding(fs->block_map);
    522 		ext2fs_mark_bb_dirty(fs);
    523 
    524 		/* Redo the counts */
    525 		blocks = 0; free_blocks = 0; group_free = 0; group = 0;
    526 		memset(free_array, 0, fs->group_desc_count * sizeof(int));
    527 		redo_flag++;
    528 		goto redo_counts;
    529 	} else if (fixit == 0)
    530 		ext2fs_unmark_valid(fs);
    531 
    532 	for (g = 0; g < fs->group_desc_count; g++) {
    533 		if (free_array[g] != ext2fs_bg_free_blocks_count(fs, g)) {
    534 			pctx.group = g;
    535 			pctx.blk = ext2fs_bg_free_blocks_count(fs, g);
    536 			pctx.blk2 = free_array[g];
    537 
    538 			if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
    539 					&pctx)) {
    540 				ext2fs_bg_free_blocks_count_set(fs, g, free_array[g]);
    541 				ext2fs_mark_super_dirty(fs);
    542 			} else
    543 				ext2fs_unmark_valid(fs);
    544 		}
    545 	}
    546 	free_blocks = EXT2FS_C2B(fs, free_blocks);
    547 	if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
    548 		pctx.group = 0;
    549 		pctx.blk = ext2fs_free_blocks_count(fs->super);
    550 		pctx.blk2 = free_blocks;
    551 
    552 		if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
    553 			ext2fs_free_blocks_count_set(fs->super, free_blocks);
    554 			ext2fs_mark_super_dirty(fs);
    555 		}
    556 	}
    557 errout:
    558 	ext2fs_free_mem(&free_array);
    559 	ext2fs_free_mem(&actual_buf);
    560 	ext2fs_free_mem(&bitmap_buf);
    561 }
    562 
    563 static void check_inode_bitmaps(e2fsck_t ctx)
    564 {
    565 	ext2_filsys fs = ctx->fs;
    566 	ext2_ino_t	i;
    567 	unsigned int	free_inodes = 0;
    568 	int		group_free = 0;
    569 	int		dirs_count = 0;
    570 	dgrp_t		group = 0;
    571 	unsigned int	inodes = 0;
    572 	ext2_ino_t	*free_array;
    573 	ext2_ino_t	*dir_array;
    574 	int		actual, bitmap;
    575 	errcode_t	retval;
    576 	struct problem_context	pctx;
    577 	problem_t	problem, save_problem;
    578 	int		fixit, had_problem;
    579 	int		csum_flag;
    580 	int		skip_group = 0;
    581 	int		redo_flag = 0;
    582 	ext2_ino_t		first_free = fs->super->s_inodes_per_group + 1;
    583 
    584 	clear_problem_context(&pctx);
    585 	free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
    586 	    fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array");
    587 
    588 	dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
    589 	   fs->group_desc_count * sizeof(ext2_ino_t), "directory count array");
    590 
    591 	if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
    592 	    (fs->super->s_inodes_count >
    593 	     ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
    594 		pctx.num = 3;
    595 		pctx.blk = 1;
    596 		pctx.blk2 = fs->super->s_inodes_count;
    597 		pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
    598 		pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
    599 		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
    600 
    601 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    602 		goto errout;
    603 	}
    604 	if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
    605 	    (fs->super->s_inodes_count >
    606 	     ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
    607 		pctx.num = 4;
    608 		pctx.blk = 1;
    609 		pctx.blk2 = fs->super->s_inodes_count;
    610 		pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
    611 		pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
    612 		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
    613 
    614 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    615 		goto errout;
    616 	}
    617 
    618 	csum_flag = ext2fs_has_group_desc_csum(fs);
    619 redo_counts:
    620 	had_problem = 0;
    621 	save_problem = 0;
    622 	pctx.ino = pctx.ino2 = 0;
    623 	if (csum_flag &&
    624 	    (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
    625 		skip_group++;
    626 
    627 	/* Protect loop from wrap-around if inodes_count is maxed */
    628 	for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
    629 		bitmap = 0;
    630 		if (skip_group &&
    631 		    i % fs->super->s_inodes_per_group == 1) {
    632 			/*
    633 			 * Current inode is the first inode
    634 			 * in the current block group.
    635 			 */
    636 			if (ext2fs_test_inode_bitmap_range(
    637 				    ctx->inode_used_map, i,
    638 				    fs->super->s_inodes_per_group)) {
    639 				/*
    640 				 * When the compared inodes in inodes bitmap
    641 				 * are 0, count the free inode,
    642 				 * skip the current block group.
    643 				 */
    644 				first_free = 1;
    645 				inodes = fs->super->s_inodes_per_group - 1;
    646 				group_free = inodes;
    647 				free_inodes += inodes;
    648 				i += inodes;
    649 				skip_group = 0;
    650 				goto do_counts;
    651 			}
    652 		}
    653 
    654 		actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
    655 		if (redo_flag)
    656 			bitmap = actual;
    657 		else if (!skip_group)
    658 			bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
    659 		if (!actual == !bitmap)
    660 			goto do_counts;
    661 
    662 		if (!actual && bitmap) {
    663 			/*
    664 			 * Inode wasn't used, but marked in bitmap
    665 			 */
    666 			problem = PR_5_INODE_UNUSED;
    667 		} else /* if (actual && !bitmap) */ {
    668 			/*
    669 			 * Inode used, but not in bitmap
    670 			 */
    671 			problem = PR_5_INODE_USED;
    672 
    673 			/* We should never hit this, because it means that
    674 			 * inodes were marked in use that weren't noticed
    675 			 * in pass1 or pass 2. It is easier to fix the problem
    676 			 * than to kill e2fsck and leave the user stuck. */
    677 			if (skip_group) {
    678 				struct problem_context pctx2;
    679 				pctx2.blk = i;
    680 				pctx2.group = group;
    681 				if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
    682 					ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
    683 					skip_group = 0;
    684 				}
    685 			}
    686 		}
    687 		if (pctx.ino == 0) {
    688 			pctx.ino = pctx.ino2 = i;
    689 			save_problem = problem;
    690 		} else {
    691 			if ((problem == save_problem) &&
    692 			    (pctx.ino2 == i-1))
    693 				pctx.ino2++;
    694 			else {
    695 				print_bitmap_problem(ctx, save_problem, &pctx);
    696 				pctx.ino = pctx.ino2 = i;
    697 				save_problem = problem;
    698 			}
    699 		}
    700 		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
    701 		had_problem++;
    702 		/*
    703 		 * If there a problem we should turn off the discard so we
    704 		 * do not compromise the filesystem.
    705 		 */
    706 		ctx->options &= ~E2F_OPT_DISCARD;
    707 
    708 do_counts:
    709 		inodes++;
    710 		if (bitmap) {
    711 			if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
    712 				dirs_count++;
    713 			if (inodes > first_free) {
    714 				e2fsck_discard_inodes(ctx, group, first_free,
    715 						      inodes - first_free);
    716 				first_free = fs->super->s_inodes_per_group + 1;
    717 			}
    718 		} else {
    719 			group_free++;
    720 			free_inodes++;
    721 			if (first_free > inodes)
    722 				first_free = inodes;
    723 		}
    724 
    725 		if ((inodes == fs->super->s_inodes_per_group) ||
    726 		    (i == fs->super->s_inodes_count)) {
    727 			/*
    728 			 * If the last inode is free, we can discard it as well.
    729 			 */
    730 			if (!bitmap && inodes >= first_free)
    731 				e2fsck_discard_inodes(ctx, group, first_free,
    732 						      inodes - first_free + 1);
    733 			/*
    734 			 * If discard zeroes data and the group inode table
    735 			 * was not zeroed yet, set itable as zeroed
    736 			 */
    737 			if ((ctx->options & E2F_OPT_DISCARD) &&
    738 			    io_channel_discard_zeroes_data(fs->io) &&
    739 			    !(ext2fs_bg_flags_test(fs, group,
    740 						   EXT2_BG_INODE_ZEROED))) {
    741 				ext2fs_bg_flags_set(fs, group,
    742 						    EXT2_BG_INODE_ZEROED);
    743 				ext2fs_group_desc_csum_set(fs, group);
    744 			}
    745 
    746 			first_free = fs->super->s_inodes_per_group + 1;
    747 			free_array[group] = group_free;
    748 			dir_array[group] = dirs_count;
    749 			group ++;
    750 			inodes = 0;
    751 			skip_group = 0;
    752 			group_free = 0;
    753 			dirs_count = 0;
    754 			if (ctx->progress)
    755 				if ((ctx->progress)(ctx, 5,
    756 					    group + fs->group_desc_count,
    757 					    fs->group_desc_count*2))
    758 					goto errout;
    759 			if (csum_flag &&
    760 			    (i != fs->super->s_inodes_count) &&
    761 			    (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
    762 			     ))
    763 				skip_group++;
    764 		}
    765 	}
    766 	if (pctx.ino)
    767 		print_bitmap_problem(ctx, save_problem, &pctx);
    768 
    769 	if (had_problem)
    770 		fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
    771 	else
    772 		fixit = -1;
    773 	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
    774 
    775 	if (fixit == 1) {
    776 		ext2fs_free_inode_bitmap(fs->inode_map);
    777 		retval = ext2fs_copy_bitmap(ctx->inode_used_map,
    778 						  &fs->inode_map);
    779 		if (retval) {
    780 			clear_problem_context(&pctx);
    781 			fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
    782 			ctx->flags |= E2F_FLAG_ABORT;
    783 			goto errout;
    784 		}
    785 		ext2fs_set_bitmap_padding(fs->inode_map);
    786 		ext2fs_mark_ib_dirty(fs);
    787 
    788 		/* redo counts */
    789 		inodes = 0; free_inodes = 0; group_free = 0;
    790 		dirs_count = 0; group = 0;
    791 		memset(free_array, 0, fs->group_desc_count * sizeof(int));
    792 		memset(dir_array, 0, fs->group_desc_count * sizeof(int));
    793 		redo_flag++;
    794 		goto redo_counts;
    795 	} else if (fixit == 0)
    796 		ext2fs_unmark_valid(fs);
    797 
    798 	for (i = 0; i < fs->group_desc_count; i++) {
    799 		if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
    800 			pctx.group = i;
    801 			pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
    802 			pctx.ino2 = free_array[i];
    803 			if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
    804 					&pctx)) {
    805 				ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
    806 				ext2fs_mark_super_dirty(fs);
    807 			} else
    808 				ext2fs_unmark_valid(fs);
    809 		}
    810 		if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
    811 			pctx.group = i;
    812 			pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
    813 			pctx.ino2 = dir_array[i];
    814 
    815 			if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
    816 					&pctx)) {
    817 				ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
    818 				ext2fs_mark_super_dirty(fs);
    819 			} else
    820 				ext2fs_unmark_valid(fs);
    821 		}
    822 	}
    823 	if (free_inodes != fs->super->s_free_inodes_count) {
    824 		pctx.group = -1;
    825 		pctx.ino = fs->super->s_free_inodes_count;
    826 		pctx.ino2 = free_inodes;
    827 
    828 		if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
    829 			fs->super->s_free_inodes_count = free_inodes;
    830 			ext2fs_mark_super_dirty(fs);
    831 		}
    832 	}
    833 errout:
    834 	ext2fs_free_mem(&free_array);
    835 	ext2fs_free_mem(&dir_array);
    836 }
    837 
    838 static void check_inode_end(e2fsck_t ctx)
    839 {
    840 	ext2_filsys fs = ctx->fs;
    841 	ext2_ino_t	end, save_inodes_count, i;
    842 	struct problem_context	pctx;
    843 
    844 	clear_problem_context(&pctx);
    845 
    846 	end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
    847 	pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
    848 						     &save_inodes_count);
    849 	if (pctx.errcode) {
    850 		pctx.num = 1;
    851 		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
    852 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    853 		return;
    854 	}
    855 	if (save_inodes_count == end)
    856 		return;
    857 
    858 	/* protect loop from wrap-around if end is maxed */
    859 	for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
    860 		if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
    861 			if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
    862 				for (; i <= end; i++)
    863 					ext2fs_mark_inode_bitmap(fs->inode_map,
    864 								 i);
    865 				ext2fs_mark_ib_dirty(fs);
    866 			} else
    867 				ext2fs_unmark_valid(fs);
    868 			break;
    869 		}
    870 	}
    871 
    872 	pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
    873 						     save_inodes_count, 0);
    874 	if (pctx.errcode) {
    875 		pctx.num = 2;
    876 		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
    877 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    878 		return;
    879 	}
    880 }
    881 
    882 static void check_block_end(e2fsck_t ctx)
    883 {
    884 	ext2_filsys fs = ctx->fs;
    885 	blk64_t	end, save_blocks_count, i;
    886 	struct problem_context	pctx;
    887 
    888 	clear_problem_context(&pctx);
    889 
    890 	end = ext2fs_get_block_bitmap_start2(fs->block_map) +
    891 		EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count) - 1;
    892 	pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
    893 						     &save_blocks_count);
    894 	if (pctx.errcode) {
    895 		pctx.num = 3;
    896 		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
    897 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    898 		return;
    899 	}
    900 	if (save_blocks_count == end)
    901 		return;
    902 
    903 	/* Protect loop from wrap-around if end is maxed */
    904 	for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
    905 		if (!ext2fs_test_block_bitmap2(fs->block_map,
    906 					       EXT2FS_C2B(fs, i))) {
    907 			if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
    908 				for (; i <= end; i++)
    909 					ext2fs_mark_block_bitmap2(fs->block_map,
    910 							EXT2FS_C2B(fs, i));
    911 				ext2fs_mark_bb_dirty(fs);
    912 			} else
    913 				ext2fs_unmark_valid(fs);
    914 			break;
    915 		}
    916 	}
    917 
    918 	pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
    919 						     save_blocks_count, 0);
    920 	if (pctx.errcode) {
    921 		pctx.num = 4;
    922 		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
    923 		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
    924 		return;
    925 	}
    926 }
    927 
    928 
    929 
    930