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