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