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