Whamcloud - gitweb
e2fsck: add support for expanding the inode size
[tools/e2fsprogs.git] / e2fsck / pass5.c
1 /*
2  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
3  *
4  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the GNU Public
8  * License.
9  * %End-Header%
10  *
11  */
12
13 #include "config.h"
14 #include <stdint.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/ioctl.h>
18 #include <fcntl.h>
19 #include <errno.h>
20
21 #include "e2fsck.h"
22 #include "problem.h"
23
24 static void check_block_bitmaps(e2fsck_t ctx);
25 static void check_inode_bitmaps(e2fsck_t ctx);
26 static void check_inode_end(e2fsck_t ctx);
27 static void check_block_end(e2fsck_t ctx);
28 static void check_inode_bitmap_checksum(e2fsck_t ctx);
29 static void check_block_bitmap_checksum(e2fsck_t ctx);
30
31 void e2fsck_pass5(e2fsck_t ctx)
32 {
33 #ifdef RESOURCE_TRACK
34         struct resource_track   rtrack;
35 #endif
36         struct problem_context  pctx;
37
38 #ifdef MTRACE
39         mtrace_print("Pass 5");
40 #endif
41
42         init_resource_track(&rtrack, ctx->fs->io);
43         clear_problem_context(&pctx);
44
45         if (!(ctx->options & E2F_OPT_PREEN))
46                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
47
48         if (ctx->progress)
49                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
50                         return;
51
52         e2fsck_read_bitmaps(ctx);
53
54         check_block_bitmaps(ctx);
55         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
56                 return;
57         check_inode_bitmaps(ctx);
58         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
59                 return;
60         check_inode_end(ctx);
61         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
62                 return;
63         check_block_end(ctx);
64         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
65                 return;
66
67         check_inode_bitmap_checksum(ctx);
68         check_block_bitmap_checksum(ctx);
69
70         ext2fs_free_inode_bitmap(ctx->inode_used_map);
71         ctx->inode_used_map = 0;
72         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
73         ctx->inode_dir_map = 0;
74         ext2fs_free_block_bitmap(ctx->block_found_map);
75         ctx->block_found_map = 0;
76         ext2fs_free_block_bitmap(ctx->block_metadata_map);
77         ctx->block_metadata_map = 0;
78
79         if (ctx->flags & E2F_FLAG_EXPAND_EISIZE) {
80                 int min_extra_isize;
81
82                 if (!ctx->expand_eisize_map)
83                         goto set_min_extra_isize;
84
85                 for (pctx.ino = 1; pctx.ino < ctx->fs->super->s_inodes_count;
86                      pctx.ino++) {
87                         if (ext2fs_test_inode_bitmap2(ctx->expand_eisize_map,
88                             pctx.ino)) {
89                                 fix_problem(ctx, PR_5_EXPAND_EISIZE, &pctx);
90                                 ext2fs_expand_extra_isize(ctx->fs, pctx.ino, 0,
91                                                           ctx->want_extra_isize,
92                                                           NULL, NULL);
93                         }
94                 }
95                 ext2fs_free_inode_bitmap(ctx->expand_eisize_map);
96
97 set_min_extra_isize:
98                 if (ctx->fs->super->s_min_extra_isize)
99                         min_extra_isize = ctx->fs->super->s_min_extra_isize;
100                 else
101                         min_extra_isize = ctx->want_extra_isize;
102                 if (ctx->min_extra_isize >= min_extra_isize &&
103                     !ctx->fs_unexpanded_inodes) {
104                         ctx->fs->super->s_min_extra_isize =ctx->min_extra_isize;
105                         ctx->fs->super->s_feature_ro_compat |=
106                                         EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE;
107                 } else {
108                         ctx->fs->super->s_min_extra_isize = 0;
109                         ctx->fs->super->s_feature_ro_compat &=
110                                         ~EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE;
111                 }
112                 ext2fs_mark_super_dirty(ctx->fs);
113         }
114
115         print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
116 }
117
118 static void check_inode_bitmap_checksum(e2fsck_t ctx)
119 {
120         struct problem_context  pctx;
121         char            *buf = NULL;
122         dgrp_t          i;
123         int             nbytes;
124         ext2_ino_t      ino_itr;
125         errcode_t       retval;
126
127         if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
128                 return;
129
130         /* If bitmap is dirty from being fixed, checksum will be corrected */
131         if (ext2fs_test_ib_dirty(ctx->fs))
132                 return;
133
134         nbytes = (size_t)(EXT2_INODES_PER_GROUP(ctx->fs->super) / 8);
135         retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
136         if (retval) {
137                 com_err(ctx->program_name, 0, "%s",
138                     _("check_inode_bitmap_checksum: Memory allocation error"));
139                 fatal_error(ctx, 0);
140         }
141
142         clear_problem_context(&pctx);
143         for (i = 0; i < ctx->fs->group_desc_count; i++) {
144                 if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_INODE_UNINIT))
145                         continue;
146
147                 ino_itr = 1 + (i * (nbytes << 3));
148                 retval = ext2fs_get_inode_bitmap_range2(ctx->fs->inode_map,
149                                                         ino_itr, nbytes << 3,
150                                                         buf);
151                 if (retval)
152                         break;
153
154                 if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
155                         continue;
156                 pctx.group = i;
157                 if (!fix_problem(ctx, PR_5_INODE_BITMAP_CSUM_INVALID, &pctx))
158                         continue;
159
160                 /*
161                  * Fixing one checksum will rewrite all of them.  The bitmap
162                  * will be checked against the one we made during pass1 for
163                  * discrepancies, and fixed if need be.
164                  */
165                 ext2fs_mark_ib_dirty(ctx->fs);
166                 break;
167         }
168
169         ext2fs_free_mem(&buf);
170 }
171
172 static void check_block_bitmap_checksum(e2fsck_t ctx)
173 {
174         struct problem_context  pctx;
175         char            *buf = NULL;
176         dgrp_t          i;
177         int             nbytes;
178         blk64_t         blk_itr;
179         errcode_t       retval;
180
181         if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
182                 return;
183
184         /* If bitmap is dirty from being fixed, checksum will be corrected */
185         if (ext2fs_test_bb_dirty(ctx->fs))
186                 return;
187
188         nbytes = (size_t)(EXT2_CLUSTERS_PER_GROUP(ctx->fs->super) / 8);
189         retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
190         if (retval) {
191                 com_err(ctx->program_name, 0, "%s",
192                     _("check_block_bitmap_checksum: Memory allocation error"));
193                 fatal_error(ctx, 0);
194         }
195
196         clear_problem_context(&pctx);
197         for (i = 0; i < ctx->fs->group_desc_count; i++) {
198                 if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_BLOCK_UNINIT))
199                         continue;
200
201                 blk_itr = EXT2FS_B2C(ctx->fs,
202                                      ctx->fs->super->s_first_data_block) +
203                           ((blk64_t) i * (nbytes << 3));
204                 retval = ext2fs_get_block_bitmap_range2(ctx->fs->block_map,
205                                                         blk_itr, nbytes << 3,
206                                                         buf);
207                 if (retval)
208                         break;
209
210                 if (ext2fs_block_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
211                         continue;
212                 pctx.group = i;
213                 if (!fix_problem(ctx, PR_5_BLOCK_BITMAP_CSUM_INVALID, &pctx))
214                         continue;
215
216                 /*
217                  * Fixing one checksum will rewrite all of them.  The bitmap
218                  * will be checked against the one we made during pass1 for
219                  * discrepancies, and fixed if need be.
220                  */
221                 ext2fs_mark_bb_dirty(ctx->fs);
222                 break;
223         }
224
225         ext2fs_free_mem(&buf);
226 }
227
228 static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start,
229                                   blk64_t count)
230 {
231         ext2_filsys fs = ctx->fs;
232
233         /*
234          * If the filesystem has changed it means that there was an corruption
235          * which should be repaired, but in some cases just one e2fsck run is
236          * not enough to fix the problem, hence it is not safe to run discard
237          * in this case.
238          */
239         if (ext2fs_test_changed(fs))
240                 ctx->options &= ~E2F_OPT_DISCARD;
241
242         if ((ctx->options & E2F_OPT_DISCARD) &&
243             (io_channel_discard(fs->io, start, count)))
244                 ctx->options &= ~E2F_OPT_DISCARD;
245 }
246
247 /*
248  * This will try to discard number 'count' inodes starting at
249  * inode number 'start' within the 'group'. Note that 'start'
250  * is 1-based, it means that we need to adjust it by -1 in this
251  * function to compute right offset in the particular inode table.
252  */
253 static void e2fsck_discard_inodes(e2fsck_t ctx, dgrp_t group,
254                                   ext2_ino_t start, int count)
255 {
256         ext2_filsys fs = ctx->fs;
257         blk64_t blk, num;
258
259         /*
260          * Sanity check for 'start'
261          */
262         if ((start < 1) || (start > EXT2_INODES_PER_GROUP(fs->super))) {
263                 printf("PROGRAMMING ERROR: Got start %d outside of group %d!"
264                        " Disabling discard\n",
265                         start, group);
266                 ctx->options &= ~E2F_OPT_DISCARD;
267         }
268
269         /*
270          * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also
271          * skip the discard on this group if discard does not zero data.
272          * The reason is that if the inode table is not zeroed discard would
273          * no help us since we need to zero it anyway, or if the inode table
274          * is zeroed then the read after discard would not be deterministic
275          * anyway and we would not be able to assume that this inode table
276          * was zeroed anymore so we would have to zero it again, which does
277          * not really make sense.
278          */
279         if (!(ctx->options & E2F_OPT_DISCARD) ||
280             !io_channel_discard_zeroes_data(fs->io))
281                 return;
282
283         /*
284          * Start is inode number within the group which starts
285          * counting from 1, so we need to adjust it.
286          */
287         start -= 1;
288
289         /*
290          * We can discard only blocks containing only unused
291          * inodes in the table.
292          */
293         blk = DIV_ROUND_UP(start,
294                 EXT2_INODES_PER_BLOCK(fs->super));
295         count -= (blk * EXT2_INODES_PER_BLOCK(fs->super) - start);
296         blk += ext2fs_inode_table_loc(fs, group);
297         num = count / EXT2_INODES_PER_BLOCK(fs->super);
298
299         if (num > 0)
300                 e2fsck_discard_blocks(ctx, blk, num);
301 }
302
303 #define NO_BLK ((blk64_t) -1)
304
305 static void print_bitmap_problem(e2fsck_t ctx, problem_t problem,
306                             struct problem_context *pctx)
307 {
308         switch (problem) {
309         case PR_5_BLOCK_UNUSED:
310                 if (pctx->blk == pctx->blk2)
311                         pctx->blk2 = 0;
312                 else
313                         problem = PR_5_BLOCK_RANGE_UNUSED;
314                 break;
315         case PR_5_BLOCK_USED:
316                 if (pctx->blk == pctx->blk2)
317                         pctx->blk2 = 0;
318                 else
319                         problem = PR_5_BLOCK_RANGE_USED;
320                 break;
321         case PR_5_INODE_UNUSED:
322                 if (pctx->ino == pctx->ino2)
323                         pctx->ino2 = 0;
324                 else
325                         problem = PR_5_INODE_RANGE_UNUSED;
326                 break;
327         case PR_5_INODE_USED:
328                 if (pctx->ino == pctx->ino2)
329                         pctx->ino2 = 0;
330                 else
331                         problem = PR_5_INODE_RANGE_USED;
332                 break;
333         }
334         fix_problem(ctx, problem, pctx);
335         pctx->blk = pctx->blk2 = NO_BLK;
336         pctx->ino = pctx->ino2 = 0;
337 }
338
339 /* Just to be more succinct */
340 #define B2C(x)  EXT2FS_B2C(fs, (x))
341 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
342 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
343 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
344
345 static void check_block_bitmaps(e2fsck_t ctx)
346 {
347         ext2_filsys fs = ctx->fs;
348         blk64_t i;
349         unsigned int    *free_array;
350         dgrp_t          g, group = 0;
351         unsigned int    blocks = 0;
352         blk64_t free_blocks = 0;
353         blk64_t first_free = ext2fs_blocks_count(fs->super);
354         unsigned int    group_free = 0;
355         int     actual, bitmap;
356         struct problem_context  pctx;
357         problem_t       problem, save_problem;
358         int             fixit, had_problem;
359         errcode_t       retval;
360         int     redo_flag = 0;
361         char *actual_buf, *bitmap_buf;
362
363         actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
364                                                      "actual bitmap buffer");
365         bitmap_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
366                                                      "bitmap block buffer");
367
368         clear_problem_context(&pctx);
369         free_array = (unsigned int *) e2fsck_allocate_memory(ctx,
370             fs->group_desc_count * sizeof(unsigned int), "free block count array");
371
372         if ((B2C(fs->super->s_first_data_block) <
373              ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
374             (B2C(ext2fs_blocks_count(fs->super)-1) >
375              ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
376                 pctx.num = 1;
377                 pctx.blk = B2C(fs->super->s_first_data_block);
378                 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
379                 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
380                 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
381                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
382
383                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
384                 goto errout;
385         }
386
387         if ((B2C(fs->super->s_first_data_block) <
388              ext2fs_get_block_bitmap_start2(fs->block_map)) ||
389             (B2C(ext2fs_blocks_count(fs->super)-1) >
390              ext2fs_get_block_bitmap_end2(fs->block_map))) {
391                 pctx.num = 2;
392                 pctx.blk = B2C(fs->super->s_first_data_block);
393                 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
394                 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
395                 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
396                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
397
398                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
399                 goto errout;
400         }
401
402 redo_counts:
403         had_problem = 0;
404         save_problem = 0;
405         pctx.blk = pctx.blk2 = NO_BLK;
406         for (i = B2C(fs->super->s_first_data_block);
407              i < ext2fs_blocks_count(fs->super);
408              i += EXT2FS_CLUSTER_RATIO(fs)) {
409                 int first_block_in_bg = (B2C(i) -
410                                          B2C(fs->super->s_first_data_block)) %
411                         fs->super->s_clusters_per_group == 0;
412                 int n, nbytes = fs->super->s_clusters_per_group / 8;
413
414                 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
415
416                 /*
417                  * Try to optimize pass5 by extracting a bitmap block
418                  * as expected from what we have on disk, and then
419                  * comparing the two.  If they are identical, then
420                  * update the free block counts and go on to the next
421                  * block group.  This is much faster than doing the
422                  * individual bit-by-bit comparison.  The one downside
423                  * is that this doesn't work if we are asking e2fsck
424                  * to do a discard operation.
425                  */
426                 if (!first_block_in_bg ||
427                     (group == fs->group_desc_count - 1) ||
428                     (ctx->options & E2F_OPT_DISCARD))
429                         goto no_optimize;
430
431                 retval = ext2fs_get_block_bitmap_range2(ctx->block_found_map,
432                                 B2C(i), fs->super->s_clusters_per_group,
433                                 actual_buf);
434                 if (retval)
435                         goto no_optimize;
436                 retval = ext2fs_get_block_bitmap_range2(fs->block_map,
437                                 B2C(i), fs->super->s_clusters_per_group,
438                                 bitmap_buf);
439                 if (retval)
440                         goto no_optimize;
441                 if (memcmp(actual_buf, bitmap_buf, nbytes) != 0)
442                         goto no_optimize;
443                 n = ext2fs_bitcount(actual_buf, nbytes);
444                 group_free = fs->super->s_clusters_per_group - n;
445                 free_blocks += group_free;
446                 i += EXT2FS_C2B(fs, fs->super->s_clusters_per_group - 1);
447                 goto next_group;
448         no_optimize:
449
450                 if (redo_flag)
451                         bitmap = actual;
452                 else
453                         bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
454
455                 if (!actual == !bitmap)
456                         goto do_counts;
457
458                 if (!actual && bitmap) {
459                         /*
460                          * Block not used, but marked in use in the bitmap.
461                          */
462                         problem = PR_5_BLOCK_UNUSED;
463                 } else {
464                         /*
465                          * Block used, but not marked in use in the bitmap.
466                          */
467                         problem = PR_5_BLOCK_USED;
468
469                         if (ext2fs_bg_flags_test(fs, group,
470                                                  EXT2_BG_BLOCK_UNINIT)) {
471                                 struct problem_context pctx2;
472                                 pctx2.blk = i;
473                                 pctx2.group = group;
474                                 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,
475                                                 &pctx2))
476                                         ext2fs_bg_flags_clear(fs, group,
477                                                         EXT2_BG_BLOCK_UNINIT);
478                         }
479                 }
480                 if (pctx.blk == NO_BLK) {
481                         pctx.blk = pctx.blk2 = i;
482                         save_problem = problem;
483                 } else {
484                         if ((problem == save_problem) &&
485                             (pctx.blk2 == i - EXT2FS_CLUSTER_RATIO(fs)))
486                                 pctx.blk2 += EXT2FS_CLUSTER_RATIO(fs);
487                         else {
488                                 print_bitmap_problem(ctx, save_problem, &pctx);
489                                 pctx.blk = pctx.blk2 = i;
490                                 save_problem = problem;
491                         }
492                 }
493                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
494                 had_problem++;
495
496                 /*
497                  * If there a problem we should turn off the discard so we
498                  * do not compromise the filesystem.
499                  */
500                 ctx->options &= ~E2F_OPT_DISCARD;
501
502         do_counts:
503                 if (!bitmap) {
504                         group_free++;
505                         free_blocks++;
506                         if (first_free > i)
507                                 first_free = i;
508                 } else if (i > first_free) {
509                         e2fsck_discard_blocks(ctx, first_free,
510                                               (i - first_free));
511                         first_free = ext2fs_blocks_count(fs->super);
512                 }
513                 blocks ++;
514                 if ((blocks == fs->super->s_clusters_per_group) ||
515                     (EXT2FS_B2C(fs, i) ==
516                      EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) {
517                         /*
518                          * If the last block of this group is free, then we can
519                          * discard it as well.
520                          */
521                         if (!bitmap && i >= first_free)
522                                 e2fsck_discard_blocks(ctx, first_free,
523                                                       (i - first_free) + 1);
524                 next_group:
525                         first_free = ext2fs_blocks_count(fs->super);
526
527                         free_array[group] = group_free;
528                         group ++;
529                         blocks = 0;
530                         group_free = 0;
531                         if (ctx->progress)
532                                 if ((ctx->progress)(ctx, 5, group,
533                                                     fs->group_desc_count*2))
534                                         goto errout;
535                 }
536         }
537         if (pctx.blk != NO_BLK)
538                 print_bitmap_problem(ctx, save_problem, &pctx);
539         if (had_problem)
540                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
541         else
542                 fixit = -1;
543         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
544
545         if (fixit == 1) {
546                 ext2fs_free_block_bitmap(fs->block_map);
547                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
548                                                   &fs->block_map);
549                 if (retval) {
550                         clear_problem_context(&pctx);
551                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
552                         ctx->flags |= E2F_FLAG_ABORT;
553                         goto errout;
554                 }
555                 ext2fs_set_bitmap_padding(fs->block_map);
556                 ext2fs_mark_bb_dirty(fs);
557
558                 /* Redo the counts */
559                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
560                 memset(free_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 (g = 0; g < fs->group_desc_count; g++) {
567                 if (free_array[g] != ext2fs_bg_free_blocks_count(fs, g)) {
568                         pctx.group = g;
569                         pctx.blk = ext2fs_bg_free_blocks_count(fs, g);
570                         pctx.blk2 = free_array[g];
571
572                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
573                                         &pctx)) {
574                                 ext2fs_bg_free_blocks_count_set(fs, g, free_array[g]);
575                                 ext2fs_mark_super_dirty(fs);
576                         } else
577                                 ext2fs_unmark_valid(fs);
578                 }
579         }
580         free_blocks = EXT2FS_C2B(fs, free_blocks);
581         if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
582                 pctx.group = 0;
583                 pctx.blk = ext2fs_free_blocks_count(fs->super);
584                 pctx.blk2 = free_blocks;
585
586                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
587                         ext2fs_free_blocks_count_set(fs->super, free_blocks);
588                         ext2fs_mark_super_dirty(fs);
589                 }
590         }
591 errout:
592         ext2fs_free_mem(&free_array);
593         ext2fs_free_mem(&actual_buf);
594         ext2fs_free_mem(&bitmap_buf);
595 }
596
597 static void check_inode_bitmaps(e2fsck_t ctx)
598 {
599         ext2_filsys fs = ctx->fs;
600         ext2_ino_t      i;
601         unsigned int    free_inodes = 0;
602         int             group_free = 0;
603         int             dirs_count = 0;
604         dgrp_t          group = 0;
605         unsigned int    inodes = 0;
606         ext2_ino_t      *free_array;
607         ext2_ino_t      *dir_array;
608         int             actual, bitmap;
609         errcode_t       retval;
610         struct problem_context  pctx;
611         problem_t       problem, save_problem;
612         int             fixit, had_problem;
613         int             csum_flag;
614         int             skip_group = 0;
615         int             redo_flag = 0;
616         ext2_ino_t              first_free = fs->super->s_inodes_per_group + 1;
617
618         clear_problem_context(&pctx);
619         free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
620             fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array");
621
622         dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
623            fs->group_desc_count * sizeof(ext2_ino_t), "directory count array");
624
625         if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
626             (fs->super->s_inodes_count >
627              ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
628                 pctx.num = 3;
629                 pctx.blk = 1;
630                 pctx.blk2 = fs->super->s_inodes_count;
631                 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
632                 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
633                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
634
635                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
636                 goto errout;
637         }
638         if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
639             (fs->super->s_inodes_count >
640              ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
641                 pctx.num = 4;
642                 pctx.blk = 1;
643                 pctx.blk2 = fs->super->s_inodes_count;
644                 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
645                 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
646                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
647
648                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
649                 goto errout;
650         }
651
652         csum_flag = ext2fs_has_group_desc_csum(fs);
653 redo_counts:
654         had_problem = 0;
655         save_problem = 0;
656         pctx.ino = pctx.ino2 = 0;
657         if (csum_flag &&
658             (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
659                 skip_group++;
660
661         /* Protect loop from wrap-around if inodes_count is maxed */
662         for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
663                 bitmap = 0;
664                 if (skip_group &&
665                     i % fs->super->s_inodes_per_group == 1) {
666                         /*
667                          * Current inode is the first inode
668                          * in the current block group.
669                          */
670                         if (ext2fs_test_inode_bitmap_range(
671                                     ctx->inode_used_map, i,
672                                     fs->super->s_inodes_per_group)) {
673                                 /*
674                                  * When the compared inodes in inodes bitmap
675                                  * are 0, count the free inode,
676                                  * skip the current block group.
677                                  */
678                                 first_free = 1;
679                                 inodes = fs->super->s_inodes_per_group - 1;
680                                 group_free = inodes;
681                                 free_inodes += inodes;
682                                 i += inodes;
683                                 skip_group = 0;
684                                 goto do_counts;
685                         }
686                 }
687
688                 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
689                 if (redo_flag)
690                         bitmap = actual;
691                 else if (!skip_group)
692                         bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
693                 if (!actual == !bitmap)
694                         goto do_counts;
695
696                 if (!actual && bitmap) {
697                         /*
698                          * Inode wasn't used, but marked in bitmap
699                          */
700                         problem = PR_5_INODE_UNUSED;
701                 } else /* if (actual && !bitmap) */ {
702                         /*
703                          * Inode used, but not in bitmap
704                          */
705                         problem = PR_5_INODE_USED;
706
707                         /* We should never hit this, because it means that
708                          * inodes were marked in use that weren't noticed
709                          * in pass1 or pass 2. It is easier to fix the problem
710                          * than to kill e2fsck and leave the user stuck. */
711                         if (skip_group) {
712                                 struct problem_context pctx2;
713                                 pctx2.blk = i;
714                                 pctx2.group = group;
715                                 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
716                                         ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
717                                         skip_group = 0;
718                                 }
719                         }
720                 }
721                 if (pctx.ino == 0) {
722                         pctx.ino = pctx.ino2 = i;
723                         save_problem = problem;
724                 } else {
725                         if ((problem == save_problem) &&
726                             (pctx.ino2 == i-1))
727                                 pctx.ino2++;
728                         else {
729                                 print_bitmap_problem(ctx, save_problem, &pctx);
730                                 pctx.ino = pctx.ino2 = i;
731                                 save_problem = problem;
732                         }
733                 }
734                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
735                 had_problem++;
736                 /*
737                  * If there a problem we should turn off the discard so we
738                  * do not compromise the filesystem.
739                  */
740                 ctx->options &= ~E2F_OPT_DISCARD;
741
742 do_counts:
743                 inodes++;
744                 if (bitmap) {
745                         if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
746                                 dirs_count++;
747                         if (inodes > first_free) {
748                                 e2fsck_discard_inodes(ctx, group, first_free,
749                                                       inodes - first_free);
750                                 first_free = fs->super->s_inodes_per_group + 1;
751                         }
752                 } else {
753                         group_free++;
754                         free_inodes++;
755                         if (first_free > inodes)
756                                 first_free = inodes;
757                 }
758
759                 if ((inodes == fs->super->s_inodes_per_group) ||
760                     (i == fs->super->s_inodes_count)) {
761                         /*
762                          * If the last inode is free, we can discard it as well.
763                          */
764                         if (!bitmap && inodes >= first_free)
765                                 e2fsck_discard_inodes(ctx, group, first_free,
766                                                       inodes - first_free + 1);
767                         /*
768                          * If discard zeroes data and the group inode table
769                          * was not zeroed yet, set itable as zeroed
770                          */
771                         if ((ctx->options & E2F_OPT_DISCARD) &&
772                             io_channel_discard_zeroes_data(fs->io) &&
773                             !(ext2fs_bg_flags_test(fs, group,
774                                                    EXT2_BG_INODE_ZEROED))) {
775                                 ext2fs_bg_flags_set(fs, group,
776                                                     EXT2_BG_INODE_ZEROED);
777                                 ext2fs_group_desc_csum_set(fs, group);
778                         }
779
780                         first_free = fs->super->s_inodes_per_group + 1;
781                         free_array[group] = group_free;
782                         dir_array[group] = dirs_count;
783                         group ++;
784                         inodes = 0;
785                         skip_group = 0;
786                         group_free = 0;
787                         dirs_count = 0;
788                         if (ctx->progress)
789                                 if ((ctx->progress)(ctx, 5,
790                                             group + fs->group_desc_count,
791                                             fs->group_desc_count*2))
792                                         goto errout;
793                         if (csum_flag &&
794                             (i != fs->super->s_inodes_count) &&
795                             (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
796                              ))
797                                 skip_group++;
798                 }
799         }
800         if (pctx.ino)
801                 print_bitmap_problem(ctx, save_problem, &pctx);
802
803         if (had_problem)
804                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
805         else
806                 fixit = -1;
807         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
808
809         if (fixit == 1) {
810                 ext2fs_free_inode_bitmap(fs->inode_map);
811                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
812                                                   &fs->inode_map);
813                 if (retval) {
814                         clear_problem_context(&pctx);
815                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
816                         ctx->flags |= E2F_FLAG_ABORT;
817                         goto errout;
818                 }
819                 ext2fs_set_bitmap_padding(fs->inode_map);
820                 ext2fs_mark_ib_dirty(fs);
821
822                 /* redo counts */
823                 inodes = 0; free_inodes = 0; group_free = 0;
824                 dirs_count = 0; group = 0;
825                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
826                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
827                 redo_flag++;
828                 goto redo_counts;
829         } else if (fixit == 0)
830                 ext2fs_unmark_valid(fs);
831
832         for (i = 0; i < fs->group_desc_count; i++) {
833                 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
834                         pctx.group = i;
835                         pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
836                         pctx.ino2 = free_array[i];
837                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
838                                         &pctx)) {
839                                 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
840                                 ext2fs_mark_super_dirty(fs);
841                         } else
842                                 ext2fs_unmark_valid(fs);
843                 }
844                 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
845                         pctx.group = i;
846                         pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
847                         pctx.ino2 = dir_array[i];
848
849                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
850                                         &pctx)) {
851                                 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
852                                 ext2fs_mark_super_dirty(fs);
853                         } else
854                                 ext2fs_unmark_valid(fs);
855                 }
856         }
857         if (free_inodes != fs->super->s_free_inodes_count) {
858                 pctx.group = -1;
859                 pctx.ino = fs->super->s_free_inodes_count;
860                 pctx.ino2 = free_inodes;
861
862                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
863                         fs->super->s_free_inodes_count = free_inodes;
864                         ext2fs_mark_super_dirty(fs);
865                 }
866         }
867 errout:
868         ext2fs_free_mem(&free_array);
869         ext2fs_free_mem(&dir_array);
870 }
871
872 static void check_inode_end(e2fsck_t ctx)
873 {
874         ext2_filsys fs = ctx->fs;
875         ext2_ino_t      end, save_inodes_count, i;
876         struct problem_context  pctx;
877         int asked = 0;
878
879         clear_problem_context(&pctx);
880
881         end = (__u64)EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
882         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
883                                                      &save_inodes_count);
884         if (pctx.errcode) {
885                 pctx.num = 1;
886                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
887                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
888                 return;
889         }
890         if (save_inodes_count == end)
891                 goto check_intra_bg_tail;
892
893         /* protect loop from wrap-around if end is maxed */
894         for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
895                 if (!ext2fs_test_inode_bitmap2(fs->inode_map, i)) {
896                         asked = 1;
897                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
898                                 for (; i <= end; i++)
899                                         ext2fs_mark_inode_bitmap2(fs->inode_map,
900                                                                  i);
901                                 ext2fs_mark_ib_dirty(fs);
902                         } else
903                                 ext2fs_unmark_valid(fs);
904                         break;
905                 }
906         }
907
908         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
909                                                      save_inodes_count, 0);
910         if (pctx.errcode) {
911                 pctx.num = 2;
912                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
913                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
914                 return;
915         }
916         /*
917          * If the number of inodes per block group != blocksize, we
918          * can also have a potential problem with the tail bits in
919          * each individual inode bitmap block.  If there is a problem,
920          * it would have been noticed when the bitmap was loaded.  And
921          * fixing this is easy; all we need to do force the bitmap to
922          * be written back to disk.
923          */
924 check_intra_bg_tail:
925         if (!asked && fs->flags & EXT2_FLAG_IBITMAP_TAIL_PROBLEM) {
926                 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx))
927                         ext2fs_mark_ib_dirty(fs);
928                 else
929                         ext2fs_unmark_valid(fs);
930         }
931 }
932
933 static void check_block_end(e2fsck_t ctx)
934 {
935         ext2_filsys fs = ctx->fs;
936         blk64_t end, save_blocks_count, i;
937         struct problem_context  pctx;
938         int asked = 0;
939
940         clear_problem_context(&pctx);
941
942         end = ext2fs_get_block_bitmap_start2(fs->block_map) +
943                 EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count) - 1;
944         pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
945                                                      &save_blocks_count);
946         if (pctx.errcode) {
947                 pctx.num = 3;
948                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
949                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
950                 return;
951         }
952         if (save_blocks_count == end)
953                 goto check_intra_bg_tail;
954
955         /* Protect loop from wrap-around if end is maxed */
956         for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
957                 if (!ext2fs_test_block_bitmap2(fs->block_map,
958                                                EXT2FS_C2B(fs, i))) {
959                         asked = 1;
960                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
961                                 for (; i <= end; i++)
962                                         ext2fs_mark_block_bitmap2(fs->block_map,
963                                                         EXT2FS_C2B(fs, i));
964                                 ext2fs_mark_bb_dirty(fs);
965                         } else
966                                 ext2fs_unmark_valid(fs);
967                         break;
968                 }
969         }
970
971         pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
972                                                      save_blocks_count, 0);
973         if (pctx.errcode) {
974                 pctx.num = 4;
975                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
976                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
977                 return;
978         }
979         /*
980          * If the number of blocks per block group != blocksize, we
981          * can also have a potential problem with the tail bits in
982          * each individual block bitmap block.  If there is a problem,
983          * it would have been noticed when the bitmap was loaded.  And
984          * fixing this is easy; all we need to do force the bitmap to
985          * be written back to disk.
986          */
987 check_intra_bg_tail:
988         if (!asked && fs->flags & EXT2_FLAG_BBITMAP_TAIL_PROBLEM) {
989                 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx))
990                         ext2fs_mark_bb_dirty(fs);
991                 else
992                         ext2fs_unmark_valid(fs);
993         }
994 }