OSDN Git Service

Merge branch 'maint' into next
[android-x86/external-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 "e2fsck.h"
14 #include "problem.h"
15
16 static void check_block_bitmaps(e2fsck_t ctx);
17 static void check_inode_bitmaps(e2fsck_t ctx);
18 static void check_inode_end(e2fsck_t ctx);
19 static void check_block_end(e2fsck_t ctx);
20
21 void e2fsck_pass5(e2fsck_t ctx)
22 {
23 #ifdef RESOURCE_TRACK
24         struct resource_track   rtrack;
25 #endif
26         struct problem_context  pctx;
27
28 #ifdef MTRACE
29         mtrace_print("Pass 5");
30 #endif
31
32         init_resource_track(&rtrack, ctx->fs->io);
33         clear_problem_context(&pctx);
34
35         if (!(ctx->options & E2F_OPT_PREEN))
36                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
37
38         if (ctx->progress)
39                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
40                         return;
41
42         e2fsck_read_bitmaps(ctx);
43
44         check_block_bitmaps(ctx);
45         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
46                 return;
47         check_inode_bitmaps(ctx);
48         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
49                 return;
50         check_inode_end(ctx);
51         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
52                 return;
53         check_block_end(ctx);
54         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
55                 return;
56
57         ext2fs_free_inode_bitmap(ctx->inode_used_map);
58         ctx->inode_used_map = 0;
59         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
60         ctx->inode_dir_map = 0;
61         ext2fs_free_block_bitmap(ctx->block_found_map);
62         ctx->block_found_map = 0;
63
64         print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
65 }
66
67 #define NO_BLK ((blk64_t) -1)
68
69 static void print_bitmap_problem(e2fsck_t ctx, int problem,
70                             struct problem_context *pctx)
71 {
72         switch (problem) {
73         case PR_5_BLOCK_UNUSED:
74                 if (pctx->blk == pctx->blk2)
75                         pctx->blk2 = 0;
76                 else
77                         problem = PR_5_BLOCK_RANGE_UNUSED;
78                 break;
79         case PR_5_BLOCK_USED:
80                 if (pctx->blk == pctx->blk2)
81                         pctx->blk2 = 0;
82                 else
83                         problem = PR_5_BLOCK_RANGE_USED;
84                 break;
85         case PR_5_INODE_UNUSED:
86                 if (pctx->ino == pctx->ino2)
87                         pctx->ino2 = 0;
88                 else
89                         problem = PR_5_INODE_RANGE_UNUSED;
90                 break;
91         case PR_5_INODE_USED:
92                 if (pctx->ino == pctx->ino2)
93                         pctx->ino2 = 0;
94                 else
95                         problem = PR_5_INODE_RANGE_USED;
96                 break;
97         }
98         fix_problem(ctx, problem, pctx);
99         pctx->blk = pctx->blk2 = NO_BLK;
100         pctx->ino = pctx->ino2 = 0;
101 }
102
103 static void check_block_bitmaps(e2fsck_t ctx)
104 {
105         ext2_filsys fs = ctx->fs;
106         blk64_t i;
107         int     *free_array;
108         int     group = 0;
109         int     blocks = 0;
110         blk64_t free_blocks = 0;
111         int     group_free = 0;
112         int     actual, bitmap;
113         struct problem_context  pctx;
114         int     problem, save_problem, fixit, had_problem;
115         errcode_t       retval;
116         int             csum_flag;
117         int             skip_group = 0;
118         int     old_desc_blocks = 0;
119         int     count = 0;
120         int     cmp_block = 0;
121         int     redo_flag = 0;
122         blk64_t super_blk, old_desc_blk, new_desc_blk;
123
124         clear_problem_context(&pctx);
125         free_array = (int *) e2fsck_allocate_memory(ctx,
126             fs->group_desc_count * sizeof(int), "free block count array");
127
128         if ((fs->super->s_first_data_block <
129              ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
130             (ext2fs_blocks_count(fs->super)-1 >
131              ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
132                 pctx.num = 1;
133                 pctx.blk = fs->super->s_first_data_block;
134                 pctx.blk2 = ext2fs_blocks_count(fs->super) -1;
135                 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
136                 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
137                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
138
139                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
140                 goto errout;
141         }
142
143         if ((fs->super->s_first_data_block <
144              ext2fs_get_block_bitmap_start2(fs->block_map)) ||
145             (ext2fs_blocks_count(fs->super)-1 >
146              ext2fs_get_block_bitmap_end2(fs->block_map))) {
147                 pctx.num = 2;
148                 pctx.blk = fs->super->s_first_data_block;
149                 pctx.blk2 = ext2fs_blocks_count(fs->super) -1;
150                 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
151                 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
152                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
153
154                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
155                 goto errout;
156         }
157
158         csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
159                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
160 redo_counts:
161         had_problem = 0;
162         save_problem = 0;
163         pctx.blk = pctx.blk2 = NO_BLK;
164         if (csum_flag &&
165             (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
166                 skip_group++;
167         for (i = fs->super->s_first_data_block;
168              i < ext2fs_blocks_count(fs->super);
169              i++) {
170                 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
171
172                 if (skip_group) {
173                         if ((i - fs->super->s_first_data_block) %
174                             fs->super->s_blocks_per_group == 0) {
175                                 super_blk = 0;
176                                 old_desc_blk = 0;
177                                 new_desc_blk = 0;
178                                 ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
179                                          &old_desc_blk, &new_desc_blk, 0);
180
181                                 if (fs->super->s_feature_incompat &
182                                                 EXT2_FEATURE_INCOMPAT_META_BG)
183                                         old_desc_blocks =
184                                                 fs->super->s_first_meta_bg;
185                                 else
186                                         old_desc_blocks = fs->desc_blocks +
187                                         fs->super->s_reserved_gdt_blocks;
188
189                                 count = 0;
190                                 cmp_block = fs->super->s_blocks_per_group;
191                                 if (group == (int)fs->group_desc_count - 1)
192                                         cmp_block =
193                                                 ext2fs_blocks_count(fs->super) %
194                                                 fs->super->s_blocks_per_group;
195                         }
196
197                         bitmap = 0;
198                         if ((i == super_blk) ||
199                             (old_desc_blk && old_desc_blocks &&
200                              (i >= old_desc_blk) &&
201                              (i < old_desc_blk + old_desc_blocks)) ||
202                             (new_desc_blk && (i == new_desc_blk)) ||
203                             (i == ext2fs_block_bitmap_loc(fs, group)) ||
204                             (i == ext2fs_inode_bitmap_loc(fs, group)) ||
205                             (i >= ext2fs_inode_table_loc(fs, group) &&
206                              (i < ext2fs_inode_table_loc(fs, group) +
207                               fs->inode_blocks_per_group))) {
208                                 bitmap = 1;
209                                 actual = (actual != 0);
210                                 count++;
211                                 cmp_block--;
212                         } else if ((i - count - fs->super->s_first_data_block) %
213                                   fs->super->s_blocks_per_group == 0) {
214                                 /*
215                                  * When the compare data blocks in block bitmap
216                                  * are 0, count the free block,
217                                  * skip the current block group.
218                                  */
219                                 if (ext2fs_test_block_bitmap_range2(
220                                             ctx->block_found_map, i,
221                                             cmp_block)) {
222                                         /*
223                                          * -1 means to skip the current block
224                                          * group.
225                                          */
226                                         blocks = fs->super->s_blocks_per_group
227                                                                         - 1;
228                                         group_free = cmp_block;
229                                         free_blocks += cmp_block;
230                                         /*
231                                          * The current block group's last block
232                                          * is set to i.
233                                          */
234                                         i += cmp_block - 1;
235                                         bitmap = 1;
236                                         goto do_counts;
237                                 }
238                         }
239                 } else if (redo_flag)
240                         bitmap = actual;
241                 else
242                         bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
243
244                 if (actual == bitmap)
245                         goto do_counts;
246
247                 if (!actual && bitmap) {
248                         /*
249                          * Block not used, but marked in use in the bitmap.
250                          */
251                         problem = PR_5_BLOCK_UNUSED;
252                 } else {
253                         /*
254                          * Block used, but not marked in use in the bitmap.
255                          */
256                         problem = PR_5_BLOCK_USED;
257
258                         if (skip_group) {
259                                 struct problem_context pctx2;
260                                 pctx2.blk = i;
261                                 pctx2.group = group;
262                                 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
263                                         ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
264                                         skip_group = 0;
265                                 }
266                         }
267                 }
268                 if (pctx.blk == NO_BLK) {
269                         pctx.blk = pctx.blk2 = i;
270                         save_problem = problem;
271                 } else {
272                         if ((problem == save_problem) &&
273                             (pctx.blk2 == i-1))
274                                 pctx.blk2++;
275                         else {
276                                 print_bitmap_problem(ctx, save_problem, &pctx);
277                                 pctx.blk = pctx.blk2 = i;
278                                 save_problem = problem;
279                         }
280                 }
281                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
282                 had_problem++;
283
284         do_counts:
285                 if (!bitmap && (!skip_group || csum_flag)) {
286                         group_free++;
287                         free_blocks++;
288                 }
289                 blocks ++;
290                 if ((blocks == fs->super->s_blocks_per_group) ||
291                     (i == ext2fs_blocks_count(fs->super)-1)) {
292                         free_array[group] = group_free;
293                         group ++;
294                         blocks = 0;
295                         group_free = 0;
296                         skip_group = 0;
297                         if (ctx->progress)
298                                 if ((ctx->progress)(ctx, 5, group,
299                                                     fs->group_desc_count*2))
300                                         goto errout;
301                         if (csum_flag &&
302                             (i != ext2fs_blocks_count(fs->super)-1) &&
303                             ext2fs_bg_flags_test(fs, group, 
304                                                 EXT2_BG_BLOCK_UNINIT))
305                                 skip_group++;
306                 }
307         }
308         if (pctx.blk != NO_BLK)
309                 print_bitmap_problem(ctx, save_problem, &pctx);
310         if (had_problem)
311                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
312         else
313                 fixit = -1;
314         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
315
316         if (fixit == 1) {
317                 ext2fs_free_block_bitmap(fs->block_map);
318                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
319                                                   &fs->block_map);
320                 if (retval) {
321                         clear_problem_context(&pctx);
322                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
323                         ctx->flags |= E2F_FLAG_ABORT;
324                         goto errout;
325                 }
326                 ext2fs_set_bitmap_padding(fs->block_map);
327                 ext2fs_mark_bb_dirty(fs);
328
329                 /* Redo the counts */
330                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
331                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
332                 redo_flag++;
333                 goto redo_counts;
334         } else if (fixit == 0)
335                 ext2fs_unmark_valid(fs);
336
337         for (i = 0; i < fs->group_desc_count; i++) {
338                 if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) {
339                         pctx.group = i;
340                         pctx.blk = ext2fs_bg_free_blocks_count(fs, i);
341                         pctx.blk2 = free_array[i];
342
343                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
344                                         &pctx)) {
345                                 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]);
346                                 ext2fs_mark_super_dirty(fs);
347                         } else
348                                 ext2fs_unmark_valid(fs);
349                 }
350         }
351         if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
352                 pctx.group = 0;
353                 pctx.blk = ext2fs_free_blocks_count(fs->super);
354                 pctx.blk2 = free_blocks;
355
356                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
357                         ext2fs_free_blocks_count_set(fs->super, free_blocks);
358                         ext2fs_mark_super_dirty(fs);
359                 } else
360                         ext2fs_unmark_valid(fs);
361         }
362 errout:
363         ext2fs_free_mem(&free_array);
364 }
365
366 static void check_inode_bitmaps(e2fsck_t ctx)
367 {
368         ext2_filsys fs = ctx->fs;
369         ext2_ino_t      i;
370         unsigned int    free_inodes = 0;
371         int             group_free = 0;
372         int             dirs_count = 0;
373         int             group = 0;
374         unsigned int    inodes = 0;
375         int             *free_array;
376         int             *dir_array;
377         int             actual, bitmap;
378         errcode_t       retval;
379         struct problem_context  pctx;
380         int             problem, save_problem, fixit, had_problem;
381         int             csum_flag;
382         int             skip_group = 0;
383         int             redo_flag = 0;
384
385         clear_problem_context(&pctx);
386         free_array = (int *) e2fsck_allocate_memory(ctx,
387             fs->group_desc_count * sizeof(int), "free inode count array");
388
389         dir_array = (int *) e2fsck_allocate_memory(ctx,
390            fs->group_desc_count * sizeof(int), "directory count array");
391
392         if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
393             (fs->super->s_inodes_count >
394              ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
395                 pctx.num = 3;
396                 pctx.blk = 1;
397                 pctx.blk2 = fs->super->s_inodes_count;
398                 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
399                 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
400                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
401
402                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
403                 goto errout;
404         }
405         if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
406             (fs->super->s_inodes_count >
407              ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
408                 pctx.num = 4;
409                 pctx.blk = 1;
410                 pctx.blk2 = fs->super->s_inodes_count;
411                 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
412                 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
413                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
414
415                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
416                 goto errout;
417         }
418
419         csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
420                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
421 redo_counts:
422         had_problem = 0;
423         save_problem = 0;
424         pctx.ino = pctx.ino2 = 0;
425         if (csum_flag &&
426             (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
427                 skip_group++;
428
429         /* Protect loop from wrap-around if inodes_count is maxed */
430         for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
431                 bitmap = 0;
432                 if (skip_group &&
433                     i % fs->super->s_inodes_per_group == 1) {
434                         /*
435                          * Current inode is the first inode
436                          * in the current block group.
437                          */
438                         if (ext2fs_test_inode_bitmap_range(
439                                     ctx->inode_used_map, i,
440                                     fs->super->s_inodes_per_group)) {
441                                 /*
442                                  * When the compared inodes in inodes bitmap
443                                  * are 0, count the free inode,
444                                  * skip the current block group.
445                                  */
446                                 inodes = fs->super->s_inodes_per_group - 1;
447                                 group_free = inodes;
448                                 free_inodes += inodes;
449                                 i += inodes;
450                                 skip_group = 0;
451                                 goto do_counts;
452                         }
453                 }
454
455                 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
456                 if (redo_flag)
457                         bitmap = actual;
458                 else if (!skip_group)
459                         bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
460                 if (actual == bitmap)
461                         goto do_counts;
462
463                 if (!actual && bitmap) {
464                         /*
465                          * Inode wasn't used, but marked in bitmap
466                          */
467                         problem = PR_5_INODE_UNUSED;
468                 } else /* if (actual && !bitmap) */ {
469                         /*
470                          * Inode used, but not in bitmap
471                          */
472                         problem = PR_5_INODE_USED;
473
474                         /* We should never hit this, because it means that
475                          * inodes were marked in use that weren't noticed
476                          * in pass1 or pass 2. It is easier to fix the problem
477                          * than to kill e2fsck and leave the user stuck. */
478                         if (skip_group) {
479                                 struct problem_context pctx2;
480                                 pctx2.blk = i;
481                                 pctx2.group = group;
482                                 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
483                                         ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
484                                         skip_group = 0;
485                                 }
486                         }
487                 }
488                 if (pctx.ino == 0) {
489                         pctx.ino = pctx.ino2 = i;
490                         save_problem = problem;
491                 } else {
492                         if ((problem == save_problem) &&
493                             (pctx.ino2 == i-1))
494                                 pctx.ino2++;
495                         else {
496                                 print_bitmap_problem(ctx, save_problem, &pctx);
497                                 pctx.ino = pctx.ino2 = i;
498                                 save_problem = problem;
499                         }
500                 }
501                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
502                 had_problem++;
503
504 do_counts:
505                 if (bitmap) {
506                         if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
507                                 dirs_count++;
508                 } else if (!skip_group || csum_flag) {
509                         group_free++;
510                         free_inodes++;
511                 }
512                 inodes++;
513                 if ((inodes == fs->super->s_inodes_per_group) ||
514                     (i == fs->super->s_inodes_count)) {
515                         free_array[group] = group_free;
516                         dir_array[group] = dirs_count;
517                         group ++;
518                         inodes = 0;
519                         skip_group = 0;
520                         group_free = 0;
521                         dirs_count = 0;
522                         if (ctx->progress)
523                                 if ((ctx->progress)(ctx, 5,
524                                             group + fs->group_desc_count,
525                                             fs->group_desc_count*2))
526                                         goto errout;
527                         if (csum_flag &&
528                             (i != fs->super->s_inodes_count) &&
529                             (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
530                              ))
531                                 skip_group++;
532                 }
533         }
534         if (pctx.ino)
535                 print_bitmap_problem(ctx, save_problem, &pctx);
536
537         if (had_problem)
538                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
539         else
540                 fixit = -1;
541         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
542
543         if (fixit == 1) {
544                 ext2fs_free_inode_bitmap(fs->inode_map);
545                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
546                                                   &fs->inode_map);
547                 if (retval) {
548                         clear_problem_context(&pctx);
549                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
550                         ctx->flags |= E2F_FLAG_ABORT;
551                         goto errout;
552                 }
553                 ext2fs_set_bitmap_padding(fs->inode_map);
554                 ext2fs_mark_ib_dirty(fs);
555
556                 /* redo counts */
557                 inodes = 0; free_inodes = 0; group_free = 0;
558                 dirs_count = 0; group = 0;
559                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
560                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
561                 redo_flag++;
562                 goto redo_counts;
563         } else if (fixit == 0)
564                 ext2fs_unmark_valid(fs);
565
566         for (i = 0; i < fs->group_desc_count; i++) {
567                 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
568                         pctx.group = i;
569                         pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
570                         pctx.ino2 = free_array[i];
571                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
572                                         &pctx)) {
573                                 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
574                                 ext2fs_mark_super_dirty(fs);
575                         } else
576                                 ext2fs_unmark_valid(fs);
577                 }
578                 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
579                         pctx.group = i;
580                         pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
581                         pctx.ino2 = dir_array[i];
582
583                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
584                                         &pctx)) {
585                                 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
586                                 ext2fs_mark_super_dirty(fs);
587                         } else
588                                 ext2fs_unmark_valid(fs);
589                 }
590         }
591         if (free_inodes != fs->super->s_free_inodes_count) {
592                 pctx.group = -1;
593                 pctx.ino = fs->super->s_free_inodes_count;
594                 pctx.ino2 = free_inodes;
595
596                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
597                         fs->super->s_free_inodes_count = free_inodes;
598                         ext2fs_mark_super_dirty(fs);
599                 } else
600                         ext2fs_unmark_valid(fs);
601         }
602 errout:
603         ext2fs_free_mem(&free_array);
604         ext2fs_free_mem(&dir_array);
605 }
606
607 static void check_inode_end(e2fsck_t ctx)
608 {
609         ext2_filsys fs = ctx->fs;
610         ext2_ino_t      end, save_inodes_count, i;
611         struct problem_context  pctx;
612
613         clear_problem_context(&pctx);
614
615         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
616         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
617                                                      &save_inodes_count);
618         if (pctx.errcode) {
619                 pctx.num = 1;
620                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
621                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
622                 return;
623         }
624         if (save_inodes_count == end)
625                 return;
626
627         /* protect loop from wrap-around if end is maxed */
628         for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
629                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
630                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
631                                 for (; i <= end; i++)
632                                         ext2fs_mark_inode_bitmap(fs->inode_map,
633                                                                  i);
634                                 ext2fs_mark_ib_dirty(fs);
635                         } else
636                                 ext2fs_unmark_valid(fs);
637                         break;
638                 }
639         }
640
641         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
642                                                      save_inodes_count, 0);
643         if (pctx.errcode) {
644                 pctx.num = 2;
645                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
646                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
647                 return;
648         }
649 }
650
651 static void check_block_end(e2fsck_t ctx)
652 {
653         ext2_filsys fs = ctx->fs;
654         blk64_t end, save_blocks_count, i;
655         struct problem_context  pctx;
656
657         clear_problem_context(&pctx);
658
659         end = ext2fs_get_block_bitmap_start2(fs->block_map) +
660                 ((blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
661         pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
662                                                      &save_blocks_count);
663         if (pctx.errcode) {
664                 pctx.num = 3;
665                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
666                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
667                 return;
668         }
669         if (save_blocks_count == end)
670                 return;
671
672         /* Protect loop from wrap-around if end is maxed */
673         for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
674                 if (!ext2fs_test_block_bitmap2(fs->block_map, i)) {
675                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
676                                 for (; i <= end; i++)
677                                         ext2fs_mark_block_bitmap2(fs->block_map,
678                                                                   i);
679                                 ext2fs_mark_bb_dirty(fs);
680                         } else
681                                 ext2fs_unmark_valid(fs);
682                         break;
683                 }
684         }
685
686         pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
687                                                      save_blocks_count, 0);
688         if (pctx.errcode) {
689                 pctx.num = 4;
690                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
691                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
692                 return;
693         }
694 }
695
696
697