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 
e2fsck_pass5(e2fsck_t ctx)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 
check_inode_bitmap_checksum(e2fsck_t ctx)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 
check_block_bitmap_checksum(e2fsck_t ctx)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 
e2fsck_discard_blocks(e2fsck_t ctx,blk64_t start,blk64_t count)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  */
e2fsck_discard_inodes(e2fsck_t ctx,dgrp_t group,ext2_ino_t start,int count)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 
print_bitmap_problem(e2fsck_t ctx,problem_t problem,struct problem_context * pctx)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 
check_block_bitmaps(e2fsck_t ctx)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 
check_inode_bitmaps(e2fsck_t ctx)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 
check_inode_end(e2fsck_t ctx)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 
check_block_end(e2fsck_t ctx)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