Whamcloud - gitweb
Use accessor functions fields for bg_flags in the block group descriptors
[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 "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 ((blk_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         blk_t   blocks = 0;
110         blk_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             (fs->super->s_blocks_count-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 = fs->super->s_blocks_count -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             (fs->super->s_blocks_count-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 = fs->super->s_blocks_count -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_flag_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
166                 skip_group++;
167         for (i = fs->super->s_first_data_block;
168              i < fs->super->s_blocks_count;
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                                                 fs->super->s_blocks_count %
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 == fs->group_desc[group].bg_block_bitmap) ||
204                                 (i == fs->group_desc[group].bg_inode_bitmap) ||
205                                 (i >= fs->group_desc[group].bg_inode_table &&
206                                 (i < fs->group_desc[group].bg_inode_table +
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_flag_clear(fs, group, EXT2_BG_BLOCK_UNINIT)
264                                                 ;
265                                         skip_group = 0;
266                                 }
267                         }
268                 }
269                 if (pctx.blk == NO_BLK) {
270                         pctx.blk = pctx.blk2 = i;
271                         save_problem = problem;
272                 } else {
273                         if ((problem == save_problem) &&
274                             (pctx.blk2 == i-1))
275                                 pctx.blk2++;
276                         else {
277                                 print_bitmap_problem(ctx, save_problem, &pctx);
278                                 pctx.blk = pctx.blk2 = i;
279                                 save_problem = problem;
280                         }
281                 }
282                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
283                 had_problem++;
284
285         do_counts:
286                 if (!bitmap && (!skip_group || csum_flag)) {
287                         group_free++;
288                         free_blocks++;
289                 }
290                 blocks ++;
291                 if ((blocks == fs->super->s_blocks_per_group) ||
292                     (i == fs->super->s_blocks_count-1)) {
293                         free_array[group] = group_free;
294                         group ++;
295                         blocks = 0;
296                         group_free = 0;
297                         skip_group = 0;
298                         if (ctx->progress)
299                                 if ((ctx->progress)(ctx, 5, group,
300                                                     fs->group_desc_count*2))
301                                         goto errout;
302                         if (csum_flag &&
303                             (i != fs->super->s_blocks_count-1) &&
304                             ext2fs_bg_flag_test(fs, group, 
305                                                 EXT2_BG_BLOCK_UNINIT))
306                                 skip_group++;
307                 }
308         }
309         if (pctx.blk != NO_BLK)
310                 print_bitmap_problem(ctx, save_problem, &pctx);
311         if (had_problem)
312                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
313         else
314                 fixit = -1;
315         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
316
317         if (fixit == 1) {
318                 ext2fs_free_block_bitmap(fs->block_map);
319                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
320                                                   &fs->block_map);
321                 if (retval) {
322                         clear_problem_context(&pctx);
323                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
324                         ctx->flags |= E2F_FLAG_ABORT;
325                         goto errout;
326                 }
327                 ext2fs_set_bitmap_padding(fs->block_map);
328                 ext2fs_mark_bb_dirty(fs);
329
330                 /* Redo the counts */
331                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
332                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
333                 redo_flag++;
334                 goto redo_counts;
335         } else if (fixit == 0)
336                 ext2fs_unmark_valid(fs);
337
338         for (i = 0; i < fs->group_desc_count; i++) {
339                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
340                         pctx.group = i;
341                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
342                         pctx.blk2 = free_array[i];
343
344                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
345                                         &pctx)) {
346                                 fs->group_desc[i].bg_free_blocks_count =
347                                         free_array[i];
348                                 ext2fs_mark_super_dirty(fs);
349                         } else
350                                 ext2fs_unmark_valid(fs);
351                 }
352         }
353         if (free_blocks != fs->super->s_free_blocks_count) {
354                 pctx.group = 0;
355                 pctx.blk = fs->super->s_free_blocks_count;
356                 pctx.blk2 = free_blocks;
357
358                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
359                         fs->super->s_free_blocks_count = free_blocks;
360                         ext2fs_mark_super_dirty(fs);
361                 } else
362                         ext2fs_unmark_valid(fs);
363         }
364 errout:
365         ext2fs_free_mem(&free_array);
366 }
367
368 static void check_inode_bitmaps(e2fsck_t ctx)
369 {
370         ext2_filsys fs = ctx->fs;
371         ext2_ino_t      i;
372         unsigned int    free_inodes = 0;
373         int             group_free = 0;
374         int             dirs_count = 0;
375         int             group = 0;
376         unsigned int    inodes = 0;
377         int             *free_array;
378         int             *dir_array;
379         int             actual, bitmap;
380         errcode_t       retval;
381         struct problem_context  pctx;
382         int             problem, save_problem, fixit, had_problem;
383         int             csum_flag;
384         int             skip_group = 0;
385         int             redo_flag = 0;
386
387         clear_problem_context(&pctx);
388         free_array = (int *) e2fsck_allocate_memory(ctx,
389             fs->group_desc_count * sizeof(int), "free inode count array");
390
391         dir_array = (int *) e2fsck_allocate_memory(ctx,
392            fs->group_desc_count * sizeof(int), "directory count array");
393
394         if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
395             (fs->super->s_inodes_count >
396              ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
397                 pctx.num = 3;
398                 pctx.blk = 1;
399                 pctx.blk2 = fs->super->s_inodes_count;
400                 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
401                 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
402                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
403
404                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
405                 goto errout;
406         }
407         if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
408             (fs->super->s_inodes_count >
409              ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
410                 pctx.num = 4;
411                 pctx.blk = 1;
412                 pctx.blk2 = fs->super->s_inodes_count;
413                 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
414                 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
415                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
416
417                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
418                 goto errout;
419         }
420
421         csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
422                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
423 redo_counts:
424         had_problem = 0;
425         save_problem = 0;
426         pctx.ino = pctx.ino2 = 0;
427         if (csum_flag &&
428             (ext2fs_bg_flag_test(fs, group, EXT2_BG_INODE_UNINIT)))
429                 skip_group++;
430
431         /* Protect loop from wrap-around if inodes_count is maxed */
432         for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
433                 bitmap = 0;
434                 if (skip_group &&
435                     i % fs->super->s_inodes_per_group == 1) {
436                         /*
437                          * Current inode is the first inode
438                          * in the current block group.
439                          */
440                         if (ext2fs_test_inode_bitmap_range(
441                                     ctx->inode_used_map, i,
442                                     fs->super->s_inodes_per_group)) {
443                                 /*
444                                  * When the compared inodes in inodes bitmap
445                                  * are 0, count the free inode,
446                                  * skip the current block group.
447                                  */
448                                 inodes = fs->super->s_inodes_per_group - 1;
449                                 group_free = inodes;
450                                 free_inodes += inodes;
451                                 i += inodes;
452                                 skip_group = 0;
453                                 goto do_counts;
454                         }
455                 }
456
457                 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
458                 if (redo_flag)
459                         bitmap = actual;
460                 else if (!skip_group)
461                         bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
462                 if (actual == bitmap)
463                         goto do_counts;
464
465                 if (!actual && bitmap) {
466                         /*
467                          * Inode wasn't used, but marked in bitmap
468                          */
469                         problem = PR_5_INODE_UNUSED;
470                 } else /* if (actual && !bitmap) */ {
471                         /*
472                          * Inode used, but not in bitmap
473                          */
474                         problem = PR_5_INODE_USED;
475
476                         /* We should never hit this, because it means that
477                          * inodes were marked in use that weren't noticed
478                          * in pass1 or pass 2. It is easier to fix the problem
479                          * than to kill e2fsck and leave the user stuck. */
480                         if (skip_group) {
481                                 struct problem_context pctx2;
482                                 pctx2.blk = i;
483                                 pctx2.group = group;
484                                 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
485                                         ext2fs_bg_flag_clear(fs, group, EXT2_BG_INODE_UNINIT)
486                                                 ;
487                                         skip_group = 0;
488                                 }
489                         }
490                 }
491                 if (pctx.ino == 0) {
492                         pctx.ino = pctx.ino2 = i;
493                         save_problem = problem;
494                 } else {
495                         if ((problem == save_problem) &&
496                             (pctx.ino2 == i-1))
497                                 pctx.ino2++;
498                         else {
499                                 print_bitmap_problem(ctx, save_problem, &pctx);
500                                 pctx.ino = pctx.ino2 = i;
501                                 save_problem = problem;
502                         }
503                 }
504                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
505                 had_problem++;
506
507 do_counts:
508                 if (bitmap) {
509                         if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
510                                 dirs_count++;
511                 } else if (!skip_group || csum_flag) {
512                         group_free++;
513                         free_inodes++;
514                 }
515                 inodes++;
516                 if ((inodes == fs->super->s_inodes_per_group) ||
517                     (i == fs->super->s_inodes_count)) {
518                         free_array[group] = group_free;
519                         dir_array[group] = dirs_count;
520                         group ++;
521                         inodes = 0;
522                         skip_group = 0;
523                         group_free = 0;
524                         dirs_count = 0;
525                         if (ctx->progress)
526                                 if ((ctx->progress)(ctx, 5,
527                                             group + fs->group_desc_count,
528                                             fs->group_desc_count*2))
529                                         goto errout;
530                         if (csum_flag &&
531                             (i != fs->super->s_inodes_count) &&
532                             (ext2fs_bg_flag_test(fs, group, EXT2_BG_INODE_UNINIT)
533                              ))
534                                 skip_group++;
535                 }
536         }
537         if (pctx.ino)
538                 print_bitmap_problem(ctx, save_problem, &pctx);
539
540         if (had_problem)
541                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
542         else
543                 fixit = -1;
544         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
545
546         if (fixit == 1) {
547                 ext2fs_free_inode_bitmap(fs->inode_map);
548                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
549                                                   &fs->inode_map);
550                 if (retval) {
551                         clear_problem_context(&pctx);
552                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
553                         ctx->flags |= E2F_FLAG_ABORT;
554                         goto errout;
555                 }
556                 ext2fs_set_bitmap_padding(fs->inode_map);
557                 ext2fs_mark_ib_dirty(fs);
558
559                 /* redo counts */
560                 inodes = 0; free_inodes = 0; group_free = 0;
561                 dirs_count = 0; group = 0;
562                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
563                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
564                 redo_flag++;
565                 goto redo_counts;
566         } else if (fixit == 0)
567                 ext2fs_unmark_valid(fs);
568
569         for (i = 0; i < fs->group_desc_count; i++) {
570                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
571                         pctx.group = i;
572                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
573                         pctx.ino2 = free_array[i];
574                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
575                                         &pctx)) {
576                                 fs->group_desc[i].bg_free_inodes_count =
577                                         free_array[i];
578                                 ext2fs_mark_super_dirty(fs);
579                         } else
580                                 ext2fs_unmark_valid(fs);
581                 }
582                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
583                         pctx.group = i;
584                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
585                         pctx.ino2 = dir_array[i];
586
587                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
588                                         &pctx)) {
589                                 fs->group_desc[i].bg_used_dirs_count =
590                                         dir_array[i];
591                                 ext2fs_mark_super_dirty(fs);
592                         } else
593                                 ext2fs_unmark_valid(fs);
594                 }
595         }
596         if (free_inodes != fs->super->s_free_inodes_count) {
597                 pctx.group = -1;
598                 pctx.ino = fs->super->s_free_inodes_count;
599                 pctx.ino2 = free_inodes;
600
601                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
602                         fs->super->s_free_inodes_count = free_inodes;
603                         ext2fs_mark_super_dirty(fs);
604                 } else
605                         ext2fs_unmark_valid(fs);
606         }
607 errout:
608         ext2fs_free_mem(&free_array);
609         ext2fs_free_mem(&dir_array);
610 }
611
612 static void check_inode_end(e2fsck_t ctx)
613 {
614         ext2_filsys fs = ctx->fs;
615         ext2_ino_t      end, save_inodes_count, i;
616         struct problem_context  pctx;
617
618         clear_problem_context(&pctx);
619
620         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
621         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
622                                                      &save_inodes_count);
623         if (pctx.errcode) {
624                 pctx.num = 1;
625                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
626                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
627                 return;
628         }
629         if (save_inodes_count == end)
630                 return;
631
632         /* protect loop from wrap-around if end is maxed */
633         for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
634                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
635                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
636                                 for (; i <= end; i++)
637                                         ext2fs_mark_inode_bitmap(fs->inode_map,
638                                                                  i);
639                                 ext2fs_mark_ib_dirty(fs);
640                         } else
641                                 ext2fs_unmark_valid(fs);
642                         break;
643                 }
644         }
645
646         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
647                                                      save_inodes_count, 0);
648         if (pctx.errcode) {
649                 pctx.num = 2;
650                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
651                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
652                 return;
653         }
654 }
655
656 static void check_block_end(e2fsck_t ctx)
657 {
658         ext2_filsys fs = ctx->fs;
659         blk64_t end, save_blocks_count, i;
660         struct problem_context  pctx;
661
662         clear_problem_context(&pctx);
663
664         end = ext2fs_get_block_bitmap_start2(fs->block_map) +
665                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
666         pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
667                                                      &save_blocks_count);
668         if (pctx.errcode) {
669                 pctx.num = 3;
670                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
671                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
672                 return;
673         }
674         if (save_blocks_count == end)
675                 return;
676
677         /* Protect loop from wrap-around if end is maxed */
678         for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
679                 if (!ext2fs_test_block_bitmap2(fs->block_map, i)) {
680                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
681                                 for (; i <= end; i++)
682                                         ext2fs_mark_block_bitmap2(fs->block_map,
683                                                                   i);
684                                 ext2fs_mark_bb_dirty(fs);
685                         } else
686                                 ext2fs_unmark_valid(fs);
687                         break;
688                 }
689         }
690
691         pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
692                                                      save_blocks_count, 0);
693         if (pctx.errcode) {
694                 pctx.num = 4;
695                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
696                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
697                 return;
698         }
699 }
700
701
702