Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / e2fsck / pass1.c
1 /*
2  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
3  * 
4  * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
5  * redistributed under the terms of the GNU Public License.
6  * 
7  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
8  * and applies the following tests to each inode:
9  *
10  *      - The mode field of the inode must be legal.
11  *      - The size and block count fields of the inode are correct.
12  *      - A data block must not be used by another inode
13  *
14  * Pass 1 also gathers the collects the following information:
15  *
16  *      - A bitmap of which inodes are in use.          (inode_used_map)
17  *      - A bitmap of which inodes are directories.     (inode_dir_map)
18  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
19  *      - A bitmap of which blocks are in use.          (block_found_map)
20  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
21  *      - The data blocks of the directory inodes.      (dir_map)
22  *
23  * Pass 1 is designed to stash away enough information so that the
24  * other passes should not need to read in the inode information
25  * during the normal course of a filesystem check.  (Althogh if an
26  * inconsistency is detected, other passes may need to read in an
27  * inode to fix it.)
28  *
29  * Note that pass 1B will be invoked if there are any duplicate blocks
30  * found.
31  */
32
33 #include <time.h>
34
35 #include <et/com_err.h>
36 #include "e2fsck.h"
37
38 /* Files counts */
39 int fs_directory_count = 0;
40 int fs_regular_count = 0;
41 int fs_blockdev_count = 0;
42 int fs_chardev_count = 0;
43 int fs_links_count = 0;
44 int fs_symlinks_count = 0;
45 int fs_fast_symlinks_count = 0;
46 int fs_fifo_count = 0;
47 int fs_total_count = 0;
48 int fs_badblocks_count = 0;
49 int fs_sockets_count = 0;
50
51 ext2fs_inode_bitmap inode_used_map = 0; /* Inodes which are in use */
52 ext2fs_inode_bitmap inode_bad_map = 0;  /* Inodes which are bad in some way */
53 ext2fs_inode_bitmap inode_dir_map = 0;  /* Inodes which are directories */
54
55 ext2fs_block_bitmap block_found_map = 0;
56 ext2fs_block_bitmap block_dup_map = 0;
57
58 static int fix_link_count = -1;
59
60 unsigned short * inode_link_info = NULL;
61
62 static int process_block(ext2_filsys fs, blk_t  *blocknr,
63                          int    blockcnt, void  *private);
64 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
65                              int blockcnt, void *private);
66 static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
67                          char *block_buf);
68 static void mark_table_blocks(ext2_filsys fs);
69 static errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
70 static errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks);
71 static void alloc_bad_map(ext2_filsys fs);
72 static void handle_fs_bad_blocks(ext2_filsys fs);
73 static void process_inodes(ext2_filsys fs, char *block_buf);
74 static int process_inode_cmp(const void *a, const void *b);
75 static int dir_block_cmp(const void *a, const void *b);
76 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
77                                   dgrp_t group, void * private);
78
79 struct process_block_struct {
80         ino_t   ino;
81         int     is_dir:1, clear:1, suppress:1;
82         int     num_blocks;
83         int     last_block;
84         int     num_illegal_blocks;
85         int     fix;
86         struct ext2_inode *inode;
87 };
88
89 struct process_inode_block {
90         ino_t   ino;
91         struct ext2_inode inode;
92 };
93
94 /*
95  * For pass1_check_directory and pass1_get_blocks
96  */
97 ino_t stashed_ino;
98 struct ext2_inode *stashed_inode;
99
100 /*
101  * For the inodes to process list.
102  */
103 static struct process_inode_block *inodes_to_process;
104 static int process_inode_count;
105 int process_inode_size = 256;
106
107 /*
108  * For the directory blocks list.
109  */
110 struct dir_block_struct *dir_blocks = 0;
111 int     dir_block_count = 0;
112 int     dir_block_size = 0;
113
114 /*
115  * Free all memory allocated by pass1 in preparation for restarting
116  * things.
117  */
118 static void unwind_pass1(ext2_filsys fs)
119 {
120         ext2fs_free_inode_bitmap(inode_used_map);       inode_used_map = 0;
121         ext2fs_free_inode_bitmap(inode_dir_map);        inode_dir_map = 0;
122         ext2fs_free_block_bitmap(block_found_map);      block_found_map = 0;
123         free(inode_link_info);  inode_link_info = 0;
124         free(inodes_to_process);inodes_to_process = 0;
125         free(dir_blocks);       dir_blocks = 0;
126         dir_block_size = 0;
127         if (block_dup_map) {
128                 free(block_dup_map); block_dup_map = 0;
129         }
130
131         /* Clear statistic counters */
132         fs_directory_count = 0;
133         fs_regular_count = 0;
134         fs_blockdev_count = 0;
135         fs_chardev_count = 0;
136         fs_links_count = 0;
137         fs_symlinks_count = 0;
138         fs_fast_symlinks_count = 0;
139         fs_fifo_count = 0;
140         fs_total_count = 0;
141         fs_badblocks_count = 0;
142         fs_sockets_count = 0;
143 }
144
145 void pass1(ext2_filsys fs)
146 {
147         ino_t   ino;
148         struct ext2_inode inode;
149         ext2_inode_scan scan;
150         char            *block_buf;
151         errcode_t       retval;
152         struct resource_track   rtrack;
153         
154         init_resource_track(&rtrack);
155         
156         if (!preen)
157                 printf("Pass 1: Checking inodes, blocks, and sizes\n");
158
159 #ifdef MTRACE
160         mtrace_print("Pass 1");
161 #endif
162
163         /*
164          * Allocate bitmaps structures
165          */
166         retval = ext2fs_allocate_inode_bitmap(fs, "in-use inode map",
167                                               &inode_used_map);
168         if (retval) {
169                 com_err("ext2fs_allocate_inode_bitmap", retval,
170                         "while allocating inode_used_map");
171                 fatal_error(0);
172         }
173         retval = ext2fs_allocate_inode_bitmap(fs, "directory inode map",
174                                               &inode_dir_map);
175         if (retval) {
176                 com_err("ext2fs_allocate_inode_bitmap", retval,
177                         "while allocating inode_dir_map");
178                 fatal_error(0);
179         }
180         retval = ext2fs_allocate_block_bitmap(fs, "in-use block map",
181                                               &block_found_map);
182         if (retval) {
183                 com_err("ext2fs_allocate_block_bitmap", retval,
184                         "while allocating block_found_map");
185                 fatal_error(0);
186         }
187         inode_link_info = allocate_memory((fs->super->s_inodes_count + 1) *
188                                           sizeof(unsigned short),
189                                           "inode link count array");
190         inodes_to_process = allocate_memory(process_inode_size *
191                                             sizeof(struct process_inode_block),
192                                             "array of inodes to process");
193         process_inode_count = 0;
194
195         dir_block_size = get_num_dirs(fs) * 4;
196         dir_block_count = 0;
197         dir_blocks = allocate_memory(sizeof(struct dir_block_struct) *
198                                      dir_block_size,
199                                      "directory block information");
200
201         mark_table_blocks(fs);
202         block_buf = allocate_memory(fs->blocksize * 3, "block interate buffer");
203         fs->get_blocks = pass1_get_blocks;
204         fs->check_directory = pass1_check_directory;
205         ehandler_operation("doing inode scan");
206         retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
207         if (retval) {
208                 com_err(program_name, retval, "while opening inode scan");
209                 fatal_error(0);
210         }
211         retval = ext2fs_get_next_inode(scan, &ino, &inode);
212         if (retval) {
213                 com_err(program_name, retval, "while starting inode scan");
214                 fatal_error(0);
215         }
216         stashed_inode = &inode;
217         ext2fs_set_inode_callback(scan, scan_callback, block_buf);
218         while (ino) {
219                 stashed_ino = ino;
220                 inode_link_info[ino] = inode.i_links_count;
221                 if (ino == EXT2_BAD_INO) {
222                         struct process_block_struct pb;
223                         
224                         pb.ino = EXT2_BAD_INO;
225                         pb.num_blocks = pb.last_block = 0;
226                         pb.num_illegal_blocks = 0;
227                         pb.suppress = pb.clear = pb.is_dir = 0;
228                         pb.fix = -1;
229                         pb.inode = &inode;
230                         retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
231                                                       process_bad_block, &pb);
232                         if (retval)
233                                 com_err(program_name, retval, "while calling e2fsc_block_interate in pass 1");
234
235                         ext2fs_mark_inode_bitmap(inode_used_map, ino);
236                         goto next;
237                 }
238                 if (ino == EXT2_ROOT_INO) {
239                         /*
240                          * Make sure the root inode is a directory; if
241                          * not, offer to clear it.  It will be
242                          * regnerated in pass #3.
243                          */
244                         if (!S_ISDIR(inode.i_mode)) {
245                                 printf("Root inode is not a directory.  ");
246                                 preenhalt();
247                                 if (ask("Clear", 1)) {
248                                         inode.i_dtime = time(0);
249                                         inode.i_links_count = 0;
250                                         inode_link_info[ino] = 0;
251                                         e2fsck_write_inode(fs, ino, &inode,
252                                                            "pass1");
253                                 } else 
254                                         ext2fs_unmark_valid(fs);
255                         }
256                         /*
257                          * If dtime is set, offer to clear it.  mke2fs
258                          * version 0.2b created filesystems with the
259                          * dtime field set for the root and lost+found
260                          * directories.  We won't worry about
261                          * /lost+found, since that can be regenerated
262                          * easily.  But we will fix the root directory
263                          * as a special case.
264                          */
265                         if (inode.i_dtime && inode.i_links_count) {
266                                 if (ask("Root inode has dtime set "
267                                         "(probably due to old mke2fs).  Fix",
268                                         1)) {
269                                         inode.i_dtime = 0;
270                                         e2fsck_write_inode(fs, ino, &inode,
271                                                            "pass1");
272                                         printf("Note: /lost+found will "
273                                                "probably be deleted as well, "
274                                                "due to the mke2fs bug.\n"
275                                                "Be sure to run mklost+found "
276                                                "to recreate it after e2fsck "
277                                                "finishes.\n\n");
278                                 } else
279                                         ext2fs_unmark_valid(fs);
280                         }
281                 }
282                 if ((ino != EXT2_ROOT_INO) && (ino < EXT2_FIRST_INO)) {
283                         ext2fs_mark_inode_bitmap(inode_used_map, ino);
284                         check_blocks(fs, ino, &inode, block_buf);
285                         goto next;
286                 }
287                 /*
288                  * This code assumes that deleted inodes have
289                  * i_links_count set to 0.  
290                  */
291                 if (!inode.i_links_count) {
292                         if (!inode.i_dtime && inode.i_mode) {
293                                 printf("Deleted inode %lu has zero dtime.\n",
294                                        ino);
295                                 if (ask("Set dtime", 1)) {
296                                         inode.i_dtime = time(0);
297                                         e2fsck_write_inode(fs, ino, &inode,
298                                                            "pass1");
299                                 } else
300                                         ext2fs_unmark_valid(fs);
301                         }
302                         goto next;
303                 }
304                 /*
305                  * 0.3c ext2fs code didn't clear i_links_count for
306                  * deleted files.  Oops.
307                  * 
308                  * In the future, when the new ext2fs behavior is the
309                  * norm, we may want to handle the case of a non-zero
310                  * i_links_count and non-zero dtime by clearing dtime
311                  * and assuming the inode is in use, instead of
312                  * assuming the inode is not in use.
313                  */
314                 if (inode.i_dtime) {
315                         if (fix_link_count == -1) {
316                                 printf("\nDeleted inode detected with non-zero link count.\n");
317                                 printf("This is probably due to old ext2fs kernel code.  \n");
318                                 fix_link_count = ask("Fix inode(s)", 1);
319                         }
320                         printf("Inode %lu is deleted w/ non-zero link_count.  %s\n",
321                                ino, clear_msg[fix_link_count]);
322                         if (fix_link_count) {
323                                 inode.i_links_count = 0;
324                                 inode_link_info[ino] = 0;
325                                 e2fsck_write_inode(fs, ino, &inode, "pass1");
326                         } else
327                                 ext2fs_unmark_valid(fs);
328                         goto next;
329                 }
330                 
331                 ext2fs_mark_inode_bitmap(inode_used_map, ino);
332                 if (inode.i_faddr || inode.i_frag || inode.i_fsize ||
333                     inode.i_file_acl || inode.i_dir_acl) {
334                         if (!inode_bad_map)
335                                 alloc_bad_map(fs);
336                         ext2fs_mark_inode_bitmap(inode_bad_map, ino);
337                 }
338                 
339                 if (S_ISDIR(inode.i_mode)) {
340                         ext2fs_mark_inode_bitmap(inode_dir_map, ino);
341                         add_dir_info(fs, ino, 0, &inode);
342                         fs_directory_count++;
343                 } else if (S_ISREG (inode.i_mode))
344                         fs_regular_count++;
345                 else if (S_ISCHR (inode.i_mode))
346                         fs_chardev_count++;
347                 else if (S_ISBLK (inode.i_mode))
348                         fs_blockdev_count++;
349                 else if (S_ISLNK (inode.i_mode)) {
350                         fs_symlinks_count++;
351                         if (!inode.i_blocks)
352                                 fs_fast_symlinks_count++;
353                 }
354                 else if (S_ISFIFO (inode.i_mode))
355                         fs_fifo_count++;
356                 else if (S_ISSOCK (inode.i_mode))
357                         fs_sockets_count++;
358                 else {
359                         if (!inode_bad_map)
360                                 alloc_bad_map(fs);
361                         ext2fs_mark_inode_bitmap(inode_bad_map, ino);
362                 }
363                 if (inode.i_block[EXT2_IND_BLOCK] ||
364                     inode.i_block[EXT2_DIND_BLOCK] ||
365                     inode.i_block[EXT2_TIND_BLOCK]) {
366                         inodes_to_process[process_inode_count].ino = ino;
367                         inodes_to_process[process_inode_count].inode = inode;
368                         process_inode_count++;
369                 } else
370                         check_blocks(fs, ino, &inode, block_buf);
371
372                 if (process_inode_count >= process_inode_size)
373                         process_inodes(fs, block_buf);
374         next:
375                 retval = ext2fs_get_next_inode(scan, &ino, &inode);
376                 if (retval) {
377                         com_err(program_name, retval,
378                                 "while doing inode scan");
379                         fatal_error(0);
380                 }
381         }
382         process_inodes(fs, block_buf);
383         ext2fs_close_inode_scan(scan);
384         ehandler_operation(0);
385
386         qsort(dir_blocks, dir_block_count, sizeof(struct dir_block_struct),
387               dir_block_cmp);
388
389         if (invalid_bitmaps)
390                 handle_fs_bad_blocks(fs);
391
392         if (restart_e2fsck) {
393                 unwind_pass1(fs);
394                 goto endit;
395         }
396
397         if (block_dup_map) {
398                 if (preen) {
399                         printf("Duplicate or bad blocks in use!\n");
400                         preenhalt();
401                 }
402                 pass1_dupblocks(fs, block_buf);
403         }
404         fs->get_blocks = 0;
405         fs->check_directory = 0;
406         free(inodes_to_process);
407 endit:
408         free(block_buf);
409         if (tflag > 1) {
410                 printf("Pass 1: ");
411                 print_resource_track(&rtrack);
412         }
413 }
414
415 /*
416  * When the inode_scan routines call this callback at the end of the
417  * glock group, call process_inodes.
418  */
419 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
420                                dgrp_t group, void * private)
421 {
422         process_inodes(fs, (char *) private);
423         return 0;
424 }
425
426 /*
427  * Process the inodes in the "inodes to process" list.
428  */
429 static void process_inodes(ext2_filsys fs, char *block_buf)
430 {
431         int                     i;
432         struct ext2_inode       *old_stashed_inode;
433         ino_t                   ino;
434         const char              *old_operation;
435         char                    buf[80];
436
437 #if 0
438         printf("begin process_inodes: ");
439 #endif
440         old_operation = ehandler_operation(0);
441         old_stashed_inode = stashed_inode;
442         qsort(inodes_to_process, process_inode_count,
443                       sizeof(struct process_inode_block), process_inode_cmp);
444         for (i=0; i < process_inode_count; i++) {
445                 stashed_inode = &inodes_to_process[i].inode;
446                 ino = inodes_to_process[i].ino;
447                 stashed_ino = ino;
448 #if 0
449                 printf("%lu ", ino);
450 #endif
451                 sprintf(buf, "reading indirect blocks of inode %lu", ino);
452                 ehandler_operation(buf);
453                 check_blocks(fs, ino, stashed_inode, block_buf);
454                 
455         }
456         stashed_inode = old_stashed_inode;
457         process_inode_count = 0;
458 #if 0
459         printf("end process inodes\n");
460 #endif
461         ehandler_operation(old_operation);
462 }
463
464 static int process_inode_cmp(const void *a, const void *b)
465 {
466         const struct process_inode_block *ib_a =
467                 (const struct process_inode_block *) a;
468         const struct process_inode_block *ib_b =
469                 (const struct process_inode_block *) b;
470
471         return (ib_a->inode.i_block[EXT2_IND_BLOCK] -
472                 ib_b->inode.i_block[EXT2_IND_BLOCK]);
473 }
474
475 static int dir_block_cmp(const void *a, const void *b)
476 {
477         const struct dir_block_struct *db_a =
478                 (const struct dir_block_struct *) a;
479         const struct dir_block_struct *db_b =
480                 (const struct dir_block_struct *) b;
481
482         return (db_a->blk - db_b->blk);
483 }
484
485 /*
486  * This procedure will allocate the inode bad map table
487  */
488 static void alloc_bad_map(ext2_filsys fs)
489 {
490         errcode_t       retval;
491         
492         retval = ext2fs_allocate_inode_bitmap(fs, "bad inode map",
493                                               &inode_bad_map);
494         if (retval) {
495                 com_err("ext2fs_allocate_inode_bitmap", retval,
496                         "while allocating inode_bad_map");
497                 fatal_error(0);
498         }
499 }
500
501 /*
502  * Marks a block as in use, setting the dup_map if it's been set
503  * already.  Called by process_block and process_bad_block.
504  */
505 static void mark_block_used(ext2_filsys fs, blk_t block)
506 {
507         errcode_t       retval;
508         
509         if (ext2fs_test_block_bitmap(block_found_map, block)) {
510                 if (!block_dup_map) {
511                         retval = ext2fs_allocate_block_bitmap(fs,
512                               "multiply claimed block map", &block_dup_map);
513                         if (retval) {
514                                 com_err("ext2fs_allocate_block_bitmap", retval,
515                                         "while allocating block_dup_map");
516                                 fatal_error(0);
517                         }
518                 }
519                 ext2fs_mark_block_bitmap(block_dup_map, block);
520         } else {
521                 ext2fs_mark_block_bitmap(block_found_map, block);
522         }
523 }
524
525 /*
526  * This subroutine is called on each inode to account for all of the
527  * blocks used by that inode.
528  */
529 static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
530                          char *block_buf)
531 {
532         struct process_block_struct pb;
533         errcode_t       retval;
534         
535         if (!inode_has_valid_blocks(inode))
536                 return;
537         
538         pb.ino = ino;
539         pb.num_blocks = pb.last_block = 0;
540         pb.num_illegal_blocks = 0;
541         pb.suppress = pb.clear = 0;
542         pb.is_dir = S_ISDIR(inode->i_mode);
543         pb.fix = -1;
544         pb.inode = inode;
545         retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
546                                       process_block, &pb);
547         if (retval)
548                 com_err(program_name, retval,
549                         "while calling ext2fs_block_iterate in check_blocks");
550
551         if (pb.clear) {
552                 e2fsck_read_inode(fs, ino, inode, "check_blocks");
553                 if (retval) {
554                         com_err("check_blocks", retval,
555                                 "while reading to be cleared inode %d", ino);
556                         fatal_error(0);
557                 }
558                 inode->i_links_count = 0;
559                 inode_link_info[ino] = 0;
560                 inode->i_dtime = time(0);
561                 e2fsck_write_inode(fs, ino, inode, "check_blocks");
562                 ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
563                 ext2fs_unmark_inode_bitmap(inode_used_map, ino);
564                 /*
565                  * The inode was probably partially accounted for
566                  * before processing was aborted, so we need to
567                  * restart the pass 1 scan.
568                  */
569                 restart_e2fsck++;
570                 return;
571         }
572
573         if (pb.fix > 0)
574                 e2fsck_read_inode(fs, ino, inode, "check_blocks");
575
576         pb.num_blocks *= (fs->blocksize / 512);
577 #if 0
578         printf("inode %lu, i_size = %lu, last_block = %lu, i_blocks=%lu, num_blocks = %lu\n",
579                ino, inode->i_size, pb.last_block, inode->i_blocks,
580                pb.num_blocks);
581 #endif
582         if (!pb.num_blocks && pb.is_dir) {
583                 printf("Inode %lu is a zero length directory.  ", ino);
584                 if (ask("Clear", 1)) {
585                         inode->i_links_count = 0;
586                         inode_link_info[ino] = 0;
587                         inode->i_dtime = time(0);
588                         e2fsck_write_inode(fs, ino, inode, "check_blocks");
589                         ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
590                         ext2fs_unmark_inode_bitmap(inode_used_map, ino);
591                         fs_directory_count--;
592                 } else
593                         ext2fs_unmark_valid(fs);
594         }
595         if (inode->i_size < pb.last_block * fs->blocksize) {
596                 printf ("Inode %lu, incorrect size, %lu (counted = %u). ",
597                         ino, inode->i_size,
598                         (pb.last_block+1) * fs->blocksize);
599                 if (ask ("Set size to counted", 1)) {
600                         inode->i_size = (pb.last_block+1) * fs->blocksize;
601                         e2fsck_write_inode(fs, ino, inode, "check_blocks");
602                 } else
603                         ext2fs_unmark_valid(fs);
604         }
605         if (pb.num_blocks != inode->i_blocks) {
606                 printf ("Inode %lu, i_blocks wrong %lu (counted=%u).  ",
607                         ino, inode->i_blocks, pb.num_blocks);
608                 if (ask ("Set i_blocks to counted", 1)) {
609                         inode->i_blocks = pb.num_blocks;
610                         e2fsck_write_inode(fs, ino, inode, "check_blocks");
611                 } else
612                                 ext2fs_unmark_valid(fs);
613         }
614 }       
615
616 /*
617  * This is a helper function for check_blocks().
618  */
619 int process_block(ext2_filsys fs,
620                   blk_t *block_nr,
621                   int blockcnt,
622                   void *private)
623 {
624         struct process_block_struct *p;
625         int     group;
626         int     illegal_block = 0;
627         char    problem[80];
628         blk_t   firstblock, group_super;
629         blk_t   blk = *block_nr;
630
631         if (!blk)
632                 return 0;
633         p = (struct process_block_struct *) private;
634
635 #if 0
636         printf("Process_block, inode %lu, block %lu, #%d\n", p->ino, blk,
637                blockcnt);
638 #endif  
639         
640         firstblock = fs->super->s_first_data_block;
641         group = (blk - firstblock) / fs->super->s_blocks_per_group;
642         group_super = ((group * fs->super->s_blocks_per_group) +
643                        fs->super->s_first_data_block);
644         if (blk < firstblock) {
645                 sprintf(problem, "< FIRSTBLOCK (%lu)", firstblock);
646                 illegal_block++;
647         } else if (blk >= fs->super->s_blocks_count) {
648                 sprintf(problem, "> BLOCKS (%lu)", fs->super->s_blocks_count);
649                 illegal_block++;
650         } else if (blk == group_super) {
651                 sprintf(problem, "is the superblock in group %d", group);
652                 illegal_block++;
653         } else if (blk > group_super &&
654                    blk <= (group_super + fs->desc_blocks)) {
655                 sprintf(problem, "is in the group descriptors in group %d",
656                         group);
657                 illegal_block++;
658         } else if (blk == fs->group_desc[group].bg_block_bitmap) {
659                 sprintf(problem, "is the block bitmap of group %d", group);
660                 illegal_block++;
661         } else if (blk == fs->group_desc[group].bg_inode_bitmap) {
662                 sprintf(problem, "is the inode bitmap of group %d", group);
663                 illegal_block++;
664         } else if (blk >= fs->group_desc[group].bg_inode_table &&
665                    blk < fs->group_desc[group].bg_inode_table + fs->inode_blocks_per_group) {
666                 sprintf(problem, "is in the inode table of group %d", group);
667                 illegal_block++;
668         }
669         if (illegal_block) {
670                 if (preen) {
671                         printf("Block %lu of inode %lu %s\n", blk, p->ino,
672                                problem);
673                         preenhalt();
674                 }
675                 if (p->fix == -1) {
676                         printf("Remove illegal block(s) in inode %lu", p->ino);
677                         p->fix = ask("", 1);
678                 }
679                 p->num_illegal_blocks++;
680                 if (!p->suppress && (p->num_illegal_blocks % 20) == 0) {
681                         printf("Too many illegal blocks in inode %lu.\n",
682                                p->ino);
683                         if (ask("Clear inode", 1)) {
684                                 p->clear = 1;
685                                 return BLOCK_ABORT;
686                         }
687                         if (ask("Supress messages", 0)) {
688                                 p->suppress = 1;
689                         }
690                 }
691                 if (!p->suppress)
692                         printf("Block #%d (%lu) %s.  %s\n", blockcnt, blk,
693                                problem, clear_msg[p->fix]);
694                 if (p->fix) {
695                         *block_nr = 0;
696                         return BLOCK_CHANGED;
697                 } else {
698                         ext2fs_unmark_valid(fs);
699                         return 0;
700                 }
701         }
702
703         p->num_blocks++;
704         if (blockcnt > 0)
705                 p->last_block = blockcnt;
706         mark_block_used(fs, blk);
707         
708         if (p->is_dir && (blockcnt >= 0)) {
709                 if (dir_block_count >= dir_block_size) {
710                         dir_block_size += 100;
711                         dir_blocks = realloc(dir_blocks,
712                                              dir_block_size *
713                                              sizeof(struct dir_block_struct));
714                 }
715
716                 dir_blocks[dir_block_count].blk = blk;
717                 dir_blocks[dir_block_count].ino = p->ino;
718                 dir_blocks[dir_block_count].blockcnt = blockcnt;
719                 dir_block_count++;
720         }
721         
722 #if 0
723         printf("process block, inode %lu, block #%d is %lu\n",
724                p->ino, blockcnt, blk);
725 #endif
726         
727         return 0;
728 }
729
730 static void bad_block_indirect(blk_t blk)
731 {
732         printf("Bad block %lu used as bad block indirect block?!?\n", blk);
733         preenhalt();
734         printf("\nThis inconsistency can not be fixed with "
735                "e2fsck; to fix it, use\n"
736                """dumpe2fs -b"" to dump out the bad block "
737                "list and ""e2fsck -L filename""\n"
738                "to read it back in again.\n");
739         if (ask("Continue", 0))
740                 return;
741         fatal_error(0);
742 }
743
744 int process_bad_block(ext2_filsys fs,
745                       blk_t *block_nr,
746                       int blockcnt,
747                       void *private)
748 {
749         struct process_block_struct *p;
750         blk_t           blk = *block_nr;
751         int             first_block;
752         int             i;
753         
754         if (!blk)
755                 return 0;
756         p = (struct process_block_struct *) private;
757
758         if ((blk < fs->super->s_first_data_block) ||
759             (blk >= fs->super->s_blocks_count)) {
760                 if (preen) {
761                         printf("Illegal block %lu in bad block inode\n", blk);
762                         preenhalt();
763                 }
764                 if (p->fix == -1)
765                         p->fix = ask("Remove illegal block(s) in bad block inode", 1);
766                 printf("Illegal block %lu in bad block inode.  %s\n", blk,
767                        clear_msg[p->fix]);
768                 if (p->fix) {
769                         *block_nr = 0;
770                         return BLOCK_CHANGED;
771                 } else {
772                         ext2fs_unmark_valid(fs);
773                         return 0;
774                 }
775         }
776
777         if (blockcnt < 0) {
778                 if (ext2fs_test_block_bitmap(block_found_map, blk))
779                         bad_block_indirect(blk);
780                 else
781                         mark_block_used(fs, blk);
782                 return 0;
783         }
784 #if 0 
785         printf ("DEBUG: Marking %lu as bad.\n", blk);
786 #endif
787         fs_badblocks_count++;
788         /*
789          * If the block is not used, then mark it as used and return.
790          * If it is already marked as found, this must mean that
791          * there's an overlap between the filesystem table blocks
792          * (bitmaps and inode table) and the bad block list.
793          */
794         if (!ext2fs_test_block_bitmap(block_found_map, blk)) {
795                 ext2fs_mark_block_bitmap(block_found_map, blk);
796                 return 0;
797         }
798         /*
799          * Try to find the where the filesystem block was used...
800          */
801         first_block = fs->super->s_first_data_block;
802         
803         for (i = 0; i < fs->group_desc_count; i++ ) {
804                 if (blk == first_block) {
805                         if (i == 0) {
806                                 printf("The primary superblock (%lu) is "
807                                        "bad.  Aiiieeee....\n", blk);
808                                 fatal_error(0);
809                         }
810                         if (!preen)
811                                 printf("Warning: Group %d's superblock "
812                                        "(%lu) is bad.\n", i, blk);
813                         return 0;
814                 }
815                 if ((blk > first_block) &&
816                     (blk <= first_block + fs->desc_blocks)) {
817                         if (i == 0) {
818                                 printf("Bad block %lu is in the primary "
819                                        "group descriptors.  Aiiieeee....\n",
820                                        blk);
821                                 fatal_error(0);
822                         }
823                         if (!preen)
824                                 printf("Warning: Group %d's copy of the "
825                                        "group descriptors has a bad "
826                                        "block (%lu).\n", i, blk);
827                         return 0;
828                 }
829                 if (blk == fs->group_desc[i].bg_block_bitmap) {
830                         printf("Group %d's block bitmap (%lu) is bad.  ",
831                                i, blk);
832                         if (ask("Relocate", 1)) {
833                                 invalid_block_bitmap[i]++;
834                                 invalid_bitmaps++;
835                         } else
836                                 ext2fs_unmark_valid(fs);
837                         return 0;
838                 }
839                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
840                         printf("Group %d's inode bitmap (%lu) is bad.  ",
841                                i, blk);
842                         if (ask("Relocate", 1)) {
843                                 invalid_inode_bitmap[i]++;
844                                 invalid_bitmaps++;
845                         } else
846                                 ext2fs_unmark_valid(fs);
847                         return 0;
848                 }
849                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
850                     (blk < (fs->group_desc[i].bg_inode_table +
851                             fs->inode_blocks_per_group))) {
852                         printf("WARNING: Severe data loss possible!!!!\n");
853                         printf("Bad block %lu in group %d's inode table.  ",
854                                blk, i);
855                         if (ask("Relocate", 1)) {
856                                 invalid_inode_table[i]++;
857                                 invalid_bitmaps++;
858                         } else
859                                 ext2fs_unmark_valid(fs);
860                         return 0;
861                 }
862                 first_block += fs->super->s_blocks_per_group;
863         }
864         /*
865          * If we've gotten to this point, then the only
866          * possibility is that the bad block inode meta data
867          * is using a bad block.
868          */
869         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
870             p->inode->i_block[EXT2_DIND_BLOCK]) {
871                 bad_block_indirect(blk);
872                 return 0;
873         }
874         
875         printf("Programming error?  block #%lu claimed for no reason "
876                "in process_bad_block.\n", blk);
877         return 0;
878 }
879
880 static void new_table_block(ext2_filsys fs, blk_t first_block, int group, 
881                             const char *name, int num, blk_t *new_block)
882 {
883         errcode_t       retval;
884         blk_t           old_block = *new_block;
885         int             i;
886         char            *buf;
887         
888         retval = ext2fs_get_free_blocks(fs, first_block,
889                         first_block + fs->super->s_blocks_per_group,
890                                         num, block_found_map, new_block);
891         if (retval) {
892                 printf("Could not allocate %d block(s) for %s: %s\n",
893                        num, name, error_message(retval));
894                 ext2fs_unmark_valid(fs);
895                 return;
896         }
897         buf = malloc(fs->blocksize);
898         if (!buf) {
899                 printf("Could not allocate block buffer for relocating %s\n",
900                        name);
901                 ext2fs_unmark_valid(fs);
902                 return;
903         }
904         ext2fs_mark_super_dirty(fs);
905         printf("Relocating group %d's %s ", group, name);
906         if (old_block)
907                 printf("from %lu ", old_block);
908         printf("to %lu...\n", *new_block);
909         for (i = 0; i < num; i++) {
910                 ext2fs_mark_block_bitmap(block_found_map, (*new_block)+i);
911                 if (old_block) {
912                         retval = io_channel_read_blk(fs->io, old_block + i,
913                                                      1, buf);
914                         if (retval)
915                                 printf("Warning: could not read block %lu "
916                                        "of %s: %s\n",
917                                        old_block + i, name,
918                                        error_message(retval));
919                 } else
920                         memset(buf, 0, fs->blocksize);
921
922                 retval = io_channel_write_blk(fs->io, (*new_block) + i,
923                                               1, buf);
924                 if (retval)
925                         printf("Warning: could not write block %lu for %s: %s\n",
926                                (*new_block) + i, name, error_message(retval));
927         }
928         free(buf);
929 }
930
931 /*
932  * This routine gets called at the end of pass 1 if bad blocks are
933  * detected in the superblock, group descriptors, inode_bitmaps, or
934  * block bitmaps.  At this point, all of the blocks have been mapped
935  * out, so we can try to allocate new block(s) to replace the bad
936  * blocks.
937  */
938 static void handle_fs_bad_blocks(ext2_filsys fs)
939 {
940         int             i;
941         int             first_block = fs->super->s_first_data_block;
942
943         for (i = 0; i < fs->group_desc_count; i++) {
944                 if (invalid_block_bitmap[i]) {
945                         new_table_block(fs, first_block, i, "block bitmap", 1, 
946                                         &fs->group_desc[i].bg_block_bitmap);
947                 }
948                 if (invalid_inode_bitmap[i]) {
949                         new_table_block(fs, first_block, i, "inode bitmap", 1, 
950                                         &fs->group_desc[i].bg_inode_bitmap);
951                 }
952                 if (invalid_inode_table[i]) {
953                         new_table_block(fs, first_block, i, "inode table",
954                                         fs->inode_blocks_per_group, 
955                                         &fs->group_desc[i].bg_inode_table);
956                         restart_e2fsck++;
957                 }
958                 first_block += fs->super->s_blocks_per_group;
959         }
960         invalid_bitmaps = 0;
961 }
962
963 /*
964  * This routine marks all blocks which are used by the superblock,
965  * group descriptors, inode bitmaps, and block bitmaps.
966  */
967 static void mark_table_blocks(ext2_filsys fs)
968 {
969         blk_t   block, b;
970         int     i,j;
971         
972         block = fs->super->s_first_data_block;
973         for (i = 0; i < fs->group_desc_count; i++) {
974                 /*
975                  * Mark block used for the block bitmap 
976                  */
977                 if (fs->group_desc[i].bg_block_bitmap) {
978                         if (ext2fs_test_block_bitmap(block_found_map,
979                                      fs->group_desc[i].bg_block_bitmap)) {
980                                 printf("Group %i's block bitmap at %lu "
981                                        "conflicts with some other fs block.\n",
982                                        i, fs->group_desc[i].bg_block_bitmap);
983                                 preenhalt();
984                                 if (ask("Relocate", 1)) {
985                                         invalid_block_bitmap[i]++;
986                                         invalid_bitmaps++;
987                                 } else {
988                                         ext2fs_unmark_valid(fs);
989                                 }
990                         } else
991                             ext2fs_mark_block_bitmap(block_found_map,
992                                      fs->group_desc[i].bg_block_bitmap);
993                 }
994                 /*
995                  * Mark block used for the inode bitmap 
996                  */
997                 if (fs->group_desc[i].bg_inode_bitmap) {
998                         if (ext2fs_test_block_bitmap(block_found_map,
999                                      fs->group_desc[i].bg_inode_bitmap)) {
1000                                 printf("Group %i's inode bitmap at %lu "
1001                                        "conflicts with some other fs block.\n",
1002                                        i, fs->group_desc[i].bg_inode_bitmap);
1003                                 preenhalt();
1004                                 if (ask("Relocate", 1)) {
1005                                         invalid_inode_bitmap[i]++;
1006                                         invalid_bitmaps++;
1007                                 } else {
1008                                         ext2fs_unmark_valid(fs);
1009                                 }
1010                         } else
1011                             ext2fs_mark_block_bitmap(block_found_map,
1012                                      fs->group_desc[i].bg_inode_bitmap);
1013                 }
1014                     
1015                 /*
1016                  * Mark the blocks used for the inode table
1017                  */
1018                 if (fs->group_desc[i].bg_inode_table) {
1019                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
1020                              j < fs->inode_blocks_per_group;
1021                              j++, b++) {
1022                                 if (ext2fs_test_block_bitmap(block_found_map,
1023                                                              b)) {
1024                                         printf("Group %i's inode table at %lu "
1025                                                "conflicts with some other "
1026                                                "fs block.\n",
1027                                                i, b);
1028                                         preenhalt();
1029                                         if (ask("Relocate", 1)) {
1030                                                 invalid_inode_table[i]++;
1031                                                 invalid_bitmaps++;
1032                                         } else {
1033                                                 ext2fs_unmark_valid(fs);
1034                                         }
1035                                 } else
1036                                     ext2fs_mark_block_bitmap(block_found_map,
1037                                                              b);
1038                         }
1039                 }
1040                             
1041                 /*
1042                  * Mark this group's copy of the superblock
1043                  */
1044                 ext2fs_mark_block_bitmap(block_found_map, block);
1045                 
1046                 /*
1047                  * Mark this group's copy of the descriptors
1048                  */
1049                 for (j = 0; j < fs->desc_blocks; j++)
1050                         ext2fs_mark_block_bitmap(block_found_map,
1051                                                  block + j + 1);
1052                 block += fs->super->s_blocks_per_group;
1053         }
1054 }
1055         
1056 /*
1057  * This subroutines short circuits ext2fs_get_blocks and
1058  * ext2fs_check_directory; we use them since we already have the inode
1059  * structure, so there's no point in letting the ext2fs library read
1060  * the inode again.
1061  */
1062 static errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
1063 {
1064         int     i;
1065         
1066         if (ino == stashed_ino) {
1067                 for (i=0; i < EXT2_N_BLOCKS; i++)
1068                         blocks[i] = stashed_inode->i_block[i];
1069                 return 0;
1070         }
1071         printf("INTERNAL ERROR: pass1_get_blocks: unexpected inode #%lu\n",
1072                ino);
1073         printf("\t(was expecting %lu)\n", stashed_ino);
1074         exit(FSCK_ERROR);
1075 }
1076
1077 static errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino)
1078 {
1079         if (ino == stashed_ino) {
1080                 if (!S_ISDIR(stashed_inode->i_mode))
1081                         return ENOTDIR;
1082                 return 0;
1083         }
1084         printf("INTERNAL ERROR: pass1_check_directory: unexpected inode #%lu\n",
1085                ino);
1086         printf("\t(was expecting %lu)\n", stashed_ino);
1087         exit(FSCK_ERROR);
1088 }