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