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