OSDN Git Service

Merge branch 'maint'
[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 #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             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         csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
162                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
163 redo_counts:
164         had_problem = 0;
165         save_problem = 0;
166         pctx.blk = pctx.blk2 = NO_BLK;
167         if (csum_flag &&
168             (fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT))
169                 skip_group++;
170         super = fs->super->s_first_data_block;
171         for (i = fs->super->s_first_data_block;
172              i < fs->super->s_blocks_count;
173              i++) {
174                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
175
176                 if (skip_group) {
177                         blk_t   super_blk, old_desc_blk, new_desc_blk;
178                         int     old_desc_blocks;
179
180                         ext2fs_super_and_bgd_loc(fs, group, &super_blk,
181                                          &old_desc_blk, &new_desc_blk, 0);
182
183                         if (fs->super->s_feature_incompat &
184                             EXT2_FEATURE_INCOMPAT_META_BG)
185                                 old_desc_blocks = fs->super->s_first_meta_bg;
186                         else
187                                 old_desc_blocks = fs->desc_blocks +
188                                         fs->super->s_reserved_gdt_blocks;
189
190                         bitmap = 0;
191                         if (i == super_blk)
192                                 bitmap = 1;
193                         if (old_desc_blk && old_desc_blocks &&
194                             (i >= old_desc_blk) &&
195                             (i < old_desc_blk + old_desc_blocks))
196                                 bitmap = 1;
197                         if (new_desc_blk &&
198                             (i == new_desc_blk))
199                                 bitmap = 1;
200                         if (i == fs->group_desc[group].bg_block_bitmap)
201                                 bitmap = 1;
202                         else if (i == fs->group_desc[group].bg_inode_bitmap)
203                                 bitmap = 1;
204                         else if (i >= fs->group_desc[group].bg_inode_table &&
205                                  (i < fs->group_desc[group].bg_inode_table
206                                   + fs->inode_blocks_per_group))
207                                 bitmap = 1;
208                         actual = (actual != 0);
209                 } else
210                         bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
211
212                 if (actual == bitmap)
213                         goto do_counts;
214
215                 if (!actual && bitmap) {
216                         /*
217                          * Block not used, but marked in use in the bitmap.
218                          */
219                         problem = PR_5_BLOCK_UNUSED;
220                 } else {
221                         /*
222                          * Block used, but not marked in use in the bitmap.
223                          */
224                         problem = PR_5_BLOCK_USED;
225
226                         if (skip_group) {
227                                 struct problem_context pctx2;
228                                 pctx2.blk = i;
229                                 pctx2.group = group;
230                                 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
231                                         fs->group_desc[group].bg_flags &=
232                                                 ~EXT2_BG_BLOCK_UNINIT;
233                                         skip_group = 0;
234                                 }
235                         }
236                 }
237                 if (pctx.blk == NO_BLK) {
238                         pctx.blk = pctx.blk2 = i;
239                         save_problem = problem;
240                 } else {
241                         if ((problem == save_problem) &&
242                             (pctx.blk2 == i-1))
243                                 pctx.blk2++;
244                         else {
245                                 print_bitmap_problem(ctx, save_problem, &pctx);
246                                 pctx.blk = pctx.blk2 = i;
247                                 save_problem = problem;
248                         }
249                 }
250                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
251                 had_problem++;
252
253         do_counts:
254                 if (!bitmap && (!skip_group || csum_flag)) {
255                         group_free++;
256                         free_blocks++;
257                 }
258                 blocks ++;
259                 if ((blocks == fs->super->s_blocks_per_group) ||
260                     (i == fs->super->s_blocks_count-1)) {
261                         free_array[group] = group_free;
262                         group ++;
263                         blocks = 0;
264                         group_free = 0;
265                         skip_group = 0;
266                         super += fs->super->s_blocks_per_group;
267                         if (ctx->progress)
268                                 if ((ctx->progress)(ctx, 5, group,
269                                                     fs->group_desc_count*2))
270                                         goto errout;
271                         if (csum_flag &&
272                             (i != fs->super->s_blocks_count-1) &&
273                             (fs->group_desc[group].bg_flags &
274                              EXT2_BG_BLOCK_UNINIT))
275                                 skip_group++;
276                 }
277         }
278         if (pctx.blk != NO_BLK)
279                 print_bitmap_problem(ctx, save_problem, &pctx);
280         if (had_problem)
281                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
282         else
283                 fixit = -1;
284         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
285
286         if (fixit == 1) {
287                 ext2fs_free_block_bitmap(fs->block_map);
288                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
289                                                   &fs->block_map);
290                 if (retval) {
291                         clear_problem_context(&pctx);
292                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
293                         ctx->flags |= E2F_FLAG_ABORT;
294                         goto errout;
295                 }
296                 ext2fs_set_bitmap_padding(fs->block_map);
297                 ext2fs_mark_bb_dirty(fs);
298
299                 /* Redo the counts */
300                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
301                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
302                 goto redo_counts;
303         } else if (fixit == 0)
304                 ext2fs_unmark_valid(fs);
305
306         for (i = 0; i < fs->group_desc_count; i++) {
307                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
308                         pctx.group = i;
309                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
310                         pctx.blk2 = free_array[i];
311
312                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
313                                         &pctx)) {
314                                 fs->group_desc[i].bg_free_blocks_count =
315                                         free_array[i];
316                                 ext2fs_mark_super_dirty(fs);
317                         } else
318                                 ext2fs_unmark_valid(fs);
319                 }
320         }
321         if (free_blocks != fs->super->s_free_blocks_count) {
322                 pctx.group = 0;
323                 pctx.blk = fs->super->s_free_blocks_count;
324                 pctx.blk2 = free_blocks;
325
326                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
327                         fs->super->s_free_blocks_count = free_blocks;
328                         ext2fs_mark_super_dirty(fs);
329                 } else
330                         ext2fs_unmark_valid(fs);
331         }
332 errout:
333         ext2fs_free_mem(&free_array);
334 }
335
336 static void check_inode_bitmaps(e2fsck_t ctx)
337 {
338         ext2_filsys fs = ctx->fs;
339         ext2_ino_t      i;
340         unsigned int    free_inodes = 0;
341         int             group_free = 0;
342         int             dirs_count = 0;
343         int             group = 0;
344         unsigned int    inodes = 0;
345         int             *free_array;
346         int             *dir_array;
347         int             actual, bitmap;
348         errcode_t       retval;
349         struct problem_context  pctx;
350         int             problem, save_problem, fixit, had_problem;
351         int             csum_flag;
352         int             skip_group = 0;
353
354         clear_problem_context(&pctx);
355         free_array = (int *) e2fsck_allocate_memory(ctx,
356             fs->group_desc_count * sizeof(int), "free inode count array");
357
358         dir_array = (int *) e2fsck_allocate_memory(ctx,
359            fs->group_desc_count * sizeof(int), "directory count array");
360
361         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
362             (fs->super->s_inodes_count >
363              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
364                 pctx.num = 3;
365                 pctx.blk = 1;
366                 pctx.blk2 = fs->super->s_inodes_count;
367                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
368                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
369                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
370
371                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
372                 goto errout;
373         }
374         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
375             (fs->super->s_inodes_count >
376              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
377                 pctx.num = 4;
378                 pctx.blk = 1;
379                 pctx.blk2 = fs->super->s_inodes_count;
380                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
381                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
382                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
383
384                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
385                 goto errout;
386         }
387
388         csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
389                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
390 redo_counts:
391         had_problem = 0;
392         save_problem = 0;
393         pctx.ino = pctx.ino2 = 0;
394         if (csum_flag &&
395             (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT))
396                 skip_group++;
397
398         /* Protect loop from wrap-around if inodes_count is maxed */
399         for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
400                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
401                 if (skip_group)
402                         bitmap = 0;
403                 else
404                         bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
405                 if (actual == bitmap)
406                         goto do_counts;
407
408                 if (!actual && bitmap) {
409                         /*
410                          * Inode wasn't used, but marked in bitmap
411                          */
412                         problem = PR_5_INODE_UNUSED;
413                 } else /* if (actual && !bitmap) */ {
414                         /*
415                          * Inode used, but not in bitmap
416                          */
417                         problem = PR_5_INODE_USED;
418
419                         /* We should never hit this, because it means that
420                          * inodes were marked in use that weren't noticed
421                          * in pass1 or pass 2. It is easier to fix the problem
422                          * than to kill e2fsck and leave the user stuck. */
423                         if (skip_group) {
424                                 struct problem_context pctx2;
425                                 pctx2.blk = i;
426                                 pctx2.group = group;
427                                 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
428                                         fs->group_desc[group].bg_flags &=
429                                                 ~EXT2_BG_INODE_UNINIT;
430                                         skip_group = 0;
431                                 }
432                         }
433                 }
434                 if (pctx.ino == 0) {
435                         pctx.ino = pctx.ino2 = i;
436                         save_problem = problem;
437                 } else {
438                         if ((problem == save_problem) &&
439                             (pctx.ino2 == i-1))
440                                 pctx.ino2++;
441                         else {
442                                 print_bitmap_problem(ctx, save_problem, &pctx);
443                                 pctx.ino = pctx.ino2 = i;
444                                 save_problem = problem;
445                         }
446                 }
447                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
448                 had_problem++;
449
450 do_counts:
451                 if (bitmap) {
452                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
453                                 dirs_count++;
454                 } else if (!skip_group || csum_flag) {
455                         group_free++;
456                         free_inodes++;
457                 }
458                 inodes++;
459                 if ((inodes == fs->super->s_inodes_per_group) ||
460                     (i == fs->super->s_inodes_count)) {
461                         free_array[group] = group_free;
462                         dir_array[group] = dirs_count;
463                         group ++;
464                         inodes = 0;
465                         skip_group = 0;
466                         group_free = 0;
467                         dirs_count = 0;
468                         if (ctx->progress)
469                                 if ((ctx->progress)(ctx, 5,
470                                             group + fs->group_desc_count,
471                                             fs->group_desc_count*2))
472                                         goto errout;
473                         if (csum_flag &&
474                             (i != fs->super->s_inodes_count) &&
475                             (fs->group_desc[group].bg_flags &
476                              EXT2_BG_INODE_UNINIT))
477                                 skip_group++;
478                 }
479         }
480         if (pctx.ino)
481                 print_bitmap_problem(ctx, save_problem, &pctx);
482
483         if (had_problem)
484                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
485         else
486                 fixit = -1;
487         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
488
489         if (fixit == 1) {
490                 ext2fs_free_inode_bitmap(fs->inode_map);
491                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
492                                                   &fs->inode_map);
493                 if (retval) {
494                         clear_problem_context(&pctx);
495                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
496                         ctx->flags |= E2F_FLAG_ABORT;
497                         goto errout;
498                 }
499                 ext2fs_set_bitmap_padding(fs->inode_map);
500                 ext2fs_mark_ib_dirty(fs);
501
502                 /* redo counts */
503                 inodes = 0; free_inodes = 0; group_free = 0;
504                 dirs_count = 0; group = 0;
505                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
506                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
507                 goto redo_counts;
508         } else if (fixit == 0)
509                 ext2fs_unmark_valid(fs);
510
511         for (i = 0; i < fs->group_desc_count; i++) {
512                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
513                         pctx.group = i;
514                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
515                         pctx.ino2 = free_array[i];
516                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
517                                         &pctx)) {
518                                 fs->group_desc[i].bg_free_inodes_count =
519                                         free_array[i];
520                                 ext2fs_mark_super_dirty(fs);
521                         } else
522                                 ext2fs_unmark_valid(fs);
523                 }
524                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
525                         pctx.group = i;
526                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
527                         pctx.ino2 = dir_array[i];
528
529                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
530                                         &pctx)) {
531                                 fs->group_desc[i].bg_used_dirs_count =
532                                         dir_array[i];
533                                 ext2fs_mark_super_dirty(fs);
534                         } else
535                                 ext2fs_unmark_valid(fs);
536                 }
537         }
538         if (free_inodes != fs->super->s_free_inodes_count) {
539                 pctx.group = -1;
540                 pctx.ino = fs->super->s_free_inodes_count;
541                 pctx.ino2 = free_inodes;
542
543                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
544                         fs->super->s_free_inodes_count = free_inodes;
545                         ext2fs_mark_super_dirty(fs);
546                 } else
547                         ext2fs_unmark_valid(fs);
548         }
549 errout:
550         ext2fs_free_mem(&free_array);
551         ext2fs_free_mem(&dir_array);
552 }
553
554 static void check_inode_end(e2fsck_t ctx)
555 {
556         ext2_filsys fs = ctx->fs;
557         ext2_ino_t      end, save_inodes_count, i;
558         struct problem_context  pctx;
559
560         clear_problem_context(&pctx);
561
562         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
563         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
564                                                      &save_inodes_count);
565         if (pctx.errcode) {
566                 pctx.num = 1;
567                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
568                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
569                 return;
570         }
571         if (save_inodes_count == end)
572                 return;
573
574         /* protect loop from wrap-around if end is maxed */     
575         for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
576                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
577                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
578                                 for (i = save_inodes_count + 1; i <= end; i++)
579                                         ext2fs_mark_inode_bitmap(fs->inode_map,
580                                                                  i);
581                                 ext2fs_mark_ib_dirty(fs);
582                         } else
583                                 ext2fs_unmark_valid(fs);
584                         break;
585                 }
586         }
587
588         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
589                                                      save_inodes_count, 0);
590         if (pctx.errcode) {
591                 pctx.num = 2;
592                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
593                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
594                 return;
595         }
596 }
597
598 static void check_block_end(e2fsck_t ctx)
599 {
600         ext2_filsys fs = ctx->fs;
601         blk_t   end, save_blocks_count, i;
602         struct problem_context  pctx;
603
604         clear_problem_context(&pctx);
605
606         end = ext2fs_get_block_bitmap_start(fs->block_map) +
607                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
608         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
609                                                      &save_blocks_count);
610         if (pctx.errcode) {
611                 pctx.num = 3;
612                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
613                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
614                 return;
615         }
616         if (save_blocks_count == end)
617                 return;
618
619         /* Protect loop from wrap-around if end is maxed */     
620         for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
621                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
622                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
623                                 for (i = save_blocks_count + 1; i <= end; i++)
624                                         ext2fs_mark_block_bitmap(fs->block_map,
625                                                                  i);
626                                 ext2fs_mark_bb_dirty(fs);
627                         } else
628                                 ext2fs_unmark_valid(fs);
629                         break;
630                 }
631         }
632
633         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
634                                                      save_blocks_count, 0);
635         if (pctx.errcode) {
636                 pctx.num = 4;
637                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
638                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
639                 return;
640         }
641 }
642
643
644