]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - e2fsck/pass5.c
e2fsck: clean up feature test macros with predicate functions
[thirdparty/e2fsprogs.git] / e2fsck / pass5.c
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 == (int)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