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