4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 * redistributed under the terms of the GNU Public License.
9 * Dictionary Abstract Data Type
10 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
11 * Free Software License:
12 * All rights are reserved by the author, with the following exceptions:
13 * Permission is granted to freely reproduce and distribute this software,
14 * possibly in exchange for a fee, provided that this copyright notice appears
15 * intact. Permission is also granted to adapt this software to produce
16 * derivative works, as long as the modified versions carry this copyright
17 * notice and additional notices stating that the work has been modified.
18 * This source code may be translated into executable form and incorporated
19 * into proprietary software; there is no requirement for such software to
20 * contain a copyright notice related to this source.
22 * linux/fs/recovery and linux/fs/revoke
23 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
25 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
27 * This file is part of the Linux kernel and is made available under
28 * the terms of the GNU General Public License, version 2, or at your
29 * option, any later version, incorporated herein by reference.
31 * Journal recovery routines for the generic filesystem journaling code;
32 * part of the ext2fs journaling system.
36 #define _GNU_SOURCE 1 /* get strnlen() */
38 #include <sys/types.h>
56 #include <sys/resource.h>
57 #include <sys/param.h>
58 #include <sys/mount.h>
59 #include <sys/ioctl.h>
67 #include "ext2fs/ext2_fs.h"
68 #include "ext2fs/ext2fs.h"
69 #include "blkid/blkid.h"
70 #include "ext2fs/ext2_ext_attr.h"
71 #include "uuid/uuid.h"
74 #define _INLINE_ __inline__
75 #define EXT2FS_ATTR(x) __attribute__(x)
78 #define EXT2FS_ATTR(x)
82 * Exit codes used by fsck-type programs
84 #define FSCK_OK 0 /* No errors */
85 #define FSCK_NONDESTRUCT 1 /* File system errors corrected */
86 #define FSCK_REBOOT 2 /* System should be rebooted */
87 #define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
88 #define FSCK_ERROR 8 /* Operational error */
89 #define FSCK_USAGE 16 /* Usage or syntax error */
90 #define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
91 #define FSCK_LIBRARY 128 /* Shared library error */
94 * The last ext2fs revision level that this version of e2fsck is able to
97 #define E2FSCK_CURRENT_REV 1
100 * The directory information structure; stores directory information
101 * collected in earlier passes, to avoid disk i/o in fetching the
102 * directory information.
105 ext2_ino_t ino; /* Inode number */
106 ext2_ino_t dotdot; /* Parent according to '..' */
107 ext2_ino_t parent; /* Parent according to treewalk */
112 * The indexed directory information structure; stores information for
113 * directories which contain a hash tree index.
116 ext2_ino_t ino; /* Inode number */
117 int numblocks; /* number of blocks */
119 short depth; /* depth of tree */
120 struct dx_dirblock_info *dx_block; /* Array of size numblocks */
123 #define DX_DIRBLOCK_ROOT 1
124 #define DX_DIRBLOCK_LEAF 2
125 #define DX_DIRBLOCK_NODE 3
126 #define DX_DIRBLOCK_CORRUPT 4
127 #define DX_DIRBLOCK_CLEARED 8
129 struct dx_dirblock_info {
134 ext2_dirhash_t min_hash;
135 ext2_dirhash_t max_hash;
136 ext2_dirhash_t node_min_hash;
137 ext2_dirhash_t node_max_hash;
140 #define DX_FLAG_REFERENCED 1
141 #define DX_FLAG_DUP_REF 2
142 #define DX_FLAG_FIRST 4
143 #define DX_FLAG_LAST 8
145 #ifdef RESOURCE_TRACK
147 * This structure is used for keeping track of how much resources have
148 * been used for a particular pass of e2fsck.
150 struct resource_track {
151 struct timeval time_start;
152 struct timeval user_start;
153 struct timeval system_start;
161 #define E2F_OPT_READONLY 0x0001
162 #define E2F_OPT_PREEN 0x0002
163 #define E2F_OPT_YES 0x0004
164 #define E2F_OPT_NO 0x0008
165 #define E2F_OPT_TIME 0x0010
166 #define E2F_OPT_TIME2 0x0020
167 #define E2F_OPT_CHECKBLOCKS 0x0040
168 #define E2F_OPT_DEBUG 0x0080
169 #define E2F_OPT_FORCE 0x0100
170 #define E2F_OPT_WRITECHECK 0x0200
171 #define E2F_OPT_COMPRESS_DIRS 0x0400
176 #define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
177 #define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
178 #define E2F_FLAG_SIGNAL_MASK 0x0003
179 #define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
181 #define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
183 #define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
184 #define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
185 #define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */
186 #define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
187 * specified by the user */
188 #define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
189 #define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
192 * Defines for indicating the e2fsck pass number
199 #define E2F_PASS_1B 6
203 * This is the global e2fsck structure.
205 typedef struct e2fsck_struct *e2fsck_t;
208 * Define the extended attribute refcount structure
210 typedef struct ea_refcount *ext2_refcount_t;
212 struct e2fsck_struct {
214 const char *program_name;
215 char *filesystem_name;
218 int flags; /* E2fsck internal flags */
220 blk_t use_superblock; /* sb requested by user */
221 blk_t superblock; /* sb used to open fs */
222 int blocksize; /* blocksize */
223 blk_t num_blocks; /* Total number of blocks */
225 blkid_cache blkid; /* blkid cache */
229 unsigned long abort_code;
231 int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
234 ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
235 ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
236 ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
237 ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
238 ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
239 ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
241 ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
242 ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
243 ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
248 ext2_icount_t inode_count;
249 ext2_icount_t inode_link_info;
251 ext2_refcount_t refcount;
252 ext2_refcount_t refcount_extra;
255 * Array of flags indicating whether an inode bitmap, block
256 * bitmap, or inode table is invalid
258 int *invalid_inode_bitmap_flag;
259 int *invalid_block_bitmap_flag;
260 int *invalid_inode_table_flag;
261 int invalid_bitmaps; /* There are invalid bitmaps/itable */
269 * For pass1_check_directory and pass1_get_blocks
271 ext2_ino_t stashed_ino;
272 struct ext2_inode *stashed_inode;
275 * Location of the lost and found directory
277 ext2_ino_t lost_and_found;
278 int bad_lost_and_found;
281 * Directory information
285 struct dir_info *dir_info;
288 * Indexed directory information
290 int dx_dir_info_count;
291 int dx_dir_info_size;
292 struct dx_dir_info *dx_dir_info;
295 * Directories to hash
297 ext2_u32_list dirs_to_hash;
302 int process_inode_size;
303 int inode_buffer_blocks;
306 * ext3 journal support
308 io_channel journal_io;
311 #ifdef RESOURCE_TRACK
313 * For timing purposes
315 struct resource_track global_rtrack;
319 * How we display the progress update (for unix)
323 int progress_last_percent;
324 unsigned int progress_last_time;
325 int interactive; /* Are we connected directly to a tty? */
326 char start_meta[2], stop_meta[2];
329 int fs_directory_count;
330 int fs_regular_count;
331 int fs_blockdev_count;
332 int fs_chardev_count;
334 int fs_symlinks_count;
335 int fs_fast_symlinks_count;
338 int fs_badblocks_count;
339 int fs_sockets_count;
345 int fs_ext_attr_inodes;
346 int fs_ext_attr_blocks;
351 * For the use of callers of the e2fsck functions; not used by
352 * e2fsck functions themselves.
357 /* Used by the region allocation code */
358 typedef __u32 region_addr_t;
359 typedef struct region_struct *region_t;
362 * Procedure declarations
365 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
368 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
371 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
372 ext2_ino_t ino, char *buf);
375 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
376 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
377 int num, int gauranteed_size);
378 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
379 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
383 static void e2fsck_rehash_directories(e2fsck_t ctx);
386 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
387 const char *description);
388 static int ask(e2fsck_t ctx, const char * string, int def);
389 static void e2fsck_read_bitmaps(e2fsck_t ctx);
390 static void preenhalt(e2fsck_t ctx);
391 #ifdef RESOURCE_TRACK
392 static void print_resource_track(const char *desc,
393 struct resource_track *track);
394 static void init_resource_track(struct resource_track *track);
396 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
397 struct ext2_inode * inode, const char * proc);
398 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
399 struct ext2_inode * inode, const char * proc);
401 static void mtrace_print(char *mesg);
403 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
404 const char *name, io_manager manager);
407 static void e2fsck_clear_progbar(e2fsck_t ctx);
408 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
409 float percent, unsigned int dpynum);
411 * problem.h --- e2fsck problem error codes
414 typedef __u32 problem_t;
416 struct problem_context {
418 ext2_ino_t ino, ino2, dir;
419 struct ext2_inode *inode;
420 struct ext2_dir_entry *dirent;
422 e2_blkcnt_t blkcount;
429 * We define a set of "latch groups"; these are problems which are
430 * handled as a set. The user answers once for a particular latch
433 #define PR_LATCH_MASK 0x0ff0 /* Latch mask */
434 #define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
435 #define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
436 #define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
437 #define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
438 #define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
439 #define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
440 #define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
441 #define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
442 #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
444 #define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
447 * Latch group descriptor flags
449 #define PRL_YES 0x0001 /* Answer yes */
450 #define PRL_NO 0x0002 /* Answer no */
451 #define PRL_LATCHED 0x0004 /* The latch group is latched */
452 #define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
454 #define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
460 /* Block bitmap not in group */
461 #define PR_0_BB_NOT_GROUP 0x000001
463 /* Inode bitmap not in group */
464 #define PR_0_IB_NOT_GROUP 0x000002
466 /* Inode table not in group */
467 #define PR_0_ITABLE_NOT_GROUP 0x000003
469 /* Superblock corrupt */
470 #define PR_0_SB_CORRUPT 0x000004
472 /* Filesystem size is wrong */
473 #define PR_0_FS_SIZE_WRONG 0x000005
475 /* Fragments not supported */
476 #define PR_0_NO_FRAGMENTS 0x000006
478 /* Bad blocks_per_group */
479 #define PR_0_BLOCKS_PER_GROUP 0x000007
481 /* Bad first_data_block */
482 #define PR_0_FIRST_DATA_BLOCK 0x000008
484 /* Adding UUID to filesystem */
485 #define PR_0_ADD_UUID 0x000009
488 #define PR_0_RELOCATE_HINT 0x00000A
490 /* Miscellaneous superblock corruption */
491 #define PR_0_MISC_CORRUPT_SUPER 0x00000B
493 /* Error determing physical device size of filesystem */
494 #define PR_0_GETSIZE_ERROR 0x00000C
496 /* Inode count in the superblock incorrect */
497 #define PR_0_INODE_COUNT_WRONG 0x00000D
499 /* The Hurd does not support the filetype feature */
500 #define PR_0_HURD_CLEAR_FILETYPE 0x00000E
502 /* Journal inode is invalid */
503 #define PR_0_JOURNAL_BAD_INODE 0x00000F
505 /* The external journal has multiple filesystems (which we can't handle yet) */
506 #define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010
508 /* Can't find external journal */
509 #define PR_0_CANT_FIND_JOURNAL 0x000011
511 /* External journal has bad superblock */
512 #define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012
514 /* Superblock has a bad journal UUID */
515 #define PR_0_JOURNAL_BAD_UUID 0x000013
517 /* Journal has an unknown superblock type */
518 #define PR_0_JOURNAL_UNSUPP_SUPER 0x000014
520 /* Journal superblock is corrupt */
521 #define PR_0_JOURNAL_BAD_SUPER 0x000015
523 /* Journal superblock is corrupt */
524 #define PR_0_JOURNAL_HAS_JOURNAL 0x000016
526 /* Superblock has recovery flag set but no journal */
527 #define PR_0_JOURNAL_RECOVER_SET 0x000017
529 /* Journal has data, but recovery flag is clear */
530 #define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018
532 /* Ask if we should clear the journal */
533 #define PR_0_JOURNAL_RESET_JOURNAL 0x000019
535 /* Filesystem revision is 0, but feature flags are set */
536 #define PR_0_FS_REV_LEVEL 0x00001A
538 /* Clearing orphan inode */
539 #define PR_0_ORPHAN_CLEAR_INODE 0x000020
541 /* Illegal block found in orphaned inode */
542 #define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021
544 /* Already cleared block found in orphaned inode */
545 #define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022
547 /* Illegal orphan inode in superblock */
548 #define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023
550 /* Illegal inode in orphaned inode list */
551 #define PR_0_ORPHAN_ILLEGAL_INODE 0x000024
553 /* Journal has unsupported read-only feature - abort */
554 #define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025
556 /* Journal has unsupported incompatible feature - abort */
557 #define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026
559 /* Journal has unsupported version number */
560 #define PR_0_JOURNAL_UNSUPP_VERSION 0x000027
562 /* Moving journal to hidden file */
563 #define PR_0_MOVE_JOURNAL 0x000028
565 /* Error moving journal */
566 #define PR_0_ERR_MOVE_JOURNAL 0x000029
568 /* Clearing V2 journal superblock */
569 #define PR_0_CLEAR_V2_JOURNAL 0x00002A
571 /* Run journal anyway */
572 #define PR_0_JOURNAL_RUN 0x00002B
574 /* Run journal anyway by default */
575 #define PR_0_JOURNAL_RUN_DEFAULT 0x00002C
577 /* Backup journal inode blocks */
578 #define PR_0_BACKUP_JNL 0x00002D
580 /* Reserved blocks w/o resize_inode */
581 #define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E
583 /* Resize_inode not enabled, but resize inode is non-zero */
584 #define PR_0_CLEAR_RESIZE_INODE 0x00002F
586 /* Resize inode invalid */
587 #define PR_0_RESIZE_INODE_INVALID 0x000030
593 /* Pass 1: Checking inodes, blocks, and sizes */
594 #define PR_1_PASS_HEADER 0x010000
596 /* Root directory is not an inode */
597 #define PR_1_ROOT_NO_DIR 0x010001
599 /* Root directory has dtime set */
600 #define PR_1_ROOT_DTIME 0x010002
602 /* Reserved inode has bad mode */
603 #define PR_1_RESERVED_BAD_MODE 0x010003
605 /* Deleted inode has zero dtime */
606 #define PR_1_ZERO_DTIME 0x010004
608 /* Inode in use, but dtime set */
609 #define PR_1_SET_DTIME 0x010005
611 /* Zero-length directory */
612 #define PR_1_ZERO_LENGTH_DIR 0x010006
614 /* Block bitmap conflicts with some other fs block */
615 #define PR_1_BB_CONFLICT 0x010007
617 /* Inode bitmap conflicts with some other fs block */
618 #define PR_1_IB_CONFLICT 0x010008
620 /* Inode table conflicts with some other fs block */
621 #define PR_1_ITABLE_CONFLICT 0x010009
623 /* Block bitmap is on a bad block */
624 #define PR_1_BB_BAD_BLOCK 0x01000A
626 /* Inode bitmap is on a bad block */
627 #define PR_1_IB_BAD_BLOCK 0x01000B
629 /* Inode has incorrect i_size */
630 #define PR_1_BAD_I_SIZE 0x01000C
632 /* Inode has incorrect i_blocks */
633 #define PR_1_BAD_I_BLOCKS 0x01000D
635 /* Illegal block number in inode */
636 #define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
638 /* Block number overlaps fs metadata */
639 #define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F
641 /* Inode has illegal blocks (latch question) */
642 #define PR_1_INODE_BLOCK_LATCH 0x010010
644 /* Too many bad blocks in inode */
645 #define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
647 /* Illegal block number in bad block inode */
648 #define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
650 /* Bad block inode has illegal blocks (latch question) */
651 #define PR_1_INODE_BBLOCK_LATCH 0x010013
653 /* Duplicate or bad blocks in use! */
654 #define PR_1_DUP_BLOCKS_PREENSTOP 0x010014
656 /* Bad block used as bad block indirect block */
657 #define PR_1_BBINODE_BAD_METABLOCK 0x010015
659 /* Inconsistency can't be fixed prompt */
660 #define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
662 /* Bad primary block */
663 #define PR_1_BAD_PRIMARY_BLOCK 0x010017
665 /* Bad primary block prompt */
666 #define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018
668 /* Bad primary superblock */
669 #define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019
671 /* Bad primary block group descriptors */
672 #define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A
674 /* Bad superblock in group */
675 #define PR_1_BAD_SUPERBLOCK 0x01001B
677 /* Bad block group descriptors in group */
678 #define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C
680 /* Block claimed for no reason */
681 #define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D
683 /* Error allocating blocks for relocating metadata */
684 #define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E
686 /* Error allocating block buffer during relocation process */
687 #define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F
689 /* Relocating metadata group information from X to Y */
690 #define PR_1_RELOC_FROM_TO 0x010020
692 /* Relocating metatdata group information to X */
693 #define PR_1_RELOC_TO 0x010021
695 /* Block read error during relocation process */
696 #define PR_1_RELOC_READ_ERR 0x010022
698 /* Block write error during relocation process */
699 #define PR_1_RELOC_WRITE_ERR 0x010023
701 /* Error allocating inode bitmap */
702 #define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024
704 /* Error allocating block bitmap */
705 #define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025
707 /* Error allocating icount structure */
708 #define PR_1_ALLOCATE_ICOUNT 0x010026
710 /* Error allocating dbcount */
711 #define PR_1_ALLOCATE_DBCOUNT 0x010027
713 /* Error while scanning inodes */
714 #define PR_1_ISCAN_ERROR 0x010028
716 /* Error while iterating over blocks */
717 #define PR_1_BLOCK_ITERATE 0x010029
719 /* Error while storing inode count information */
720 #define PR_1_ICOUNT_STORE 0x01002A
722 /* Error while storing directory block information */
723 #define PR_1_ADD_DBLOCK 0x01002B
725 /* Error while reading inode (for clearing) */
726 #define PR_1_READ_INODE 0x01002C
728 /* Suppress messages prompt */
729 #define PR_1_SUPPRESS_MESSAGES 0x01002D
731 /* Imagic flag set on an inode when filesystem doesn't support it */
732 #define PR_1_SET_IMAGIC 0x01002F
734 /* Immutable flag set on a device or socket inode */
735 #define PR_1_SET_IMMUTABLE 0x010030
737 /* Compression flag set on a non-compressed filesystem */
738 #define PR_1_COMPR_SET 0x010031
740 /* Non-zero size on on device, fifo or socket inode */
741 #define PR_1_SET_NONZSIZE 0x010032
743 /* Filesystem revision is 0, but feature flags are set */
744 #define PR_1_FS_REV_LEVEL 0x010033
746 /* Journal inode not in use, needs clearing */
747 #define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034
749 /* Journal inode has wrong mode */
750 #define PR_1_JOURNAL_BAD_MODE 0x010035
752 /* Inode that was part of orphan linked list */
753 #define PR_1_LOW_DTIME 0x010036
755 /* Latch question which asks how to deal with low dtime inodes */
756 #define PR_1_ORPHAN_LIST_REFUGEES 0x010037
758 /* Error allocating refcount structure */
759 #define PR_1_ALLOCATE_REFCOUNT 0x010038
761 /* Error reading Extended Attribute block */
762 #define PR_1_READ_EA_BLOCK 0x010039
764 /* Invalid Extended Attribute block */
765 #define PR_1_BAD_EA_BLOCK 0x01003A
767 /* Error reading Extended Attribute block while fixing refcount -- abort */
768 #define PR_1_EXTATTR_READ_ABORT 0x01003B
770 /* Extended attribute reference count incorrect */
771 #define PR_1_EXTATTR_REFCOUNT 0x01003C
773 /* Error writing Extended Attribute block while fixing refcount */
774 #define PR_1_EXTATTR_WRITE 0x01003D
776 /* Multiple EA blocks not supported */
777 #define PR_1_EA_MULTI_BLOCK 0x01003E
779 /* Error allocating EA region allocation structure */
780 #define PR_1_EA_ALLOC_REGION 0x01003F
782 /* Error EA allocation collision */
783 #define PR_1_EA_ALLOC_COLLISION 0x010040
785 /* Bad extended attribute name */
786 #define PR_1_EA_BAD_NAME 0x010041
788 /* Bad extended attribute value */
789 #define PR_1_EA_BAD_VALUE 0x010042
791 /* Inode too big (latch question) */
792 #define PR_1_INODE_TOOBIG 0x010043
794 /* Directory too big */
795 #define PR_1_TOOBIG_DIR 0x010044
797 /* Regular file too big */
798 #define PR_1_TOOBIG_REG 0x010045
800 /* Symlink too big */
801 #define PR_1_TOOBIG_SYMLINK 0x010046
803 /* INDEX_FL flag set on a non-HTREE filesystem */
804 #define PR_1_HTREE_SET 0x010047
806 /* INDEX_FL flag set on a non-directory */
807 #define PR_1_HTREE_NODIR 0x010048
809 /* Invalid root node in HTREE directory */
810 #define PR_1_HTREE_BADROOT 0x010049
812 /* Unsupported hash version in HTREE directory */
813 #define PR_1_HTREE_HASHV 0x01004A
815 /* Incompatible flag in HTREE root node */
816 #define PR_1_HTREE_INCOMPAT 0x01004B
819 #define PR_1_HTREE_DEPTH 0x01004C
821 /* Bad block has indirect block that conflicts with filesystem block */
822 #define PR_1_BB_FS_BLOCK 0x01004D
824 /* Resize inode failed */
825 #define PR_1_RESIZE_INODE_CREATE 0x01004E
827 /* inode->i_size is too long */
828 #define PR_1_EXTRA_ISIZE 0x01004F
830 /* attribute name is too long */
831 #define PR_1_ATTR_NAME_LEN 0x010050
833 /* wrong EA value offset */
834 #define PR_1_ATTR_VALUE_OFFSET 0x010051
836 /* wrong EA blocknumber */
837 #define PR_1_ATTR_VALUE_BLOCK 0x010052
839 /* wrong EA value size */
840 #define PR_1_ATTR_VALUE_SIZE 0x010053
842 /* wrong EA hash value */
843 #define PR_1_ATTR_HASH 0x010054
849 /* Pass 1B: Rescan for duplicate/bad blocks */
850 #define PR_1B_PASS_HEADER 0x011000
852 /* Duplicate/bad block(s) header */
853 #define PR_1B_DUP_BLOCK_HEADER 0x011001
855 /* Duplicate/bad block(s) in inode */
856 #define PR_1B_DUP_BLOCK 0x011002
858 /* Duplicate/bad block(s) end */
859 #define PR_1B_DUP_BLOCK_END 0x011003
861 /* Error while scanning inodes */
862 #define PR_1B_ISCAN_ERROR 0x011004
864 /* Error allocating inode bitmap */
865 #define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
867 /* Error while iterating over blocks */
868 #define PR_1B_BLOCK_ITERATE 0x0110006
870 /* Error adjusting EA refcount */
871 #define PR_1B_ADJ_EA_REFCOUNT 0x0110007
874 /* Pass 1C: Scan directories for inodes with dup blocks. */
875 #define PR_1C_PASS_HEADER 0x012000
878 /* Pass 1D: Reconciling duplicate blocks */
879 #define PR_1D_PASS_HEADER 0x013000
881 /* File has duplicate blocks */
882 #define PR_1D_DUP_FILE 0x013001
884 /* List of files sharing duplicate blocks */
885 #define PR_1D_DUP_FILE_LIST 0x013002
887 /* File sharing blocks with filesystem metadata */
888 #define PR_1D_SHARE_METADATA 0x013003
890 /* Report of how many duplicate/bad inodes */
891 #define PR_1D_NUM_DUP_INODES 0x013004
893 /* Duplicated blocks already reassigned or cloned. */
894 #define PR_1D_DUP_BLOCKS_DEALT 0x013005
896 /* Clone duplicate/bad blocks? */
897 #define PR_1D_CLONE_QUESTION 0x013006
900 #define PR_1D_DELETE_QUESTION 0x013007
902 /* Couldn't clone file (error) */
903 #define PR_1D_CLONE_ERROR 0x013008
909 /* Pass 2: Checking directory structure */
910 #define PR_2_PASS_HEADER 0x020000
912 /* Bad inode number for '.' */
913 #define PR_2_BAD_INODE_DOT 0x020001
915 /* Directory entry has bad inode number */
916 #define PR_2_BAD_INO 0x020002
918 /* Directory entry has deleted or unused inode */
919 #define PR_2_UNUSED_INODE 0x020003
921 /* Directry entry is link to '.' */
922 #define PR_2_LINK_DOT 0x020004
924 /* Directory entry points to inode now located in a bad block */
925 #define PR_2_BB_INODE 0x020005
927 /* Directory entry contains a link to a directory */
928 #define PR_2_LINK_DIR 0x020006
930 /* Directory entry contains a link to the root directry */
931 #define PR_2_LINK_ROOT 0x020007
933 /* Directory entry has illegal characters in its name */
934 #define PR_2_BAD_NAME 0x020008
936 /* Missing '.' in directory inode */
937 #define PR_2_MISSING_DOT 0x020009
939 /* Missing '..' in directory inode */
940 #define PR_2_MISSING_DOT_DOT 0x02000A
942 /* First entry in directory inode doesn't contain '.' */
943 #define PR_2_1ST_NOT_DOT 0x02000B
945 /* Second entry in directory inode doesn't contain '..' */
946 #define PR_2_2ND_NOT_DOT_DOT 0x02000C
948 /* i_faddr should be zero */
949 #define PR_2_FADDR_ZERO 0x02000D
951 /* i_file_acl should be zero */
952 #define PR_2_FILE_ACL_ZERO 0x02000E
954 /* i_dir_acl should be zero */
955 #define PR_2_DIR_ACL_ZERO 0x02000F
957 /* i_frag should be zero */
958 #define PR_2_FRAG_ZERO 0x020010
960 /* i_fsize should be zero */
961 #define PR_2_FSIZE_ZERO 0x020011
963 /* inode has bad mode */
964 #define PR_2_BAD_MODE 0x020012
966 /* directory corrupted */
967 #define PR_2_DIR_CORRUPTED 0x020013
969 /* filename too long */
970 #define PR_2_FILENAME_LONG 0x020014
972 /* Directory inode has a missing block (hole) */
973 #define PR_2_DIRECTORY_HOLE 0x020015
975 /* '.' is not NULL terminated */
976 #define PR_2_DOT_NULL_TERM 0x020016
978 /* '..' is not NULL terminated */
979 #define PR_2_DOT_DOT_NULL_TERM 0x020017
981 /* Illegal character device in inode */
982 #define PR_2_BAD_CHAR_DEV 0x020018
984 /* Illegal block device in inode */
985 #define PR_2_BAD_BLOCK_DEV 0x020019
987 /* Duplicate '.' entry */
988 #define PR_2_DUP_DOT 0x02001A
990 /* Duplicate '..' entry */
991 #define PR_2_DUP_DOT_DOT 0x02001B
993 /* Internal error: couldn't find dir_info */
994 #define PR_2_NO_DIRINFO 0x02001C
996 /* Final rec_len is wrong */
997 #define PR_2_FINAL_RECLEN 0x02001D
999 /* Error allocating icount structure */
1000 #define PR_2_ALLOCATE_ICOUNT 0x02001E
1002 /* Error iterating over directory blocks */
1003 #define PR_2_DBLIST_ITERATE 0x02001F
1005 /* Error reading directory block */
1006 #define PR_2_READ_DIRBLOCK 0x020020
1008 /* Error writing directory block */
1009 #define PR_2_WRITE_DIRBLOCK 0x020021
1011 /* Error allocating new directory block */
1012 #define PR_2_ALLOC_DIRBOCK 0x020022
1014 /* Error deallocating inode */
1015 #define PR_2_DEALLOC_INODE 0x020023
1017 /* Directory entry for '.' is big. Split? */
1018 #define PR_2_SPLIT_DOT 0x020024
1021 #define PR_2_BAD_FIFO 0x020025
1023 /* Illegal socket */
1024 #define PR_2_BAD_SOCKET 0x020026
1026 /* Directory filetype not set */
1027 #define PR_2_SET_FILETYPE 0x020027
1029 /* Directory filetype incorrect */
1030 #define PR_2_BAD_FILETYPE 0x020028
1032 /* Directory filetype set when it shouldn't be */
1033 #define PR_2_CLEAR_FILETYPE 0x020029
1035 /* Directory filename can't be zero-length */
1036 #define PR_2_NULL_NAME 0x020030
1038 /* Invalid symlink */
1039 #define PR_2_INVALID_SYMLINK 0x020031
1041 /* i_file_acl (extended attribute) is bad */
1042 #define PR_2_FILE_ACL_BAD 0x020032
1044 /* Filesystem contains large files, but has no such flag in sb */
1045 #define PR_2_FEATURE_LARGE_FILES 0x020033
1047 /* Node in HTREE directory not referenced */
1048 #define PR_2_HTREE_NOTREF 0x020034
1050 /* Node in HTREE directory referenced twice */
1051 #define PR_2_HTREE_DUPREF 0x020035
1053 /* Node in HTREE directory has bad min hash */
1054 #define PR_2_HTREE_MIN_HASH 0x020036
1056 /* Node in HTREE directory has bad max hash */
1057 #define PR_2_HTREE_MAX_HASH 0x020037
1059 /* Clear invalid HTREE directory */
1060 #define PR_2_HTREE_CLEAR 0x020038
1062 /* Clear the htree flag forcibly */
1063 /* #define PR_2_HTREE_FCLR 0x020039 */
1065 /* Bad block in htree interior node */
1066 #define PR_2_HTREE_BADBLK 0x02003A
1068 /* Error adjusting EA refcount */
1069 #define PR_2_ADJ_EA_REFCOUNT 0x02003B
1071 /* Invalid HTREE root node */
1072 #define PR_2_HTREE_BAD_ROOT 0x02003C
1074 /* Invalid HTREE limit */
1075 #define PR_2_HTREE_BAD_LIMIT 0x02003D
1077 /* Invalid HTREE count */
1078 #define PR_2_HTREE_BAD_COUNT 0x02003E
1080 /* HTREE interior node has out-of-order hashes in table */
1081 #define PR_2_HTREE_HASH_ORDER 0x02003F
1083 /* Node in HTREE directory has bad depth */
1084 #define PR_2_HTREE_BAD_DEPTH 0x020040
1086 /* Duplicate directory entry found */
1087 #define PR_2_DUPLICATE_DIRENT 0x020041
1089 /* Non-unique filename found */
1090 #define PR_2_NON_UNIQUE_FILE 0x020042
1092 /* Duplicate directory entry found */
1093 #define PR_2_REPORT_DUP_DIRENT 0x020043
1099 /* Pass 3: Checking directory connectivity */
1100 #define PR_3_PASS_HEADER 0x030000
1102 /* Root inode not allocated */
1103 #define PR_3_NO_ROOT_INODE 0x030001
1105 /* No room in lost+found */
1106 #define PR_3_EXPAND_LF_DIR 0x030002
1108 /* Unconnected directory inode */
1109 #define PR_3_UNCONNECTED_DIR 0x030003
1111 /* /lost+found not found */
1112 #define PR_3_NO_LF_DIR 0x030004
1114 /* .. entry is incorrect */
1115 #define PR_3_BAD_DOT_DOT 0x030005
1117 /* Bad or non-existent /lost+found. Cannot reconnect */
1118 #define PR_3_NO_LPF 0x030006
1120 /* Could not expand /lost+found */
1121 #define PR_3_CANT_EXPAND_LPF 0x030007
1123 /* Could not reconnect inode */
1124 #define PR_3_CANT_RECONNECT 0x030008
1126 /* Error while trying to find /lost+found */
1127 #define PR_3_ERR_FIND_LPF 0x030009
1129 /* Error in ext2fs_new_block while creating /lost+found */
1130 #define PR_3_ERR_LPF_NEW_BLOCK 0x03000A
1132 /* Error in ext2fs_new_inode while creating /lost+found */
1133 #define PR_3_ERR_LPF_NEW_INODE 0x03000B
1135 /* Error in ext2fs_new_dir_block while creating /lost+found */
1136 #define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C
1138 /* Error while writing directory block for /lost+found */
1139 #define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D
1141 /* Error while adjusting inode count */
1142 #define PR_3_ADJUST_INODE 0x03000E
1144 /* Couldn't fix parent directory -- error */
1145 #define PR_3_FIX_PARENT_ERR 0x03000F
1147 /* Couldn't fix parent directory -- couldn't find it */
1148 #define PR_3_FIX_PARENT_NOFIND 0x030010
1150 /* Error allocating inode bitmap */
1151 #define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011
1153 /* Error creating root directory */
1154 #define PR_3_CREATE_ROOT_ERROR 0x030012
1156 /* Error creating lost and found directory */
1157 #define PR_3_CREATE_LPF_ERROR 0x030013
1159 /* Root inode is not directory; aborting */
1160 #define PR_3_ROOT_NOT_DIR_ABORT 0x030014
1162 /* Cannot proceed without a root inode. */
1163 #define PR_3_NO_ROOT_INODE_ABORT 0x030015
1165 /* Internal error: couldn't find dir_info */
1166 #define PR_3_NO_DIRINFO 0x030016
1168 /* Lost+found is not a directory */
1169 #define PR_3_LPF_NOTDIR 0x030017
1172 * Pass 3a --- rehashing diretories
1174 /* Pass 3a: Reindexing directories */
1175 #define PR_3A_PASS_HEADER 0x031000
1177 /* Error iterating over directories */
1178 #define PR_3A_OPTIMIZE_ITER 0x031001
1180 /* Error rehash directory */
1181 #define PR_3A_OPTIMIZE_DIR_ERR 0x031002
1183 /* Rehashing dir header */
1184 #define PR_3A_OPTIMIZE_DIR_HEADER 0x031003
1186 /* Rehashing directory %d */
1187 #define PR_3A_OPTIMIZE_DIR 0x031004
1189 /* Rehashing dir end */
1190 #define PR_3A_OPTIMIZE_DIR_END 0x031005
1196 /* Pass 4: Checking reference counts */
1197 #define PR_4_PASS_HEADER 0x040000
1199 /* Unattached zero-length inode */
1200 #define PR_4_ZERO_LEN_INODE 0x040001
1202 /* Unattached inode */
1203 #define PR_4_UNATTACHED_INODE 0x040002
1205 /* Inode ref count wrong */
1206 #define PR_4_BAD_REF_COUNT 0x040003
1208 /* Inconsistent inode count information cached */
1209 #define PR_4_INCONSISTENT_COUNT 0x040004
1215 /* Pass 5: Checking group summary information */
1216 #define PR_5_PASS_HEADER 0x050000
1218 /* Padding at end of inode bitmap is not set. */
1219 #define PR_5_INODE_BMAP_PADDING 0x050001
1221 /* Padding at end of block bitmap is not set. */
1222 #define PR_5_BLOCK_BMAP_PADDING 0x050002
1224 /* Block bitmap differences header */
1225 #define PR_5_BLOCK_BITMAP_HEADER 0x050003
1227 /* Block not used, but marked in bitmap */
1228 #define PR_5_BLOCK_UNUSED 0x050004
1230 /* Block used, but not marked used in bitmap */
1231 #define PR_5_BLOCK_USED 0x050005
1233 /* Block bitmap differences end */
1234 #define PR_5_BLOCK_BITMAP_END 0x050006
1236 /* Inode bitmap differences header */
1237 #define PR_5_INODE_BITMAP_HEADER 0x050007
1239 /* Inode not used, but marked in bitmap */
1240 #define PR_5_INODE_UNUSED 0x050008
1242 /* Inode used, but not marked used in bitmap */
1243 #define PR_5_INODE_USED 0x050009
1245 /* Inode bitmap differences end */
1246 #define PR_5_INODE_BITMAP_END 0x05000A
1248 /* Free inodes count for group wrong */
1249 #define PR_5_FREE_INODE_COUNT_GROUP 0x05000B
1251 /* Directories count for group wrong */
1252 #define PR_5_FREE_DIR_COUNT_GROUP 0x05000C
1254 /* Free inodes count wrong */
1255 #define PR_5_FREE_INODE_COUNT 0x05000D
1257 /* Free blocks count for group wrong */
1258 #define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E
1260 /* Free blocks count wrong */
1261 #define PR_5_FREE_BLOCK_COUNT 0x05000F
1263 /* Programming error: bitmap endpoints don't match */
1264 #define PR_5_BMAP_ENDPOINTS 0x050010
1266 /* Internal error: fudging end of bitmap */
1267 #define PR_5_FUDGE_BITMAP_ERROR 0x050011
1269 /* Error copying in replacement inode bitmap */
1270 #define PR_5_COPY_IBITMAP_ERROR 0x050012
1272 /* Error copying in replacement block bitmap */
1273 #define PR_5_COPY_BBITMAP_ERROR 0x050013
1275 /* Block range not used, but marked in bitmap */
1276 #define PR_5_BLOCK_RANGE_UNUSED 0x050014
1278 /* Block range used, but not marked used in bitmap */
1279 #define PR_5_BLOCK_RANGE_USED 0x050015
1281 /* Inode range not used, but marked in bitmap */
1282 #define PR_5_INODE_RANGE_UNUSED 0x050016
1284 /* Inode rangeused, but not marked used in bitmap */
1285 #define PR_5_INODE_RANGE_USED 0x050017
1288 * Function declarations
1290 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
1291 static int end_problem_latch(e2fsck_t ctx, int mask);
1292 static int set_latch_flags(int mask, int setflags, int clearflags);
1293 static void clear_problem_context(struct problem_context *ctx);
1296 * Dictionary Abstract Data Type
1297 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
1299 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
1307 * Blurb for inclusion into C++ translation units
1310 typedef unsigned long dictcount_t;
1311 #define DICTCOUNT_T_MAX ULONG_MAX
1314 * The dictionary is implemented as a red-black tree
1317 typedef enum { dnode_red, dnode_black } dnode_color_t;
1319 typedef struct dnode_t {
1320 struct dnode_t *dict_left;
1321 struct dnode_t *dict_right;
1322 struct dnode_t *dict_parent;
1323 dnode_color_t dict_color;
1324 const void *dict_key;
1328 typedef int (*dict_comp_t)(const void *, const void *);
1329 typedef void (*dnode_free_t)(dnode_t *);
1331 typedef struct dict_t {
1332 dnode_t dict_nilnode;
1333 dictcount_t dict_nodecount;
1334 dictcount_t dict_maxcount;
1335 dict_comp_t dict_compare;
1336 dnode_free_t dict_freenode;
1340 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
1342 typedef struct dict_load_t {
1343 dict_t *dict_dictptr;
1344 dnode_t dict_nilnode;
1347 #define dict_count(D) ((D)->dict_nodecount)
1348 #define dnode_get(N) ((N)->dict_data)
1349 #define dnode_getkey(N) ((N)->dict_key)
1354 * Compatibility header file for e2fsck which should be included
1355 * instead of linux/jfs.h
1357 * Copyright (C) 2000 Stephen C. Tweedie
1361 * Pull in the definition of the e2fsck context structure
1365 struct buffer_head {
1379 struct ext2_inode i_ext2;
1388 #define K_DEV_JOURNAL 2
1390 typedef struct kdev_s *kdev_t;
1392 #define lock_buffer(bh) do {} while(0)
1393 #define unlock_buffer(bh) do {} while(0)
1394 #define buffer_req(bh) 1
1395 #define do_readahead(journal, start) do {} while(0)
1397 static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
1403 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1406 * We use the standard libext2fs portability tricks for inline
1410 static _INLINE_ kmem_cache_t * do_cache_create(int len)
1412 kmem_cache_t *new_cache;
1414 new_cache = malloc(sizeof(*new_cache));
1416 new_cache->object_length = len;
1420 static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1426 * Now pull in the real linux/jfs.h definitions.
1428 #include "ext2fs/kernel-jbd.h"
1431 * badblocks.c --- replace/append bad blocks to the bad block inode
1434 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
1438 static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
1440 printf(_("Bad block %u out of range; ignored.\n"), blk);
1444 static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1445 int replace_bad_blocks)
1447 ext2_filsys fs = ctx->fs;
1449 badblocks_list bb_list = 0;
1453 e2fsck_read_bitmaps(ctx);
1456 * Make sure the bad block inode is sane. If there are any
1457 * illegal blocks, clear them.
1459 retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
1460 check_bb_inode_blocks, 0);
1462 com_err("ext2fs_block_iterate", retval,
1463 _("while sanity checking the bad blocks inode"));
1468 * If we're appending to the bad blocks inode, read in the
1469 * current bad blocks.
1471 if (!replace_bad_blocks) {
1472 retval = ext2fs_read_bb_inode(fs, &bb_list);
1474 com_err("ext2fs_read_bb_inode", retval,
1475 _("while reading the bad blocks inode"));
1481 * Now read in the bad blocks from the file; if
1482 * bad_blocks_file is null, then try to run the badblocks
1485 if (bad_blocks_file) {
1486 f = fopen(bad_blocks_file, "r");
1488 com_err("read_bad_blocks_file", errno,
1489 _("while trying to open %s"), bad_blocks_file);
1493 sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
1494 (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
1495 (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
1496 fs->device_name, fs->super->s_blocks_count);
1497 f = popen(buf, "r");
1499 com_err("read_bad_blocks_file", errno,
1500 _("while trying popen '%s'"), buf);
1504 retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
1505 if (bad_blocks_file)
1510 com_err("ext2fs_read_bb_FILE", retval,
1511 _("while reading in list of bad blocks from file"));
1516 * Finally, update the bad blocks from the bad_block_map
1518 retval = ext2fs_update_bb_inode(fs, bb_list);
1520 com_err("ext2fs_update_bb_inode", retval,
1521 _("while updating bad block inode"));
1525 ext2fs_badblocks_list_free(bb_list);
1529 ctx->flags |= E2F_FLAG_ABORT;
1534 static int check_bb_inode_blocks(ext2_filsys fs,
1536 int blockcnt EXT2FS_ATTR((unused)),
1537 void *priv_data EXT2FS_ATTR((unused)))
1543 * If the block number is outrageous, clear it and ignore it.
1545 if (*block_nr >= fs->super->s_blocks_count ||
1546 *block_nr < fs->super->s_first_data_block) {
1547 printf(_("Warning illegal block %u found in bad block inode. Cleared.\n"), *block_nr);
1549 return BLOCK_CHANGED;
1556 * Dictionary Abstract Data Type
1561 * These macros provide short convenient names for structure members,
1562 * which are embellished with dict_ prefixes so that they are
1563 * properly confined to the documented namespace. It's legal for a
1564 * program which uses dict to define, for instance, a macro called ``parent''.
1565 * Such a macro would interfere with the dnode_t struct definition.
1566 * In general, highly portable and reusable C modules which expose their
1567 * structures need to confine structure member names to well-defined spaces.
1568 * The resulting identifiers aren't necessarily convenient to use, nor
1569 * readable, in the implementation, however!
1572 #define left dict_left
1573 #define right dict_right
1574 #define parent dict_parent
1575 #define color dict_color
1576 #define key dict_key
1577 #define data dict_data
1579 #define nilnode dict_nilnode
1580 #define maxcount dict_maxcount
1581 #define compare dict_compare
1582 #define dupes dict_dupes
1584 #define dict_root(D) ((D)->nilnode.left)
1585 #define dict_nil(D) (&(D)->nilnode)
1586 #define DICT_DEPTH_MAX 64
1588 static void dnode_free(dnode_t *node);
1591 * Perform a ``left rotation'' adjustment on the tree. The given node P and
1592 * its right child C are rearranged so that the P instead becomes the left
1593 * child of C. The left subtree of C is inherited as the new right subtree
1594 * for P. The ordering of the keys within the tree is thus preserved.
1597 static void rotate_left(dnode_t *upper)
1599 dnode_t *lower, *lowleft, *upparent;
1601 lower = upper->right;
1602 upper->right = lowleft = lower->left;
1603 lowleft->parent = upper;
1605 lower->parent = upparent = upper->parent;
1607 /* don't need to check for root node here because root->parent is
1608 the sentinel nil node, and root->parent->left points back to root */
1610 if (upper == upparent->left) {
1611 upparent->left = lower;
1613 assert (upper == upparent->right);
1614 upparent->right = lower;
1617 lower->left = upper;
1618 upper->parent = lower;
1622 * This operation is the ``mirror'' image of rotate_left. It is
1623 * the same procedure, but with left and right interchanged.
1626 static void rotate_right(dnode_t *upper)
1628 dnode_t *lower, *lowright, *upparent;
1630 lower = upper->left;
1631 upper->left = lowright = lower->right;
1632 lowright->parent = upper;
1634 lower->parent = upparent = upper->parent;
1636 if (upper == upparent->right) {
1637 upparent->right = lower;
1639 assert (upper == upparent->left);
1640 upparent->left = lower;
1643 lower->right = upper;
1644 upper->parent = lower;
1648 * Do a postorder traversal of the tree rooted at the specified
1649 * node and free everything under it. Used by dict_free().
1652 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1656 free_nodes(dict, node->left, nil);
1657 free_nodes(dict, node->right, nil);
1658 dict->dict_freenode(node);
1662 * Verify that the tree contains the given node. This is done by
1663 * traversing all of the nodes and comparing their pointers to the
1664 * given pointer. Returns 1 if the node is found, otherwise
1665 * returns zero. It is intended for debugging purposes.
1668 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1672 || verify_dict_has_node(nil, root->left, node)
1673 || verify_dict_has_node(nil, root->right, node);
1680 * Select a different set of node allocator routines.
1683 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1685 assert (dict_count(dict) == 0);
1686 dict->dict_freenode = fr;
1690 * Free all the nodes in the dictionary by using the dictionary's
1691 * installed free routine. The dictionary is emptied.
1694 static void dict_free_nodes(dict_t *dict)
1696 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1697 free_nodes(dict, root, nil);
1698 dict->dict_nodecount = 0;
1699 dict->nilnode.left = &dict->nilnode;
1700 dict->nilnode.right = &dict->nilnode;
1704 * Initialize a user-supplied dictionary object.
1707 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1709 dict->compare = comp;
1710 dict->dict_freenode = dnode_free;
1711 dict->dict_nodecount = 0;
1712 dict->maxcount = maxcount;
1713 dict->nilnode.left = &dict->nilnode;
1714 dict->nilnode.right = &dict->nilnode;
1715 dict->nilnode.parent = &dict->nilnode;
1716 dict->nilnode.color = dnode_black;
1722 * Locate a node in the dictionary having the given key.
1723 * If the node is not found, a null a pointer is returned (rather than
1724 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
1725 * located node is returned.
1728 static dnode_t *dict_lookup(dict_t *dict, const void *key)
1730 dnode_t *root = dict_root(dict);
1731 dnode_t *nil = dict_nil(dict);
1735 /* simple binary search adapted for trees that contain duplicate keys */
1737 while (root != nil) {
1738 result = dict->compare(key, root->key);
1741 else if (result > 0)
1744 if (!dict->dupes) { /* no duplicates, return match */
1746 } else { /* could be dupes, find leftmost one */
1750 while (root != nil && dict->compare(key, root->key))
1752 } while (root != nil);
1762 * Insert a node into the dictionary. The node should have been
1763 * initialized with a data field. All other fields are ignored.
1764 * The behavior is undefined if the user attempts to insert into
1765 * a dictionary that is already full (for which the dict_isfull()
1766 * function returns true).
1769 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1771 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1772 dnode_t *parent = nil, *uncle, *grandpa;
1777 /* basic binary tree insert */
1779 while (where != nil) {
1781 result = dict->compare(key, where->key);
1782 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
1783 assert (dict->dupes || result != 0);
1785 where = where->left;
1787 where = where->right;
1790 assert (where == nil);
1793 parent->left = node;
1795 parent->right = node;
1797 node->parent = parent;
1801 dict->dict_nodecount++;
1803 /* red black adjustments */
1805 node->color = dnode_red;
1807 while (parent->color == dnode_red) {
1808 grandpa = parent->parent;
1809 if (parent == grandpa->left) {
1810 uncle = grandpa->right;
1811 if (uncle->color == dnode_red) { /* red parent, red uncle */
1812 parent->color = dnode_black;
1813 uncle->color = dnode_black;
1814 grandpa->color = dnode_red;
1816 parent = grandpa->parent;
1817 } else { /* red parent, black uncle */
1818 if (node == parent->right) {
1819 rotate_left(parent);
1821 assert (grandpa == parent->parent);
1822 /* rotation between parent and child preserves grandpa */
1824 parent->color = dnode_black;
1825 grandpa->color = dnode_red;
1826 rotate_right(grandpa);
1829 } else { /* symmetric cases: parent == parent->parent->right */
1830 uncle = grandpa->left;
1831 if (uncle->color == dnode_red) {
1832 parent->color = dnode_black;
1833 uncle->color = dnode_black;
1834 grandpa->color = dnode_red;
1836 parent = grandpa->parent;
1838 if (node == parent->left) {
1839 rotate_right(parent);
1841 assert (grandpa == parent->parent);
1843 parent->color = dnode_black;
1844 grandpa->color = dnode_red;
1845 rotate_left(grandpa);
1851 dict_root(dict)->color = dnode_black;
1856 * Allocate a node using the dictionary's allocator routine, give it
1860 static dnode_t *dnode_init(dnode_t *dnode, void *data)
1863 dnode->parent = NULL;
1865 dnode->right = NULL;
1869 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1871 dnode_t *node = malloc(sizeof(dnode_t));
1874 dnode_init(node, data);
1875 dict_insert(dict, node, key);
1882 * Return the node with the lowest (leftmost) key. If the dictionary is empty
1883 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
1886 static dnode_t *dict_first(dict_t *dict)
1888 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
1891 while ((left = root->left) != nil)
1894 return (root == nil) ? NULL : root;
1898 * Return the given node's successor node---the node which has the
1899 * next key in the the left to right ordering. If the node has
1900 * no successor, a null pointer is returned rather than a pointer to
1904 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
1906 dnode_t *nil = dict_nil(dict), *parent, *left;
1908 if (curr->right != nil) {
1910 while ((left = curr->left) != nil)
1915 parent = curr->parent;
1917 while (parent != nil && curr == parent->right) {
1919 parent = curr->parent;
1922 return (parent == nil) ? NULL : parent;
1926 static void dnode_free(dnode_t *node)
1946 * dirinfo.c --- maintains the directory information table for e2fsck.
1950 * This subroutine is called during pass1 to create a directory info
1951 * entry. During pass1, the passed-in parent is 0; it will get filled
1954 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
1956 struct dir_info *dir;
1958 ext2_ino_t num_dirs;
1960 unsigned long old_size;
1963 printf("add_dir_info for inode %lu...\n", ino);
1965 if (!ctx->dir_info) {
1966 ctx->dir_info_count = 0;
1967 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
1969 num_dirs = 1024; /* Guess */
1970 ctx->dir_info_size = num_dirs + 10;
1971 ctx->dir_info = (struct dir_info *)
1972 e2fsck_allocate_memory(ctx, ctx->dir_info_size
1973 * sizeof (struct dir_info),
1977 if (ctx->dir_info_count >= ctx->dir_info_size) {
1978 old_size = ctx->dir_info_size * sizeof(struct dir_info);
1979 ctx->dir_info_size += 10;
1980 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
1981 sizeof(struct dir_info),
1984 ctx->dir_info_size -= 10;
1990 * Normally, add_dir_info is called with each inode in
1991 * sequential order; but once in a while (like when pass 3
1992 * needs to recreate the root directory or lost+found
1993 * directory) it is called out of order. In those cases, we
1994 * need to move the dir_info entries down to make room, since
1995 * the dir_info array needs to be sorted by inode number for
1996 * get_dir_info()'s sake.
1998 if (ctx->dir_info_count &&
1999 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
2000 for (i = ctx->dir_info_count-1; i > 0; i--)
2001 if (ctx->dir_info[i-1].ino < ino)
2003 dir = &ctx->dir_info[i];
2004 if (dir->ino != ino)
2005 for (j = ctx->dir_info_count++; j > i; j--)
2006 ctx->dir_info[j] = ctx->dir_info[j-1];
2008 dir = &ctx->dir_info[ctx->dir_info_count++];
2011 dir->dotdot = parent;
2012 dir->parent = parent;
2016 * get_dir_info() --- given an inode number, try to find the directory
2017 * information entry for it.
2019 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2024 high = ctx->dir_info_count-1;
2027 if (ino == ctx->dir_info[low].ino)
2028 return &ctx->dir_info[low];
2029 if (ino == ctx->dir_info[high].ino)
2030 return &ctx->dir_info[high];
2032 while (low < high) {
2034 if (mid == low || mid == high)
2036 if (ino == ctx->dir_info[mid].ino)
2037 return &ctx->dir_info[mid];
2038 if (ino < ctx->dir_info[mid].ino)
2047 * Free the dir_info structure when it isn't needed any more.
2049 static void e2fsck_free_dir_info(e2fsck_t ctx)
2051 if (ctx->dir_info) {
2052 ext2fs_free_mem(&ctx->dir_info);
2055 ctx->dir_info_size = 0;
2056 ctx->dir_info_count = 0;
2060 * Return the count of number of directories in the dir_info structure
2062 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2064 return ctx->dir_info_count;
2068 * A simple interator function
2070 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2072 if (*control >= ctx->dir_info_count)
2075 return(ctx->dir_info + (*control)++);
2079 * dirinfo.c --- maintains the directory information table for e2fsck.
2086 * This subroutine is called during pass1 to create a directory info
2087 * entry. During pass1, the passed-in parent is 0; it will get filled
2090 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2092 struct dx_dir_info *dir;
2095 unsigned long old_size;
2098 printf("add_dx_dir_info for inode %lu...\n", ino);
2100 if (!ctx->dx_dir_info) {
2101 ctx->dx_dir_info_count = 0;
2102 ctx->dx_dir_info_size = 100; /* Guess */
2103 ctx->dx_dir_info = (struct dx_dir_info *)
2104 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
2105 * sizeof (struct dx_dir_info),
2109 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
2110 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
2111 ctx->dx_dir_info_size += 10;
2112 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
2113 sizeof(struct dx_dir_info),
2116 ctx->dx_dir_info_size -= 10;
2122 * Normally, add_dx_dir_info is called with each inode in
2123 * sequential order; but once in a while (like when pass 3
2124 * needs to recreate the root directory or lost+found
2125 * directory) it is called out of order. In those cases, we
2126 * need to move the dx_dir_info entries down to make room, since
2127 * the dx_dir_info array needs to be sorted by inode number for
2128 * get_dx_dir_info()'s sake.
2130 if (ctx->dx_dir_info_count &&
2131 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
2132 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
2133 if (ctx->dx_dir_info[i-1].ino < ino)
2135 dir = &ctx->dx_dir_info[i];
2136 if (dir->ino != ino)
2137 for (j = ctx->dx_dir_info_count++; j > i; j--)
2138 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
2140 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
2143 dir->numblocks = num_blocks;
2144 dir->hashversion = 0;
2145 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
2146 * sizeof (struct dx_dirblock_info),
2147 "dx_block info array");
2152 * get_dx_dir_info() --- given an inode number, try to find the directory
2153 * information entry for it.
2155 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2160 high = ctx->dx_dir_info_count-1;
2161 if (!ctx->dx_dir_info)
2163 if (ino == ctx->dx_dir_info[low].ino)
2164 return &ctx->dx_dir_info[low];
2165 if (ino == ctx->dx_dir_info[high].ino)
2166 return &ctx->dx_dir_info[high];
2168 while (low < high) {
2170 if (mid == low || mid == high)
2172 if (ino == ctx->dx_dir_info[mid].ino)
2173 return &ctx->dx_dir_info[mid];
2174 if (ino < ctx->dx_dir_info[mid].ino)
2183 * Free the dx_dir_info structure when it isn't needed any more.
2185 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2188 struct dx_dir_info *dir;
2190 if (ctx->dx_dir_info) {
2191 dir = ctx->dx_dir_info;
2192 for (i=0; i < ctx->dx_dir_info_count; i++) {
2193 if (dir->dx_block) {
2194 ext2fs_free_mem(&dir->dx_block);
2198 ext2fs_free_mem(&ctx->dx_dir_info);
2199 ctx->dx_dir_info = 0;
2201 ctx->dx_dir_info_size = 0;
2202 ctx->dx_dir_info_count = 0;
2206 * A simple interator function
2208 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2210 if (*control >= ctx->dx_dir_info_count)
2213 return(ctx->dx_dir_info + (*control)++);
2216 #endif /* ENABLE_HTREE */
2218 * e2fsck.c - a consistency checker for the new extended file system.
2223 * This function allocates an e2fsck context
2225 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2230 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
2234 memset(context, 0, sizeof(struct e2fsck_struct));
2236 context->process_inode_size = 256;
2237 context->ext_attr_ver = 2;
2243 struct ea_refcount_el {
2248 struct ea_refcount {
2252 struct ea_refcount_el *list;
2255 static void ea_refcount_free(ext2_refcount_t refcount)
2261 ext2fs_free_mem(&refcount->list);
2262 ext2fs_free_mem(&refcount);
2266 * This function resets an e2fsck context; it is called when e2fsck
2267 * needs to be restarted.
2269 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
2272 ctx->lost_and_found = 0;
2273 ctx->bad_lost_and_found = 0;
2274 if (ctx->inode_used_map) {
2275 ext2fs_free_inode_bitmap(ctx->inode_used_map);
2276 ctx->inode_used_map = 0;
2278 if (ctx->inode_dir_map) {
2279 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
2280 ctx->inode_dir_map = 0;
2282 if (ctx->inode_reg_map) {
2283 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
2284 ctx->inode_reg_map = 0;
2286 if (ctx->block_found_map) {
2287 ext2fs_free_block_bitmap(ctx->block_found_map);
2288 ctx->block_found_map = 0;
2290 if (ctx->inode_link_info) {
2291 ext2fs_free_icount(ctx->inode_link_info);
2292 ctx->inode_link_info = 0;
2294 if (ctx->journal_io) {
2295 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2296 io_channel_close(ctx->journal_io);
2297 ctx->journal_io = 0;
2299 if (ctx->fs && ctx->fs->dblist) {
2300 ext2fs_free_dblist(ctx->fs->dblist);
2301 ctx->fs->dblist = 0;
2303 e2fsck_free_dir_info(ctx);
2305 e2fsck_free_dx_dir_info(ctx);
2307 if (ctx->refcount) {
2308 ea_refcount_free(ctx->refcount);
2311 if (ctx->refcount_extra) {
2312 ea_refcount_free(ctx->refcount_extra);
2313 ctx->refcount_extra = 0;
2315 if (ctx->block_dup_map) {
2316 ext2fs_free_block_bitmap(ctx->block_dup_map);
2317 ctx->block_dup_map = 0;
2319 if (ctx->block_ea_map) {
2320 ext2fs_free_block_bitmap(ctx->block_ea_map);
2321 ctx->block_ea_map = 0;
2323 if (ctx->inode_bb_map) {
2324 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
2325 ctx->inode_bb_map = 0;
2327 if (ctx->inode_bad_map) {
2328 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2329 ctx->inode_bad_map = 0;
2331 if (ctx->inode_imagic_map) {
2332 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
2333 ctx->inode_imagic_map = 0;
2335 if (ctx->dirs_to_hash) {
2336 ext2fs_u32_list_free(ctx->dirs_to_hash);
2337 ctx->dirs_to_hash = 0;
2341 * Clear the array of invalid meta-data flags
2343 if (ctx->invalid_inode_bitmap_flag) {
2344 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
2345 ctx->invalid_inode_bitmap_flag = 0;
2347 if (ctx->invalid_block_bitmap_flag) {
2348 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
2349 ctx->invalid_block_bitmap_flag = 0;
2351 if (ctx->invalid_inode_table_flag) {
2352 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
2353 ctx->invalid_inode_table_flag = 0;
2356 /* Clear statistic counters */
2357 ctx->fs_directory_count = 0;
2358 ctx->fs_regular_count = 0;
2359 ctx->fs_blockdev_count = 0;
2360 ctx->fs_chardev_count = 0;
2361 ctx->fs_links_count = 0;
2362 ctx->fs_symlinks_count = 0;
2363 ctx->fs_fast_symlinks_count = 0;
2364 ctx->fs_fifo_count = 0;
2365 ctx->fs_total_count = 0;
2366 ctx->fs_badblocks_count = 0;
2367 ctx->fs_sockets_count = 0;
2368 ctx->fs_ind_count = 0;
2369 ctx->fs_dind_count = 0;
2370 ctx->fs_tind_count = 0;
2371 ctx->fs_fragmented = 0;
2372 ctx->large_files = 0;
2374 /* Reset the superblock to the user's requested value */
2375 ctx->superblock = ctx->use_superblock;
2380 static void e2fsck_free_context(e2fsck_t ctx)
2385 e2fsck_reset_context(ctx);
2387 blkid_put_cache(ctx->blkid);
2389 ext2fs_free_mem(&ctx);
2397 * The strategy we use for keeping track of EA refcounts is as
2398 * follows. We keep a sorted array of first EA blocks and its
2399 * reference counts. Once the refcount has dropped to zero, it is
2400 * removed from the array to save memory space. Once the EA block is
2401 * checked, its bit is set in the block_ea_map bitmap.
2405 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2407 ext2_refcount_t refcount;
2411 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2414 memset(refcount, 0, sizeof(struct ea_refcount));
2418 refcount->size = size;
2419 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2421 printf("Refcount allocated %d entries, %d bytes.\n",
2422 refcount->size, bytes);
2424 retval = ext2fs_get_mem(bytes, &refcount->list);
2427 memset(refcount->list, 0, bytes);
2429 refcount->count = 0;
2430 refcount->cursor = 0;
2436 ea_refcount_free(refcount);
2441 * collapse_refcount() --- go through the refcount array, and get rid
2442 * of any count == zero entries
2444 static void refcount_collapse(ext2_refcount_t refcount)
2447 struct ea_refcount_el *list;
2449 list = refcount->list;
2450 for (i = 0, j = 0; i < refcount->count; i++) {
2451 if (list[i].ea_count) {
2457 #if defined(DEBUG) || defined(TEST_PROGRAM)
2458 printf("Refcount_collapse: size was %d, now %d\n",
2459 refcount->count, j);
2461 refcount->count = j;
2466 * insert_refcount_el() --- Insert a new entry into the sorted list at a
2467 * specified position.
2469 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2472 struct ea_refcount_el *el;
2477 if (refcount->count >= refcount->size) {
2478 new_size = refcount->size + 100;
2480 printf("Reallocating refcount %d entries...\n", new_size);
2482 retval = ext2fs_resize_mem((size_t) refcount->size *
2483 sizeof(struct ea_refcount_el),
2485 sizeof(struct ea_refcount_el),
2489 refcount->size = new_size;
2491 num = (int) refcount->count - pos;
2493 return 0; /* should never happen */
2495 memmove(&refcount->list[pos+1], &refcount->list[pos],
2496 sizeof(struct ea_refcount_el) * num);
2499 el = &refcount->list[pos];
2507 * get_refcount_el() --- given an block number, try to find refcount
2508 * information in the sorted list. If the create flag is set,
2509 * and we can't find an entry, create one in the sorted list.
2511 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2512 blk_t blk, int create)
2516 blk_t lowval, highval;
2518 if (!refcount || !refcount->list)
2522 high = (int) refcount->count-1;
2523 if (create && ((refcount->count == 0) ||
2524 (blk > refcount->list[high].ea_blk))) {
2525 if (refcount->count >= refcount->size)
2526 refcount_collapse(refcount);
2528 return insert_refcount_el(refcount, blk,
2529 (unsigned) refcount->count);
2531 if (refcount->count == 0)
2534 if (refcount->cursor >= refcount->count)
2535 refcount->cursor = 0;
2536 if (blk == refcount->list[refcount->cursor].ea_blk)
2537 return &refcount->list[refcount->cursor++];
2539 printf("Non-cursor get_refcount_el: %u\n", blk);
2541 while (low <= high) {
2548 /* Interpolate for efficiency */
2549 lowval = refcount->list[low].ea_blk;
2550 highval = refcount->list[high].ea_blk;
2554 else if (blk > highval)
2557 range = ((float) (blk - lowval)) /
2559 mid = low + ((int) (range * (high-low)));
2562 if (blk == refcount->list[mid].ea_blk) {
2563 refcount->cursor = mid+1;
2564 return &refcount->list[mid];
2566 if (blk < refcount->list[mid].ea_blk)
2572 * If we need to create a new entry, it should be right at
2573 * low (where high will be left at low-1).
2576 if (refcount->count >= refcount->size) {
2577 refcount_collapse(refcount);
2578 if (refcount->count < refcount->size)
2581 return insert_refcount_el(refcount, blk, low);
2587 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2589 struct ea_refcount_el *el;
2591 el = get_refcount_el(refcount, blk, 1);
2593 return EXT2_ET_NO_MEMORY;
2597 *ret = el->ea_count;
2602 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2604 struct ea_refcount_el *el;
2606 el = get_refcount_el(refcount, blk, 0);
2607 if (!el || el->ea_count == 0)
2608 return EXT2_ET_INVALID_ARGUMENT;
2613 *ret = el->ea_count;
2618 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2620 struct ea_refcount_el *el;
2623 * Get the refcount element
2625 el = get_refcount_el(refcount, blk, count ? 1 : 0);
2627 return count ? EXT2_ET_NO_MEMORY : 0;
2628 el->ea_count = count;
2632 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2634 refcount->cursor = 0;
2638 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2640 struct ea_refcount_el *list;
2643 if (refcount->cursor >= refcount->count)
2645 list = refcount->list;
2646 if (list[refcount->cursor].ea_count) {
2648 *ret = list[refcount->cursor].ea_count;
2649 return list[refcount->cursor++].ea_blk;
2657 * ehandler.c --- handle bad block errors which come up during the
2658 * course of an e2fsck session.
2662 static const char *operation;
2665 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2666 void *data, size_t size EXT2FS_ATTR((unused)),
2667 int actual EXT2FS_ATTR((unused)), errcode_t error)
2671 ext2_filsys fs = (ext2_filsys) channel->app_data;
2674 ctx = (e2fsck_t) fs->priv_data;
2677 * If more than one block was read, try reading each block
2678 * separately. We could use the actual bytes read to figure
2679 * out where to start, but we don't bother.
2683 for (i=0; i < count; i++, p += channel->block_size, block++) {
2684 error = io_channel_read_blk(channel, block,
2692 printf(_("Error reading block %lu (%s) while %s. "), block,
2693 error_message(error), operation);
2695 printf(_("Error reading block %lu (%s). "), block,
2696 error_message(error));
2698 if (ask(ctx, _("Ignore error"), 1)) {
2699 if (ask(ctx, _("Force rewrite"), 1))
2700 io_channel_write_blk(channel, block, 1, data);
2708 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2709 const void *data, size_t size EXT2FS_ATTR((unused)),
2710 int actual EXT2FS_ATTR((unused)), errcode_t error)
2714 ext2_filsys fs = (ext2_filsys) channel->app_data;
2717 ctx = (e2fsck_t) fs->priv_data;
2720 * If more than one block was written, try writing each block
2721 * separately. We could use the actual bytes read to figure
2722 * out where to start, but we don't bother.
2725 p = (const char *) data;
2726 for (i=0; i < count; i++, p += channel->block_size, block++) {
2727 error = io_channel_write_blk(channel, block,
2736 printf(_("Error writing block %lu (%s) while %s. "), block,
2737 error_message(error), operation);
2739 printf(_("Error writing block %lu (%s). "), block,
2740 error_message(error));
2742 if (ask(ctx, _("Ignore error"), 1))
2748 static inline const char *ehandler_operation(const char *op)
2750 const char *ret = operation;
2756 static void ehandler_init(io_channel channel)
2758 channel->read_error = e2fsck_handle_read_error;
2759 channel->write_error = e2fsck_handle_write_error;
2763 * journal.c --- code for handling the "ext3" journal
2765 * Copyright (C) 2000 Andreas Dilger
2766 * Copyright (C) 2000 Theodore Ts'o
2768 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2769 * Copyright (C) 1999 Red Hat Software
2771 * This file may be redistributed under the terms of the
2772 * GNU General Public License version 2 or at your discretion
2773 * any later version.
2776 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2779 #ifdef __CONFIG_JBD_DEBUG__E2FS /* Enabled by configure --enable-jfs-debug */
2780 static int bh_count = 0;
2784 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2785 * This creates a larger static binary, and a smaller binary using
2786 * shared libraries. It's also probably slightly less CPU-efficient,
2787 * which is why it's not on by default. But, it's a good way of
2788 * testing the functions in inode_io.c and fileio.c.
2792 /* Kernel compatibility functions for handling the journal. These allow us
2793 * to use the recovery.c file virtually unchanged from the kernel, so we
2794 * don't have to do much to keep kernel and user recovery in sync.
2796 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2802 struct inode *inode = journal->j_inode;
2811 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2812 &inode->i_ext2, NULL, 0, block, &pblk);
2818 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2820 struct buffer_head *bh;
2822 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2826 jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
2827 (unsigned long) blocknr, blocksize, ++bh_count);
2829 bh->b_ctx = kdev->k_ctx;
2830 if (kdev->k_dev == K_DEV_FS)
2831 bh->b_io = kdev->k_ctx->fs->io;
2833 bh->b_io = kdev->k_ctx->journal_io;
2834 bh->b_size = blocksize;
2835 bh->b_blocknr = blocknr;
2840 static void sync_blockdev(kdev_t kdev)
2844 if (kdev->k_dev == K_DEV_FS)
2845 io = kdev->k_ctx->fs->io;
2847 io = kdev->k_ctx->journal_io;
2849 io_channel_flush(io);
2852 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2855 struct buffer_head *bh;
2857 for (; nr > 0; --nr) {
2859 if (rw == READ && !bh->b_uptodate) {
2860 jfs_debug(3, "reading block %lu/%p\n",
2861 (unsigned long) bh->b_blocknr, (void *) bh);
2862 retval = io_channel_read_blk(bh->b_io,
2866 com_err(bh->b_ctx->device_name, retval,
2867 "while reading block %lu\n",
2868 (unsigned long) bh->b_blocknr);
2873 } else if (rw == WRITE && bh->b_dirty) {
2874 jfs_debug(3, "writing block %lu/%p\n",
2875 (unsigned long) bh->b_blocknr, (void *) bh);
2876 retval = io_channel_write_blk(bh->b_io,
2880 com_err(bh->b_ctx->device_name, retval,
2881 "while writing block %lu\n",
2882 (unsigned long) bh->b_blocknr);
2889 jfs_debug(3, "no-op %s for block %lu\n",
2890 rw == READ ? "read" : "write",
2891 (unsigned long) bh->b_blocknr);
2896 static inline void mark_buffer_dirty(struct buffer_head *bh)
2901 static inline void mark_buffer_clean(struct buffer_head * bh)
2906 static void brelse(struct buffer_head *bh)
2909 ll_rw_block(WRITE, 1, &bh);
2910 jfs_debug(3, "freeing block %lu/%p (total %d)\n",
2911 (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
2912 ext2fs_free_mem(&bh);
2915 static inline int buffer_uptodate(struct buffer_head *bh)
2917 return bh->b_uptodate;
2920 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2922 bh->b_uptodate = val;
2925 static void wait_on_buffer(struct buffer_head *bh)
2927 if (!bh->b_uptodate)
2928 ll_rw_block(READ, 1, &bh);
2932 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2934 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2936 /* if we had an error doing journal recovery, we need a full fsck */
2938 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2939 ext2fs_mark_super_dirty(ctx->fs);
2942 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2944 struct ext2_super_block *sb = ctx->fs->super;
2945 struct ext2_super_block jsuper;
2946 struct problem_context pctx;
2947 struct buffer_head *bh;
2948 struct inode *j_inode = NULL;
2949 struct kdev_s *dev_fs = NULL, *dev_journal;
2950 const char *journal_name = 0;
2951 journal_t *journal = NULL;
2952 errcode_t retval = 0;
2953 io_manager io_ptr = 0;
2954 unsigned long start = 0;
2956 int ext_journal = 0;
2957 int tried_backup_jnl = 0;
2960 clear_problem_context(&pctx);
2962 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2964 return EXT2_ET_NO_MEMORY;
2967 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2969 retval = EXT2_ET_NO_MEMORY;
2972 dev_journal = dev_fs+1;
2974 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2975 dev_fs->k_dev = K_DEV_FS;
2976 dev_journal->k_dev = K_DEV_JOURNAL;
2978 journal->j_dev = dev_journal;
2979 journal->j_fs_dev = dev_fs;
2980 journal->j_inode = NULL;
2981 journal->j_blocksize = ctx->fs->blocksize;
2983 if (uuid_is_null(sb->s_journal_uuid)) {
2984 if (!sb->s_journal_inum)
2985 return EXT2_ET_BAD_INODE_NUM;
2986 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2989 retval = EXT2_ET_NO_MEMORY;
2993 j_inode->i_ctx = ctx;
2994 j_inode->i_ino = sb->s_journal_inum;
2996 if ((retval = ext2fs_read_inode(ctx->fs,
2998 &j_inode->i_ext2))) {
3000 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
3003 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
3004 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
3006 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
3007 j_inode->i_ext2.i_links_count = 1;
3008 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
3011 if (!j_inode->i_ext2.i_links_count ||
3012 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
3013 retval = EXT2_ET_NO_JOURNAL;
3014 goto try_backup_journal;
3016 if (j_inode->i_ext2.i_size / journal->j_blocksize <
3017 JFS_MIN_JOURNAL_BLOCKS) {
3018 retval = EXT2_ET_JOURNAL_TOO_SMALL;
3019 goto try_backup_journal;
3021 for (i=0; i < EXT2_N_BLOCKS; i++) {
3022 blk = j_inode->i_ext2.i_block[i];
3024 if (i < EXT2_NDIR_BLOCKS) {
3025 retval = EXT2_ET_JOURNAL_TOO_SMALL;
3026 goto try_backup_journal;
3030 if (blk < sb->s_first_data_block ||
3031 blk >= sb->s_blocks_count) {
3032 retval = EXT2_ET_BAD_BLOCK_NUM;
3033 goto try_backup_journal;
3036 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
3039 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
3045 io_ptr = inode_io_manager;
3047 journal->j_inode = j_inode;
3048 ctx->journal_io = ctx->fs->io;
3049 if ((retval = journal_bmap(journal, 0, &start)) != 0)
3054 if (!ctx->journal_name) {
3057 uuid_unparse(sb->s_journal_uuid, uuid);
3058 ctx->journal_name = blkid_get_devname(ctx->blkid,
3060 if (!ctx->journal_name)
3061 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
3063 journal_name = ctx->journal_name;
3065 if (!journal_name) {
3066 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
3067 return EXT2_ET_LOAD_EXT_JOURNAL;
3070 jfs_debug(1, "Using journal file %s\n", journal_name);
3071 io_ptr = unix_io_manager;
3075 test_io_backing_manager = io_ptr;
3076 io_ptr = test_io_manager;
3078 #ifndef USE_INODE_IO
3081 retval = io_ptr->open(journal_name, IO_FLAG_RW,
3086 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
3089 if (ctx->fs->blocksize == 1024)
3091 bh = getblk(dev_journal, start, ctx->fs->blocksize);
3093 retval = EXT2_ET_NO_MEMORY;
3096 ll_rw_block(READ, 1, &bh);
3097 if ((retval = bh->b_err) != 0)
3099 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
3102 #ifdef EXT2FS_ENABLE_SWAPFS
3103 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
3104 ext2fs_swap_super(&jsuper);
3106 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
3107 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
3108 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
3109 retval = EXT2_ET_LOAD_EXT_JOURNAL;
3112 /* Make sure the journal UUID is correct */
3113 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
3114 sizeof(jsuper.s_uuid))) {
3115 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
3116 retval = EXT2_ET_LOAD_EXT_JOURNAL;
3120 journal->j_maxlen = jsuper.s_blocks_count;
3124 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
3125 retval = EXT2_ET_NO_MEMORY;
3129 journal->j_sb_buffer = bh;
3130 journal->j_superblock = (journal_superblock_t *)bh->b_data;
3134 ext2fs_free_mem(&j_inode);
3137 *ret_journal = journal;
3142 ext2fs_free_mem(&dev_fs);
3144 ext2fs_free_mem(&j_inode);
3146 ext2fs_free_mem(&journal);
3151 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
3152 struct problem_context *pctx)
3154 struct ext2_super_block *sb = ctx->fs->super;
3155 int recover = ctx->fs->super->s_feature_incompat &
3156 EXT3_FEATURE_INCOMPAT_RECOVER;
3157 int has_journal = ctx->fs->super->s_feature_compat &
3158 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3160 if (has_journal || sb->s_journal_inum) {
3161 /* The journal inode is bogus, remove and force full fsck */
3162 pctx->ino = sb->s_journal_inum;
3163 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
3164 if (has_journal && sb->s_journal_inum)
3165 printf("*** ext3 journal has been deleted - "
3166 "filesystem is now ext2 only ***\n\n");
3167 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3168 sb->s_journal_inum = 0;
3169 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
3170 e2fsck_clear_recover(ctx, 1);
3173 return EXT2_ET_BAD_INODE_NUM;
3174 } else if (recover) {
3175 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
3176 e2fsck_clear_recover(ctx, 1);
3179 return EXT2_ET_UNSUPP_FEATURE;
3184 #define V1_SB_SIZE 0x0024
3185 static void clear_v2_journal_fields(journal_t *journal)
3187 e2fsck_t ctx = journal->j_dev->k_ctx;
3188 struct problem_context pctx;
3190 clear_problem_context(&pctx);
3192 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
3195 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
3196 ctx->fs->blocksize-V1_SB_SIZE);
3197 mark_buffer_dirty(journal->j_sb_buffer);
3201 static errcode_t e2fsck_journal_load(journal_t *journal)
3203 e2fsck_t ctx = journal->j_dev->k_ctx;
3204 journal_superblock_t *jsb;
3205 struct buffer_head *jbh = journal->j_sb_buffer;
3206 struct problem_context pctx;
3208 clear_problem_context(&pctx);
3210 ll_rw_block(READ, 1, &jbh);
3212 com_err(ctx->device_name, jbh->b_err,
3213 _("reading journal superblock\n"));
3217 jsb = journal->j_superblock;
3218 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
3219 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
3220 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3222 switch (ntohl(jsb->s_header.h_blocktype)) {
3223 case JFS_SUPERBLOCK_V1:
3224 journal->j_format_version = 1;
3225 if (jsb->s_feature_compat ||
3226 jsb->s_feature_incompat ||
3227 jsb->s_feature_ro_compat ||
3229 clear_v2_journal_fields(journal);
3232 case JFS_SUPERBLOCK_V2:
3233 journal->j_format_version = 2;
3234 if (ntohl(jsb->s_nr_users) > 1 &&
3235 uuid_is_null(ctx->fs->super->s_journal_uuid))
3236 clear_v2_journal_fields(journal);
3237 if (ntohl(jsb->s_nr_users) > 1) {
3238 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
3239 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3244 * These should never appear in a journal super block, so if
3245 * they do, the journal is badly corrupted.
3247 case JFS_DESCRIPTOR_BLOCK:
3248 case JFS_COMMIT_BLOCK:
3249 case JFS_REVOKE_BLOCK:
3250 return EXT2_ET_CORRUPT_SUPERBLOCK;
3252 /* If we don't understand the superblock major type, but there
3253 * is a magic number, then it is likely to be a new format we
3254 * just don't understand, so leave it alone. */
3256 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3259 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
3260 return EXT2_ET_UNSUPP_FEATURE;
3262 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
3263 return EXT2_ET_RO_UNSUPP_FEATURE;
3265 /* We have now checked whether we know enough about the journal
3266 * format to be able to proceed safely, so any other checks that
3267 * fail we should attempt to recover from. */
3268 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
3269 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3270 _("%s: no valid journal superblock found\n"),
3272 return EXT2_ET_CORRUPT_SUPERBLOCK;
3275 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
3276 journal->j_maxlen = ntohl(jsb->s_maxlen);
3277 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
3278 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3279 _("%s: journal too short\n"),
3281 return EXT2_ET_CORRUPT_SUPERBLOCK;
3284 journal->j_tail_sequence = ntohl(jsb->s_sequence);
3285 journal->j_transaction_sequence = journal->j_tail_sequence;
3286 journal->j_tail = ntohl(jsb->s_start);
3287 journal->j_first = ntohl(jsb->s_first);
3288 journal->j_last = ntohl(jsb->s_maxlen);
3293 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
3304 /* Leave a valid existing V1 superblock signature alone.
3305 * Anything unrecognisable we overwrite with a new V2
3308 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
3309 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
3310 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
3311 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
3314 /* Zero out everything else beyond the superblock header */
3316 p = ((char *) jsb) + sizeof(journal_header_t);
3317 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
3319 jsb->s_blocksize = htonl(ctx->fs->blocksize);
3320 jsb->s_maxlen = htonl(journal->j_maxlen);
3321 jsb->s_first = htonl(1);
3323 /* Initialize the journal sequence number so that there is "no"
3324 * chance we will find old "valid" transactions in the journal.
3325 * This avoids the need to zero the whole journal (slow to do,
3326 * and risky when we are just recovering the filesystem).
3328 uuid_generate(u.uuid);
3329 for (i = 0; i < 4; i ++)
3330 new_seq ^= u.val[i];
3331 jsb->s_sequence = htonl(new_seq);
3333 mark_buffer_dirty(journal->j_sb_buffer);
3334 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
3337 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
3339 struct problem_context *pctx)
3341 struct ext2_super_block *sb = ctx->fs->super;
3342 int recover = ctx->fs->super->s_feature_incompat &
3343 EXT3_FEATURE_INCOMPAT_RECOVER;
3345 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
3346 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
3347 e2fsck_journal_reset_super(ctx, journal->j_superblock,
3349 journal->j_transaction_sequence = 1;
3350 e2fsck_clear_recover(ctx, recover);
3353 return EXT2_ET_CORRUPT_SUPERBLOCK;
3354 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
3355 return EXT2_ET_CORRUPT_SUPERBLOCK;
3360 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
3361 int reset, int drop)
3363 journal_superblock_t *jsb;
3366 mark_buffer_clean(journal->j_sb_buffer);
3367 else if (!(ctx->options & E2F_OPT_READONLY)) {
3368 jsb = journal->j_superblock;
3369 jsb->s_sequence = htonl(journal->j_transaction_sequence);
3371 jsb->s_start = 0; /* this marks the journal as empty */
3372 mark_buffer_dirty(journal->j_sb_buffer);
3374 brelse(journal->j_sb_buffer);
3376 if (ctx->journal_io) {
3377 if (ctx->fs && ctx->fs->io != ctx->journal_io)
3378 io_channel_close(ctx->journal_io);
3379 ctx->journal_io = 0;
3382 #ifndef USE_INODE_IO
3383 if (journal->j_inode)
3384 ext2fs_free_mem(&journal->j_inode);
3386 if (journal->j_fs_dev)
3387 ext2fs_free_mem(&journal->j_fs_dev);
3388 ext2fs_free_mem(&journal);
3392 * This function makes sure that the superblock fields regarding the
3393 * journal are consistent.
3395 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
3397 struct ext2_super_block *sb = ctx->fs->super;
3399 int recover = ctx->fs->super->s_feature_incompat &
3400 EXT3_FEATURE_INCOMPAT_RECOVER;
3401 struct problem_context pctx;
3403 int reset = 0, force_fsck = 0;
3406 /* If we don't have any journal features, don't do anything more */
3407 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3408 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
3409 uuid_is_null(sb->s_journal_uuid))
3412 clear_problem_context(&pctx);
3413 pctx.num = sb->s_journal_inum;
3415 retval = e2fsck_get_journal(ctx, &journal);
3417 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3418 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3419 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3420 (retval == EXT2_ET_NO_JOURNAL))
3421 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3425 retval = e2fsck_journal_load(journal);
3427 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3428 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3429 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3431 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3432 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3434 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3435 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3436 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3438 e2fsck_journal_release(ctx, journal, 0, 1);
3443 * We want to make the flags consistent here. We will not leave with
3444 * needs_recovery set but has_journal clear. We can't get in a loop
3445 * with -y, -n, or -p, only if a user isn't making up their mind.
3448 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3449 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3451 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3453 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3454 goto no_has_journal;
3456 * Need a full fsck if we are releasing a
3457 * journal stored on a reserved inode.
3459 force_fsck = recover ||
3460 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3461 /* Clear all of the journal fields */
3462 sb->s_journal_inum = 0;
3463 sb->s_journal_dev = 0;
3464 memset(sb->s_journal_uuid, 0,
3465 sizeof(sb->s_journal_uuid));
3466 e2fsck_clear_recover(ctx, force_fsck);
3467 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3468 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3469 ext2fs_mark_super_dirty(ctx->fs);
3473 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3474 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3475 journal->j_superblock->s_start != 0) {
3476 /* Print status information */
3477 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3478 if (ctx->superblock)
3479 problem = PR_0_JOURNAL_RUN_DEFAULT;
3481 problem = PR_0_JOURNAL_RUN;
3482 if (fix_problem(ctx, problem, &pctx)) {
3483 ctx->options |= E2F_OPT_FORCE;
3484 sb->s_feature_incompat |=
3485 EXT3_FEATURE_INCOMPAT_RECOVER;
3486 ext2fs_mark_super_dirty(ctx->fs);
3487 } else if (fix_problem(ctx,
3488 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3490 sb->s_state &= ~EXT2_VALID_FS;
3491 ext2fs_mark_super_dirty(ctx->fs);
3494 * If the user answers no to the above question, we
3495 * ignore the fact that journal apparently has data;
3496 * accidentally replaying over valid data would be far
3497 * worse than skipping a questionable recovery.
3499 * XXX should we abort with a fatal error here? What
3500 * will the ext3 kernel code do if a filesystem with
3501 * !NEEDS_RECOVERY but with a non-zero
3502 * journal->j_superblock->s_start is mounted?
3506 e2fsck_journal_release(ctx, journal, reset, 0);
3510 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3515 journal_init_revoke_caches();
3516 retval = e2fsck_get_journal(ctx, &journal);
3520 retval = e2fsck_journal_load(journal);
3524 retval = journal_init_revoke(journal, 1024);
3528 retval = -journal_recover(journal);
3532 if (journal->j_superblock->s_errno) {
3533 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3534 ext2fs_mark_super_dirty(ctx->fs);
3535 journal->j_superblock->s_errno = 0;
3536 mark_buffer_dirty(journal->j_sb_buffer);
3540 journal_destroy_revoke(journal);
3541 journal_destroy_revoke_caches();
3542 e2fsck_journal_release(ctx, journal, 1, 0);
3546 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3548 io_manager io_ptr = ctx->fs->io->manager;
3549 int blocksize = ctx->fs->blocksize;
3550 errcode_t retval, recover_retval;
3552 printf(_("%s: recovering journal\n"), ctx->device_name);
3553 if (ctx->options & E2F_OPT_READONLY) {
3554 printf(_("%s: won't do journal recovery while read-only\n"),
3556 return EXT2_ET_FILE_RO;
3559 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3560 ext2fs_flush(ctx->fs); /* Force out any modifications */
3562 recover_retval = recover_ext3_journal(ctx);
3565 * Reload the filesystem context to get up-to-date data from disk
3566 * because journal recovery will change the filesystem under us.
3568 ext2fs_close(ctx->fs);
3569 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3570 ctx->superblock, blocksize, io_ptr,
3574 com_err(ctx->program_name, retval,
3575 _("while trying to re-open %s"),
3577 fatal_error(ctx, 0);
3579 ctx->fs->priv_data = ctx;
3581 /* Set the superblock flags */
3582 e2fsck_clear_recover(ctx, recover_retval);
3583 return recover_retval;
3587 * This function will move the journal inode from a visible file in
3588 * the filesystem directory hierarchy to the reserved inode if necessary.
3590 static const char * const journal_names[] = {
3591 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3593 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3595 struct ext2_super_block *sb = ctx->fs->super;
3596 struct problem_context pctx;
3597 struct ext2_inode inode;
3598 ext2_filsys fs = ctx->fs;
3601 const char * const * cpp;
3602 int group, mount_flags;
3604 clear_problem_context(&pctx);
3607 * If the filesystem is opened read-only, or there is no
3608 * journal, then do nothing.
3610 if ((ctx->options & E2F_OPT_READONLY) ||
3611 (sb->s_journal_inum == 0) ||
3612 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3616 * Read in the journal inode
3618 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3622 * If it's necessary to backup the journal inode, do so.
3624 if ((sb->s_jnl_backup_type == 0) ||
3625 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3626 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3627 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3628 memcpy(sb->s_jnl_blocks, inode.i_block,
3630 sb->s_jnl_blocks[16] = inode.i_size;
3631 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3632 ext2fs_mark_super_dirty(fs);
3633 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3638 * If the journal is already the hidden inode, then do nothing
3640 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3644 * The journal inode had better have only one link and not be readable.
3646 if (inode.i_links_count != 1)
3650 * If the filesystem is mounted, or we can't tell whether
3651 * or not it's mounted, do nothing.
3653 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3654 if (retval || (mount_flags & EXT2_MF_MOUNTED))
3658 * If we can't find the name of the journal inode, then do
3661 for (cpp = journal_names; *cpp; cpp++) {
3662 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3663 strlen(*cpp), 0, &ino);
3664 if ((retval == 0) && (ino == sb->s_journal_inum))
3670 /* We need the inode bitmap to be loaded */
3671 retval = ext2fs_read_bitmaps(fs);
3676 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3680 * OK, we've done all the checks, let's actually move the
3681 * journal inode. Errors at this point mean we need to force
3682 * an ext2 filesystem check.
3684 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3686 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3688 sb->s_journal_inum = EXT2_JOURNAL_INO;
3689 ext2fs_mark_super_dirty(fs);
3690 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3691 inode.i_links_count = 0;
3692 inode.i_dtime = time(0);
3693 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3696 group = ext2fs_group_of_ino(fs, ino);
3697 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3698 ext2fs_mark_ib_dirty(fs);
3699 fs->group_desc[group].bg_free_inodes_count++;
3700 fs->super->s_free_inodes_count++;
3704 pctx.errcode = retval;
3705 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3706 fs->super->s_state &= ~EXT2_VALID_FS;
3707 ext2fs_mark_super_dirty(fs);
3712 * message.c --- print e2fsck messages (with compression)
3714 * print_e2fsck_message() prints a message to the user, using
3715 * compression techniques and expansions of abbreviations.
3717 * The following % expansions are supported:
3719 * %b <blk> block number
3720 * %B <blkcount> integer
3721 * %c <blk2> block number
3722 * %Di <dirent>->ino inode number
3723 * %Dn <dirent>->name string
3724 * %Dr <dirent>->rec_len
3725 * %Dl <dirent>->name_len
3726 * %Dt <dirent>->filetype
3727 * %d <dir> inode number
3728 * %g <group> integer
3729 * %i <ino> inode number
3730 * %Is <inode> -> i_size
3731 * %IS <inode> -> i_extra_isize
3732 * %Ib <inode> -> i_blocks
3733 * %Il <inode> -> i_links_count
3734 * %Im <inode> -> i_mode
3735 * %IM <inode> -> i_mtime
3736 * %IF <inode> -> i_faddr
3737 * %If <inode> -> i_file_acl
3738 * %Id <inode> -> i_dir_acl
3739 * %Iu <inode> -> i_uid
3740 * %Ig <inode> -> i_gid
3741 * %j <ino2> inode number
3742 * %m <com_err error message>
3744 * %p ext2fs_get_pathname of directory <ino>
3745 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
3746 * the containing directory. (If dirent is NULL
3747 * then return the pathname of directory <ino2>)
3748 * %q ext2fs_get_pathname of directory <dir>
3749 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
3750 * the containing directory.
3751 * %s <str> miscellaneous string
3752 * %S backup superblock
3753 * %X <num> hexadecimal format
3755 * The following '@' expansions are supported:
3757 * @a extended attribute
3758 * @A error allocating
3762 * @C conflicts with some other fs block
3766 * @E Entry '%Dn' in %p (%i)
3768 * @F for @i %i (%Q) is
3770 * @h HTREE directory inode
3788 * This structure defines the abbreviations used by the text strings
3789 * below. The first character in the string is the index letter. An
3790 * abbreviation of the form '@<i>' is expanded by looking up the index
3791 * letter <i> in the table below.
3793 static const char * const abbrevs[] = {
3794 N_("aextended attribute"),
3795 N_("Aerror allocating"),
3799 N_("Cconflicts with some other fs @b"),
3806 N_("E@e '%Dn' in %p (%i)"),
3808 N_("Ffor @i %i (%Q) is"),
3826 * Give more user friendly names to the "special" inodes.
3828 #define num_special_inodes 11
3829 static const char * const special_inode_name[] =
3831 N_("<The NULL inode>"), /* 0 */
3832 N_("<The bad blocks inode>"), /* 1 */
3834 N_("<The ACL index inode>"), /* 3 */
3835 N_("<The ACL data inode>"), /* 4 */
3836 N_("<The boot loader inode>"), /* 5 */
3837 N_("<The undelete directory inode>"), /* 6 */
3838 N_("<The group descriptor inode>"), /* 7 */
3839 N_("<The journal inode>"), /* 8 */
3840 N_("<Reserved inode 9>"), /* 9 */
3841 N_("<Reserved inode 10>"), /* 10 */
3845 * This function does "safe" printing. It will convert non-printable
3846 * ASCII characters using '^' and M- notation.
3848 static void safe_print(const char *cp, int len)
3858 fputs("M-", stdout);
3861 if ((ch < 32) || (ch == 0x7f)) {
3863 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3871 * This function prints a pathname, using the ext2fs_get_pathname
3874 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3879 if (!dir && (ino < num_special_inodes)) {
3880 fputs(_(special_inode_name[ino]), stdout);
3884 retval = ext2fs_get_pathname(fs, dir, ino, &path);
3886 fputs("???", stdout);
3888 safe_print(path, -1);
3889 ext2fs_free_mem(&path);
3893 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3894 struct problem_context *pctx, int first);
3896 * This function handles the '@' expansion. We allow recursive
3897 * expansion; an @ expression can contain further '@' and '%'
3900 static void expand_at_expression(e2fsck_t ctx, char ch,
3901 struct problem_context *pctx,
3904 const char * const *cpp;
3907 /* Search for the abbreviation */
3908 for (cpp = abbrevs; *cpp; cpp++) {
3914 if (*first && islower(*str)) {
3916 fputc(toupper(*str++), stdout);
3918 print_e2fsck_message(ctx, str, pctx, *first);
3924 * This function expands '%IX' expressions
3926 static void expand_inode_expression(char ch,
3927 struct problem_context *ctx)
3929 struct ext2_inode *inode;
3930 struct ext2_inode_large *large_inode;
3935 if (!ctx || !ctx->inode)
3939 large_inode = (struct ext2_inode_large *) inode;
3943 if (LINUX_S_ISDIR(inode->i_mode))
3944 printf("%u", inode->i_size);
3946 #ifdef EXT2_NO_64_TYPE
3947 if (inode->i_size_high)
3948 printf("0x%x%08x", inode->i_size_high,
3951 printf("%u", inode->i_size);
3953 printf("%llu", (inode->i_size |
3954 ((__u64) inode->i_size_high << 32)));
3959 printf("%u", large_inode->i_extra_isize);
3962 printf("%u", inode->i_blocks);
3965 printf("%d", inode->i_links_count);
3968 printf("0%o", inode->i_mode);
3971 /* The diet libc doesn't respect the TZ environemnt variable */
3973 time_str = getenv("TZ");
3976 do_gmt = !strcmp(time_str, "GMT");
3979 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3980 printf("%.24s", time_str);
3983 printf("%u", inode->i_faddr);
3986 printf("%u", inode->i_file_acl);
3989 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3990 inode->i_dir_acl : 0));
3993 printf("%d", (inode->i_uid |
3994 (inode->osd2.linux2.l_i_uid_high << 16)));
3997 printf("%d", (inode->i_gid |
3998 (inode->osd2.linux2.l_i_gid_high << 16)));
4002 printf("%%I%c", ch);
4008 * This function expands '%dX' expressions
4010 static _INLINE_ void expand_dirent_expression(char ch,
4011 struct problem_context *ctx)
4013 struct ext2_dir_entry *dirent;
4016 if (!ctx || !ctx->dirent)
4019 dirent = ctx->dirent;
4023 printf("%u", dirent->inode);
4026 len = dirent->name_len & 0xFF;
4027 if (len > EXT2_NAME_LEN)
4028 len = EXT2_NAME_LEN;
4029 if (len > dirent->rec_len)
4030 len = dirent->rec_len;
4031 safe_print(dirent->name, len);
4034 printf("%u", dirent->rec_len);
4037 printf("%u", dirent->name_len & 0xFF);
4040 printf("%u", dirent->name_len >> 8);
4044 printf("%%D%c", ch);
4049 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
4050 struct problem_context *ctx)
4060 printf("%u", ctx->blk);
4063 #ifdef EXT2_NO_64_TYPE
4064 printf("%d", ctx->blkcount);
4066 printf("%lld", ctx->blkcount);
4070 printf("%u", ctx->blk2);
4073 printf("%u", ctx->dir);
4076 printf("%d", ctx->group);
4079 printf("%u", ctx->ino);
4082 printf("%u", ctx->ino2);
4085 printf("%s", error_message(ctx->errcode));
4088 #ifdef EXT2_NO_64_TYPE
4089 printf("%u", ctx->num);
4091 printf("%llu", ctx->num);
4095 print_pathname(fs, ctx->ino, 0);
4098 print_pathname(fs, ctx->ino2,
4099 ctx->dirent ? ctx->dirent->inode : 0);
4102 print_pathname(fs, ctx->dir, 0);
4105 print_pathname(fs, ctx->dir, ctx->ino);
4108 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4111 printf("%s", ctx->str ? ctx->str : "NULL");
4114 #ifdef EXT2_NO_64_TYPE
4115 printf("0x%x", ctx->num);
4117 printf("0x%llx", ctx->num);
4128 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4129 struct problem_context *pctx, int first)
4131 ext2_filsys fs = ctx->fs;
4135 e2fsck_clear_progbar(ctx);
4136 for (cp = msg; *cp; cp++) {
4139 expand_at_expression(ctx, *cp, pctx, &first);
4140 } else if (cp[0] == '%' && cp[1] == 'I') {
4142 expand_inode_expression(*cp, pctx);
4143 } else if (cp[0] == '%' && cp[1] == 'D') {
4145 expand_dirent_expression(*cp, pctx);
4146 } else if ((cp[0] == '%')) {
4148 expand_percent_expression(fs, *cp, pctx);
4150 for (i=0; cp[i]; i++)
4151 if ((cp[i] == '@') || cp[i] == '%')
4153 printf("%.*s", i, cp);
4162 * region.c --- code which manages allocations within a region.
4166 region_addr_t start;
4168 struct region_el *next;
4171 struct region_struct {
4174 struct region_el *allocated;
4177 static region_t region_create(region_addr_t min, region_addr_t max)
4181 region = malloc(sizeof(struct region_struct));
4184 memset(region, 0, sizeof(struct region_struct));
4190 static void region_free(region_t region)
4192 struct region_el *r, *next;
4194 for (r = region->allocated; r; r = next) {
4198 memset(region, 0, sizeof(struct region_struct));
4202 static int region_allocate(region_t region, region_addr_t start, int n)
4204 struct region_el *r, *new_region, *prev, *next;
4208 if ((start < region->min) || (end > region->max))
4214 * Search through the linked list. If we find that it
4215 * conflicts witih something that's already allocated, return
4216 * 1; if we can find an existing region which we can grow, do
4217 * so. Otherwise, stop when we find the appropriate place
4218 * insert a new region element into the linked list.
4220 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4221 if (((start >= r->start) && (start < r->end)) ||
4222 ((end > r->start) && (end <= r->end)) ||
4223 ((start <= r->start) && (end >= r->end)))
4225 if (end == r->start) {
4229 if (start == r->end) {
4230 if ((next = r->next)) {
4231 if (end > next->start)
4233 if (end == next->start) {
4235 r->next = next->next;
4243 if (start < r->start)
4247 * Insert a new region element structure into the linked list
4249 new_region = malloc(sizeof(struct region_el));
4252 new_region->start = start;
4253 new_region->end = start + n;
4254 new_region->next = r;
4256 prev->next = new_region;
4258 region->allocated = new_region;
4263 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4265 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4266 * and applies the following tests to each inode:
4268 * - The mode field of the inode must be legal.
4269 * - The size and block count fields of the inode are correct.
4270 * - A data block must not be used by another inode
4272 * Pass 1 also gathers the collects the following information:
4274 * - A bitmap of which inodes are in use. (inode_used_map)
4275 * - A bitmap of which inodes are directories. (inode_dir_map)
4276 * - A bitmap of which inodes are regular files. (inode_reg_map)
4277 * - A bitmap of which inodes have bad fields. (inode_bad_map)
4278 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
4279 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
4280 * - A bitmap of which blocks are in use. (block_found_map)
4281 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
4282 * - The data blocks of the directory inodes. (dir_map)
4284 * Pass 1 is designed to stash away enough information so that the
4285 * other passes should not need to read in the inode information
4286 * during the normal course of a filesystem check. (Althogh if an
4287 * inconsistency is detected, other passes may need to read in an
4290 * Note that pass 1B will be invoked if there are any duplicate blocks
4295 static int process_block(ext2_filsys fs, blk_t *blocknr,
4296 e2_blkcnt_t blockcnt, blk_t ref_blk,
4297 int ref_offset, void *priv_data);
4298 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4299 e2_blkcnt_t blockcnt, blk_t ref_blk,
4300 int ref_offset, void *priv_data);
4301 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4303 static void mark_table_blocks(e2fsck_t ctx);
4304 static void alloc_bb_map(e2fsck_t ctx);
4305 static void alloc_imagic_map(e2fsck_t ctx);
4306 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4307 static void handle_fs_bad_blocks(e2fsck_t ctx);
4308 static void process_inodes(e2fsck_t ctx, char *block_buf);
4309 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4310 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4311 dgrp_t group, void * priv_data);
4312 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4313 char *block_buf, int adjust_sign);
4314 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4316 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4317 struct ext2_inode * inode, int bufsize,
4320 struct process_block_struct_1 {
4322 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
4323 fragmented:1, compressed:1, bbcheck:1;
4326 e2_blkcnt_t last_block;
4327 int num_illegal_blocks;
4328 blk_t previous_block;
4329 struct ext2_inode *inode;
4330 struct problem_context *pctx;
4331 ext2fs_block_bitmap fs_meta_blocks;
4335 struct process_inode_block {
4337 struct ext2_inode inode;
4340 struct scan_callback_struct {
4346 * For the inodes to process list.
4348 static struct process_inode_block *inodes_to_process;
4349 static int process_inode_count;
4351 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4352 EXT2_MIN_BLOCK_LOG_SIZE + 1];
4355 * Free all memory allocated by pass1 in preparation for restarting
4358 static void unwind_pass1(void)
4360 ext2fs_free_mem(&inodes_to_process);
4361 inodes_to_process = 0;
4365 * Check to make sure a device inode is real. Returns 1 if the device
4366 * checks out, 0 if not.
4368 * Note: this routine is now also used to check FIFO's and Sockets,
4369 * since they have the same requirement; the i_block fields should be
4373 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4378 * If i_blocks is non-zero, or the index flag is set, then
4379 * this is a bogus device/fifo/socket
4381 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4382 (inode->i_flags & EXT2_INDEX_FL))
4386 * We should be able to do the test below all the time, but
4387 * because the kernel doesn't forcibly clear the device
4388 * inode's additional i_block fields, there are some rare
4389 * occasions when a legitimate device inode will have non-zero
4390 * additional i_block fields. So for now, we only complain
4391 * when the immutable flag is set, which should never happen
4392 * for devices. (And that's when the problem is caused, since
4393 * you can't set or clear immutable flags for devices.) Once
4394 * the kernel has been fixed we can change this...
4396 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4397 for (i=4; i < EXT2_N_BLOCKS; i++)
4398 if (inode->i_block[i])
4405 * Check to make sure a symlink inode is real. Returns 1 if the symlink
4406 * checks out, 0 if not.
4409 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4415 if ((inode->i_size_high || inode->i_size == 0) ||
4416 (inode->i_flags & EXT2_INDEX_FL))
4419 blocks = ext2fs_inode_data_blocks(fs, inode);
4421 if ((inode->i_size >= fs->blocksize) ||
4422 (blocks != fs->blocksize >> 9) ||
4423 (inode->i_block[0] < fs->super->s_first_data_block) ||
4424 (inode->i_block[0] >= fs->super->s_blocks_count))
4427 for (i = 1; i < EXT2_N_BLOCKS; i++)
4428 if (inode->i_block[i])
4431 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4434 len = strnlen(buf, fs->blocksize);
4435 if (len == fs->blocksize)
4438 if (inode->i_size >= sizeof(inode->i_block))
4441 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4442 if (len == sizeof(inode->i_block))
4445 if (len != inode->i_size)
4451 * If the immutable (or append-only) flag is set on the inode, offer
4454 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4455 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4457 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4460 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4463 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4464 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4468 * If device, fifo or socket, check size is zero -- if not offer to
4471 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4473 struct ext2_inode *inode = pctx->inode;
4475 if ((inode->i_size == 0) && (inode->i_size_high == 0))
4478 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4482 inode->i_size_high = 0;
4483 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4486 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4488 struct ext2_super_block *sb = ctx->fs->super;
4489 struct ext2_inode_large *inode;
4490 struct ext2_ext_attr_entry *entry;
4492 int storage_size, remain, offs;
4495 inode = (struct ext2_inode_large *) pctx->inode;
4496 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4497 inode->i_extra_isize;
4498 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4499 inode->i_extra_isize + sizeof(__u32);
4500 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4501 entry = (struct ext2_ext_attr_entry *) start;
4503 /* scan all entry's headers first */
4505 /* take finish entry 0UL into account */
4506 remain = storage_size - sizeof(__u32);
4509 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4511 /* header eats this space */
4512 remain -= sizeof(struct ext2_ext_attr_entry);
4514 /* is attribute name valid? */
4515 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4516 pctx->num = entry->e_name_len;
4517 problem = PR_1_ATTR_NAME_LEN;
4521 /* attribute len eats this space */
4522 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4524 /* check value size */
4525 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4526 pctx->num = entry->e_value_size;
4527 problem = PR_1_ATTR_VALUE_SIZE;
4531 /* check value placement */
4532 if (entry->e_value_offs +
4533 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4534 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4535 pctx->num = entry->e_value_offs;
4536 problem = PR_1_ATTR_VALUE_OFFSET;
4540 /* e_value_block must be 0 in inode's ea */
4541 if (entry->e_value_block != 0) {
4542 pctx->num = entry->e_value_block;
4543 problem = PR_1_ATTR_VALUE_BLOCK;
4547 /* e_hash must be 0 in inode's ea */
4548 if (entry->e_hash != 0) {
4549 pctx->num = entry->e_hash;
4550 problem = PR_1_ATTR_HASH;
4554 remain -= entry->e_value_size;
4555 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4557 entry = EXT2_EXT_ATTR_NEXT(entry);
4561 * it seems like a corruption. it's very unlikely we could repair
4562 * EA(s) in automatic fashion -bzzz
4565 problem = PR_1_ATTR_HASH;
4567 if (problem == 0 || !fix_problem(ctx, problem, pctx))
4570 /* simple remove all possible EA(s) */
4571 *((__u32 *)start) = 0UL;
4572 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4573 EXT2_INODE_SIZE(sb), "pass1");
4576 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4578 struct ext2_super_block *sb = ctx->fs->super;
4579 struct ext2_inode_large *inode;
4583 inode = (struct ext2_inode_large *) pctx->inode;
4584 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4585 /* this isn't large inode. so, nothing to check */
4590 printf("inode #%u, i_extra_size %d\n", pctx->ino,
4591 inode->i_extra_isize);
4593 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4594 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4595 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4597 * For now we will allow i_extra_isize to be 0, but really
4598 * implementations should never allow i_extra_isize to be 0
4600 if (inode->i_extra_isize &&
4601 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4602 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4604 inode->i_extra_isize = min;
4605 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4606 EXT2_INODE_SIZE(sb), "pass1");
4610 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4611 inode->i_extra_isize);
4612 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4613 /* it seems inode has an extended attribute(s) in body */
4614 check_ea_in_inode(ctx, pctx);
4618 static void e2fsck_pass1(e2fsck_t ctx)
4622 ext2_filsys fs = ctx->fs;
4624 struct ext2_inode *inode;
4625 ext2_inode_scan scan;
4627 #ifdef RESOURCE_TRACK
4628 struct resource_track rtrack;
4630 unsigned char frag, fsize;
4631 struct problem_context pctx;
4632 struct scan_callback_struct scan_struct;
4633 struct ext2_super_block *sb = ctx->fs->super;
4635 int busted_fs_time = 0;
4638 #ifdef RESOURCE_TRACK
4639 init_resource_track(&rtrack);
4641 clear_problem_context(&pctx);
4643 if (!(ctx->options & E2F_OPT_PREEN))
4644 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4646 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4647 !(ctx->options & E2F_OPT_NO)) {
4648 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4649 ctx->dirs_to_hash = 0;
4653 mtrace_print("Pass 1");
4656 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4658 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4659 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4660 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4661 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4662 max_sizes = (max_sizes * (1UL << i)) - 1;
4663 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4667 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4670 * Allocate bitmaps structures
4672 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4673 &ctx->inode_used_map);
4676 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4677 ctx->flags |= E2F_FLAG_ABORT;
4680 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4681 _("directory inode map"), &ctx->inode_dir_map);
4684 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4685 ctx->flags |= E2F_FLAG_ABORT;
4688 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4689 _("regular file inode map"), &ctx->inode_reg_map);
4692 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4693 ctx->flags |= E2F_FLAG_ABORT;
4696 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4697 &ctx->block_found_map);
4700 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4701 ctx->flags |= E2F_FLAG_ABORT;
4704 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4705 &ctx->inode_link_info);
4707 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4708 ctx->flags |= E2F_FLAG_ABORT;
4711 inode_size = EXT2_INODE_SIZE(fs->super);
4712 inode = (struct ext2_inode *)
4713 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4715 inodes_to_process = (struct process_inode_block *)
4716 e2fsck_allocate_memory(ctx,
4717 (ctx->process_inode_size *
4718 sizeof(struct process_inode_block)),
4719 "array of inodes to process");
4720 process_inode_count = 0;
4722 pctx.errcode = ext2fs_init_dblist(fs, 0);
4724 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4725 ctx->flags |= E2F_FLAG_ABORT;
4730 * If the last orphan field is set, clear it, since the pass1
4731 * processing will automatically find and clear the orphans.
4732 * In the future, we may want to try using the last_orphan
4733 * linked list ourselves, but for now, we clear it so that the
4734 * ext3 mount code won't get confused.
4736 if (!(ctx->options & E2F_OPT_READONLY)) {
4737 if (fs->super->s_last_orphan) {
4738 fs->super->s_last_orphan = 0;
4739 ext2fs_mark_super_dirty(fs);
4743 mark_table_blocks(ctx);
4744 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4745 "block interate buffer");
4746 e2fsck_use_inode_shortcuts(ctx, 1);
4747 ehandler_operation(_("doing inode scan"));
4748 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4751 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4752 ctx->flags |= E2F_FLAG_ABORT;
4755 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4756 ctx->stashed_inode = inode;
4757 scan_struct.ctx = ctx;
4758 scan_struct.block_buf = block_buf;
4759 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4761 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4763 if (fs->super->s_wtime < fs->super->s_inodes_count)
4767 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4769 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4771 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4772 if (!ctx->inode_bb_map)
4774 ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4775 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4779 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4780 ctx->flags |= E2F_FLAG_ABORT;
4787 ctx->stashed_ino = ino;
4788 if (inode->i_links_count) {
4789 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4790 ino, inode->i_links_count);
4792 pctx.num = inode->i_links_count;
4793 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4794 ctx->flags |= E2F_FLAG_ABORT;
4798 if (ino == EXT2_BAD_INO) {
4799 struct process_block_struct_1 pb;
4801 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4802 &pb.fs_meta_blocks);
4805 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4806 ctx->flags |= E2F_FLAG_ABORT;
4809 pb.ino = EXT2_BAD_INO;
4810 pb.num_blocks = pb.last_block = 0;
4811 pb.num_illegal_blocks = 0;
4812 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4813 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4817 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4818 block_buf, process_bad_block, &pb);
4819 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4821 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4822 ctx->flags |= E2F_FLAG_ABORT;
4826 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4827 ctx->flags |= E2F_FLAG_ABORT;
4830 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4831 clear_problem_context(&pctx);
4833 } else if (ino == EXT2_ROOT_INO) {
4835 * Make sure the root inode is a directory; if
4836 * not, offer to clear it. It will be
4837 * regnerated in pass #3.
4839 if (!LINUX_S_ISDIR(inode->i_mode)) {
4840 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4841 inode->i_dtime = time(0);
4842 inode->i_links_count = 0;
4843 ext2fs_icount_store(ctx->inode_link_info,
4845 e2fsck_write_inode(ctx, ino, inode,
4851 * If dtime is set, offer to clear it. mke2fs
4852 * version 0.2b created filesystems with the
4853 * dtime field set for the root and lost+found
4854 * directories. We won't worry about
4855 * /lost+found, since that can be regenerated
4856 * easily. But we will fix the root directory
4857 * as a special case.
4859 if (inode->i_dtime && inode->i_links_count) {
4860 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4862 e2fsck_write_inode(ctx, ino, inode,
4866 } else if (ino == EXT2_JOURNAL_INO) {
4867 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4868 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4869 if (!LINUX_S_ISREG(inode->i_mode) &&
4870 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4872 inode->i_mode = LINUX_S_IFREG;
4873 e2fsck_write_inode(ctx, ino, inode,
4876 check_blocks(ctx, &pctx, block_buf);
4879 if ((inode->i_links_count || inode->i_blocks ||
4880 inode->i_blocks || inode->i_block[0]) &&
4881 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4883 memset(inode, 0, inode_size);
4884 ext2fs_icount_store(ctx->inode_link_info,
4886 e2fsck_write_inode_full(ctx, ino, inode,
4887 inode_size, "pass1");
4889 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4892 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4893 if (ino == EXT2_BOOT_LOADER_INO) {
4894 if (LINUX_S_ISDIR(inode->i_mode))
4895 problem = PR_1_RESERVED_BAD_MODE;
4896 } else if (ino == EXT2_RESIZE_INO) {
4897 if (inode->i_mode &&
4898 !LINUX_S_ISREG(inode->i_mode))
4899 problem = PR_1_RESERVED_BAD_MODE;
4901 if (inode->i_mode != 0)
4902 problem = PR_1_RESERVED_BAD_MODE;
4905 if (fix_problem(ctx, problem, &pctx)) {
4907 e2fsck_write_inode(ctx, ino, inode,
4911 check_blocks(ctx, &pctx, block_buf);
4915 * Check for inodes who might have been part of the
4916 * orphaned list linked list. They should have gotten
4917 * dealt with by now, unless the list had somehow been
4920 * FIXME: In the future, inodes which are still in use
4921 * (and which are therefore) pending truncation should
4922 * be handled specially. Right now we just clear the
4923 * dtime field, and the normal e2fsck handling of
4924 * inodes where i_size and the inode blocks are
4925 * inconsistent is to fix i_size, instead of releasing
4926 * the extra blocks. This won't catch the inodes that
4927 * was at the end of the orphan list, but it's better
4928 * than nothing. The right answer is that there
4929 * shouldn't be any bugs in the orphan list handling. :-)
4931 if (inode->i_dtime && !busted_fs_time &&
4932 inode->i_dtime < ctx->fs->super->s_inodes_count) {
4933 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4934 inode->i_dtime = inode->i_links_count ?
4936 e2fsck_write_inode(ctx, ino, inode,
4942 * This code assumes that deleted inodes have
4943 * i_links_count set to 0.
4945 if (!inode->i_links_count) {
4946 if (!inode->i_dtime && inode->i_mode) {
4947 if (fix_problem(ctx,
4948 PR_1_ZERO_DTIME, &pctx)) {
4949 inode->i_dtime = time(0);
4950 e2fsck_write_inode(ctx, ino, inode,
4957 * n.b. 0.3c ext2fs code didn't clear i_links_count for
4958 * deleted files. Oops.
4960 * Since all new ext2 implementations get this right,
4961 * we now assume that the case of non-zero
4962 * i_links_count and non-zero dtime means that we
4963 * should keep the file, not delete it.
4966 if (inode->i_dtime) {
4967 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4969 e2fsck_write_inode(ctx, ino, inode, "pass1");
4973 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4974 switch (fs->super->s_creator_os) {
4976 frag = inode->osd2.linux2.l_i_frag;
4977 fsize = inode->osd2.linux2.l_i_fsize;
4980 frag = inode->osd2.hurd2.h_i_frag;
4981 fsize = inode->osd2.hurd2.h_i_fsize;
4984 frag = inode->osd2.masix2.m_i_frag;
4985 fsize = inode->osd2.masix2.m_i_fsize;
4991 if (inode->i_faddr || frag || fsize ||
4992 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4993 mark_inode_bad(ctx, ino);
4994 if (inode->i_flags & EXT2_IMAGIC_FL) {
4996 if (!ctx->inode_imagic_map)
4997 alloc_imagic_map(ctx);
4998 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
5001 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
5002 inode->i_flags &= ~EXT2_IMAGIC_FL;
5003 e2fsck_write_inode(ctx, ino,
5009 check_inode_extra_space(ctx, &pctx);
5011 if (LINUX_S_ISDIR(inode->i_mode)) {
5012 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
5013 e2fsck_add_dir_info(ctx, ino, 0);
5014 ctx->fs_directory_count++;
5015 } else if (LINUX_S_ISREG (inode->i_mode)) {
5016 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
5017 ctx->fs_regular_count++;
5018 } else if (LINUX_S_ISCHR (inode->i_mode) &&
5019 e2fsck_pass1_check_device_inode(fs, inode)) {
5020 check_immutable(ctx, &pctx);
5021 check_size(ctx, &pctx);
5022 ctx->fs_chardev_count++;
5023 } else if (LINUX_S_ISBLK (inode->i_mode) &&
5024 e2fsck_pass1_check_device_inode(fs, inode)) {
5025 check_immutable(ctx, &pctx);
5026 check_size(ctx, &pctx);
5027 ctx->fs_blockdev_count++;
5028 } else if (LINUX_S_ISLNK (inode->i_mode) &&
5029 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
5030 check_immutable(ctx, &pctx);
5031 ctx->fs_symlinks_count++;
5032 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
5033 ctx->fs_fast_symlinks_count++;
5034 check_blocks(ctx, &pctx, block_buf);
5038 else if (LINUX_S_ISFIFO (inode->i_mode) &&
5039 e2fsck_pass1_check_device_inode(fs, inode)) {
5040 check_immutable(ctx, &pctx);
5041 check_size(ctx, &pctx);
5042 ctx->fs_fifo_count++;
5043 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
5044 e2fsck_pass1_check_device_inode(fs, inode)) {
5045 check_immutable(ctx, &pctx);
5046 check_size(ctx, &pctx);
5047 ctx->fs_sockets_count++;
5049 mark_inode_bad(ctx, ino);
5050 if (inode->i_block[EXT2_IND_BLOCK])
5051 ctx->fs_ind_count++;
5052 if (inode->i_block[EXT2_DIND_BLOCK])
5053 ctx->fs_dind_count++;
5054 if (inode->i_block[EXT2_TIND_BLOCK])
5055 ctx->fs_tind_count++;
5056 if (inode->i_block[EXT2_IND_BLOCK] ||
5057 inode->i_block[EXT2_DIND_BLOCK] ||
5058 inode->i_block[EXT2_TIND_BLOCK] ||
5059 inode->i_file_acl) {
5060 inodes_to_process[process_inode_count].ino = ino;
5061 inodes_to_process[process_inode_count].inode = *inode;
5062 process_inode_count++;
5064 check_blocks(ctx, &pctx, block_buf);
5066 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5069 if (process_inode_count >= ctx->process_inode_size) {
5070 process_inodes(ctx, block_buf);
5072 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5076 process_inodes(ctx, block_buf);
5077 ext2fs_close_inode_scan(scan);
5078 ehandler_operation(0);
5081 * If any extended attribute blocks' reference counts need to
5082 * be adjusted, either up (ctx->refcount_extra), or down
5083 * (ctx->refcount), then fix them.
5085 if (ctx->refcount) {
5086 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5087 ea_refcount_free(ctx->refcount);
5090 if (ctx->refcount_extra) {
5091 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5093 ea_refcount_free(ctx->refcount_extra);
5094 ctx->refcount_extra = 0;
5097 if (ctx->invalid_bitmaps)
5098 handle_fs_bad_blocks(ctx);
5100 /* We don't need the block_ea_map any more */
5101 if (ctx->block_ea_map) {
5102 ext2fs_free_block_bitmap(ctx->block_ea_map);
5103 ctx->block_ea_map = 0;
5106 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5107 ext2fs_block_bitmap save_bmap;
5109 save_bmap = fs->block_map;
5110 fs->block_map = ctx->block_found_map;
5111 clear_problem_context(&pctx);
5112 pctx.errcode = ext2fs_create_resize_inode(fs);
5114 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5115 /* Should never get here */
5116 ctx->flags |= E2F_FLAG_ABORT;
5119 fs->block_map = save_bmap;
5120 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5123 if (ctx->flags & E2F_FLAG_RESTART) {
5125 * Only the master copy of the superblock and block
5126 * group descriptors are going to be written during a
5127 * restart, so set the superblock to be used to be the
5128 * master superblock.
5130 ctx->use_superblock = 0;
5135 if (ctx->block_dup_map) {
5136 if (ctx->options & E2F_OPT_PREEN) {
5137 clear_problem_context(&pctx);
5138 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5140 e2fsck_pass1_dupblocks(ctx, block_buf);
5142 ext2fs_free_mem(&inodes_to_process);
5144 e2fsck_use_inode_shortcuts(ctx, 0);
5146 ext2fs_free_mem(&block_buf);
5147 ext2fs_free_mem(&inode);
5149 #ifdef RESOURCE_TRACK
5150 if (ctx->options & E2F_OPT_TIME2) {
5151 e2fsck_clear_progbar(ctx);
5152 print_resource_track(_("Pass 1"), &rtrack);
5158 * When the inode_scan routines call this callback at the end of the
5159 * glock group, call process_inodes.
5161 static errcode_t scan_callback(ext2_filsys fs,
5162 ext2_inode_scan scan EXT2FS_ATTR((unused)),
5163 dgrp_t group, void * priv_data)
5165 struct scan_callback_struct *scan_struct;
5168 scan_struct = (struct scan_callback_struct *) priv_data;
5169 ctx = scan_struct->ctx;
5171 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5174 if ((ctx->progress)(ctx, 1, group+1,
5175 ctx->fs->group_desc_count))
5176 return EXT2_ET_CANCEL_REQUESTED;
5182 * Process the inodes in the "inodes to process" list.
5184 static void process_inodes(e2fsck_t ctx, char *block_buf)
5187 struct ext2_inode *old_stashed_inode;
5188 ext2_ino_t old_stashed_ino;
5189 const char *old_operation;
5191 struct problem_context pctx;
5194 printf("begin process_inodes: ");
5196 if (process_inode_count == 0)
5198 old_operation = ehandler_operation(0);
5199 old_stashed_inode = ctx->stashed_inode;
5200 old_stashed_ino = ctx->stashed_ino;
5201 qsort(inodes_to_process, process_inode_count,
5202 sizeof(struct process_inode_block), process_inode_cmp);
5203 clear_problem_context(&pctx);
5204 for (i=0; i < process_inode_count; i++) {
5205 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5206 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5209 printf("%u ", pctx.ino);
5211 sprintf(buf, _("reading indirect blocks of inode %u"),
5213 ehandler_operation(buf);
5214 check_blocks(ctx, &pctx, block_buf);
5215 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5218 ctx->stashed_inode = old_stashed_inode;
5219 ctx->stashed_ino = old_stashed_ino;
5220 process_inode_count = 0;
5222 printf("end process inodes\n");
5224 ehandler_operation(old_operation);
5227 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5229 const struct process_inode_block *ib_a =
5230 (const struct process_inode_block *) a;
5231 const struct process_inode_block *ib_b =
5232 (const struct process_inode_block *) b;
5235 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5236 ib_b->inode.i_block[EXT2_IND_BLOCK]);
5238 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5243 * Mark an inode as being bad in some what
5245 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5247 struct problem_context pctx;
5249 if (!ctx->inode_bad_map) {
5250 clear_problem_context(&pctx);
5252 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5253 _("bad inode map"), &ctx->inode_bad_map);
5256 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5257 /* Should never get here */
5258 ctx->flags |= E2F_FLAG_ABORT;
5262 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5267 * This procedure will allocate the inode "bb" (badblock) map table
5269 static void alloc_bb_map(e2fsck_t ctx)
5271 struct problem_context pctx;
5273 clear_problem_context(&pctx);
5274 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5275 _("inode in bad block map"),
5276 &ctx->inode_bb_map);
5279 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5280 /* Should never get here */
5281 ctx->flags |= E2F_FLAG_ABORT;
5287 * This procedure will allocate the inode imagic table
5289 static void alloc_imagic_map(e2fsck_t ctx)
5291 struct problem_context pctx;
5293 clear_problem_context(&pctx);
5294 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5295 _("imagic inode map"),
5296 &ctx->inode_imagic_map);
5299 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5300 /* Should never get here */
5301 ctx->flags |= E2F_FLAG_ABORT;
5307 * Marks a block as in use, setting the dup_map if it's been set
5308 * already. Called by process_block and process_bad_block.
5310 * WARNING: Assumes checks have already been done to make sure block
5311 * is valid. This is true in both process_block and process_bad_block.
5313 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5315 struct problem_context pctx;
5317 clear_problem_context(&pctx);
5319 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5320 if (!ctx->block_dup_map) {
5321 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5322 _("multiply claimed block map"),
5323 &ctx->block_dup_map);
5326 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5328 /* Should never get here */
5329 ctx->flags |= E2F_FLAG_ABORT;
5333 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5335 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5340 * Adjust the extended attribute block's reference counts at the end
5341 * of pass 1, either by subtracting out references for EA blocks that
5342 * are still referenced in ctx->refcount, or by adding references for
5343 * EA blocks that had extra references as accounted for in
5344 * ctx->refcount_extra.
5346 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5347 char *block_buf, int adjust_sign)
5349 struct ext2_ext_attr_header *header;
5350 struct problem_context pctx;
5351 ext2_filsys fs = ctx->fs;
5356 clear_problem_context(&pctx);
5358 ea_refcount_intr_begin(refcount);
5360 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5363 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5365 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5368 header = (struct ext2_ext_attr_header *) block_buf;
5369 pctx.blkcount = header->h_refcount;
5370 should_be = header->h_refcount + adjust_sign * count;
5371 pctx.num = should_be;
5372 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5373 header->h_refcount = should_be;
5374 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5377 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5385 * Handle processing the extended attribute blocks
5387 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5390 ext2_filsys fs = ctx->fs;
5391 ext2_ino_t ino = pctx->ino;
5392 struct ext2_inode *inode = pctx->inode;
5395 struct ext2_ext_attr_header *header;
5396 struct ext2_ext_attr_entry *entry;
5400 blk = inode->i_file_acl;
5405 * If the Extended attribute flag isn't set, then a non-zero
5406 * file acl means that the inode is corrupted.
5408 * Or if the extended attribute block is an invalid block,
5409 * then the inode is also corrupted.
5411 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5412 (blk < fs->super->s_first_data_block) ||
5413 (blk >= fs->super->s_blocks_count)) {
5414 mark_inode_bad(ctx, ino);
5418 /* If ea bitmap hasn't been allocated, create it */
5419 if (!ctx->block_ea_map) {
5420 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5421 _("ext attr block map"),
5422 &ctx->block_ea_map);
5423 if (pctx->errcode) {
5425 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5426 ctx->flags |= E2F_FLAG_ABORT;
5431 /* Create the EA refcount structure if necessary */
5432 if (!ctx->refcount) {
5433 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5434 if (pctx->errcode) {
5436 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5437 ctx->flags |= E2F_FLAG_ABORT;
5443 /* Debugging text */
5444 printf("Inode %u has EA block %u\n", ino, blk);
5447 /* Have we seen this EA block before? */
5448 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5449 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5451 /* Ooops, this EA was referenced more than it stated */
5452 if (!ctx->refcount_extra) {
5453 pctx->errcode = ea_refcount_create(0,
5454 &ctx->refcount_extra);
5455 if (pctx->errcode) {
5457 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5458 ctx->flags |= E2F_FLAG_ABORT;
5462 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5467 * OK, we haven't seen this EA block yet. So we need to
5471 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5472 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5474 header = (struct ext2_ext_attr_header *) block_buf;
5475 pctx->blk = inode->i_file_acl;
5476 if (((ctx->ext_attr_ver == 1) &&
5477 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5478 ((ctx->ext_attr_ver == 2) &&
5479 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5480 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5484 if (header->h_blocks != 1) {
5485 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5489 region = region_create(0, fs->blocksize);
5491 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5492 ctx->flags |= E2F_FLAG_ABORT;
5495 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5496 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5500 entry = (struct ext2_ext_attr_entry *)(header+1);
5501 end = block_buf + fs->blocksize;
5502 while ((char *)entry < end && *(__u32 *)entry) {
5503 if (region_allocate(region, (char *)entry - (char *)header,
5504 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5505 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5508 if ((ctx->ext_attr_ver == 1 &&
5509 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5510 (ctx->ext_attr_ver == 2 &&
5511 entry->e_name_index == 0)) {
5512 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5515 if (entry->e_value_block != 0) {
5516 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5519 if (entry->e_value_size &&
5520 region_allocate(region, entry->e_value_offs,
5521 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5522 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5525 entry = EXT2_EXT_ATTR_NEXT(entry);
5527 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5528 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5531 region_free(region);
5533 count = header->h_refcount - 1;
5535 ea_refcount_store(ctx->refcount, blk, count);
5536 mark_block_used(ctx, blk);
5537 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5542 inode->i_file_acl = 0;
5543 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5547 /* Returns 1 if bad htree, 0 if OK */
5548 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5549 ext2_ino_t ino EXT2FS_ATTR((unused)),
5550 struct ext2_inode *inode,
5553 struct ext2_dx_root_info *root;
5554 ext2_filsys fs = ctx->fs;
5558 if ((!LINUX_S_ISDIR(inode->i_mode) &&
5559 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5560 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5561 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5564 blk = inode->i_block[0];
5566 (blk < fs->super->s_first_data_block) ||
5567 (blk >= fs->super->s_blocks_count)) &&
5568 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5571 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5572 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5575 /* XXX should check that beginning matches a directory */
5576 root = (struct ext2_dx_root_info *) (block_buf + 24);
5578 if ((root->reserved_zero || root->info_length < 8) &&
5579 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5582 pctx->num = root->hash_version;
5583 if ((root->hash_version != EXT2_HASH_LEGACY) &&
5584 (root->hash_version != EXT2_HASH_HALF_MD4) &&
5585 (root->hash_version != EXT2_HASH_TEA) &&
5586 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5589 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5590 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5593 pctx->num = root->indirect_levels;
5594 if ((root->indirect_levels > 1) &&
5595 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5602 * This subroutine is called on each inode to account for all of the
5603 * blocks used by that inode.
5605 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5608 ext2_filsys fs = ctx->fs;
5609 struct process_block_struct_1 pb;
5610 ext2_ino_t ino = pctx->ino;
5611 struct ext2_inode *inode = pctx->inode;
5613 int dirty_inode = 0;
5619 pb.num_illegal_blocks = 0;
5620 pb.suppress = 0; pb.clear = 0;
5623 pb.previous_block = 0;
5624 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5625 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5626 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5633 if (inode->i_flags & EXT2_COMPRBLK_FL) {
5634 if (fs->super->s_feature_incompat &
5635 EXT2_FEATURE_INCOMPAT_COMPRESSION)
5638 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5639 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5645 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5648 if (ext2fs_inode_has_valid_blocks(inode))
5649 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5650 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5651 block_buf, process_block, &pb);
5652 end_problem_latch(ctx, PR_LATCH_BLOCK);
5653 end_problem_latch(ctx, PR_LATCH_TOOBIG);
5654 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5657 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5659 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5660 ctx->fs_fragmented++;
5663 inode->i_links_count = 0;
5664 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5665 inode->i_dtime = time(0);
5667 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5668 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5669 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5671 * The inode was probably partially accounted for
5672 * before processing was aborted, so we need to
5673 * restart the pass 1 scan.
5675 ctx->flags |= E2F_FLAG_RESTART;
5679 if (inode->i_flags & EXT2_INDEX_FL) {
5680 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5681 inode->i_flags &= ~EXT2_INDEX_FL;
5685 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5689 if (ctx->dirs_to_hash && pb.is_dir &&
5690 !(inode->i_flags & EXT2_INDEX_FL) &&
5691 ((inode->i_size / fs->blocksize) >= 3))
5692 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5694 if (!pb.num_blocks && pb.is_dir) {
5695 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5696 inode->i_links_count = 0;
5697 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5698 inode->i_dtime = time(0);
5700 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5701 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5702 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5703 ctx->fs_directory_count--;
5708 pb.num_blocks *= (fs->blocksize / 512);
5710 printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5711 ino, inode->i_size, pb.last_block, inode->i_blocks,
5715 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5716 if (nblock > (pb.last_block + 1))
5718 else if (nblock < (pb.last_block + 1)) {
5719 if (((pb.last_block + 1) - nblock) >
5720 fs->super->s_prealloc_dir_blocks)
5724 size = EXT2_I_SIZE(inode);
5725 if ((pb.last_block >= 0) &&
5726 (size < (__u64) pb.last_block * fs->blocksize))
5728 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5731 /* i_size for symlinks is checked elsewhere */
5732 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5733 pctx->num = (pb.last_block+1) * fs->blocksize;
5734 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5735 inode->i_size = pctx->num;
5736 if (!LINUX_S_ISDIR(inode->i_mode))
5737 inode->i_size_high = pctx->num >> 32;
5742 if (LINUX_S_ISREG(inode->i_mode) &&
5743 (inode->i_size_high || inode->i_size & 0x80000000UL))
5745 if (pb.num_blocks != inode->i_blocks) {
5746 pctx->num = pb.num_blocks;
5747 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5748 inode->i_blocks = pb.num_blocks;
5755 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5760 * Helper function called by process block when an illegal block is
5761 * found. It returns a description about why the block is illegal
5763 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5767 static char problem[80];
5769 super = fs->super->s_first_data_block;
5770 strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5771 if (block < super) {
5772 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5774 } else if (block >= fs->super->s_blocks_count) {
5775 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5778 for (i = 0; i < fs->group_desc_count; i++) {
5779 if (block == super) {
5780 sprintf(problem, "is the superblock in group %d", i);
5783 if (block > super &&
5784 block <= (super + fs->desc_blocks)) {
5785 sprintf(problem, "is in the group descriptors "
5789 if (block == fs->group_desc[i].bg_block_bitmap) {
5790 sprintf(problem, "is the block bitmap of group %d", i);
5793 if (block == fs->group_desc[i].bg_inode_bitmap) {
5794 sprintf(problem, "is the inode bitmap of group %d", i);
5797 if (block >= fs->group_desc[i].bg_inode_table &&
5798 (block < fs->group_desc[i].bg_inode_table
5799 + fs->inode_blocks_per_group)) {
5800 sprintf(problem, "is in the inode table of group %d",
5804 super += fs->super->s_blocks_per_group;
5811 * This is a helper function for check_blocks().
5813 static int process_block(ext2_filsys fs,
5815 e2_blkcnt_t blockcnt,
5816 blk_t ref_block EXT2FS_ATTR((unused)),
5817 int ref_offset EXT2FS_ATTR((unused)),
5820 struct process_block_struct_1 *p;
5821 struct problem_context *pctx;
5822 blk_t blk = *block_nr;
5827 p = (struct process_block_struct_1 *) priv_data;
5831 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5832 /* todo: Check that the comprblk_fl is high, that the
5833 blkaddr pattern looks right (all non-holes up to
5834 first EXT2FS_COMPRESSED_BLKADDR, then all
5835 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5836 that the feature_incompat bit is high, and that the
5837 inode is a regular file. If we're doing a "full
5838 check" (a concept introduced to e2fsck by e2compr,
5839 meaning that we look at data blocks as well as
5840 metadata) then call some library routine that
5841 checks the compressed data. I'll have to think
5842 about this, because one particularly important
5843 problem to be able to fix is to recalculate the
5844 cluster size if necessary. I think that perhaps
5845 we'd better do most/all e2compr-specific checks
5846 separately, after the non-e2compr checks. If not
5847 doing a full check, it may be useful to test that
5848 the personality is linux; e.g. if it isn't then
5849 perhaps this really is just an illegal block. */
5854 if (p->is_dir == 0) {
5856 * Should never happen, since only directories
5857 * get called with BLOCK_FLAG_HOLE
5860 printf("process_block() called with blk == 0, "
5861 "blockcnt=%d, inode %lu???\n",
5868 if (blockcnt * fs->blocksize < p->inode->i_size) {
5870 printf("Missing block (#%d) in directory inode %lu!\n",
5879 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5884 * Simplistic fragmentation check. We merely require that the
5885 * file be contiguous. (Which can never be true for really
5886 * big files that are greater than a block group.)
5888 if (!HOLE_BLKADDR(p->previous_block)) {
5889 if (p->previous_block+1 != blk)
5892 p->previous_block = blk;
5894 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5895 problem = PR_1_TOOBIG_DIR;
5896 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5897 problem = PR_1_TOOBIG_REG;
5898 if (!p->is_dir && !p->is_reg && blockcnt > 0)
5899 problem = PR_1_TOOBIG_SYMLINK;
5901 if (blk < fs->super->s_first_data_block ||
5902 blk >= fs->super->s_blocks_count)
5903 problem = PR_1_ILLEGAL_BLOCK_NUM;
5906 p->num_illegal_blocks++;
5907 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5908 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5912 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5914 set_latch_flags(PR_LATCH_BLOCK,
5919 pctx->blkcount = blockcnt;
5920 if (fix_problem(ctx, problem, pctx)) {
5921 blk = *block_nr = 0;
5922 ret_code = BLOCK_CHANGED;
5928 if (p->ino == EXT2_RESIZE_INO) {
5930 * The resize inode has already be sanity checked
5931 * during pass #0 (the superblock checks). All we
5932 * have to do is mark the double indirect block as
5933 * being in use; all of the other blocks are handled
5934 * by mark_table_blocks()).
5936 if (blockcnt == BLOCK_COUNT_DIND)
5937 mark_block_used(ctx, blk);
5939 mark_block_used(ctx, blk);
5942 p->last_block = blockcnt;
5944 if (p->is_dir && (blockcnt >= 0)) {
5945 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5947 if (pctx->errcode) {
5949 pctx->num = blockcnt;
5950 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5951 /* Should never get here */
5952 ctx->flags |= E2F_FLAG_ABORT;
5959 static int process_bad_block(ext2_filsys fs,
5961 e2_blkcnt_t blockcnt,
5962 blk_t ref_block EXT2FS_ATTR((unused)),
5963 int ref_offset EXT2FS_ATTR((unused)),
5966 struct process_block_struct_1 *p;
5967 blk_t blk = *block_nr;
5970 struct problem_context *pctx;
5974 * Note: This function processes blocks for the bad blocks
5975 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
5981 p = (struct process_block_struct_1 *) priv_data;
5985 pctx->ino = EXT2_BAD_INO;
5987 pctx->blkcount = blockcnt;
5989 if ((blk < fs->super->s_first_data_block) ||
5990 (blk >= fs->super->s_blocks_count)) {
5991 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5993 return BLOCK_CHANGED;
5999 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
6001 if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
6003 return BLOCK_CHANGED;
6005 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
6008 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
6011 return BLOCK_CHANGED;
6013 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6016 mark_block_used(ctx, blk);
6020 printf ("DEBUG: Marking %u as bad.\n", blk);
6022 ctx->fs_badblocks_count++;
6024 * If the block is not used, then mark it as used and return.
6025 * If it is already marked as found, this must mean that
6026 * there's an overlap between the filesystem table blocks
6027 * (bitmaps and inode table) and the bad block list.
6029 if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
6030 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6034 * Try to find the where the filesystem block was used...
6036 first_block = fs->super->s_first_data_block;
6038 for (i = 0; i < fs->group_desc_count; i++ ) {
6041 if (!ext2fs_bg_has_super(fs, i))
6043 if (blk == first_block) {
6045 if (fix_problem(ctx,
6046 PR_1_BAD_PRIMARY_SUPERBLOCK,
6049 return BLOCK_CHANGED;
6053 fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
6056 if ((blk > first_block) &&
6057 (blk <= first_block + fs->desc_blocks)) {
6059 pctx->blk = *block_nr;
6060 if (fix_problem(ctx,
6061 PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
6063 return BLOCK_CHANGED;
6067 fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6071 if (blk == fs->group_desc[i].bg_block_bitmap) {
6072 if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6073 ctx->invalid_block_bitmap_flag[i]++;
6074 ctx->invalid_bitmaps++;
6078 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6079 if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6080 ctx->invalid_inode_bitmap_flag[i]++;
6081 ctx->invalid_bitmaps++;
6085 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6086 (blk < (fs->group_desc[i].bg_inode_table +
6087 fs->inode_blocks_per_group))) {
6089 * If there are bad blocks in the inode table,
6090 * the inode scan code will try to do
6091 * something reasonable automatically.
6095 first_block += fs->super->s_blocks_per_group;
6098 * If we've gotten to this point, then the only
6099 * possibility is that the bad block inode meta data
6100 * is using a bad block.
6102 if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6103 (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6104 (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6106 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6108 return BLOCK_CHANGED;
6110 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6117 /* Warn user that the block wasn't claimed */
6118 fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6123 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6124 const char *name, int num, blk_t *new_block)
6126 ext2_filsys fs = ctx->fs;
6127 blk_t old_block = *new_block;
6130 struct problem_context pctx;
6132 clear_problem_context(&pctx);
6135 pctx.blk = old_block;
6138 pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6139 first_block + fs->super->s_blocks_per_group,
6140 num, ctx->block_found_map, new_block);
6143 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6144 ext2fs_unmark_valid(fs);
6147 pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6149 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6150 ext2fs_unmark_valid(fs);
6153 ext2fs_mark_super_dirty(fs);
6154 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6155 pctx.blk2 = *new_block;
6156 fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6157 PR_1_RELOC_TO), &pctx);
6159 for (i = 0; i < num; i++) {
6161 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6163 pctx.errcode = io_channel_read_blk(fs->io,
6164 old_block + i, 1, buf);
6166 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6168 memset(buf, 0, fs->blocksize);
6170 pctx.blk = (*new_block) + i;
6171 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6174 fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6176 ext2fs_free_mem(&buf);
6180 * This routine gets called at the end of pass 1 if bad blocks are
6181 * detected in the superblock, group descriptors, inode_bitmaps, or
6182 * block bitmaps. At this point, all of the blocks have been mapped
6183 * out, so we can try to allocate new block(s) to replace the bad
6186 static void handle_fs_bad_blocks(e2fsck_t ctx)
6188 ext2_filsys fs = ctx->fs;
6190 int first_block = fs->super->s_first_data_block;
6192 for (i = 0; i < fs->group_desc_count; i++) {
6193 if (ctx->invalid_block_bitmap_flag[i]) {
6194 new_table_block(ctx, first_block, i, _("block bitmap"),
6195 1, &fs->group_desc[i].bg_block_bitmap);
6197 if (ctx->invalid_inode_bitmap_flag[i]) {
6198 new_table_block(ctx, first_block, i, _("inode bitmap"),
6199 1, &fs->group_desc[i].bg_inode_bitmap);
6201 if (ctx->invalid_inode_table_flag[i]) {
6202 new_table_block(ctx, first_block, i, _("inode table"),
6203 fs->inode_blocks_per_group,
6204 &fs->group_desc[i].bg_inode_table);
6205 ctx->flags |= E2F_FLAG_RESTART;
6207 first_block += fs->super->s_blocks_per_group;
6209 ctx->invalid_bitmaps = 0;
6213 * This routine marks all blocks which are used by the superblock,
6214 * group descriptors, inode bitmaps, and block bitmaps.
6216 static void mark_table_blocks(e2fsck_t ctx)
6218 ext2_filsys fs = ctx->fs;
6222 struct problem_context pctx;
6224 clear_problem_context(&pctx);
6226 block = fs->super->s_first_data_block;
6227 for (i = 0; i < fs->group_desc_count; i++) {
6230 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6233 * Mark the blocks used for the inode table
6235 if (fs->group_desc[i].bg_inode_table) {
6236 for (j = 0, b = fs->group_desc[i].bg_inode_table;
6237 j < fs->inode_blocks_per_group;
6239 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6242 if (fix_problem(ctx,
6243 PR_1_ITABLE_CONFLICT, &pctx)) {
6244 ctx->invalid_inode_table_flag[i]++;
6245 ctx->invalid_bitmaps++;
6248 ext2fs_mark_block_bitmap(ctx->block_found_map,
6255 * Mark block used for the block bitmap
6257 if (fs->group_desc[i].bg_block_bitmap) {
6258 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6259 fs->group_desc[i].bg_block_bitmap)) {
6260 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6261 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6262 ctx->invalid_block_bitmap_flag[i]++;
6263 ctx->invalid_bitmaps++;
6266 ext2fs_mark_block_bitmap(ctx->block_found_map,
6267 fs->group_desc[i].bg_block_bitmap);
6272 * Mark block used for the inode bitmap
6274 if (fs->group_desc[i].bg_inode_bitmap) {
6275 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6276 fs->group_desc[i].bg_inode_bitmap)) {
6277 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6278 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6279 ctx->invalid_inode_bitmap_flag[i]++;
6280 ctx->invalid_bitmaps++;
6283 ext2fs_mark_block_bitmap(ctx->block_found_map,
6284 fs->group_desc[i].bg_inode_bitmap);
6287 block += fs->super->s_blocks_per_group;
6292 * Thes subroutines short circuits ext2fs_get_blocks and
6293 * ext2fs_check_directory; we use them since we already have the inode
6294 * structure, so there's no point in letting the ext2fs library read
6297 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6300 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6303 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6304 return EXT2_ET_CALLBACK_NOTHANDLED;
6306 for (i=0; i < EXT2_N_BLOCKS; i++)
6307 blocks[i] = ctx->stashed_inode->i_block[i];
6311 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6312 struct ext2_inode *inode)
6314 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6316 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6317 return EXT2_ET_CALLBACK_NOTHANDLED;
6318 *inode = *ctx->stashed_inode;
6322 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6323 struct ext2_inode *inode)
6325 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6327 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6328 *ctx->stashed_inode = *inode;
6329 return EXT2_ET_CALLBACK_NOTHANDLED;
6332 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6334 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6336 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6337 return EXT2_ET_CALLBACK_NOTHANDLED;
6339 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6340 return EXT2_ET_NO_DIRECTORY;
6344 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6346 ext2_filsys fs = ctx->fs;
6349 fs->get_blocks = pass1_get_blocks;
6350 fs->check_directory = pass1_check_directory;
6351 fs->read_inode = pass1_read_inode;
6352 fs->write_inode = pass1_write_inode;
6353 ctx->stashed_ino = 0;
6356 fs->check_directory = 0;
6358 fs->write_inode = 0;
6363 * pass1b.c --- Pass #1b of e2fsck
6365 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
6366 * only invoked if pass 1 discovered blocks which are in use by more
6369 * Pass1B scans the data blocks of all the inodes again, generating a
6370 * complete list of duplicate blocks and which inodes have claimed
6373 * Pass1C does a tree-traversal of the filesystem, to determine the
6374 * parent directories of these inodes. This step is necessary so that
6375 * e2fsck can print out the pathnames of affected inodes.
6377 * Pass1D is a reconciliation pass. For each inode with duplicate
6378 * blocks, the user is prompted if s/he would like to clone the file
6379 * (so that the file gets a fresh copy of the duplicated blocks) or
6380 * simply to delete the file.
6385 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6386 #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
6387 #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
6389 /* Define an extension to the ext2 library's block count information */
6390 #define BLOCK_COUNT_EXTATTR (-5)
6394 struct block_el *next;
6399 struct inode_el *next;
6404 struct inode_el *inode_list;
6408 * This structure stores information about a particular inode which
6409 * is sharing blocks with other inodes. This information is collected
6410 * to display to the user, so that the user knows what files he or she
6411 * is dealing with, when trying to decide how to resolve the conflict
6412 * of multiply-claimed blocks.
6417 struct ext2_inode inode;
6418 struct block_el *block_list;
6421 static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
6422 e2_blkcnt_t blockcnt, blk_t ref_blk,
6423 int ref_offset, void *priv_data);
6424 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6425 struct dup_inode *dp, char *block_buf);
6426 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6427 struct dup_inode *dp, char* block_buf);
6428 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6430 static void pass1b(e2fsck_t ctx, char *block_buf);
6431 static void pass1c(e2fsck_t ctx, char *block_buf);
6432 static void pass1d(e2fsck_t ctx, char *block_buf);
6434 static int dup_inode_count = 0;
6436 static dict_t blk_dict, ino_dict;
6438 static ext2fs_inode_bitmap inode_dup_map;
6440 static int dict_int_cmp(const void *a, const void *b)
6451 * Add a duplicate block record
6453 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6454 struct ext2_inode *inode)
6457 struct dup_block *db;
6458 struct dup_inode *di;
6459 struct block_el *blk_el;
6460 struct inode_el *ino_el;
6462 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6464 db = (struct dup_block *) dnode_get(n);
6466 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6467 sizeof(struct dup_block), "duplicate block header");
6470 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6472 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6473 sizeof(struct inode_el), "inode element");
6474 ino_el->inode = ino;
6475 ino_el->next = db->inode_list;
6476 db->inode_list = ino_el;
6479 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6481 di = (struct dup_inode *) dnode_get(n);
6483 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6484 sizeof(struct dup_inode), "duplicate inode header");
6485 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6486 di->num_dupblocks = 0;
6489 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6491 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6492 sizeof(struct block_el), "block element");
6493 blk_el->block = blk;
6494 blk_el->next = di->block_list;
6495 di->block_list = blk_el;
6496 di->num_dupblocks++;
6500 * Free a duplicate inode record
6502 static void inode_dnode_free(dnode_t *node)
6504 struct dup_inode *di;
6505 struct block_el *p, *next;
6507 di = (struct dup_inode *) dnode_get(node);
6508 for (p = di->block_list; p; p = next) {
6516 * Free a duplicate block record
6518 static void block_dnode_free(dnode_t *node)
6520 struct dup_block *db;
6521 struct inode_el *p, *next;
6523 db = (struct dup_block *) dnode_get(node);
6524 for (p = db->inode_list; p; p = next) {
6533 * Main procedure for handling duplicate blocks
6535 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6537 ext2_filsys fs = ctx->fs;
6538 struct problem_context pctx;
6540 clear_problem_context(&pctx);
6542 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6543 _("multiply claimed inode map"), &inode_dup_map);
6545 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6546 ctx->flags |= E2F_FLAG_ABORT;
6550 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6551 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6552 dict_set_allocator(&ino_dict, inode_dnode_free);
6553 dict_set_allocator(&blk_dict, block_dnode_free);
6555 pass1b(ctx, block_buf);
6556 pass1c(ctx, block_buf);
6557 pass1d(ctx, block_buf);
6560 * Time to free all of the accumulated data structures that we
6561 * don't need anymore.
6563 dict_free_nodes(&ino_dict);
6564 dict_free_nodes(&blk_dict);
6568 * Scan the inodes looking for inodes that contain duplicate blocks.
6570 struct process_block_struct_1b {
6574 struct ext2_inode *inode;
6575 struct problem_context *pctx;
6578 static void pass1b(e2fsck_t ctx, char *block_buf)
6580 ext2_filsys fs = ctx->fs;
6582 struct ext2_inode inode;
6583 ext2_inode_scan scan;
6584 struct process_block_struct_1b pb;
6585 struct problem_context pctx;
6587 clear_problem_context(&pctx);
6589 if (!(ctx->options & E2F_OPT_PREEN))
6590 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6591 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6594 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6595 ctx->flags |= E2F_FLAG_ABORT;
6598 ctx->stashed_inode = &inode;
6601 pctx.str = "pass1b";
6603 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6604 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6607 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6608 ctx->flags |= E2F_FLAG_ABORT;
6613 pctx.ino = ctx->stashed_ino = ino;
6614 if ((ino != EXT2_BAD_INO) &&
6615 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6622 if (ext2fs_inode_has_valid_blocks(&inode) ||
6623 (ino == EXT2_BAD_INO))
6624 pctx.errcode = ext2fs_block_iterate2(fs, ino,
6625 0, block_buf, process_pass1b_block, &pb);
6626 if (inode.i_file_acl)
6627 process_pass1b_block(fs, &inode.i_file_acl,
6628 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6629 if (pb.dup_blocks) {
6630 end_problem_latch(ctx, PR_LATCH_DBLOCK);
6631 if (ino >= EXT2_FIRST_INODE(fs->super) ||
6632 ino == EXT2_ROOT_INO)
6636 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6638 ext2fs_close_inode_scan(scan);
6639 e2fsck_use_inode_shortcuts(ctx, 0);
6642 static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)),
6644 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
6645 blk_t ref_blk EXT2FS_ATTR((unused)),
6646 int ref_offset EXT2FS_ATTR((unused)),
6649 struct process_block_struct_1b *p;
6652 if (HOLE_BLKADDR(*block_nr))
6654 p = (struct process_block_struct_1b *) priv_data;
6657 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6660 /* OK, this is a duplicate block */
6661 if (p->ino != EXT2_BAD_INO) {
6662 p->pctx->blk = *block_nr;
6663 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6666 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6668 add_dupe(ctx, p->ino, *block_nr, p->inode);
6674 * Pass 1c: Scan directories for inodes with duplicate blocks. This
6675 * is used so that we can print pathnames when prompting the user for
6678 struct search_dir_struct {
6680 ext2_ino_t first_inode;
6681 ext2_ino_t max_inode;
6684 static int search_dirent_proc(ext2_ino_t dir, int entry,
6685 struct ext2_dir_entry *dirent,
6686 int offset EXT2FS_ATTR((unused)),
6687 int blocksize EXT2FS_ATTR((unused)),
6688 char *buf EXT2FS_ATTR((unused)),
6691 struct search_dir_struct *sd;
6692 struct dup_inode *p;
6695 sd = (struct search_dir_struct *) priv_data;
6697 if (dirent->inode > sd->max_inode)
6698 /* Should abort this inode, but not everything */
6701 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6702 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6705 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6708 p = (struct dup_inode *) dnode_get(n);
6712 return(sd->count ? 0 : DIRENT_ABORT);
6716 static void pass1c(e2fsck_t ctx, char *block_buf)
6718 ext2_filsys fs = ctx->fs;
6719 struct search_dir_struct sd;
6720 struct problem_context pctx;
6722 clear_problem_context(&pctx);
6724 if (!(ctx->options & E2F_OPT_PREEN))
6725 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6728 * Search through all directories to translate inodes to names
6729 * (by searching for the containing directory for that inode.)
6731 sd.count = dup_inode_count;
6732 sd.first_inode = EXT2_FIRST_INODE(fs->super);
6733 sd.max_inode = fs->super->s_inodes_count;
6734 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6735 search_dirent_proc, &sd);
6738 static void pass1d(e2fsck_t ctx, char *block_buf)
6740 ext2_filsys fs = ctx->fs;
6741 struct dup_inode *p, *t;
6742 struct dup_block *q;
6743 ext2_ino_t *shared, ino;
6748 struct problem_context pctx;
6753 clear_problem_context(&pctx);
6755 if (!(ctx->options & E2F_OPT_PREEN))
6756 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6757 e2fsck_read_bitmaps(ctx);
6759 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6760 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6761 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6762 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6763 "Shared inode list");
6764 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6765 p = (struct dup_inode *) dnode_get(n);
6768 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6769 if (ino == EXT2_BAD_INO)
6773 * Find all of the inodes which share blocks with this
6774 * one. First we find all of the duplicate blocks
6775 * belonging to this inode, and then search each block
6776 * get the list of inodes, and merge them together.
6778 for (s = p->block_list; s; s = s->next) {
6779 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6781 continue; /* Should never happen... */
6782 q = (struct dup_block *) dnode_get(m);
6785 if (check_if_fs_block(ctx, s->block)) {
6791 * Add all inodes used by this block to the
6792 * shared[] --- which is a unique list, so
6793 * if an inode is already in shared[], don't
6796 for (r = q->inode_list; r; r = r->next) {
6797 if (r->inode == ino)
6799 for (i = 0; i < shared_len; i++)
6800 if (shared[i] == r->inode)
6802 if (i == shared_len) {
6803 shared[shared_len++] = r->inode;
6809 * Report the inode that we are working on
6811 pctx.inode = &p->inode;
6814 pctx.blkcount = p->num_dupblocks;
6815 pctx.num = meta_data ? shared_len+1 : shared_len;
6816 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6821 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6823 for (i = 0; i < shared_len; i++) {
6824 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6826 continue; /* should never happen */
6827 t = (struct dup_inode *) dnode_get(m);
6829 * Report the inode that we are sharing with
6831 pctx.inode = &t->inode;
6832 pctx.ino = shared[i];
6834 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6837 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6840 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6841 pctx.errcode = clone_file(ctx, ino, p, block_buf);
6843 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6847 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6848 delete_file(ctx, ino, p, block_buf);
6850 ext2fs_unmark_valid(fs);
6852 ext2fs_free_mem(&shared);
6856 * Drop the refcount on the dup_block structure, and clear the entry
6857 * in the block_dup_map if appropriate.
6859 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6862 if (p->num_bad <= 0 ||
6863 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6864 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6867 static int delete_file_block(ext2_filsys fs,
6869 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
6870 blk_t ref_block EXT2FS_ATTR((unused)),
6871 int ref_offset EXT2FS_ATTR((unused)),
6874 struct process_block_struct_1b *pb;
6875 struct dup_block *p;
6879 pb = (struct process_block_struct_1b *) priv_data;
6882 if (HOLE_BLKADDR(*block_nr))
6885 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6886 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6888 p = (struct dup_block *) dnode_get(n);
6889 decrement_badcount(ctx, *block_nr, p);
6891 com_err("delete_file_block", 0,
6892 _("internal error; can't find dup_blk for %d\n"),
6895 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6896 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6902 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6903 struct dup_inode *dp, char* block_buf)
6905 ext2_filsys fs = ctx->fs;
6906 struct process_block_struct_1b pb;
6907 struct ext2_inode inode;
6908 struct problem_context pctx;
6911 clear_problem_context(&pctx);
6912 pctx.ino = pb.ino = ino;
6913 pb.dup_blocks = dp->num_dupblocks;
6915 pctx.str = "delete_file";
6917 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6918 if (ext2fs_inode_has_valid_blocks(&inode))
6919 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6920 delete_file_block, &pb);
6922 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6923 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6924 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6925 if (ctx->inode_bad_map)
6926 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6927 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6929 /* Inode may have changed by block_iterate, so reread it */
6930 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6931 inode.i_links_count = 0;
6932 inode.i_dtime = time(0);
6933 if (inode.i_file_acl &&
6934 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6936 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6937 block_buf, -1, &count);
6938 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6943 pctx.blk = inode.i_file_acl;
6944 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6947 * If the count is zero, then arrange to have the
6948 * block deleted. If the block is in the block_dup_map,
6949 * also call delete_file_block since it will take care
6950 * of keeping the accounting straight.
6953 ext2fs_test_block_bitmap(ctx->block_dup_map,
6955 delete_file_block(fs, &inode.i_file_acl,
6956 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6958 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6961 struct clone_struct {
6968 static int clone_file_block(ext2_filsys fs,
6970 e2_blkcnt_t blockcnt,
6971 blk_t ref_block EXT2FS_ATTR((unused)),
6972 int ref_offset EXT2FS_ATTR((unused)),
6975 struct dup_block *p;
6978 struct clone_struct *cs = (struct clone_struct *) priv_data;
6984 if (HOLE_BLKADDR(*block_nr))
6987 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6988 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6990 p = (struct dup_block *) dnode_get(n);
6991 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6994 cs->errcode = retval;
6997 if (cs->dir && (blockcnt >= 0)) {
6998 retval = ext2fs_set_dir_block(fs->dblist,
6999 cs->dir, new_block, blockcnt);
7001 cs->errcode = retval;
7006 printf("Cloning block %u to %u\n", *block_nr,
7009 retval = io_channel_read_blk(fs->io, *block_nr, 1,
7012 cs->errcode = retval;
7015 retval = io_channel_write_blk(fs->io, new_block, 1,
7018 cs->errcode = retval;
7021 decrement_badcount(ctx, *block_nr, p);
7022 *block_nr = new_block;
7023 ext2fs_mark_block_bitmap(ctx->block_found_map,
7025 ext2fs_mark_block_bitmap(fs->block_map, new_block);
7026 return BLOCK_CHANGED;
7028 com_err("clone_file_block", 0,
7029 _("internal error; can't find dup_blk for %d\n"),
7035 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
7036 struct dup_inode *dp, char* block_buf)
7038 ext2_filsys fs = ctx->fs;
7040 struct clone_struct cs;
7041 struct problem_context pctx;
7044 struct inode_el *ino_el;
7045 struct dup_block *db;
7046 struct dup_inode *di;
7048 clear_problem_context(&pctx);
7052 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
7056 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
7060 pctx.str = "clone_file";
7061 if (ext2fs_inode_has_valid_blocks(&dp->inode))
7062 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7063 clone_file_block, &cs);
7064 ext2fs_mark_bb_dirty(fs);
7066 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7067 retval = pctx.errcode;
7071 com_err("clone_file", cs.errcode,
7072 _("returned from clone_file_block"));
7073 retval = cs.errcode;
7076 /* The inode may have changed on disk, so we have to re-read it */
7077 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7078 blk = dp->inode.i_file_acl;
7079 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7080 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7082 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7084 * If we cloned the EA block, find all other inodes
7085 * which refered to that EA block, and modify
7086 * them to point to the new EA block.
7088 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7089 db = (struct dup_block *) dnode_get(n);
7090 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7091 if (ino_el->inode == ino)
7093 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7094 di = (struct dup_inode *) dnode_get(n);
7095 if (di->inode.i_file_acl == blk) {
7096 di->inode.i_file_acl = dp->inode.i_file_acl;
7097 e2fsck_write_inode(ctx, ino_el->inode,
7098 &di->inode, "clone file EA");
7099 decrement_badcount(ctx, blk, db);
7105 ext2fs_free_mem(&cs.buf);
7110 * This routine returns 1 if a block overlaps with one of the superblocks,
7111 * group descriptors, inode bitmaps, or block bitmaps.
7113 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7115 ext2_filsys fs = ctx->fs;
7119 block = fs->super->s_first_data_block;
7120 for (i = 0; i < fs->group_desc_count; i++) {
7122 /* Check superblocks/block group descriptros */
7123 if (ext2fs_bg_has_super(fs, i)) {
7124 if (test_block >= block &&
7125 (test_block <= block + fs->desc_blocks))
7129 /* Check the inode table */
7130 if ((fs->group_desc[i].bg_inode_table) &&
7131 (test_block >= fs->group_desc[i].bg_inode_table) &&
7132 (test_block < (fs->group_desc[i].bg_inode_table +
7133 fs->inode_blocks_per_group)))
7136 /* Check the bitmap blocks */
7137 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7138 (test_block == fs->group_desc[i].bg_inode_bitmap))
7141 block += fs->super->s_blocks_per_group;
7146 * pass2.c --- check directory structure
7148 * Pass 2 of e2fsck iterates through all active directory inodes, and
7149 * applies to following tests to each directory entry in the directory
7150 * blocks in the inodes:
7152 * - The length of the directory entry (rec_len) should be at
7153 * least 8 bytes, and no more than the remaining space
7154 * left in the directory block.
7155 * - The length of the name in the directory entry (name_len)
7156 * should be less than (rec_len - 8).
7157 * - The inode number in the directory entry should be within
7159 * - The inode number should refer to a in-use inode.
7160 * - The first entry should be '.', and its inode should be
7161 * the inode of the directory.
7162 * - The second entry should be '..'.
7164 * To minimize disk seek time, the directory blocks are processed in
7165 * sorted order of block numbers.
7167 * Pass 2 also collects the following information:
7168 * - The inode numbers of the subdirectories for each directory.
7170 * Pass 2 relies on the following information from previous passes:
7171 * - The directory information collected in pass 1.
7172 * - The inode_used_map bitmap
7173 * - The inode_bad_map bitmap
7174 * - The inode_dir_map bitmap
7176 * Pass 2 frees the following data structures
7177 * - The inode_bad_map bitmap
7178 * - The inode_reg_map bitmap
7181 /* #define DX_DEBUG */
7184 * Keeps track of how many times an inode is referenced.
7186 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7187 static int check_dir_block(ext2_filsys fs,
7188 struct ext2_db_entry *dir_blocks_info,
7190 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7191 struct problem_context *pctx);
7192 static int update_dir_block(ext2_filsys fs,
7194 e2_blkcnt_t blockcnt,
7198 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7199 static int htree_depth(struct dx_dir_info *dx_dir,
7200 struct dx_dirblock_info *dx_db);
7201 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7203 struct check_dir_struct {
7205 struct problem_context pctx;
7210 static void e2fsck_pass2(e2fsck_t ctx)
7212 struct ext2_super_block *sb = ctx->fs->super;
7213 struct problem_context pctx;
7214 ext2_filsys fs = ctx->fs;
7216 #ifdef RESOURCE_TRACK
7217 struct resource_track rtrack;
7219 struct dir_info *dir;
7220 struct check_dir_struct cd;
7221 struct dx_dir_info *dx_dir;
7222 struct dx_dirblock_info *dx_db, *dx_parent;
7228 #ifdef RESOURCE_TRACK
7229 init_resource_track(&rtrack);
7232 clear_problem_context(&cd.pctx);
7235 mtrace_print("Pass 2");
7238 if (!(ctx->options & E2F_OPT_PREEN))
7239 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7241 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7242 0, ctx->inode_link_info,
7244 if (cd.pctx.errcode) {
7245 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7246 ctx->flags |= E2F_FLAG_ABORT;
7249 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7250 "directory scan buffer");
7253 * Set up the parent pointer for the root directory, if
7254 * present. (If the root directory is not present, we will
7255 * create it in pass 3.)
7257 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7259 dir->parent = EXT2_ROOT_INO;
7264 cd.max = ext2fs_dblist_count(fs->dblist);
7267 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7269 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7270 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7272 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7274 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7276 if (cd.pctx.errcode) {
7277 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7278 ctx->flags |= E2F_FLAG_ABORT;
7283 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7284 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7286 if (dx_dir->numblocks == 0)
7288 clear_problem_context(&pctx);
7290 pctx.dir = dx_dir->ino;
7291 dx_db = dx_dir->dx_block;
7292 if (dx_db->flags & DX_FLAG_REFERENCED)
7293 dx_db->flags |= DX_FLAG_DUP_REF;
7295 dx_db->flags |= DX_FLAG_REFERENCED;
7297 * Find all of the first and last leaf blocks, and
7298 * update their parent's min and max hash values
7300 for (b=0, dx_db = dx_dir->dx_block;
7301 b < dx_dir->numblocks;
7303 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7304 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7306 dx_parent = &dx_dir->dx_block[dx_db->parent];
7308 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7310 if (dx_db->flags & DX_FLAG_FIRST)
7311 dx_parent->min_hash = dx_db->min_hash;
7313 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7315 if (dx_db->flags & DX_FLAG_LAST)
7316 dx_parent->max_hash = dx_db->max_hash;
7319 for (b=0, dx_db = dx_dir->dx_block;
7320 b < dx_dir->numblocks;
7323 pctx.group = dx_db->parent;
7325 if (!(dx_db->flags & DX_FLAG_FIRST) &&
7326 (dx_db->min_hash < dx_db->node_min_hash)) {
7327 pctx.blk = dx_db->min_hash;
7328 pctx.blk2 = dx_db->node_min_hash;
7329 code = PR_2_HTREE_MIN_HASH;
7330 fix_problem(ctx, code, &pctx);
7333 if (dx_db->type == DX_DIRBLOCK_LEAF) {
7334 depth = htree_depth(dx_dir, dx_db);
7335 if (depth != dx_dir->depth) {
7336 code = PR_2_HTREE_BAD_DEPTH;
7337 fix_problem(ctx, code, &pctx);
7342 * This test doesn't apply for the root block
7346 (dx_db->max_hash > dx_db->node_max_hash)) {
7347 pctx.blk = dx_db->max_hash;
7348 pctx.blk2 = dx_db->node_max_hash;
7349 code = PR_2_HTREE_MAX_HASH;
7350 fix_problem(ctx, code, &pctx);
7353 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7354 code = PR_2_HTREE_NOTREF;
7355 fix_problem(ctx, code, &pctx);
7357 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7358 code = PR_2_HTREE_DUPREF;
7359 fix_problem(ctx, code, &pctx);
7365 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7366 clear_htree(ctx, dx_dir->ino);
7367 dx_dir->numblocks = 0;
7371 ext2fs_free_mem(&buf);
7372 ext2fs_free_dblist(fs->dblist);
7374 if (ctx->inode_bad_map) {
7375 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7376 ctx->inode_bad_map = 0;
7378 if (ctx->inode_reg_map) {
7379 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7380 ctx->inode_reg_map = 0;
7383 clear_problem_context(&pctx);
7384 if (ctx->large_files) {
7385 if (!(sb->s_feature_ro_compat &
7386 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7387 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7388 sb->s_feature_ro_compat |=
7389 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7390 ext2fs_mark_super_dirty(fs);
7392 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7393 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7394 ext2fs_update_dynamic_rev(fs);
7395 ext2fs_mark_super_dirty(fs);
7397 } else if (!ctx->large_files &&
7398 (sb->s_feature_ro_compat &
7399 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7400 if (fs->flags & EXT2_FLAG_RW) {
7401 sb->s_feature_ro_compat &=
7402 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7403 ext2fs_mark_super_dirty(fs);
7407 #ifdef RESOURCE_TRACK
7408 if (ctx->options & E2F_OPT_TIME2) {
7409 e2fsck_clear_progbar(ctx);
7410 print_resource_track(_("Pass 2"), &rtrack);
7415 #define MAX_DEPTH 32000
7416 static int htree_depth(struct dx_dir_info *dx_dir,
7417 struct dx_dirblock_info *dx_db)
7421 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7422 dx_db = &dx_dir->dx_block[dx_db->parent];
7428 static int dict_de_cmp(const void *a, const void *b)
7430 const struct ext2_dir_entry *de_a, *de_b;
7433 de_a = (const struct ext2_dir_entry *) a;
7434 a_len = de_a->name_len & 0xFF;
7435 de_b = (const struct ext2_dir_entry *) b;
7436 b_len = de_b->name_len & 0xFF;
7439 return (a_len - b_len);
7441 return strncmp(de_a->name, de_b->name, a_len);
7445 * This is special sort function that makes sure that directory blocks
7446 * with a dirblock of zero are sorted to the beginning of the list.
7447 * This guarantees that the root node of the htree directories are
7448 * processed first, so we know what hash version to use.
7450 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7452 const struct ext2_db_entry *db_a =
7453 (const struct ext2_db_entry *) a;
7454 const struct ext2_db_entry *db_b =
7455 (const struct ext2_db_entry *) b;
7457 if (db_a->blockcnt && !db_b->blockcnt)
7460 if (!db_a->blockcnt && db_b->blockcnt)
7463 if (db_a->blk != db_b->blk)
7464 return (int) (db_a->blk - db_b->blk);
7466 if (db_a->ino != db_b->ino)
7467 return (int) (db_a->ino - db_b->ino);
7469 return (int) (db_a->blockcnt - db_b->blockcnt);
7474 * Make sure the first entry in the directory is '.', and that the
7475 * directory entry is sane.
7477 static int check_dot(e2fsck_t ctx,
7478 struct ext2_dir_entry *dirent,
7479 ext2_ino_t ino, struct problem_context *pctx)
7481 struct ext2_dir_entry *nextdir;
7488 problem = PR_2_MISSING_DOT;
7489 else if (((dirent->name_len & 0xFF) != 1) ||
7490 (dirent->name[0] != '.'))
7491 problem = PR_2_1ST_NOT_DOT;
7492 else if (dirent->name[1] != '\0')
7493 problem = PR_2_DOT_NULL_TERM;
7496 if (fix_problem(ctx, problem, pctx)) {
7497 if (dirent->rec_len < 12)
7498 dirent->rec_len = 12;
7499 dirent->inode = ino;
7500 dirent->name_len = 1;
7501 dirent->name[0] = '.';
7502 dirent->name[1] = '\0';
7507 if (dirent->inode != ino) {
7508 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7509 dirent->inode = ino;
7513 if (dirent->rec_len > 12) {
7514 new_len = dirent->rec_len - 12;
7517 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7518 nextdir = (struct ext2_dir_entry *)
7519 ((char *) dirent + 12);
7520 dirent->rec_len = 12;
7521 nextdir->rec_len = new_len;
7523 nextdir->name_len = 0;
7532 * Make sure the second entry in the directory is '..', and that the
7533 * directory entry is sane. We do not check the inode number of '..'
7534 * here; this gets done in pass 3.
7536 static int check_dotdot(e2fsck_t ctx,
7537 struct ext2_dir_entry *dirent,
7538 struct dir_info *dir, struct problem_context *pctx)
7543 problem = PR_2_MISSING_DOT_DOT;
7544 else if (((dirent->name_len & 0xFF) != 2) ||
7545 (dirent->name[0] != '.') ||
7546 (dirent->name[1] != '.'))
7547 problem = PR_2_2ND_NOT_DOT_DOT;
7548 else if (dirent->name[2] != '\0')
7549 problem = PR_2_DOT_DOT_NULL_TERM;
7552 if (fix_problem(ctx, problem, pctx)) {
7553 if (dirent->rec_len < 12)
7554 dirent->rec_len = 12;
7556 * Note: we don't have the parent inode just
7557 * yet, so we will fill it in with the root
7558 * inode. This will get fixed in pass 3.
7560 dirent->inode = EXT2_ROOT_INO;
7561 dirent->name_len = 2;
7562 dirent->name[0] = '.';
7563 dirent->name[1] = '.';
7564 dirent->name[2] = '\0';
7569 dir->dotdot = dirent->inode;
7574 * Check to make sure a directory entry doesn't contain any illegal
7577 static int check_name(e2fsck_t ctx,
7578 struct ext2_dir_entry *dirent,
7579 struct problem_context *pctx)
7585 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7586 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7588 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7591 dirent->name[i] = '.';
7600 * Check the directory filetype (if present)
7604 * Given a mode, return the ext2 file type
7606 static int ext2_file_type(unsigned int mode)
7608 if (LINUX_S_ISREG(mode))
7609 return EXT2_FT_REG_FILE;
7611 if (LINUX_S_ISDIR(mode))
7614 if (LINUX_S_ISCHR(mode))
7615 return EXT2_FT_CHRDEV;
7617 if (LINUX_S_ISBLK(mode))
7618 return EXT2_FT_BLKDEV;
7620 if (LINUX_S_ISLNK(mode))
7621 return EXT2_FT_SYMLINK;
7623 if (LINUX_S_ISFIFO(mode))
7624 return EXT2_FT_FIFO;
7626 if (LINUX_S_ISSOCK(mode))
7627 return EXT2_FT_SOCK;
7632 static _INLINE_ int check_filetype(e2fsck_t ctx,
7633 struct ext2_dir_entry *dirent,
7634 struct problem_context *pctx)
7636 int filetype = dirent->name_len >> 8;
7637 int should_be = EXT2_FT_UNKNOWN;
7638 struct ext2_inode inode;
7640 if (!(ctx->fs->super->s_feature_incompat &
7641 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7642 if (filetype == 0 ||
7643 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7645 dirent->name_len = dirent->name_len & 0xFF;
7649 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7650 should_be = EXT2_FT_DIR;
7651 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7653 should_be = EXT2_FT_REG_FILE;
7654 } else if (ctx->inode_bad_map &&
7655 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7659 e2fsck_read_inode(ctx, dirent->inode, &inode,
7661 should_be = ext2_file_type(inode.i_mode);
7663 if (filetype == should_be)
7665 pctx->num = should_be;
7667 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7671 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7676 static void parse_int_node(ext2_filsys fs,
7677 struct ext2_db_entry *db,
7678 struct check_dir_struct *cd,
7679 struct dx_dir_info *dx_dir,
7682 struct ext2_dx_root_info *root;
7683 struct ext2_dx_entry *ent;
7684 struct ext2_dx_countlimit *limit;
7685 struct dx_dirblock_info *dx_db;
7686 int i, expect_limit, count;
7688 ext2_dirhash_t min_hash = 0xffffffff;
7689 ext2_dirhash_t max_hash = 0;
7690 ext2_dirhash_t hash = 0, prev_hash;
7692 if (db->blockcnt == 0) {
7693 root = (struct ext2_dx_root_info *) (block_buf + 24);
7696 printf("Root node dump:\n");
7697 printf("\t Reserved zero: %d\n", root->reserved_zero);
7698 printf("\t Hash Version: %d\n", root->hash_version);
7699 printf("\t Info length: %d\n", root->info_length);
7700 printf("\t Indirect levels: %d\n", root->indirect_levels);
7701 printf("\t Flags: %d\n", root->unused_flags);
7704 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7706 ent = (struct ext2_dx_entry *) (block_buf+8);
7708 limit = (struct ext2_dx_countlimit *) ent;
7711 printf("Number of entries (count): %d\n",
7712 ext2fs_le16_to_cpu(limit->count));
7713 printf("Number of entries (limit): %d\n",
7714 ext2fs_le16_to_cpu(limit->limit));
7717 count = ext2fs_le16_to_cpu(limit->count);
7718 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7719 sizeof(struct ext2_dx_entry);
7720 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7721 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7722 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7723 goto clear_and_exit;
7725 if (count > expect_limit) {
7726 cd->pctx.num = count;
7727 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7728 goto clear_and_exit;
7729 count = expect_limit;
7732 for (i=0; i < count; i++) {
7734 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7736 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7737 hash, ext2fs_le32_to_cpu(ent[i].block));
7739 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7740 /* Check to make sure the block is valid */
7741 if (blk > (blk_t) dx_dir->numblocks) {
7743 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7745 goto clear_and_exit;
7747 if (hash < prev_hash &&
7748 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7749 goto clear_and_exit;
7750 dx_db = &dx_dir->dx_block[blk];
7751 if (dx_db->flags & DX_FLAG_REFERENCED) {
7752 dx_db->flags |= DX_FLAG_DUP_REF;
7754 dx_db->flags |= DX_FLAG_REFERENCED;
7755 dx_db->parent = db->blockcnt;
7757 if (hash < min_hash)
7759 if (hash > max_hash)
7761 dx_db->node_min_hash = hash;
7763 dx_db->node_max_hash =
7764 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7766 dx_db->node_max_hash = 0xfffffffe;
7767 dx_db->flags |= DX_FLAG_LAST;
7770 dx_db->flags |= DX_FLAG_FIRST;
7773 printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7774 db->blockcnt, min_hash, max_hash);
7776 dx_db = &dx_dir->dx_block[db->blockcnt];
7777 dx_db->min_hash = min_hash;
7778 dx_db->max_hash = max_hash;
7782 clear_htree(cd->ctx, cd->pctx.ino);
7783 dx_dir->numblocks = 0;
7785 #endif /* ENABLE_HTREE */
7788 * Given a busted directory, try to salvage it somehow.
7791 static void salvage_directory(ext2_filsys fs,
7792 struct ext2_dir_entry *dirent,
7793 struct ext2_dir_entry *prev,
7794 unsigned int *offset)
7796 char *cp = (char *) dirent;
7797 int left = fs->blocksize - *offset - dirent->rec_len;
7798 int name_len = dirent->name_len & 0xFF;
7801 * Special case of directory entry of size 8: copy what's left
7802 * of the directory block up to cover up the invalid hole.
7804 if ((left >= 12) && (dirent->rec_len == 8)) {
7805 memmove(cp, cp+8, left);
7806 memset(cp + left, 0, 8);
7810 * If the directory entry overruns the end of the directory
7811 * block, and the name is small enough to fit, then adjust the
7815 (name_len + 8 <= dirent->rec_len + left) &&
7816 dirent->inode <= fs->super->s_inodes_count &&
7817 strnlen(dirent->name, name_len) == name_len) {
7818 dirent->rec_len += left;
7822 * If the directory entry is a multiple of four, so it is
7823 * valid, let the previous directory entry absorb the invalid
7826 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7827 prev->rec_len += dirent->rec_len;
7828 *offset += dirent->rec_len;
7832 * Default salvage method --- kill all of the directory
7833 * entries for the rest of the block. We will either try to
7834 * absorb it into the previous directory entry, or create a
7835 * new empty directory entry the rest of the directory block.
7838 prev->rec_len += fs->blocksize - *offset;
7839 *offset = fs->blocksize;
7841 dirent->rec_len = fs->blocksize - *offset;
7842 dirent->name_len = 0;
7847 static int check_dir_block(ext2_filsys fs,
7848 struct ext2_db_entry *db,
7851 struct dir_info *subdir, *dir;
7852 struct dx_dir_info *dx_dir;
7854 struct dx_dirblock_info *dx_db = 0;
7855 #endif /* ENABLE_HTREE */
7856 struct ext2_dir_entry *dirent, *prev;
7857 ext2_dirhash_t hash;
7858 unsigned int offset = 0;
7859 int dir_modified = 0;
7861 blk_t block_nr = db->blk;
7862 ext2_ino_t ino = db->ino;
7864 struct check_dir_struct *cd;
7868 struct ext2_dx_root_info *root;
7869 struct ext2_dx_countlimit *limit;
7870 static dict_t de_dict;
7871 struct problem_context pctx;
7874 cd = (struct check_dir_struct *) priv_data;
7878 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7879 return DIRENT_ABORT;
7881 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7882 return DIRENT_ABORT;
7885 * Make sure the inode is still in use (could have been
7886 * deleted in the duplicate/bad blocks pass.
7888 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7892 cd->pctx.blk = block_nr;
7893 cd->pctx.blkcount = db->blockcnt;
7895 cd->pctx.dirent = 0;
7899 if (allocate_dir_block(ctx, db, &cd->pctx))
7909 if (ctx->dirs_to_hash &&
7910 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7914 printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7918 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7919 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7920 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7921 if (cd->pctx.errcode) {
7922 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7923 ctx->flags |= E2F_FLAG_ABORT;
7924 return DIRENT_ABORT;
7926 memset(buf, 0, fs->blocksize);
7929 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7930 if (dx_dir && dx_dir->numblocks) {
7931 if (db->blockcnt >= dx_dir->numblocks) {
7932 printf("XXX should never happen!!!\n");
7935 dx_db = &dx_dir->dx_block[db->blockcnt];
7936 dx_db->type = DX_DIRBLOCK_LEAF;
7937 dx_db->phys = block_nr;
7938 dx_db->min_hash = ~0;
7939 dx_db->max_hash = 0;
7941 dirent = (struct ext2_dir_entry *) buf;
7942 limit = (struct ext2_dx_countlimit *) (buf+8);
7943 if (db->blockcnt == 0) {
7944 root = (struct ext2_dx_root_info *) (buf + 24);
7945 dx_db->type = DX_DIRBLOCK_ROOT;
7946 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7947 if ((root->reserved_zero ||
7948 root->info_length < 8 ||
7949 root->indirect_levels > 1) &&
7950 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7951 clear_htree(ctx, ino);
7952 dx_dir->numblocks = 0;
7955 dx_dir->hashversion = root->hash_version;
7956 dx_dir->depth = root->indirect_levels + 1;
7957 } else if ((dirent->inode == 0) &&
7958 (dirent->rec_len == fs->blocksize) &&
7959 (dirent->name_len == 0) &&
7960 (ext2fs_le16_to_cpu(limit->limit) ==
7961 ((fs->blocksize-8) /
7962 sizeof(struct ext2_dx_entry))))
7963 dx_db->type = DX_DIRBLOCK_NODE;
7965 #endif /* ENABLE_HTREE */
7967 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7971 dirent = (struct ext2_dir_entry *) (buf + offset);
7972 cd->pctx.dirent = dirent;
7973 cd->pctx.num = offset;
7974 if (((offset + dirent->rec_len) > fs->blocksize) ||
7975 (dirent->rec_len < 12) ||
7976 ((dirent->rec_len % 4) != 0) ||
7977 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7978 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7979 salvage_directory(fs, dirent, prev, &offset);
7983 goto abort_free_dict;
7985 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7986 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7987 dirent->name_len = EXT2_NAME_LEN;
7992 if (dot_state == 0) {
7993 if (check_dot(ctx, dirent, ino, &cd->pctx))
7995 } else if (dot_state == 1) {
7996 dir = e2fsck_get_dir_info(ctx, ino);
7998 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7999 goto abort_free_dict;
8001 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
8003 } else if (dirent->inode == ino) {
8004 problem = PR_2_LINK_DOT;
8005 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
8015 * Make sure the inode listed is a legal one.
8017 if (((dirent->inode != EXT2_ROOT_INO) &&
8018 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
8019 (dirent->inode > fs->super->s_inodes_count)) {
8020 problem = PR_2_BAD_INO;
8021 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
8024 * If the inode is unused, offer to clear it.
8026 problem = PR_2_UNUSED_INODE;
8027 } else if (ctx->inode_bb_map &&
8028 (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
8031 * If the inode is in a bad block, offer to
8034 problem = PR_2_BB_INODE;
8035 } else if ((dot_state > 1) &&
8036 ((dirent->name_len & 0xFF) == 1) &&
8037 (dirent->name[0] == '.')) {
8039 * If there's a '.' entry in anything other
8040 * than the first directory entry, it's a
8041 * duplicate entry that should be removed.
8043 problem = PR_2_DUP_DOT;
8044 } else if ((dot_state > 1) &&
8045 ((dirent->name_len & 0xFF) == 2) &&
8046 (dirent->name[0] == '.') &&
8047 (dirent->name[1] == '.')) {
8049 * If there's a '..' entry in anything other
8050 * than the second directory entry, it's a
8051 * duplicate entry that should be removed.
8053 problem = PR_2_DUP_DOT_DOT;
8054 } else if ((dot_state > 1) &&
8055 (dirent->inode == EXT2_ROOT_INO)) {
8057 * Don't allow links to the root directory.
8058 * We check this specially to make sure we
8059 * catch this error case even if the root
8060 * directory hasn't been created yet.
8062 problem = PR_2_LINK_ROOT;
8063 } else if ((dot_state > 1) &&
8064 (dirent->name_len & 0xFF) == 0) {
8066 * Don't allow zero-length directory names.
8068 problem = PR_2_NULL_NAME;
8072 if (fix_problem(ctx, problem, &cd->pctx)) {
8077 ext2fs_unmark_valid(fs);
8078 if (problem == PR_2_BAD_INO)
8084 * If the inode was marked as having bad fields in
8085 * pass1, process it and offer to fix/clear it.
8086 * (We wait until now so that we can display the
8087 * pathname to the user.)
8089 if (ctx->inode_bad_map &&
8090 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8092 if (e2fsck_process_bad_inode(ctx, ino,
8094 buf + fs->blocksize)) {
8099 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100 return DIRENT_ABORT;
8103 if (check_name(ctx, dirent, &cd->pctx))
8106 if (check_filetype(ctx, dirent, &cd->pctx))
8111 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8112 (dirent->name_len & 0xFF),
8113 fs->super->s_hash_seed, &hash, 0);
8114 if (hash < dx_db->min_hash)
8115 dx_db->min_hash = hash;
8116 if (hash > dx_db->max_hash)
8117 dx_db->max_hash = hash;
8122 * If this is a directory, then mark its parent in its
8123 * dir_info structure. If the parent field is already
8124 * filled in, then this directory has more than one
8125 * hard link. We assume the first link is correct,
8126 * and ask the user if he/she wants to clear this one.
8128 if ((dot_state > 1) &&
8129 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8131 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8133 cd->pctx.ino = dirent->inode;
8134 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8135 goto abort_free_dict;
8137 if (subdir->parent) {
8138 cd->pctx.ino2 = subdir->parent;
8139 if (fix_problem(ctx, PR_2_LINK_DIR,
8147 subdir->parent = ino;
8152 } else if (dict_lookup(&de_dict, dirent)) {
8153 clear_problem_context(&pctx);
8155 pctx.dirent = dirent;
8156 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8157 if (!ctx->dirs_to_hash)
8158 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8159 if (ctx->dirs_to_hash)
8160 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8163 dict_alloc_insert(&de_dict, dirent, dirent);
8165 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8168 ctx->fs_links_count++;
8169 ctx->fs_total_count++;
8172 offset += dirent->rec_len;
8174 } while (offset < fs->blocksize);
8181 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8182 db->blockcnt, dx_db->type,
8183 dx_db->min_hash, dx_db->max_hash);
8185 cd->pctx.dir = cd->pctx.ino;
8186 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8187 (dx_db->type == DX_DIRBLOCK_NODE))
8188 parse_int_node(fs, db, cd, dx_dir, buf);
8190 #endif /* ENABLE_HTREE */
8191 if (offset != fs->blocksize) {
8192 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8193 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8194 dirent->rec_len = cd->pctx.num;
8199 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8200 if (cd->pctx.errcode) {
8201 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8203 goto abort_free_dict;
8205 ext2fs_mark_changed(fs);
8207 dict_free_nodes(&de_dict);
8210 dict_free_nodes(&de_dict);
8211 ctx->flags |= E2F_FLAG_ABORT;
8212 return DIRENT_ABORT;
8216 * This function is called to deallocate a block, and is an interator
8217 * functioned called by deallocate inode via ext2fs_iterate_block().
8219 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8220 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
8221 blk_t ref_block EXT2FS_ATTR((unused)),
8222 int ref_offset EXT2FS_ATTR((unused)),
8225 e2fsck_t ctx = (e2fsck_t) priv_data;
8227 if (HOLE_BLKADDR(*block_nr))
8229 if ((*block_nr < fs->super->s_first_data_block) ||
8230 (*block_nr >= fs->super->s_blocks_count))
8232 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8233 ext2fs_block_alloc_stats(fs, *block_nr, -1);
8238 * This fuction deallocates an inode
8240 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8242 ext2_filsys fs = ctx->fs;
8243 struct ext2_inode inode;
8244 struct problem_context pctx;
8247 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8248 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8249 inode.i_links_count = 0;
8250 inode.i_dtime = time(0);
8251 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8252 clear_problem_context(&pctx);
8256 * Fix up the bitmaps...
8258 e2fsck_read_bitmaps(ctx);
8259 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8260 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8261 if (ctx->inode_bad_map)
8262 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8263 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8265 if (inode.i_file_acl &&
8266 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8267 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8268 block_buf, -1, &count);
8269 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8274 pctx.blk = inode.i_file_acl;
8275 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8276 ctx->flags |= E2F_FLAG_ABORT;
8280 ext2fs_unmark_block_bitmap(ctx->block_found_map,
8282 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8284 inode.i_file_acl = 0;
8287 if (!ext2fs_inode_has_valid_blocks(&inode))
8290 if (LINUX_S_ISREG(inode.i_mode) &&
8291 (inode.i_size_high || inode.i_size & 0x80000000UL))
8294 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8295 deallocate_inode_block, ctx);
8297 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8298 ctx->flags |= E2F_FLAG_ABORT;
8304 * This fuction clears the htree flag on an inode
8306 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8308 struct ext2_inode inode;
8310 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8311 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8312 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8313 if (ctx->dirs_to_hash)
8314 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8318 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8319 ext2_ino_t ino, char *buf)
8321 ext2_filsys fs = ctx->fs;
8322 struct ext2_inode inode;
8323 int inode_modified = 0;
8325 unsigned char *frag, *fsize;
8326 struct problem_context pctx;
8329 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8331 clear_problem_context(&pctx);
8334 pctx.inode = &inode;
8336 if (inode.i_file_acl &&
8337 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8338 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8339 inode.i_file_acl = 0;
8340 #ifdef EXT2FS_ENABLE_SWAPFS
8342 * This is a special kludge to deal with long symlinks
8343 * on big endian systems. i_blocks had already been
8344 * decremented earlier in pass 1, but since i_file_acl
8345 * hadn't yet been cleared, ext2fs_read_inode()
8346 * assumed that the file was short symlink and would
8347 * not have byte swapped i_block[0]. Hence, we have
8348 * to byte-swap it here.
8350 if (LINUX_S_ISLNK(inode.i_mode) &&
8351 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8352 (inode.i_blocks == fs->blocksize >> 9))
8353 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8359 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8360 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8361 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8362 !(LINUX_S_ISSOCK(inode.i_mode)))
8363 problem = PR_2_BAD_MODE;
8364 else if (LINUX_S_ISCHR(inode.i_mode)
8365 && !e2fsck_pass1_check_device_inode(fs, &inode))
8366 problem = PR_2_BAD_CHAR_DEV;
8367 else if (LINUX_S_ISBLK(inode.i_mode)
8368 && !e2fsck_pass1_check_device_inode(fs, &inode))
8369 problem = PR_2_BAD_BLOCK_DEV;
8370 else if (LINUX_S_ISFIFO(inode.i_mode)
8371 && !e2fsck_pass1_check_device_inode(fs, &inode))
8372 problem = PR_2_BAD_FIFO;
8373 else if (LINUX_S_ISSOCK(inode.i_mode)
8374 && !e2fsck_pass1_check_device_inode(fs, &inode))
8375 problem = PR_2_BAD_SOCKET;
8376 else if (LINUX_S_ISLNK(inode.i_mode)
8377 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8378 problem = PR_2_INVALID_SYMLINK;
8382 if (fix_problem(ctx, problem, &pctx)) {
8383 deallocate_inode(ctx, ino, 0);
8384 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8392 if (inode.i_faddr) {
8393 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8400 switch (fs->super->s_creator_os) {
8402 frag = &inode.osd2.linux2.l_i_frag;
8403 fsize = &inode.osd2.linux2.l_i_fsize;
8406 frag = &inode.osd2.hurd2.h_i_frag;
8407 fsize = &inode.osd2.hurd2.h_i_fsize;
8410 frag = &inode.osd2.masix2.m_i_frag;
8411 fsize = &inode.osd2.masix2.m_i_fsize;
8416 if (frag && *frag) {
8418 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8425 if (fsize && *fsize) {
8427 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8435 if (inode.i_file_acl &&
8436 ((inode.i_file_acl < fs->super->s_first_data_block) ||
8437 (inode.i_file_acl >= fs->super->s_blocks_count))) {
8438 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8439 inode.i_file_acl = 0;
8444 if (inode.i_dir_acl &&
8445 LINUX_S_ISDIR(inode.i_mode)) {
8446 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8447 inode.i_dir_acl = 0;
8454 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8456 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8462 * allocate_dir_block --- this function allocates a new directory
8463 * block for a particular inode; this is done if a directory has
8464 * a "hole" in it, or if a directory has a illegal block number
8465 * that was zeroed out and now needs to be replaced.
8467 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8468 struct problem_context *pctx)
8470 ext2_filsys fs = ctx->fs;
8473 struct ext2_inode inode;
8475 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8479 * Read the inode and block bitmaps in; we'll be messing with
8482 e2fsck_read_bitmaps(ctx);
8485 * First, find a free block
8487 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8488 if (pctx->errcode) {
8489 pctx->str = "ext2fs_new_block";
8490 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8493 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8494 ext2fs_mark_block_bitmap(fs->block_map, blk);
8495 ext2fs_mark_bb_dirty(fs);
8498 * Now let's create the actual data block for the inode
8501 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8503 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8504 EXT2_ROOT_INO, &block);
8506 if (pctx->errcode) {
8507 pctx->str = "ext2fs_new_dir_block";
8508 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8512 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8513 ext2fs_free_mem(&block);
8514 if (pctx->errcode) {
8515 pctx->str = "ext2fs_write_dir_block";
8516 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8521 * Update the inode block count
8523 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8524 inode.i_blocks += fs->blocksize / 512;
8525 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8526 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8527 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8530 * Finally, update the block pointers for the inode
8533 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8534 0, update_dir_block, db);
8535 if (pctx->errcode) {
8536 pctx->str = "ext2fs_block_iterate";
8537 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8545 * This is a helper function for allocate_dir_block().
8547 static int update_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)),
8549 e2_blkcnt_t blockcnt,
8550 blk_t ref_block EXT2FS_ATTR((unused)),
8551 int ref_offset EXT2FS_ATTR((unused)),
8554 struct ext2_db_entry *db;
8556 db = (struct ext2_db_entry *) priv_data;
8557 if (db->blockcnt == (int) blockcnt) {
8558 *block_nr = db->blk;
8559 return BLOCK_CHANGED;
8565 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8567 * Pass #3 assures that all directories are connected to the
8568 * filesystem tree, using the following algorithm:
8570 * First, the root directory is checked to make sure it exists; if
8571 * not, e2fsck will offer to create a new one. It is then marked as
8574 * Then, pass3 interates over all directory inodes; for each directory
8575 * it attempts to trace up the filesystem tree, using dirinfo.parent
8576 * until it reaches a directory which has been marked "done". If it
8577 * can not do so, then the directory must be disconnected, and e2fsck
8578 * will offer to reconnect it to /lost+found. While it is chasing
8579 * parent pointers up the filesystem tree, if pass3 sees a directory
8580 * twice, then it has detected a filesystem loop, and it will again
8581 * offer to reconnect the directory to /lost+found in to break the
8584 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8585 * reconnect inodes to /lost+found; this subroutine is also used by
8586 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
8587 * is responsible for creating /lost+found if it does not exist.
8589 * Pass 3 frees the following data structures:
8590 * - The dirinfo directory information cache.
8593 static void check_root(e2fsck_t ctx);
8594 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8595 struct problem_context *pctx);
8596 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8598 static ext2fs_inode_bitmap inode_loop_detect;
8599 static ext2fs_inode_bitmap inode_done_map;
8601 static void e2fsck_pass3(e2fsck_t ctx)
8603 ext2_filsys fs = ctx->fs;
8605 #ifdef RESOURCE_TRACK
8606 struct resource_track rtrack;
8608 struct problem_context pctx;
8609 struct dir_info *dir;
8610 unsigned long maxdirs, count;
8612 #ifdef RESOURCE_TRACK
8613 init_resource_track(&rtrack);
8616 clear_problem_context(&pctx);
8619 mtrace_print("Pass 3");
8622 if (!(ctx->options & E2F_OPT_PREEN))
8623 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8626 * Allocate some bitmaps to do loop detection.
8628 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8632 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8633 ctx->flags |= E2F_FLAG_ABORT;
8636 #ifdef RESOURCE_TRACK
8637 if (ctx->options & E2F_OPT_TIME) {
8638 e2fsck_clear_progbar(ctx);
8639 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8644 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8647 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8649 maxdirs = e2fsck_get_num_dirinfo(ctx);
8653 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8656 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8657 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8659 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8661 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8662 if (check_directory(ctx, dir, &pctx))
8667 * Force the creation of /lost+found if not present
8669 if ((ctx->flags & E2F_OPT_READONLY) == 0)
8670 e2fsck_get_lost_and_found(ctx, 1);
8673 * If there are any directories that need to be indexed or
8674 * optimized, do it here.
8676 e2fsck_rehash_directories(ctx);
8679 e2fsck_free_dir_info(ctx);
8680 if (inode_loop_detect) {
8681 ext2fs_free_inode_bitmap(inode_loop_detect);
8682 inode_loop_detect = 0;
8684 if (inode_done_map) {
8685 ext2fs_free_inode_bitmap(inode_done_map);
8689 #ifdef RESOURCE_TRACK
8690 if (ctx->options & E2F_OPT_TIME2) {
8691 e2fsck_clear_progbar(ctx);
8692 print_resource_track(_("Pass 3"), &rtrack);
8698 * This makes sure the root inode is present; if not, we ask if the
8699 * user wants us to create it. Not creating it is a fatal error.
8701 static void check_root(e2fsck_t ctx)
8703 ext2_filsys fs = ctx->fs;
8705 struct ext2_inode inode;
8707 struct problem_context pctx;
8709 clear_problem_context(&pctx);
8711 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8713 * If the root inode is not a directory, die here. The
8714 * user must have answered 'no' in pass1 when we
8715 * offered to clear it.
8717 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8719 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8720 ctx->flags |= E2F_FLAG_ABORT;
8725 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8726 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8727 ctx->flags |= E2F_FLAG_ABORT;
8731 e2fsck_read_bitmaps(ctx);
8734 * First, find a free block
8736 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8738 pctx.str = "ext2fs_new_block";
8739 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8740 ctx->flags |= E2F_FLAG_ABORT;
8743 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8744 ext2fs_mark_block_bitmap(fs->block_map, blk);
8745 ext2fs_mark_bb_dirty(fs);
8748 * Now let's create the actual data block for the inode
8750 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8753 pctx.str = "ext2fs_new_dir_block";
8754 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8755 ctx->flags |= E2F_FLAG_ABORT;
8759 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8761 pctx.str = "ext2fs_write_dir_block";
8762 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8763 ctx->flags |= E2F_FLAG_ABORT;
8766 ext2fs_free_mem(&block);
8769 * Set up the inode structure
8771 memset(&inode, 0, sizeof(inode));
8772 inode.i_mode = 040755;
8773 inode.i_size = fs->blocksize;
8774 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8775 inode.i_links_count = 2;
8776 inode.i_blocks = fs->blocksize / 512;
8777 inode.i_block[0] = blk;
8780 * Write out the inode.
8782 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8784 pctx.str = "ext2fs_write_inode";
8785 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8786 ctx->flags |= E2F_FLAG_ABORT;
8791 * Miscellaneous bookkeeping...
8793 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8794 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8795 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8797 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8798 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8799 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8800 ext2fs_mark_ib_dirty(fs);
8804 * This subroutine is responsible for making sure that a particular
8805 * directory is connected to the root; if it isn't we trace it up as
8806 * far as we can go, and then offer to connect the resulting parent to
8807 * the lost+found. We have to do loop detection; if we ever discover
8808 * a loop, we treat that as a disconnected directory and offer to
8809 * reparent it to lost+found.
8811 * However, loop detection is expensive, because for very large
8812 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8813 * is non-trivial. Loops in filesystems are also a rare error case,
8814 * and we shouldn't optimize for error cases. So we try two passes of
8815 * the algorithm. The first time, we ignore loop detection and merely
8816 * increment a counter; if the counter exceeds some extreme threshold,
8817 * then we try again with the loop detection bitmap enabled.
8819 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8820 struct problem_context *pctx)
8822 ext2_filsys fs = ctx->fs;
8823 struct dir_info *p = dir;
8824 int loop_pass = 0, parent_count = 0;
8831 * Mark this inode as being "done"; by the time we
8832 * return from this function, the inode we either be
8833 * verified as being connected to the directory tree,
8834 * or we will have offered to reconnect this to
8837 * If it was marked done already, then we've reached a
8838 * parent we've already checked.
8840 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8844 * If this directory doesn't have a parent, or we've
8845 * seen the parent once already, then offer to
8846 * reparent it to lost+found
8850 (ext2fs_test_inode_bitmap(inode_loop_detect,
8853 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8854 if (e2fsck_reconnect_file(ctx, pctx->ino))
8855 ext2fs_unmark_valid(fs);
8857 p = e2fsck_get_dir_info(ctx, pctx->ino);
8858 p->parent = ctx->lost_and_found;
8859 fix_dotdot(ctx, p, ctx->lost_and_found);
8864 p = e2fsck_get_dir_info(ctx, p->parent);
8866 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8870 ext2fs_mark_inode_bitmap(inode_loop_detect,
8872 } else if (parent_count++ > 2048) {
8874 * If we've run into a path depth that's
8875 * greater than 2048, try again with the inode
8876 * loop bitmap turned on and start from the
8880 if (inode_loop_detect)
8881 ext2fs_clear_inode_bitmap(inode_loop_detect);
8883 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8884 if (pctx->errcode) {
8887 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8888 ctx->flags |= E2F_FLAG_ABORT;
8897 * Make sure that .. and the parent directory are the same;
8898 * offer to fix it if not.
8900 if (dir->parent != dir->dotdot) {
8901 pctx->ino = dir->ino;
8902 pctx->ino2 = dir->dotdot;
8903 pctx->dir = dir->parent;
8904 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8905 fix_dotdot(ctx, dir, dir->parent);
8911 * This routine gets the lost_and_found inode, making it a directory
8914 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8916 ext2_filsys fs = ctx->fs;
8920 struct ext2_inode inode;
8922 static const char name[] = "lost+found";
8923 struct problem_context pctx;
8924 struct dir_info *dirinfo;
8926 if (ctx->lost_and_found)
8927 return ctx->lost_and_found;
8929 clear_problem_context(&pctx);
8931 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8932 sizeof(name)-1, 0, &ino);
8936 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8937 ctx->lost_and_found = ino;
8941 /* Lost+found isn't a directory! */
8945 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8948 /* OK, unlink the old /lost+found file. */
8949 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8951 pctx.str = "ext2fs_unlink";
8952 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8955 dirinfo = e2fsck_get_dir_info(ctx, ino);
8957 dirinfo->parent = 0;
8958 e2fsck_adjust_inode_count(ctx, ino, -1);
8959 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8960 pctx.errcode = retval;
8961 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8963 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8967 * Read the inode and block bitmaps in; we'll be messing with
8970 e2fsck_read_bitmaps(ctx);
8973 * First, find a free block
8975 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8977 pctx.errcode = retval;
8978 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8981 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8982 ext2fs_block_alloc_stats(fs, blk, +1);
8985 * Next find a free inode.
8987 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8988 ctx->inode_used_map, &ino);
8990 pctx.errcode = retval;
8991 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8994 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8995 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8996 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8999 * Now let's create the actual data block for the inode
9001 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
9003 pctx.errcode = retval;
9004 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
9008 retval = ext2fs_write_dir_block(fs, blk, block);
9009 ext2fs_free_mem(&block);
9011 pctx.errcode = retval;
9012 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
9017 * Set up the inode structure
9019 memset(&inode, 0, sizeof(inode));
9020 inode.i_mode = 040700;
9021 inode.i_size = fs->blocksize;
9022 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
9023 inode.i_links_count = 2;
9024 inode.i_blocks = fs->blocksize / 512;
9025 inode.i_block[0] = blk;
9028 * Next, write out the inode.
9030 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
9032 pctx.str = "ext2fs_write_inode";
9033 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
9037 * Finally, create the directory link
9039 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
9041 pctx.str = "ext2fs_link";
9042 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
9047 * Miscellaneous bookkeeping that needs to be kept straight.
9049 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
9050 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
9051 ext2fs_icount_store(ctx->inode_count, ino, 2);
9052 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
9053 ctx->lost_and_found = ino;
9055 printf("/lost+found created; inode #%lu\n", ino);
9061 * This routine will connect a file to lost+found
9063 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
9065 ext2_filsys fs = ctx->fs;
9068 struct problem_context pctx;
9069 struct ext2_inode inode;
9072 clear_problem_context(&pctx);
9075 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9076 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9077 ctx->bad_lost_and_found++;
9079 if (ctx->bad_lost_and_found) {
9080 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9084 sprintf(name, "#%u", ino);
9085 if (ext2fs_read_inode(fs, ino, &inode) == 0)
9086 file_type = ext2_file_type(inode.i_mode);
9087 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9088 if (retval == EXT2_ET_DIR_NO_SPACE) {
9089 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9091 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9094 pctx.errcode = retval;
9095 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9098 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9102 pctx.errcode = retval;
9103 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9106 e2fsck_adjust_inode_count(ctx, ino, 1);
9112 * Utility routine to adjust the inode counts on an inode.
9114 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9116 ext2_filsys fs = ctx->fs;
9118 struct ext2_inode inode;
9123 retval = ext2fs_read_inode(fs, ino, &inode);
9128 printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9129 inode.i_links_count);
9133 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9134 if (inode.i_links_count == (__u16) ~0)
9136 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9137 inode.i_links_count++;
9138 } else if (adj == -1) {
9139 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9140 if (inode.i_links_count == 0)
9142 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9143 inode.i_links_count--;
9146 retval = ext2fs_write_inode(fs, ino, &inode);
9154 * Fix parent --- this routine fixes up the parent of a directory.
9156 struct fix_dotdot_struct {
9163 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9164 int offset EXT2FS_ATTR((unused)),
9165 int blocksize EXT2FS_ATTR((unused)),
9166 char *buf EXT2FS_ATTR((unused)),
9169 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9171 struct problem_context pctx;
9173 if ((dirent->name_len & 0xFF) != 2)
9175 if (strncmp(dirent->name, "..", 2))
9178 clear_problem_context(&pctx);
9180 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9182 pctx.errcode = retval;
9183 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9185 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9187 pctx.errcode = retval;
9188 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9190 dirent->inode = fp->parent;
9193 return DIRENT_ABORT | DIRENT_CHANGED;
9196 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9198 ext2_filsys fs = ctx->fs;
9200 struct fix_dotdot_struct fp;
9201 struct problem_context pctx;
9209 printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9212 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9213 0, fix_dotdot_proc, &fp);
9214 if (retval || !fp.done) {
9215 clear_problem_context(&pctx);
9216 pctx.ino = dir->ino;
9217 pctx.errcode = retval;
9218 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9219 PR_3_FIX_PARENT_NOFIND, &pctx);
9220 ext2fs_unmark_valid(fs);
9222 dir->dotdot = parent;
9228 * These routines are responsible for expanding a /lost+found if it is
9232 struct expand_dir_struct {
9234 int guaranteed_size;
9241 static int expand_dir_proc(ext2_filsys fs,
9243 e2_blkcnt_t blockcnt,
9244 blk_t ref_block EXT2FS_ATTR((unused)),
9245 int ref_offset EXT2FS_ATTR((unused)),
9248 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9250 static blk_t last_blk = 0;
9257 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9261 es->last_block = blockcnt;
9263 last_blk = *blocknr;
9266 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9273 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9279 retval = ext2fs_write_dir_block(fs, new_blk, block);
9281 retval = ext2fs_get_mem(fs->blocksize, &block);
9286 memset(block, 0, fs->blocksize);
9287 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9293 ext2fs_free_mem(&block);
9295 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9296 ext2fs_block_alloc_stats(fs, new_blk, +1);
9300 return (BLOCK_CHANGED | BLOCK_ABORT);
9302 return BLOCK_CHANGED;
9305 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9306 int num, int guaranteed_size)
9308 ext2_filsys fs = ctx->fs;
9310 struct expand_dir_struct es;
9311 struct ext2_inode inode;
9313 if (!(fs->flags & EXT2_FLAG_RW))
9314 return EXT2_ET_RO_FILSYS;
9317 * Read the inode and block bitmaps in; we'll be messing with
9320 e2fsck_read_bitmaps(ctx);
9322 retval = ext2fs_check_directory(fs, dir);
9327 es.guaranteed_size = guaranteed_size;
9333 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9334 0, expand_dir_proc, &es);
9340 * Update the size and block count fields in the inode.
9342 retval = ext2fs_read_inode(fs, dir, &inode);
9346 inode.i_size = (es.last_block + 1) * fs->blocksize;
9347 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9349 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9355 * pass4.c -- pass #4 of e2fsck: Check reference counts
9357 * Pass 4 frees the following data structures:
9358 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
9359 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
9363 * This routine is called when an inode is not connected to the
9366 * This subroutine returns 1 then the caller shouldn't bother with the
9367 * rest of the pass 4 tests.
9369 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9371 ext2_filsys fs = ctx->fs;
9372 struct ext2_inode inode;
9373 struct problem_context pctx;
9375 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9376 clear_problem_context(&pctx);
9378 pctx.inode = &inode;
9381 * Offer to delete any zero-length files that does not have
9382 * blocks. If there is an EA block, it might have useful
9383 * information, so we won't prompt to delete it, but let it be
9384 * reconnected to lost+found.
9386 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9387 LINUX_S_ISDIR(inode.i_mode))) {
9388 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9389 ext2fs_icount_store(ctx->inode_link_info, i, 0);
9390 inode.i_links_count = 0;
9391 inode.i_dtime = time(0);
9392 e2fsck_write_inode(ctx, i, &inode,
9393 "disconnect_inode");
9395 * Fix up the bitmaps...
9397 e2fsck_read_bitmaps(ctx);
9398 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9399 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9400 ext2fs_inode_alloc_stats2(fs, i, -1,
9401 LINUX_S_ISDIR(inode.i_mode));
9407 * Prompt to reconnect.
9409 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9410 if (e2fsck_reconnect_file(ctx, i))
9411 ext2fs_unmark_valid(fs);
9414 * If we don't attach the inode, then skip the
9415 * i_links_test since there's no point in trying to
9416 * force i_links_count to zero.
9418 ext2fs_unmark_valid(fs);
9425 static void e2fsck_pass4(e2fsck_t ctx)
9427 ext2_filsys fs = ctx->fs;
9429 struct ext2_inode inode;
9430 #ifdef RESOURCE_TRACK
9431 struct resource_track rtrack;
9433 struct problem_context pctx;
9434 __u16 link_count, link_counted;
9436 int group, maxgroup;
9438 #ifdef RESOURCE_TRACK
9439 init_resource_track(&rtrack);
9443 mtrace_print("Pass 4");
9446 clear_problem_context(&pctx);
9448 if (!(ctx->options & E2F_OPT_PREEN))
9449 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9452 maxgroup = fs->group_desc_count;
9454 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9457 for (i=1; i <= fs->super->s_inodes_count; i++) {
9458 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9460 if ((i % fs->super->s_inodes_per_group) == 0) {
9463 if ((ctx->progress)(ctx, 4, group, maxgroup))
9466 if (i == EXT2_BAD_INO ||
9467 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9469 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9470 (ctx->inode_imagic_map &&
9471 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9472 (ctx->inode_bb_map &&
9473 ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9475 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9476 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9477 if (link_counted == 0) {
9479 buf = e2fsck_allocate_memory(ctx,
9480 fs->blocksize, "bad_inode buffer");
9481 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9483 if (disconnect_inode(ctx, i))
9485 ext2fs_icount_fetch(ctx->inode_link_info, i,
9487 ext2fs_icount_fetch(ctx->inode_count, i,
9490 if (link_counted != link_count) {
9491 e2fsck_read_inode(ctx, i, &inode, "pass4");
9493 pctx.inode = &inode;
9494 if (link_count != inode.i_links_count) {
9495 pctx.num = link_count;
9497 PR_4_INCONSISTENT_COUNT, &pctx);
9499 pctx.num = link_counted;
9500 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9501 inode.i_links_count = link_counted;
9502 e2fsck_write_inode(ctx, i, &inode, "pass4");
9506 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9507 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9508 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9509 ctx->inode_bb_map = 0;
9510 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9511 ctx->inode_imagic_map = 0;
9513 ext2fs_free_mem(&buf);
9514 #ifdef RESOURCE_TRACK
9515 if (ctx->options & E2F_OPT_TIME2) {
9516 e2fsck_clear_progbar(ctx);
9517 print_resource_track(_("Pass 4"), &rtrack);
9523 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9526 #define NO_BLK ((blk_t) -1)
9528 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9529 struct problem_context *pctx)
9532 case PR_5_BLOCK_UNUSED:
9533 if (pctx->blk == pctx->blk2)
9536 problem = PR_5_BLOCK_RANGE_UNUSED;
9538 case PR_5_BLOCK_USED:
9539 if (pctx->blk == pctx->blk2)
9542 problem = PR_5_BLOCK_RANGE_USED;
9544 case PR_5_INODE_UNUSED:
9545 if (pctx->ino == pctx->ino2)
9548 problem = PR_5_INODE_RANGE_UNUSED;
9550 case PR_5_INODE_USED:
9551 if (pctx->ino == pctx->ino2)
9554 problem = PR_5_INODE_RANGE_USED;
9557 fix_problem(ctx, problem, pctx);
9558 pctx->blk = pctx->blk2 = NO_BLK;
9559 pctx->ino = pctx->ino2 = 0;
9562 static void check_block_bitmaps(e2fsck_t ctx)
9564 ext2_filsys fs = ctx->fs;
9568 unsigned int blocks = 0;
9569 unsigned int free_blocks = 0;
9572 struct problem_context pctx;
9573 int problem, save_problem, fixit, had_problem;
9576 clear_problem_context(&pctx);
9577 free_array = (int *) e2fsck_allocate_memory(ctx,
9578 fs->group_desc_count * sizeof(int), "free block count array");
9580 if ((fs->super->s_first_data_block <
9581 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9582 (fs->super->s_blocks_count-1 >
9583 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9585 pctx.blk = fs->super->s_first_data_block;
9586 pctx.blk2 = fs->super->s_blocks_count -1;
9587 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9588 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9589 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9591 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9595 if ((fs->super->s_first_data_block <
9596 ext2fs_get_block_bitmap_start(fs->block_map)) ||
9597 (fs->super->s_blocks_count-1 >
9598 ext2fs_get_block_bitmap_end(fs->block_map))) {
9600 pctx.blk = fs->super->s_first_data_block;
9601 pctx.blk2 = fs->super->s_blocks_count -1;
9602 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9603 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9604 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9606 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9613 pctx.blk = pctx.blk2 = NO_BLK;
9614 for (i = fs->super->s_first_data_block;
9615 i < fs->super->s_blocks_count;
9617 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9618 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9620 if (actual == bitmap)
9623 if (!actual && bitmap) {
9625 * Block not used, but marked in use in the bitmap.
9627 problem = PR_5_BLOCK_UNUSED;
9630 * Block used, but not marked in use in the bitmap.
9632 problem = PR_5_BLOCK_USED;
9634 if (pctx.blk == NO_BLK) {
9635 pctx.blk = pctx.blk2 = i;
9636 save_problem = problem;
9638 if ((problem == save_problem) &&
9642 print_bitmap_problem(ctx, save_problem, &pctx);
9643 pctx.blk = pctx.blk2 = i;
9644 save_problem = problem;
9647 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9656 if ((blocks == fs->super->s_blocks_per_group) ||
9657 (i == fs->super->s_blocks_count-1)) {
9658 free_array[group] = group_free;
9663 if ((ctx->progress)(ctx, 5, group,
9664 fs->group_desc_count*2))
9668 if (pctx.blk != NO_BLK)
9669 print_bitmap_problem(ctx, save_problem, &pctx);
9671 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9674 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9677 ext2fs_free_block_bitmap(fs->block_map);
9678 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9681 clear_problem_context(&pctx);
9682 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9683 ctx->flags |= E2F_FLAG_ABORT;
9686 ext2fs_set_bitmap_padding(fs->block_map);
9687 ext2fs_mark_bb_dirty(fs);
9689 /* Redo the counts */
9690 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9691 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9693 } else if (fixit == 0)
9694 ext2fs_unmark_valid(fs);
9696 for (i = 0; i < fs->group_desc_count; i++) {
9697 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9699 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9700 pctx.blk2 = free_array[i];
9702 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9704 fs->group_desc[i].bg_free_blocks_count =
9706 ext2fs_mark_super_dirty(fs);
9708 ext2fs_unmark_valid(fs);
9711 if (free_blocks != fs->super->s_free_blocks_count) {
9713 pctx.blk = fs->super->s_free_blocks_count;
9714 pctx.blk2 = free_blocks;
9716 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9717 fs->super->s_free_blocks_count = free_blocks;
9718 ext2fs_mark_super_dirty(fs);
9720 ext2fs_unmark_valid(fs);
9722 ext2fs_free_mem(&free_array);
9725 static void check_inode_bitmaps(e2fsck_t ctx)
9727 ext2_filsys fs = ctx->fs;
9729 unsigned int free_inodes = 0;
9733 unsigned int inodes = 0;
9738 struct problem_context pctx;
9739 int problem, save_problem, fixit, had_problem;
9741 clear_problem_context(&pctx);
9742 free_array = (int *) e2fsck_allocate_memory(ctx,
9743 fs->group_desc_count * sizeof(int), "free inode count array");
9745 dir_array = (int *) e2fsck_allocate_memory(ctx,
9746 fs->group_desc_count * sizeof(int), "directory count array");
9748 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9749 (fs->super->s_inodes_count >
9750 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9753 pctx.blk2 = fs->super->s_inodes_count;
9754 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9755 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9756 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9758 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9761 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9762 (fs->super->s_inodes_count >
9763 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9766 pctx.blk2 = fs->super->s_inodes_count;
9767 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9768 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9769 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9771 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9778 pctx.ino = pctx.ino2 = 0;
9779 for (i = 1; i <= fs->super->s_inodes_count; i++) {
9780 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9781 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9783 if (actual == bitmap)
9786 if (!actual && bitmap) {
9788 * Inode wasn't used, but marked in bitmap
9790 problem = PR_5_INODE_UNUSED;
9791 } else /* if (actual && !bitmap) */ {
9793 * Inode used, but not in bitmap
9795 problem = PR_5_INODE_USED;
9797 if (pctx.ino == 0) {
9798 pctx.ino = pctx.ino2 = i;
9799 save_problem = problem;
9801 if ((problem == save_problem) &&
9805 print_bitmap_problem(ctx, save_problem, &pctx);
9806 pctx.ino = pctx.ino2 = i;
9807 save_problem = problem;
9810 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9818 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9822 if ((inodes == fs->super->s_inodes_per_group) ||
9823 (i == fs->super->s_inodes_count)) {
9824 free_array[group] = group_free;
9825 dir_array[group] = dirs_count;
9831 if ((ctx->progress)(ctx, 5,
9832 group + fs->group_desc_count,
9833 fs->group_desc_count*2))
9838 print_bitmap_problem(ctx, save_problem, &pctx);
9841 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9844 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9847 ext2fs_free_inode_bitmap(fs->inode_map);
9848 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9851 clear_problem_context(&pctx);
9852 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9853 ctx->flags |= E2F_FLAG_ABORT;
9856 ext2fs_set_bitmap_padding(fs->inode_map);
9857 ext2fs_mark_ib_dirty(fs);
9860 inodes = 0; free_inodes = 0; group_free = 0;
9861 dirs_count = 0; group = 0;
9862 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9863 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9865 } else if (fixit == 0)
9866 ext2fs_unmark_valid(fs);
9868 for (i = 0; i < fs->group_desc_count; i++) {
9869 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9871 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9872 pctx.ino2 = free_array[i];
9873 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9875 fs->group_desc[i].bg_free_inodes_count =
9877 ext2fs_mark_super_dirty(fs);
9879 ext2fs_unmark_valid(fs);
9881 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9883 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9884 pctx.ino2 = dir_array[i];
9886 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9888 fs->group_desc[i].bg_used_dirs_count =
9890 ext2fs_mark_super_dirty(fs);
9892 ext2fs_unmark_valid(fs);
9895 if (free_inodes != fs->super->s_free_inodes_count) {
9897 pctx.ino = fs->super->s_free_inodes_count;
9898 pctx.ino2 = free_inodes;
9900 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9901 fs->super->s_free_inodes_count = free_inodes;
9902 ext2fs_mark_super_dirty(fs);
9904 ext2fs_unmark_valid(fs);
9906 ext2fs_free_mem(&free_array);
9907 ext2fs_free_mem(&dir_array);
9910 static void check_inode_end(e2fsck_t ctx)
9912 ext2_filsys fs = ctx->fs;
9913 ext2_ino_t end, save_inodes_count, i;
9914 struct problem_context pctx;
9916 clear_problem_context(&pctx);
9918 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9919 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9920 &save_inodes_count);
9923 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9924 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9927 if (save_inodes_count == end)
9930 for (i = save_inodes_count + 1; i <= end; i++) {
9931 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9932 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9933 for (i = save_inodes_count + 1; i <= end; i++)
9934 ext2fs_mark_inode_bitmap(fs->inode_map,
9936 ext2fs_mark_ib_dirty(fs);
9938 ext2fs_unmark_valid(fs);
9943 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9944 save_inodes_count, 0);
9947 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9948 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9953 static void check_block_end(e2fsck_t ctx)
9955 ext2_filsys fs = ctx->fs;
9956 blk_t end, save_blocks_count, i;
9957 struct problem_context pctx;
9959 clear_problem_context(&pctx);
9961 end = fs->block_map->start +
9962 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9963 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9964 &save_blocks_count);
9967 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9968 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9971 if (save_blocks_count == end)
9974 for (i = save_blocks_count + 1; i <= end; i++) {
9975 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9976 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9977 for (i = save_blocks_count + 1; i <= end; i++)
9978 ext2fs_mark_block_bitmap(fs->block_map,
9980 ext2fs_mark_bb_dirty(fs);
9982 ext2fs_unmark_valid(fs);
9987 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9988 save_blocks_count, 0);
9991 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9992 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9997 static void e2fsck_pass5(e2fsck_t ctx)
9999 #ifdef RESOURCE_TRACK
10000 struct resource_track rtrack;
10002 struct problem_context pctx;
10005 mtrace_print("Pass 5");
10008 #ifdef RESOURCE_TRACK
10009 init_resource_track(&rtrack);
10012 clear_problem_context(&pctx);
10014 if (!(ctx->options & E2F_OPT_PREEN))
10015 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
10018 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
10021 e2fsck_read_bitmaps(ctx);
10023 check_block_bitmaps(ctx);
10024 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10026 check_inode_bitmaps(ctx);
10027 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10029 check_inode_end(ctx);
10030 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10032 check_block_end(ctx);
10033 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10036 ext2fs_free_inode_bitmap(ctx->inode_used_map);
10037 ctx->inode_used_map = 0;
10038 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
10039 ctx->inode_dir_map = 0;
10040 ext2fs_free_block_bitmap(ctx->block_found_map);
10041 ctx->block_found_map = 0;
10043 #ifdef RESOURCE_TRACK
10044 if (ctx->options & E2F_OPT_TIME2) {
10045 e2fsck_clear_progbar(ctx);
10046 print_resource_track(_("Pass 5"), &rtrack);
10052 * problem.c --- report filesystem problems to the user
10055 #define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
10056 #define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
10057 #define PR_NO_DEFAULT 0x000004 /* Default to no */
10058 #define PR_MSG_ONLY 0x000008 /* Print message only */
10060 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
10062 #define PR_FATAL 0x001000 /* Fatal error */
10063 #define PR_AFTER_CODE 0x002000 /* After asking the first question, */
10065 #define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
10066 #define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
10067 #define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
10068 #define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
10069 #define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
10072 #define PROMPT_NONE 0
10073 #define PROMPT_FIX 1
10074 #define PROMPT_CLEAR 2
10075 #define PROMPT_RELOCATE 3
10076 #define PROMPT_ALLOCATE 4
10077 #define PROMPT_EXPAND 5
10078 #define PROMPT_CONNECT 6
10079 #define PROMPT_CREATE 7
10080 #define PROMPT_SALVAGE 8
10081 #define PROMPT_TRUNCATE 9
10082 #define PROMPT_CLEAR_INODE 10
10083 #define PROMPT_ABORT 11
10084 #define PROMPT_SPLIT 12
10085 #define PROMPT_CONTINUE 13
10086 #define PROMPT_CLONE 14
10087 #define PROMPT_DELETE 15
10088 #define PROMPT_SUPPRESS 16
10089 #define PROMPT_UNLINK 17
10090 #define PROMPT_CLEAR_HTREE 18
10091 #define PROMPT_RECREATE 19
10092 #define PROMPT_NULL 20
10094 struct e2fsck_problem {
10095 problem_t e2p_code;
10096 const char * e2p_description;
10099 problem_t second_code;
10102 struct latch_descr {
10104 problem_t question;
10105 problem_t end_message;
10110 * These are the prompts which are used to ask the user if they want
10111 * to fix a problem.
10113 static const char * const prompt[] = {
10114 N_("(no prompt)"), /* 0 */
10116 N_("Clear"), /* 2 */
10117 N_("Relocate"), /* 3 */
10118 N_("Allocate"), /* 4 */
10119 N_("Expand"), /* 5 */
10120 N_("Connect to /lost+found"), /* 6 */
10121 N_("Create"), /* 7 */
10122 N_("Salvage"), /* 8 */
10123 N_("Truncate"), /* 9 */
10124 N_("Clear inode"), /* 10 */
10125 N_("Abort"), /* 11 */
10126 N_("Split"), /* 12 */
10127 N_("Continue"), /* 13 */
10128 N_("Clone duplicate/bad blocks"), /* 14 */
10129 N_("Delete file"), /* 15 */
10130 N_("Suppress messages"),/* 16 */
10131 N_("Unlink"), /* 17 */
10132 N_("Clear HTree index"),/* 18 */
10133 N_("Recreate"), /* 19 */
10138 * These messages are printed when we are preen mode and we will be
10139 * automatically fixing the problem.
10141 static const char * const preen_msg[] = {
10142 N_("(NONE)"), /* 0 */
10143 N_("FIXED"), /* 1 */
10144 N_("CLEARED"), /* 2 */
10145 N_("RELOCATED"), /* 3 */
10146 N_("ALLOCATED"), /* 4 */
10147 N_("EXPANDED"), /* 5 */
10148 N_("RECONNECTED"), /* 6 */
10149 N_("CREATED"), /* 7 */
10150 N_("SALVAGED"), /* 8 */
10151 N_("TRUNCATED"), /* 9 */
10152 N_("INODE CLEARED"), /* 10 */
10153 N_("ABORTED"), /* 11 */
10154 N_("SPLIT"), /* 12 */
10155 N_("CONTINUING"), /* 13 */
10156 N_("DUPLICATE/BAD BLOCKS CLONED"), /* 14 */
10157 N_("FILE DELETED"), /* 15 */
10158 N_("SUPPRESSED"), /* 16 */
10159 N_("UNLINKED"), /* 17 */
10160 N_("HTREE INDEX CLEARED"),/* 18 */
10161 N_("WILL RECREATE"), /* 19 */
10165 static const struct e2fsck_problem problem_table[] = {
10167 /* Pre-Pass 1 errors */
10169 /* Block bitmap not in group */
10170 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
10171 PROMPT_RELOCATE, PR_LATCH_RELOC },
10173 /* Inode bitmap not in group */
10174 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
10175 PROMPT_RELOCATE, PR_LATCH_RELOC },
10177 /* Inode table not in group */
10178 { PR_0_ITABLE_NOT_GROUP,
10179 N_("@i table for @g %g is not in @g. (@b %b)\n"
10180 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10181 PROMPT_RELOCATE, PR_LATCH_RELOC },
10183 /* Superblock corrupt */
10185 N_("\nThe @S could not be read or does not describe a correct ext2\n"
10186 "@f. If the @v is valid and it really contains an ext2\n"
10187 "@f (and not swap or ufs or something else), then the @S\n"
10188 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10189 " e2fsck -b %S <@v>\n\n"),
10190 PROMPT_NONE, PR_FATAL },
10192 /* Filesystem size is wrong */
10193 { PR_0_FS_SIZE_WRONG,
10194 N_("The @f size (according to the @S) is %b @bs\n"
10195 "The physical size of the @v is %c @bs\n"
10196 "Either the @S or the partition table is likely to be corrupt!\n"),
10199 /* Fragments not supported */
10200 { PR_0_NO_FRAGMENTS,
10201 N_("@S @b_size = %b, fragsize = %c.\n"
10202 "This version of e2fsck does not support fragment sizes different\n"
10203 "from the @b size.\n"),
10204 PROMPT_NONE, PR_FATAL },
10206 /* Bad blocks_per_group */
10207 { PR_0_BLOCKS_PER_GROUP,
10208 N_("@S @bs_per_group = %b, should have been %c\n"),
10209 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10211 /* Bad first_data_block */
10212 { PR_0_FIRST_DATA_BLOCK,
10213 N_("@S first_data_@b = %b, should have been %c\n"),
10214 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10216 /* Adding UUID to filesystem */
10218 N_("@f did not have a UUID; generating one.\n\n"),
10221 /* Relocate hint */
10222 { PR_0_RELOCATE_HINT,
10223 N_("Note: if there is several inode or block bitmap blocks\n"
10224 "which require relocation, or one part of the inode table\n"
10225 "which must be moved, you may wish to try running e2fsck\n"
10226 "with the '-b %S' option first. The problem may lie only\n"
10227 "with the primary block group descriptor, and the backup\n"
10228 "block group descriptor may be OK.\n\n"),
10229 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10231 /* Miscellaneous superblock corruption */
10232 { PR_0_MISC_CORRUPT_SUPER,
10233 N_("Corruption found in @S. (%s = %N).\n"),
10234 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10236 /* Error determing physical device size of filesystem */
10237 { PR_0_GETSIZE_ERROR,
10238 N_("Error determining size of the physical @v: %m\n"),
10239 PROMPT_NONE, PR_FATAL },
10241 /* Inode count in superblock is incorrect */
10242 { PR_0_INODE_COUNT_WRONG,
10243 N_("@i count in @S is %i, should be %j.\n"),
10246 { PR_0_HURD_CLEAR_FILETYPE,
10247 N_("The Hurd does not support the filetype feature.\n"),
10250 /* Journal inode is invalid */
10251 { PR_0_JOURNAL_BAD_INODE,
10252 N_("@S has a bad ext3 @j (@i %i).\n"),
10253 PROMPT_CLEAR, PR_PREEN_OK },
10255 /* The external journal has (unsupported) multiple filesystems */
10256 { PR_0_JOURNAL_UNSUPP_MULTIFS,
10257 N_("External @j has multiple @f users (unsupported).\n"),
10258 PROMPT_NONE, PR_FATAL },
10260 /* Can't find external journal */
10261 { PR_0_CANT_FIND_JOURNAL,
10262 N_("Can't find external @j\n"),
10263 PROMPT_NONE, PR_FATAL },
10265 /* External journal has bad superblock */
10266 { PR_0_EXT_JOURNAL_BAD_SUPER,
10267 N_("External @j has bad @S\n"),
10268 PROMPT_NONE, PR_FATAL },
10270 /* Superblock has a bad journal UUID */
10271 { PR_0_JOURNAL_BAD_UUID,
10272 N_("External @j does not support this @f\n"),
10273 PROMPT_NONE, PR_FATAL },
10275 /* Journal has an unknown superblock type */
10276 { PR_0_JOURNAL_UNSUPP_SUPER,
10277 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10278 "It is likely that your copy of e2fsck is old and/or doesn't "
10279 "support this @j format.\n"
10280 "It is also possible the @j @S is corrupt.\n"),
10281 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10283 /* Journal superblock is corrupt */
10284 { PR_0_JOURNAL_BAD_SUPER,
10285 N_("Ext3 @j @S is corrupt.\n"),
10286 PROMPT_FIX, PR_PREEN_OK },
10288 /* Superblock flag should be cleared */
10289 { PR_0_JOURNAL_HAS_JOURNAL,
10290 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10291 PROMPT_CLEAR, PR_PREEN_OK },
10293 /* Superblock flag is incorrect */
10294 { PR_0_JOURNAL_RECOVER_SET,
10295 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10296 PROMPT_CLEAR, PR_PREEN_OK },
10298 /* Journal has data, but recovery flag is clear */
10299 { PR_0_JOURNAL_RECOVERY_CLEAR,
10300 N_("ext3 recovery flag clear, but @j has data.\n"),
10303 /* Ask if we should clear the journal */
10304 { PR_0_JOURNAL_RESET_JOURNAL,
10306 PROMPT_NULL, PR_PREEN_NOMSG },
10308 /* Ask if we should run the journal anyway */
10309 { PR_0_JOURNAL_RUN,
10310 N_("Run @j anyway"),
10313 /* Run the journal by default */
10314 { PR_0_JOURNAL_RUN_DEFAULT,
10315 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10318 /* Clearing orphan inode */
10319 { PR_0_ORPHAN_CLEAR_INODE,
10320 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10323 /* Illegal block found in orphaned inode */
10324 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10325 N_("@I @b #%B (%b) found in @o @i %i.\n"),
10328 /* Already cleared block found in orphaned inode */
10329 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10330 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10333 /* Illegal orphan inode in superblock */
10334 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10335 N_("@I @o @i %i in @S.\n"),
10338 /* Illegal inode in orphaned inode list */
10339 { PR_0_ORPHAN_ILLEGAL_INODE,
10340 N_("@I @i %i in @o @i list.\n"),
10343 /* Filesystem revision is 0, but feature flags are set */
10344 { PR_0_FS_REV_LEVEL,
10345 "@f has feature flag(s) set, but is a revision 0 @f. ",
10346 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10348 /* Journal superblock has an unknown read-only feature flag set */
10349 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10350 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10353 /* Journal superblock has an unknown incompatible feature flag set */
10354 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10355 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10358 /* Journal has unsupported version number */
10359 { PR_0_JOURNAL_UNSUPP_VERSION,
10360 N_("@j version not supported by this e2fsck.\n"),
10363 /* Moving journal to hidden file */
10364 { PR_0_MOVE_JOURNAL,
10365 N_("Moving @j from /%s to hidden inode.\n\n"),
10368 /* Error moving journal to hidden file */
10369 { PR_0_ERR_MOVE_JOURNAL,
10370 N_("Error moving @j: %m\n\n"),
10373 /* Clearing V2 journal superblock */
10374 { PR_0_CLEAR_V2_JOURNAL,
10375 N_("Found invalid V2 @j @S fields (from V1 journal).\n"
10376 "Clearing fields beyond the V1 @j @S...\n\n"),
10379 /* Backup journal inode blocks */
10381 N_("Backing up @j @i @b information.\n\n"),
10384 /* Reserved blocks w/o resize_inode */
10385 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10386 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10387 "is %N; @s zero. "),
10390 /* Resize_inode not enabled, but resize inode is non-zero */
10391 { PR_0_CLEAR_RESIZE_INODE,
10392 N_("Resize_@i not enabled, but the resize inode is non-zero. "),
10395 /* Resize inode invalid */
10396 { PR_0_RESIZE_INODE_INVALID,
10397 N_("Resize @i not valid. "),
10398 PROMPT_RECREATE, 0 },
10400 /* Pass 1 errors */
10402 /* Pass 1: Checking inodes, blocks, and sizes */
10403 { PR_1_PASS_HEADER,
10404 N_("Pass 1: Checking @is, @bs, and sizes\n"),
10407 /* Root directory is not an inode */
10408 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
10411 /* Root directory has dtime set */
10413 N_("@r has dtime set (probably due to old mke2fs). "),
10414 PROMPT_FIX, PR_PREEN_OK },
10416 /* Reserved inode has bad mode */
10417 { PR_1_RESERVED_BAD_MODE,
10418 N_("Reserved @i %i %Q has bad mode. "),
10419 PROMPT_CLEAR, PR_PREEN_OK },
10421 /* Deleted inode has zero dtime */
10423 N_("@D @i %i has zero dtime. "),
10424 PROMPT_FIX, PR_PREEN_OK },
10426 /* Inode in use, but dtime set */
10428 N_("@i %i is in use, but has dtime set. "),
10429 PROMPT_FIX, PR_PREEN_OK },
10431 /* Zero-length directory */
10432 { PR_1_ZERO_LENGTH_DIR,
10433 N_("@i %i is a @z @d. "),
10434 PROMPT_CLEAR, PR_PREEN_OK },
10436 /* Block bitmap conflicts with some other fs block */
10437 { PR_1_BB_CONFLICT,
10438 N_("@g %g's @b @B at %b @C.\n"),
10439 PROMPT_RELOCATE, 0 },
10441 /* Inode bitmap conflicts with some other fs block */
10442 { PR_1_IB_CONFLICT,
10443 N_("@g %g's @i @B at %b @C.\n"),
10444 PROMPT_RELOCATE, 0 },
10446 /* Inode table conflicts with some other fs block */
10447 { PR_1_ITABLE_CONFLICT,
10448 N_("@g %g's @i table at %b @C.\n"),
10449 PROMPT_RELOCATE, 0 },
10451 /* Block bitmap is on a bad block */
10452 { PR_1_BB_BAD_BLOCK,
10453 N_("@g %g's @b @B (%b) is bad. "),
10454 PROMPT_RELOCATE, 0 },
10456 /* Inode bitmap is on a bad block */
10457 { PR_1_IB_BAD_BLOCK,
10458 N_("@g %g's @i @B (%b) is bad. "),
10459 PROMPT_RELOCATE, 0 },
10461 /* Inode has incorrect i_size */
10463 N_("@i %i, i_size is %Is, @s %N. "),
10464 PROMPT_FIX, PR_PREEN_OK },
10466 /* Inode has incorrect i_blocks */
10467 { PR_1_BAD_I_BLOCKS,
10468 N_("@i %i, i_@bs is %Ib, @s %N. "),
10469 PROMPT_FIX, PR_PREEN_OK },
10471 /* Illegal blocknumber in inode */
10472 { PR_1_ILLEGAL_BLOCK_NUM,
10473 N_("@I @b #%B (%b) in @i %i. "),
10474 PROMPT_CLEAR, PR_LATCH_BLOCK },
10476 /* Block number overlaps fs metadata */
10477 { PR_1_BLOCK_OVERLAPS_METADATA,
10478 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
10479 PROMPT_CLEAR, PR_LATCH_BLOCK },
10481 /* Inode has illegal blocks (latch question) */
10482 { PR_1_INODE_BLOCK_LATCH,
10483 N_("@i %i has illegal @b(s). "),
10486 /* Too many bad blocks in inode */
10487 { PR_1_TOO_MANY_BAD_BLOCKS,
10488 N_("Too many illegal @bs in @i %i.\n"),
10489 PROMPT_CLEAR_INODE, PR_NO_OK },
10491 /* Illegal block number in bad block inode */
10492 { PR_1_BB_ILLEGAL_BLOCK_NUM,
10493 N_("@I @b #%B (%b) in bad @b @i. "),
10494 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10496 /* Bad block inode has illegal blocks (latch question) */
10497 { PR_1_INODE_BBLOCK_LATCH,
10498 N_("Bad @b @i has illegal @b(s). "),
10501 /* Duplicate or bad blocks in use! */
10502 { PR_1_DUP_BLOCKS_PREENSTOP,
10503 N_("Duplicate or bad @b in use!\n"),
10506 /* Bad block used as bad block indirect block */
10507 { PR_1_BBINODE_BAD_METABLOCK,
10508 N_("Bad @b %b used as bad @b @i indirect @b. "),
10509 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10511 /* Inconsistency can't be fixed prompt */
10512 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10513 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
10514 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10516 PROMPT_CONTINUE, PR_PREEN_NOMSG },
10518 /* Bad primary block */
10519 { PR_1_BAD_PRIMARY_BLOCK,
10520 N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10521 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10523 /* Bad primary block prompt */
10524 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10525 N_("You can clear the this @b (and hope for the best) from the\n"
10526 "bad @b list and hope that @b is really OK, but there are no\n"
10527 "guarantees.\n\n"),
10528 PROMPT_CLEAR, PR_PREEN_NOMSG },
10530 /* Bad primary superblock */
10531 { PR_1_BAD_PRIMARY_SUPERBLOCK,
10532 N_("The primary @S (%b) is on the bad @b list.\n"),
10533 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10535 /* Bad primary block group descriptors */
10536 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10537 N_("Block %b in the primary @g descriptors "
10538 "is on the bad @b list\n"),
10539 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10541 /* Bad superblock in group */
10542 { PR_1_BAD_SUPERBLOCK,
10543 N_("Warning: Group %g's @S (%b) is bad.\n"),
10544 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10546 /* Bad block group descriptors in group */
10547 { PR_1_BAD_GROUP_DESCRIPTORS,
10548 N_("Warning: Group %g's copy of the @g descriptors has a bad "
10550 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10552 /* Block claimed for no reason */
10553 { PR_1_PROGERR_CLAIMED_BLOCK,
10554 N_("Programming error? @b #%b claimed for no reason in "
10555 "process_bad_@b.\n"),
10556 PROMPT_NONE, PR_PREEN_OK },
10558 /* Error allocating blocks for relocating metadata */
10559 { PR_1_RELOC_BLOCK_ALLOCATE,
10560 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10561 PROMPT_NONE, PR_PREEN_OK },
10563 /* Error allocating block buffer during relocation process */
10564 { PR_1_RELOC_MEMORY_ALLOCATE,
10565 N_("@A @b buffer for relocating %s\n"),
10566 PROMPT_NONE, PR_PREEN_OK },
10568 /* Relocating metadata group information from X to Y */
10569 { PR_1_RELOC_FROM_TO,
10570 N_("Relocating @g %g's %s from %b to %c...\n"),
10571 PROMPT_NONE, PR_PREEN_OK },
10573 /* Relocating metatdata group information to X */
10575 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10576 PROMPT_NONE, PR_PREEN_OK },
10578 /* Block read error during relocation process */
10579 { PR_1_RELOC_READ_ERR,
10580 N_("Warning: could not read @b %b of %s: %m\n"),
10581 PROMPT_NONE, PR_PREEN_OK },
10583 /* Block write error during relocation process */
10584 { PR_1_RELOC_WRITE_ERR,
10585 N_("Warning: could not write @b %b for %s: %m\n"),
10586 PROMPT_NONE, PR_PREEN_OK },
10588 /* Error allocating inode bitmap */
10589 { PR_1_ALLOCATE_IBITMAP_ERROR,
10590 "@A @i @B (%N): %m\n",
10591 PROMPT_NONE, PR_FATAL },
10593 /* Error allocating block bitmap */
10594 { PR_1_ALLOCATE_BBITMAP_ERROR,
10595 "@A @b @B (%N): %m\n",
10596 PROMPT_NONE, PR_FATAL },
10598 /* Error allocating icount structure */
10599 { PR_1_ALLOCATE_ICOUNT,
10600 N_("@A icount link information: %m\n"),
10601 PROMPT_NONE, PR_FATAL },
10603 /* Error allocating dbcount */
10604 { PR_1_ALLOCATE_DBCOUNT,
10605 N_("@A @d @b array: %m\n"),
10606 PROMPT_NONE, PR_FATAL },
10608 /* Error while scanning inodes */
10609 { PR_1_ISCAN_ERROR,
10610 N_("Error while scanning @is (%i): %m\n"),
10611 PROMPT_NONE, PR_FATAL },
10613 /* Error while iterating over blocks */
10614 { PR_1_BLOCK_ITERATE,
10615 N_("Error while iterating over @bs in @i %i: %m\n"),
10616 PROMPT_NONE, PR_FATAL },
10618 /* Error while storing inode count information */
10619 { PR_1_ICOUNT_STORE,
10620 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10621 PROMPT_NONE, PR_FATAL },
10623 /* Error while storing directory block information */
10625 N_("Error storing @d @b information "
10626 "(@i=%i, @b=%b, num=%N): %m\n"),
10627 PROMPT_NONE, PR_FATAL },
10629 /* Error while reading inode (for clearing) */
10631 N_("Error reading @i %i: %m\n"),
10632 PROMPT_NONE, PR_FATAL },
10634 /* Suppress messages prompt */
10635 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10637 /* Imagic flag set on an inode when filesystem doesn't support it */
10639 N_("@i %i has imagic flag set. "),
10642 /* Immutable flag set on a device or socket inode */
10643 { PR_1_SET_IMMUTABLE,
10644 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10645 "or append-only flag set. "),
10646 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10648 /* Compression flag set on an inode when filesystem doesn't support it */
10650 N_("@i %i has @cion flag set on @f without @cion support. "),
10653 /* Non-zero size for device, fifo or socket inode */
10654 { PR_1_SET_NONZSIZE,
10655 "Special (@v/socket/fifo) @i %i has non-zero size. ",
10656 PROMPT_FIX, PR_PREEN_OK },
10658 /* Filesystem revision is 0, but feature flags are set */
10659 { PR_1_FS_REV_LEVEL,
10660 "@f has feature flag(s) set, but is a revision 0 @f. ",
10661 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10663 /* Journal inode is not in use, but contains data */
10664 { PR_1_JOURNAL_INODE_NOT_CLEAR,
10665 "@j @i is not in use, but contains data. ",
10666 PROMPT_CLEAR, PR_PREEN_OK },
10668 /* Journal has bad mode */
10669 { PR_1_JOURNAL_BAD_MODE,
10670 N_("@j is not regular file. "),
10671 PROMPT_FIX, PR_PREEN_OK },
10673 /* Deal with inodes that were part of orphan linked list */
10675 N_("@i %i was part of the orphaned @i list. "),
10676 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10678 /* Deal with inodes that were part of corrupted orphan linked
10679 list (latch question) */
10680 { PR_1_ORPHAN_LIST_REFUGEES,
10681 N_("@is that were part of a corrupted orphan linked list found. "),
10684 /* Error allocating refcount structure */
10685 { PR_1_ALLOCATE_REFCOUNT,
10686 "@A refcount structure (%N): %m\n",
10687 PROMPT_NONE, PR_FATAL },
10689 /* Error reading extended attribute block */
10690 { PR_1_READ_EA_BLOCK,
10691 N_("Error reading @a @b %b for @i %i. "),
10694 /* Invalid extended attribute block */
10695 { PR_1_BAD_EA_BLOCK,
10696 N_("@i %i has a bad @a @b %b. "),
10699 /* Error reading Extended Attribute block while fixing refcount */
10700 { PR_1_EXTATTR_READ_ABORT,
10701 N_("Error reading @a @b %b (%m). "),
10704 /* Extended attribute reference count incorrect */
10705 { PR_1_EXTATTR_REFCOUNT,
10706 N_("@a @b %b has reference count %B, should be %N. "),
10709 /* Error writing Extended Attribute block while fixing refcount */
10710 { PR_1_EXTATTR_WRITE,
10711 N_("Error writing @a @b %b (%m). "),
10714 /* Multiple EA blocks not supported */
10715 { PR_1_EA_MULTI_BLOCK,
10716 N_("@a @b %b has h_blocks > 1. "),
10719 /* Error allocating EA region allocation structure */
10720 { PR_1_EA_ALLOC_REGION,
10721 N_("Error allocating @a @b %b. "),
10724 /* Error EA allocation collision */
10725 { PR_1_EA_ALLOC_COLLISION,
10726 N_("@a @b %b is corrupt (allocation collision). "),
10729 /* Bad extended attribute name */
10730 { PR_1_EA_BAD_NAME,
10731 N_("@a @b %b is corrupt (invalid name). "),
10734 /* Bad extended attribute value */
10735 { PR_1_EA_BAD_VALUE,
10736 N_("@a @b %b is corrupt (invalid value). "),
10739 /* Inode too big (latch question) */
10740 { PR_1_INODE_TOOBIG,
10741 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
10743 /* Directory too big */
10745 N_("@b #%B (%b) causes @d to be too big. "),
10746 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10748 /* Regular file too big */
10750 N_("@b #%B (%b) causes file to be too big. "),
10751 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10753 /* Symlink too big */
10754 { PR_1_TOOBIG_SYMLINK,
10755 N_("@b #%B (%b) causes symlink to be too big. "),
10756 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10758 /* INDEX_FL flag set on a non-HTREE filesystem */
10760 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10761 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10763 /* INDEX_FL flag set on a non-directory */
10764 { PR_1_HTREE_NODIR,
10765 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10766 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10768 /* Invalid root node in HTREE directory */
10769 { PR_1_HTREE_BADROOT,
10770 N_("@h %i has an invalid root node.\n"),
10771 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10773 /* Unsupported hash version in HTREE directory */
10774 { PR_1_HTREE_HASHV,
10775 N_("@h %i has an unsupported hash version (%N)\n"),
10776 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10778 /* Incompatible flag in HTREE root node */
10779 { PR_1_HTREE_INCOMPAT,
10780 N_("@h %i uses an incompatible htree root node flag.\n"),
10781 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10783 /* HTREE too deep */
10784 { PR_1_HTREE_DEPTH,
10785 N_("@h %i has a tree depth (%N) which is too big\n"),
10786 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10788 /* Bad block has indirect block that conflicts with filesystem block */
10789 { PR_1_BB_FS_BLOCK,
10790 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10792 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10794 /* Resize inode failed */
10795 { PR_1_RESIZE_INODE_CREATE,
10796 N_("Resize @i (re)creation failed: %m."),
10799 /* invalid inode->i_extra_isize */
10800 { PR_1_EXTRA_ISIZE,
10801 N_("@i %i has a extra size (%IS) which is invalid\n"),
10802 PROMPT_FIX, PR_PREEN_OK },
10804 /* invalid ea entry->e_name_len */
10805 { PR_1_ATTR_NAME_LEN,
10806 N_("@a in @i %i has a namelen (%N) which is invalid\n"),
10807 PROMPT_CLEAR, PR_PREEN_OK },
10809 /* invalid ea entry->e_value_size */
10810 { PR_1_ATTR_VALUE_SIZE,
10811 N_("@a in @i %i has a value size (%N) which is invalid\n"),
10812 PROMPT_CLEAR, PR_PREEN_OK },
10814 /* invalid ea entry->e_value_offs */
10815 { PR_1_ATTR_VALUE_OFFSET,
10816 N_("@a in @i %i has a value offset (%N) which is invalid\n"),
10817 PROMPT_CLEAR, PR_PREEN_OK },
10819 /* invalid ea entry->e_value_block */
10820 { PR_1_ATTR_VALUE_BLOCK,
10821 N_("@a in @i %i has a value block (%N) which is invalid (must be 0)\n"),
10822 PROMPT_CLEAR, PR_PREEN_OK },
10824 /* invalid ea entry->e_hash */
10826 N_("@a in @i %i has a hash (%N) which is invalid (must be 0)\n"),
10827 PROMPT_CLEAR, PR_PREEN_OK },
10829 /* Pass 1b errors */
10831 /* Pass 1B: Rescan for duplicate/bad blocks */
10832 { PR_1B_PASS_HEADER,
10833 N_("Duplicate @bs found... invoking duplicate @b passes.\n"
10834 "Pass 1B: Rescan for duplicate/bad @bs\n"),
10837 /* Duplicate/bad block(s) header */
10838 { PR_1B_DUP_BLOCK_HEADER,
10839 N_("Duplicate/bad @b(s) in @i %i:"),
10842 /* Duplicate/bad block(s) in inode */
10845 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10847 /* Duplicate/bad block(s) end */
10848 { PR_1B_DUP_BLOCK_END,
10850 PROMPT_NONE, PR_PREEN_NOHDR },
10852 /* Error while scanning inodes */
10853 { PR_1B_ISCAN_ERROR,
10854 N_("Error while scanning inodes (%i): %m\n"),
10855 PROMPT_NONE, PR_FATAL },
10857 /* Error allocating inode bitmap */
10858 { PR_1B_ALLOCATE_IBITMAP_ERROR,
10859 N_("@A @i @B (inode_dup_map): %m\n"),
10860 PROMPT_NONE, PR_FATAL },
10862 /* Error while iterating over blocks */
10863 { PR_1B_BLOCK_ITERATE,
10864 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10867 /* Error adjusting EA refcount */
10868 { PR_1B_ADJ_EA_REFCOUNT,
10869 N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
10873 /* Pass 1C: Scan directories for inodes with dup blocks. */
10874 { PR_1C_PASS_HEADER,
10875 N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
10879 /* Pass 1D: Reconciling duplicate blocks */
10880 { PR_1D_PASS_HEADER,
10881 N_("Pass 1D: Reconciling duplicate @bs\n"),
10884 /* File has duplicate blocks */
10886 N_("File %Q (@i #%i, mod time %IM) \n"
10887 " has %B duplicate @b(s), shared with %N file(s):\n"),
10890 /* List of files sharing duplicate blocks */
10891 { PR_1D_DUP_FILE_LIST,
10892 N_("\t%Q (@i #%i, mod time %IM)\n"),
10895 /* File sharing blocks with filesystem metadata */
10896 { PR_1D_SHARE_METADATA,
10897 N_("\t<@f metadata>\n"),
10900 /* Report of how many duplicate/bad inodes */
10901 { PR_1D_NUM_DUP_INODES,
10902 N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
10905 /* Duplicated blocks already reassigned or cloned. */
10906 { PR_1D_DUP_BLOCKS_DEALT,
10907 N_("Duplicated @bs already reassigned or cloned.\n\n"),
10910 /* Clone duplicate/bad blocks? */
10911 { PR_1D_CLONE_QUESTION,
10912 "", PROMPT_CLONE, PR_NO_OK },
10915 { PR_1D_DELETE_QUESTION,
10916 "", PROMPT_DELETE, 0 },
10918 /* Couldn't clone file (error) */
10919 { PR_1D_CLONE_ERROR,
10920 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10922 /* Pass 2 errors */
10924 /* Pass 2: Checking directory structure */
10925 { PR_2_PASS_HEADER,
10926 N_("Pass 2: Checking @d structure\n"),
10929 /* Bad inode number for '.' */
10930 { PR_2_BAD_INODE_DOT,
10931 N_("Bad @i number for '.' in @d @i %i.\n"),
10934 /* Directory entry has bad inode number */
10936 N_("@E has bad @i #: %Di.\n"),
10939 /* Directory entry has deleted or unused inode */
10940 { PR_2_UNUSED_INODE,
10941 N_("@E has @D/unused @i %Di. "),
10942 PROMPT_CLEAR, PR_PREEN_OK },
10944 /* Directry entry is link to '.' */
10946 N_("@E @L to '.' "),
10949 /* Directory entry points to inode now located in a bad block */
10951 N_("@E points to @i (%Di) located in a bad @b.\n"),
10954 /* Directory entry contains a link to a directory */
10956 N_("@E @L to @d %P (%Di).\n"),
10959 /* Directory entry contains a link to the root directry */
10961 N_("@E @L to the @r.\n"),
10964 /* Directory entry has illegal characters in its name */
10966 N_("@E has illegal characters in its name.\n"),
10969 /* Missing '.' in directory inode */
10970 { PR_2_MISSING_DOT,
10971 N_("Missing '.' in @d @i %i.\n"),
10974 /* Missing '..' in directory inode */
10975 { PR_2_MISSING_DOT_DOT,
10976 N_("Missing '..' in @d @i %i.\n"),
10979 /* First entry in directory inode doesn't contain '.' */
10980 { PR_2_1ST_NOT_DOT,
10981 N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
10984 /* Second entry in directory inode doesn't contain '..' */
10985 { PR_2_2ND_NOT_DOT_DOT,
10986 N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
10989 /* i_faddr should be zero */
10991 N_("i_faddr @F %IF, @s zero.\n"),
10994 /* i_file_acl should be zero */
10995 { PR_2_FILE_ACL_ZERO,
10996 N_("i_file_acl @F %If, @s zero.\n"),
10999 /* i_dir_acl should be zero */
11000 { PR_2_DIR_ACL_ZERO,
11001 N_("i_dir_acl @F %Id, @s zero.\n"),
11004 /* i_frag should be zero */
11006 N_("i_frag @F %N, @s zero.\n"),
11009 /* i_fsize should be zero */
11011 N_("i_fsize @F %N, @s zero.\n"),
11014 /* inode has bad mode */
11016 N_("@i %i (%Q) has a bad mode (%Im).\n"),
11019 /* directory corrupted */
11020 { PR_2_DIR_CORRUPTED,
11021 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
11022 PROMPT_SALVAGE, 0 },
11024 /* filename too long */
11025 { PR_2_FILENAME_LONG,
11026 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
11027 PROMPT_TRUNCATE, 0 },
11029 /* Directory inode has a missing block (hole) */
11030 { PR_2_DIRECTORY_HOLE,
11031 N_("@d @i %i has an unallocated @b #%B. "),
11032 PROMPT_ALLOCATE, 0 },
11034 /* '.' is not NULL terminated */
11035 { PR_2_DOT_NULL_TERM,
11036 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
11039 /* '..' is not NULL terminated */
11040 { PR_2_DOT_DOT_NULL_TERM,
11041 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
11044 /* Illegal character device inode */
11045 { PR_2_BAD_CHAR_DEV,
11046 N_("@i %i (%Q) is an @I character @v.\n"),
11049 /* Illegal block device inode */
11050 { PR_2_BAD_BLOCK_DEV,
11051 N_("@i %i (%Q) is an @I @b @v.\n"),
11054 /* Duplicate '.' entry */
11056 N_("@E is duplicate '.' @e.\n"),
11059 /* Duplicate '..' entry */
11060 { PR_2_DUP_DOT_DOT,
11061 N_("@E is duplicate '..' @e.\n"),
11064 /* Internal error: couldn't find dir_info */
11066 N_("Internal error: couldn't find dir_info for %i.\n"),
11067 PROMPT_NONE, PR_FATAL },
11069 /* Final rec_len is wrong */
11070 { PR_2_FINAL_RECLEN,
11071 N_("@E has rec_len of %Dr, should be %N.\n"),
11074 /* Error allocating icount structure */
11075 { PR_2_ALLOCATE_ICOUNT,
11076 N_("@A icount structure: %m\n"),
11077 PROMPT_NONE, PR_FATAL },
11079 /* Error iterating over directory blocks */
11080 { PR_2_DBLIST_ITERATE,
11081 N_("Error iterating over @d @bs: %m\n"),
11082 PROMPT_NONE, PR_FATAL },
11084 /* Error reading directory block */
11085 { PR_2_READ_DIRBLOCK,
11086 N_("Error reading @d @b %b (@i %i): %m\n"),
11087 PROMPT_CONTINUE, 0 },
11089 /* Error writing directory block */
11090 { PR_2_WRITE_DIRBLOCK,
11091 N_("Error writing @d @b %b (@i %i): %m\n"),
11092 PROMPT_CONTINUE, 0 },
11094 /* Error allocating new directory block */
11095 { PR_2_ALLOC_DIRBOCK,
11096 N_("@A new @d @b for @i %i (%s): %m\n"),
11099 /* Error deallocating inode */
11100 { PR_2_DEALLOC_INODE,
11101 N_("Error deallocating @i %i: %m\n"),
11102 PROMPT_NONE, PR_FATAL },
11104 /* Directory entry for '.' is big. Split? */
11106 N_("@d @e for '.' is big. "),
11107 PROMPT_SPLIT, PR_NO_OK },
11109 /* Illegal FIFO inode */
11111 N_("@i %i (%Q) is an @I FIFO.\n"),
11114 /* Illegal socket inode */
11116 N_("@i %i (%Q) is an @I socket.\n"),
11119 /* Directory filetype not set */
11120 { PR_2_SET_FILETYPE,
11121 N_("Setting filetype for @E to %N.\n"),
11122 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11124 /* Directory filetype incorrect */
11125 { PR_2_BAD_FILETYPE,
11126 N_("@E has an incorrect filetype (was %Dt, should be %N).\n"),
11129 /* Directory filetype set on filesystem */
11130 { PR_2_CLEAR_FILETYPE,
11131 N_("@E has filetype set.\n"),
11132 PROMPT_CLEAR, PR_PREEN_OK },
11134 /* Directory filename is null */
11136 N_("@E has a zero-length name.\n"),
11139 /* Invalid symlink */
11140 { PR_2_INVALID_SYMLINK,
11141 N_("Symlink %Q (@i #%i) is invalid.\n"),
11144 /* i_file_acl (extended attribute block) is bad */
11145 { PR_2_FILE_ACL_BAD,
11146 N_("@a @b @F invalid (%If).\n"),
11149 /* Filesystem contains large files, but has no such flag in sb */
11150 { PR_2_FEATURE_LARGE_FILES,
11151 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11154 /* Node in HTREE directory not referenced */
11155 { PR_2_HTREE_NOTREF,
11156 N_("@p @h %d: node (%B) not referenced\n"),
11159 /* Node in HTREE directory referenced twice */
11160 { PR_2_HTREE_DUPREF,
11161 N_("@p @h %d: node (%B) referenced twice\n"),
11164 /* Node in HTREE directory has bad min hash */
11165 { PR_2_HTREE_MIN_HASH,
11166 N_("@p @h %d: node (%B) has bad min hash\n"),
11169 /* Node in HTREE directory has bad max hash */
11170 { PR_2_HTREE_MAX_HASH,
11171 N_("@p @h %d: node (%B) has bad max hash\n"),
11174 /* Clear invalid HTREE directory */
11175 { PR_2_HTREE_CLEAR,
11176 N_("Invalid @h %d (%q). "), PROMPT_CLEAR, 0 },
11178 /* Bad block in htree interior node */
11179 { PR_2_HTREE_BADBLK,
11180 N_("@p @h %d (%q): bad @b number %b.\n"),
11181 PROMPT_CLEAR_HTREE, 0 },
11183 /* Error adjusting EA refcount */
11184 { PR_2_ADJ_EA_REFCOUNT,
11185 N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
11186 PROMPT_NONE, PR_FATAL },
11188 /* Invalid HTREE root node */
11189 { PR_2_HTREE_BAD_ROOT,
11190 N_("@p @h %d: root node is invalid\n"),
11191 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11193 /* Invalid HTREE limit */
11194 { PR_2_HTREE_BAD_LIMIT,
11195 N_("@p @h %d: node (%B) has bad limit (%N)\n"),
11196 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11198 /* Invalid HTREE count */
11199 { PR_2_HTREE_BAD_COUNT,
11200 N_("@p @h %d: node (%B) has bad count (%N)\n"),
11201 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11203 /* HTREE interior node has out-of-order hashes in table */
11204 { PR_2_HTREE_HASH_ORDER,
11205 N_("@p @h %d: node (%B) has an unordered hash table\n"),
11206 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11208 /* Node in HTREE directory has bad depth */
11209 { PR_2_HTREE_BAD_DEPTH,
11210 N_("@p @h %d: node (%B) has bad depth\n"),
11213 /* Duplicate directory entry found */
11214 { PR_2_DUPLICATE_DIRENT,
11215 N_("Duplicate @E found. "),
11218 /* Non-unique filename found */
11219 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11220 N_("@E has a non-unique filename.\nRename to %s"),
11223 /* Duplicate directory entry found */
11224 { PR_2_REPORT_DUP_DIRENT,
11225 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11228 /* Pass 3 errors */
11230 /* Pass 3: Checking directory connectivity */
11231 { PR_3_PASS_HEADER,
11232 N_("Pass 3: Checking @d connectivity\n"),
11235 /* Root inode not allocated */
11236 { PR_3_NO_ROOT_INODE,
11237 N_("@r not allocated. "),
11238 PROMPT_ALLOCATE, 0 },
11240 /* No room in lost+found */
11241 { PR_3_EXPAND_LF_DIR,
11242 N_("No room in @l @d. "),
11243 PROMPT_EXPAND, 0 },
11245 /* Unconnected directory inode */
11246 { PR_3_UNCONNECTED_DIR,
11247 N_("Unconnected @d @i %i (%p)\n"),
11248 PROMPT_CONNECT, 0 },
11250 /* /lost+found not found */
11252 N_("/@l not found. "),
11253 PROMPT_CREATE, PR_PREEN_OK },
11255 /* .. entry is incorrect */
11256 { PR_3_BAD_DOT_DOT,
11257 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11260 /* Bad or non-existent /lost+found. Cannot reconnect */
11262 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
11265 /* Could not expand /lost+found */
11266 { PR_3_CANT_EXPAND_LPF,
11267 N_("Could not expand /@l: %m\n"),
11270 /* Could not reconnect inode */
11271 { PR_3_CANT_RECONNECT,
11272 N_("Could not reconnect %i: %m\n"),
11275 /* Error while trying to find /lost+found */
11276 { PR_3_ERR_FIND_LPF,
11277 N_("Error while trying to find /@l: %m\n"),
11280 /* Error in ext2fs_new_block while creating /lost+found */
11281 { PR_3_ERR_LPF_NEW_BLOCK,
11282 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11285 /* Error in ext2fs_new_inode while creating /lost+found */
11286 { PR_3_ERR_LPF_NEW_INODE,
11287 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11290 /* Error in ext2fs_new_dir_block while creating /lost+found */
11291 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11292 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11295 /* Error while writing directory block for /lost+found */
11296 { PR_3_ERR_LPF_WRITE_BLOCK,
11297 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11300 /* Error while adjusting inode count */
11301 { PR_3_ADJUST_INODE,
11302 N_("Error while adjusting @i count on @i %i\n"),
11305 /* Couldn't fix parent directory -- error */
11306 { PR_3_FIX_PARENT_ERR,
11307 N_("Couldn't fix parent of @i %i: %m\n\n"),
11310 /* Couldn't fix parent directory -- couldn't find it */
11311 { PR_3_FIX_PARENT_NOFIND,
11312 N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
11315 /* Error allocating inode bitmap */
11316 { PR_3_ALLOCATE_IBITMAP_ERROR,
11317 N_("@A @i @B (%N): %m\n"),
11318 PROMPT_NONE, PR_FATAL },
11320 /* Error creating root directory */
11321 { PR_3_CREATE_ROOT_ERROR,
11322 N_("Error creating root @d (%s): %m\n"),
11323 PROMPT_NONE, PR_FATAL },
11325 /* Error creating lost and found directory */
11326 { PR_3_CREATE_LPF_ERROR,
11327 N_("Error creating /@l @d (%s): %m\n"),
11328 PROMPT_NONE, PR_FATAL },
11330 /* Root inode is not directory; aborting */
11331 { PR_3_ROOT_NOT_DIR_ABORT,
11332 N_("@r is not a @d; aborting.\n"),
11333 PROMPT_NONE, PR_FATAL },
11335 /* Cannot proceed without a root inode. */
11336 { PR_3_NO_ROOT_INODE_ABORT,
11337 N_("Cannot proceed without a @r.\n"),
11338 PROMPT_NONE, PR_FATAL },
11340 /* Internal error: couldn't find dir_info */
11342 N_("Internal error: couldn't find dir_info for %i.\n"),
11343 PROMPT_NONE, PR_FATAL },
11345 /* Lost+found not a directory */
11347 N_("/@l is not a @d (ino=%i)\n"),
11348 PROMPT_UNLINK, 0 },
11350 /* Pass 3A Directory Optimization */
11352 /* Pass 3A: Optimizing directories */
11353 { PR_3A_PASS_HEADER,
11354 N_("Pass 3A: Optimizing directories\n"),
11355 PROMPT_NONE, PR_PREEN_NOMSG },
11357 /* Error iterating over directories */
11358 { PR_3A_OPTIMIZE_ITER,
11359 N_("Failed to create dirs_to_hash iterator: %m"),
11362 /* Error rehash directory */
11363 { PR_3A_OPTIMIZE_DIR_ERR,
11364 N_("Failed to optimize directory %q (%d): %m"),
11367 /* Rehashing dir header */
11368 { PR_3A_OPTIMIZE_DIR_HEADER,
11369 N_("Optimizing directories: "),
11370 PROMPT_NONE, PR_MSG_ONLY },
11372 /* Rehashing directory %d */
11373 { PR_3A_OPTIMIZE_DIR,
11375 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11377 /* Rehashing dir end */
11378 { PR_3A_OPTIMIZE_DIR_END,
11380 PROMPT_NONE, PR_PREEN_NOHDR },
11382 /* Pass 4 errors */
11384 /* Pass 4: Checking reference counts */
11385 { PR_4_PASS_HEADER,
11386 N_("Pass 4: Checking reference counts\n"),
11389 /* Unattached zero-length inode */
11390 { PR_4_ZERO_LEN_INODE,
11392 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11394 /* Unattached inode */
11395 { PR_4_UNATTACHED_INODE,
11397 PROMPT_CONNECT, 0 },
11399 /* Inode ref count wrong */
11400 { PR_4_BAD_REF_COUNT,
11401 N_("@i %i ref count is %Il, @s %N. "),
11402 PROMPT_FIX, PR_PREEN_OK },
11404 { PR_4_INCONSISTENT_COUNT,
11405 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11406 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11407 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
11408 "They should be the same!\n"),
11411 /* Pass 5 errors */
11413 /* Pass 5: Checking group summary information */
11414 { PR_5_PASS_HEADER,
11415 N_("Pass 5: Checking @g summary information\n"),
11418 /* Padding at end of inode bitmap is not set. */
11419 { PR_5_INODE_BMAP_PADDING,
11420 N_("Padding at end of @i @B is not set. "),
11421 PROMPT_FIX, PR_PREEN_OK },
11423 /* Padding at end of block bitmap is not set. */
11424 { PR_5_BLOCK_BMAP_PADDING,
11425 N_("Padding at end of @b @B is not set. "),
11426 PROMPT_FIX, PR_PREEN_OK },
11428 /* Block bitmap differences header */
11429 { PR_5_BLOCK_BITMAP_HEADER,
11430 N_("@b @B differences: "),
11431 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11433 /* Block not used, but marked in bitmap */
11434 { PR_5_BLOCK_UNUSED,
11436 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11438 /* Block used, but not marked used in bitmap */
11441 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11443 /* Block bitmap differences end */
11444 { PR_5_BLOCK_BITMAP_END,
11446 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11448 /* Inode bitmap differences header */
11449 { PR_5_INODE_BITMAP_HEADER,
11450 N_("@i @B differences: "),
11451 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11453 /* Inode not used, but marked in bitmap */
11454 { PR_5_INODE_UNUSED,
11456 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11458 /* Inode used, but not marked used in bitmap */
11461 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11463 /* Inode bitmap differences end */
11464 { PR_5_INODE_BITMAP_END,
11466 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11468 /* Free inodes count for group wrong */
11469 { PR_5_FREE_INODE_COUNT_GROUP,
11470 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11471 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11473 /* Directories count for group wrong */
11474 { PR_5_FREE_DIR_COUNT_GROUP,
11475 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11476 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11478 /* Free inodes count wrong */
11479 { PR_5_FREE_INODE_COUNT,
11480 N_("Free @is count wrong (%i, counted=%j).\n"),
11481 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11483 /* Free blocks count for group wrong */
11484 { PR_5_FREE_BLOCK_COUNT_GROUP,
11485 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11486 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11488 /* Free blocks count wrong */
11489 { PR_5_FREE_BLOCK_COUNT,
11490 N_("Free @bs count wrong (%b, counted=%c).\n"),
11491 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11493 /* Programming error: bitmap endpoints don't match */
11494 { PR_5_BMAP_ENDPOINTS,
11495 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11496 "match calculated @B endpoints (%i, %j)\n"),
11497 PROMPT_NONE, PR_FATAL },
11499 /* Internal error: fudging end of bitmap */
11500 { PR_5_FUDGE_BITMAP_ERROR,
11501 N_("Internal error: fudging end of bitmap (%N)\n"),
11502 PROMPT_NONE, PR_FATAL },
11504 /* Error copying in replacement inode bitmap */
11505 { PR_5_COPY_IBITMAP_ERROR,
11506 "Error copying in replacement @i @B: %m\n",
11507 PROMPT_NONE, PR_FATAL },
11509 /* Error copying in replacement block bitmap */
11510 { PR_5_COPY_BBITMAP_ERROR,
11511 "Error copying in replacement @b @B: %m\n",
11512 PROMPT_NONE, PR_FATAL },
11514 /* Block range not used, but marked in bitmap */
11515 { PR_5_BLOCK_RANGE_UNUSED,
11517 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11519 /* Block range used, but not marked used in bitmap */
11520 { PR_5_BLOCK_RANGE_USED,
11522 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11524 /* Inode range not used, but marked in bitmap */
11525 { PR_5_INODE_RANGE_UNUSED,
11527 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11529 /* Inode range used, but not marked used in bitmap */
11530 { PR_5_INODE_RANGE_USED,
11532 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11538 * This is the latch flags register. It allows several problems to be
11539 * "latched" together. This means that the user has to answer but one
11540 * question for the set of problems, and all of the associated
11541 * problems will be either fixed or not fixed.
11543 static struct latch_descr pr_latch_info[] = {
11544 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11545 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11546 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11547 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11548 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11549 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11550 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11551 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11552 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11556 static const struct e2fsck_problem *find_problem(problem_t code)
11560 for (i=0; problem_table[i].e2p_code; i++) {
11561 if (problem_table[i].e2p_code == code)
11562 return &problem_table[i];
11567 static struct latch_descr *find_latch(int code)
11571 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11572 if (pr_latch_info[i].latch_code == code)
11573 return &pr_latch_info[i];
11578 int end_problem_latch(e2fsck_t ctx, int mask)
11580 struct latch_descr *ldesc;
11581 struct problem_context pctx;
11584 ldesc = find_latch(mask);
11585 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11586 clear_problem_context(&pctx);
11587 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11589 ldesc->flags &= ~(PRL_VARIABLE);
11593 int set_latch_flags(int mask, int setflags, int clearflags)
11595 struct latch_descr *ldesc;
11597 ldesc = find_latch(mask);
11600 ldesc->flags |= setflags;
11601 ldesc->flags &= ~clearflags;
11605 void clear_problem_context(struct problem_context *ctx)
11607 memset(ctx, 0, sizeof(struct problem_context));
11608 ctx->blkcount = -1;
11612 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11614 ext2_filsys fs = ctx->fs;
11615 const struct e2fsck_problem *ptr;
11616 struct latch_descr *ldesc = 0;
11617 const char *message;
11618 int def_yn, answer, ans;
11619 int print_answer = 0;
11622 ptr = find_problem(code);
11624 printf(_("Unhandled error code (0x%x)!\n"), code);
11628 if ((ptr->flags & PR_NO_DEFAULT) ||
11629 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11630 (ctx->options & E2F_OPT_NO))
11634 * Do special latch processing. This is where we ask the
11635 * latch question, if it exists
11637 if (ptr->flags & PR_LATCH_MASK) {
11638 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11639 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11640 ans = fix_problem(ctx, ldesc->question, pctx);
11642 ldesc->flags |= PRL_YES;
11644 ldesc->flags |= PRL_NO;
11645 ldesc->flags |= PRL_LATCHED;
11647 if (ldesc->flags & PRL_SUPPRESS)
11650 if ((ptr->flags & PR_PREEN_NOMSG) &&
11651 (ctx->options & E2F_OPT_PREEN))
11653 if ((ptr->flags & PR_NO_NOMSG) &&
11654 (ctx->options & E2F_OPT_NO))
11657 message = ptr->e2p_description;
11658 if ((ctx->options & E2F_OPT_PREEN) &&
11659 !(ptr->flags & PR_PREEN_NOHDR)) {
11660 printf("%s: ", ctx->device_name ?
11661 ctx->device_name : ctx->filesystem_name);
11664 print_e2fsck_message(ctx, _(message), pctx, 1);
11666 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11669 if (ptr->flags & PR_FATAL)
11670 fatal_error(ctx, 0);
11672 if (ptr->prompt == PROMPT_NONE) {
11673 if (ptr->flags & PR_NOCOLLATE)
11678 if (ctx->options & E2F_OPT_PREEN) {
11680 if (!(ptr->flags & PR_PREEN_NOMSG))
11682 } else if ((ptr->flags & PR_LATCH_MASK) &&
11683 (ldesc->flags & (PRL_YES | PRL_NO))) {
11686 if (ldesc->flags & PRL_YES)
11691 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11692 if (!answer && !(ptr->flags & PR_NO_OK))
11693 ext2fs_unmark_valid(fs);
11696 printf("%s.\n", answer ?
11697 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11701 if ((ptr->prompt == PROMPT_ABORT) && answer)
11702 fatal_error(ctx, 0);
11704 if (ptr->flags & PR_AFTER_CODE)
11705 answer = fix_problem(ctx, ptr->second_code, pctx);
11711 * linux/fs/recovery.c
11713 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11717 * Maintain information about the progress of the recovery job, so that
11718 * the different passes can carry information between them.
11720 struct recovery_info
11722 tid_t start_transaction;
11723 tid_t end_transaction;
11727 int nr_revoke_hits;
11730 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11731 static int do_one_pass(journal_t *journal,
11732 struct recovery_info *info, enum passtype pass);
11733 static int scan_revoke_records(journal_t *, struct buffer_head *,
11734 tid_t, struct recovery_info *);
11737 * Read a block from the journal
11740 static int jread(struct buffer_head **bhp, journal_t *journal,
11741 unsigned int offset)
11744 unsigned long blocknr;
11745 struct buffer_head *bh;
11749 J_ASSERT (offset < journal->j_maxlen);
11751 err = journal_bmap(journal, offset, &blocknr);
11754 printk (KERN_ERR "JBD: bad block at offset %u\n",
11759 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11763 if (!buffer_uptodate(bh)) {
11764 /* If this is a brand new buffer, start readahead.
11765 Otherwise, we assume we are already reading it. */
11766 if (!buffer_req(bh))
11767 do_readahead(journal, offset);
11768 wait_on_buffer(bh);
11771 if (!buffer_uptodate(bh)) {
11772 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11784 * Count the number of in-use tags in a journal descriptor block.
11787 static int count_tags(struct buffer_head *bh, int size)
11790 journal_block_tag_t * tag;
11793 tagp = &bh->b_data[sizeof(journal_header_t)];
11795 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11796 tag = (journal_block_tag_t *) tagp;
11799 tagp += sizeof(journal_block_tag_t);
11800 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11803 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11811 /* Make sure we wrap around the log correctly! */
11812 #define wrap(journal, var) \
11814 if (var >= (journal)->j_last) \
11815 var -= ((journal)->j_last - (journal)->j_first); \
11819 * int journal_recover(journal_t *journal) - recovers a on-disk journal
11820 * @journal: the journal to recover
11822 * The primary function for recovering the log contents when mounting a
11823 * journaled device.
11825 * Recovery is done in three passes. In the first pass, we look for the
11826 * end of the log. In the second, we assemble the list of revoke
11827 * blocks. In the third and final pass, we replay any un-revoked blocks
11830 int journal_recover(journal_t *journal)
11833 journal_superblock_t * sb;
11835 struct recovery_info info;
11837 memset(&info, 0, sizeof(info));
11838 sb = journal->j_superblock;
11841 * The journal superblock's s_start field (the current log head)
11842 * is always zero if, and only if, the journal was cleanly
11846 if (!sb->s_start) {
11847 jbd_debug(1, "No recovery required, last transaction %d\n",
11848 ntohl(sb->s_sequence));
11849 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11853 err = do_one_pass(journal, &info, PASS_SCAN);
11855 err = do_one_pass(journal, &info, PASS_REVOKE);
11857 err = do_one_pass(journal, &info, PASS_REPLAY);
11859 jbd_debug(0, "JBD: recovery, exit status %d, "
11860 "recovered transactions %u to %u\n",
11861 err, info.start_transaction, info.end_transaction);
11862 jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11863 info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11865 /* Restart the log at the next transaction ID, thus invalidating
11866 * any existing commit records in the log. */
11867 journal->j_transaction_sequence = ++info.end_transaction;
11869 journal_clear_revoke(journal);
11870 sync_blockdev(journal->j_fs_dev);
11874 static int do_one_pass(journal_t *journal,
11875 struct recovery_info *info, enum passtype pass)
11877 unsigned int first_commit_ID, next_commit_ID;
11878 unsigned long next_log_block;
11879 int err, success = 0;
11880 journal_superblock_t * sb;
11881 journal_header_t * tmp;
11882 struct buffer_head * bh;
11883 unsigned int sequence;
11886 /* Precompute the maximum metadata descriptors in a descriptor block */
11887 int MAX_BLOCKS_PER_DESC;
11888 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11889 / sizeof(journal_block_tag_t));
11892 * First thing is to establish what we expect to find in the log
11893 * (in terms of transaction IDs), and where (in terms of log
11894 * block offsets): query the superblock.
11897 sb = journal->j_superblock;
11898 next_commit_ID = ntohl(sb->s_sequence);
11899 next_log_block = ntohl(sb->s_start);
11901 first_commit_ID = next_commit_ID;
11902 if (pass == PASS_SCAN)
11903 info->start_transaction = first_commit_ID;
11905 jbd_debug(1, "Starting recovery pass %d\n", pass);
11908 * Now we walk through the log, transaction by transaction,
11909 * making sure that each transaction has a commit block in the
11910 * expected place. Each complete transaction gets replayed back
11911 * into the main filesystem.
11917 journal_block_tag_t * tag;
11918 struct buffer_head * obh;
11919 struct buffer_head * nbh;
11921 /* If we already know where to stop the log traversal,
11922 * check right now that we haven't gone past the end of
11925 if (pass != PASS_SCAN)
11926 if (tid_geq(next_commit_ID, info->end_transaction))
11929 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11930 next_commit_ID, next_log_block, journal->j_last);
11932 /* Skip over each chunk of the transaction looking
11933 * either the next descriptor block or the final commit
11936 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11937 err = jread(&bh, journal, next_log_block);
11942 wrap(journal, next_log_block);
11944 /* What kind of buffer is it?
11946 * If it is a descriptor block, check that it has the
11947 * expected sequence number. Otherwise, we're all done
11950 tmp = (journal_header_t *)bh->b_data;
11952 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11957 blocktype = ntohl(tmp->h_blocktype);
11958 sequence = ntohl(tmp->h_sequence);
11959 jbd_debug(3, "Found magic %d, sequence %d\n",
11960 blocktype, sequence);
11962 if (sequence != next_commit_ID) {
11967 /* OK, we have a valid descriptor block which matches
11968 * all of the sequence number checks. What are we going
11969 * to do with it? That depends on the pass... */
11971 switch(blocktype) {
11972 case JFS_DESCRIPTOR_BLOCK:
11973 /* If it is a valid descriptor block, replay it
11974 * in pass REPLAY; otherwise, just skip over the
11975 * blocks it describes. */
11976 if (pass != PASS_REPLAY) {
11978 count_tags(bh, journal->j_blocksize);
11979 wrap(journal, next_log_block);
11984 /* A descriptor block: we can now write all of
11985 * the data blocks. Yay, useful work is finally
11986 * getting done here! */
11988 tagp = &bh->b_data[sizeof(journal_header_t)];
11989 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11990 <= journal->j_blocksize) {
11991 unsigned long io_block;
11993 tag = (journal_block_tag_t *) tagp;
11994 flags = ntohl(tag->t_flags);
11996 io_block = next_log_block++;
11997 wrap(journal, next_log_block);
11998 err = jread(&obh, journal, io_block);
12000 /* Recover what we can, but
12001 * report failure at the end. */
12004 "JBD: IO error %d recovering "
12005 "block %ld in log\n",
12008 unsigned long blocknr;
12010 J_ASSERT(obh != NULL);
12011 blocknr = ntohl(tag->t_blocknr);
12013 /* If the block has been
12014 * revoked, then we're all done
12016 if (journal_test_revoke
12020 ++info->nr_revoke_hits;
12024 /* Find a buffer for the new
12025 * data being restored */
12026 nbh = getblk(journal->j_fs_dev,
12028 journal->j_blocksize);
12031 "JBD: Out of memory "
12032 "during recovery.\n");
12040 memcpy(nbh->b_data, obh->b_data,
12041 journal->j_blocksize);
12042 if (flags & JFS_FLAG_ESCAPE) {
12043 *((unsigned int *)bh->b_data) =
12044 htonl(JFS_MAGIC_NUMBER);
12047 BUFFER_TRACE(nbh, "marking dirty");
12048 mark_buffer_uptodate(nbh, 1);
12049 mark_buffer_dirty(nbh);
12050 BUFFER_TRACE(nbh, "marking uptodate");
12051 ++info->nr_replays;
12052 /* ll_rw_block(WRITE, 1, &nbh); */
12053 unlock_buffer(nbh);
12059 tagp += sizeof(journal_block_tag_t);
12060 if (!(flags & JFS_FLAG_SAME_UUID))
12063 if (flags & JFS_FLAG_LAST_TAG)
12070 case JFS_COMMIT_BLOCK:
12071 /* Found an expected commit block: not much to
12072 * do other than move on to the next sequence
12078 case JFS_REVOKE_BLOCK:
12079 /* If we aren't in the REVOKE pass, then we can
12080 * just skip over this block. */
12081 if (pass != PASS_REVOKE) {
12086 err = scan_revoke_records(journal, bh,
12087 next_commit_ID, info);
12094 jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12102 * We broke out of the log scan loop: either we came to the
12103 * known end of the log or we found an unexpected block in the
12104 * log. If the latter happened, then we know that the "current"
12105 * transaction marks the end of the valid log.
12108 if (pass == PASS_SCAN)
12109 info->end_transaction = next_commit_ID;
12111 /* It's really bad news if different passes end up at
12112 * different places (but possible due to IO errors). */
12113 if (info->end_transaction != next_commit_ID) {
12114 printk (KERN_ERR "JBD: recovery pass %d ended at "
12115 "transaction %u, expected %u\n",
12116 pass, next_commit_ID, info->end_transaction);
12129 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12131 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12132 tid_t sequence, struct recovery_info *info)
12134 journal_revoke_header_t *header;
12137 header = (journal_revoke_header_t *) bh->b_data;
12138 offset = sizeof(journal_revoke_header_t);
12139 max = ntohl(header->r_count);
12141 while (offset < max) {
12142 unsigned long blocknr;
12145 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12147 err = journal_set_revoke(journal, blocknr, sequence);
12150 ++info->nr_revokes;
12157 * rehash.c --- rebuild hash tree directories
12159 * This algorithm is designed for simplicity of implementation and to
12160 * pack the directory as much as possible. It however requires twice
12161 * as much memory as the size of the directory. The maximum size
12162 * directory supported using a 4k blocksize is roughly a gigabyte, and
12163 * so there may very well be problems with machines that don't have
12164 * virtual memory, and obscenely large directories.
12166 * An alternate algorithm which is much more disk intensive could be
12167 * written, and probably will need to be written in the future. The
12168 * design goals of such an algorithm are: (a) use (roughly) constant
12169 * amounts of memory, no matter how large the directory, (b) the
12170 * directory must be safe at all times, even if e2fsck is interrupted
12171 * in the middle, (c) we must use minimal amounts of extra disk
12172 * blocks. This pretty much requires an incremental approach, where
12173 * we are reading from one part of the directory, and inserting into
12174 * the front half. So the algorithm will have to keep track of a
12175 * moving block boundary between the new tree and the old tree, and
12176 * files will need to be moved from the old directory and inserted
12177 * into the new tree. If the new directory requires space which isn't
12178 * yet available, blocks from the beginning part of the old directory
12179 * may need to be moved to the end of the directory to make room for
12182 * --------------------------------------------------------
12183 * | new tree | | old tree |
12184 * --------------------------------------------------------
12186 * tail new head old
12188 * This is going to be a pain in the tuckus to implement, and will
12189 * require a lot more disk accesses. So I'm going to skip it for now;
12190 * it's only really going to be an issue for really, really big
12191 * filesystems (when we reach the level of tens of millions of files
12192 * in a single directory). It will probably be easier to simply
12193 * require that e2fsck use VM first.
12196 struct fill_dir_struct {
12198 struct ext2_inode *inode;
12201 struct hash_entry *harray;
12202 int max_array, num_array;
12208 struct hash_entry {
12209 ext2_dirhash_t hash;
12210 ext2_dirhash_t minor_hash;
12211 struct ext2_dir_entry *dir;
12218 ext2_dirhash_t *hashes;
12221 static int fill_dir_block(ext2_filsys fs,
12223 e2_blkcnt_t blockcnt,
12224 blk_t ref_block EXT2FS_ATTR((unused)),
12225 int ref_offset EXT2FS_ATTR((unused)),
12228 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
12229 struct hash_entry *new_array, *ent;
12230 struct ext2_dir_entry *dirent;
12232 unsigned int offset, dir_offset;
12237 offset = blockcnt * fs->blocksize;
12238 if (offset + fs->blocksize > fd->inode->i_size) {
12239 fd->err = EXT2_ET_DIR_CORRUPTED;
12240 return BLOCK_ABORT;
12242 dir = (fd->buf+offset);
12243 if (HOLE_BLKADDR(*block_nr)) {
12244 memset(dir, 0, fs->blocksize);
12245 dirent = (struct ext2_dir_entry *) dir;
12246 dirent->rec_len = fs->blocksize;
12248 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12250 return BLOCK_ABORT;
12252 /* While the directory block is "hot", index it. */
12254 while (dir_offset < fs->blocksize) {
12255 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12256 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12257 (dirent->rec_len < 8) ||
12258 ((dirent->rec_len % 4) != 0) ||
12259 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12260 fd->err = EXT2_ET_DIR_CORRUPTED;
12261 return BLOCK_ABORT;
12263 dir_offset += dirent->rec_len;
12264 if (dirent->inode == 0)
12266 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12267 (dirent->name[0] == '.'))
12269 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12270 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12271 fd->parent = dirent->inode;
12274 if (fd->num_array >= fd->max_array) {
12275 new_array = realloc(fd->harray,
12276 sizeof(struct hash_entry) * (fd->max_array+500));
12279 return BLOCK_ABORT;
12281 fd->harray = new_array;
12282 fd->max_array += 500;
12284 ent = fd->harray + fd->num_array++;
12286 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12288 ent->hash = ent->minor_hash = 0;
12290 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12292 dirent->name_len & 0xFF,
12293 fs->super->s_hash_seed,
12294 &ent->hash, &ent->minor_hash);
12296 return BLOCK_ABORT;
12303 /* Used for sorting the hash entry */
12304 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12306 const struct hash_entry *he_a = (const struct hash_entry *) a;
12307 const struct hash_entry *he_b = (const struct hash_entry *) b;
12311 min_len = he_a->dir->name_len;
12312 if (min_len > he_b->dir->name_len)
12313 min_len = he_b->dir->name_len;
12315 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12317 if (he_a->dir->name_len > he_b->dir->name_len)
12319 else if (he_a->dir->name_len < he_b->dir->name_len)
12322 ret = he_b->dir->inode - he_a->dir->inode;
12327 /* Used for sorting the hash entry */
12328 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12330 const struct hash_entry *he_a = (const struct hash_entry *) a;
12331 const struct hash_entry *he_b = (const struct hash_entry *) b;
12334 if (he_a->hash > he_b->hash)
12336 else if (he_a->hash < he_b->hash)
12339 if (he_a->minor_hash > he_b->minor_hash)
12341 else if (he_a->minor_hash < he_b->minor_hash)
12344 ret = name_cmp(a, b);
12349 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12355 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12358 outdir->buf = new_mem;
12359 new_mem = realloc(outdir->hashes,
12360 blocks * sizeof(ext2_dirhash_t));
12363 outdir->hashes = new_mem;
12365 outdir->buf = malloc(blocks * fs->blocksize);
12366 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12369 outdir->max = blocks;
12373 static void free_out_dir(struct out_dir *outdir)
12377 if (outdir->hashes)
12378 free(outdir->hashes);
12383 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12388 if (outdir->num >= outdir->max) {
12389 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12393 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12394 memset(*ret, 0, fs->blocksize);
12399 * This function is used to make a unique filename. We do this by
12400 * appending ~0, and then incrementing the number. However, we cannot
12401 * expand the length of the filename beyond the padding available in
12402 * the directory entry.
12404 static void mutate_name(char *str, __u16 *len)
12407 __u16 l = *len & 0xFF, h = *len & 0xff00;
12410 * First check to see if it looks the name has been mutated
12413 for (i = l-1; i > 0; i--) {
12414 if (!isdigit(str[i]))
12417 if ((i == l-1) || (str[i] != '~')) {
12418 if (((l-1) & 3) < 2)
12427 for (i = l-1; i >= 0; i--) {
12428 if (isdigit(str[i])) {
12440 else if (str[0] == 'Z') {
12445 } else if (i > 0) {
12458 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12460 struct fill_dir_struct *fd)
12462 struct problem_context pctx;
12463 struct hash_entry *ent, *prev;
12466 char new_name[256];
12469 clear_problem_context(&pctx);
12472 for (i=1; i < fd->num_array; i++) {
12473 ent = fd->harray + i;
12475 if (!ent->dir->inode ||
12476 ((ent->dir->name_len & 0xFF) !=
12477 (prev->dir->name_len & 0xFF)) ||
12478 (strncmp(ent->dir->name, prev->dir->name,
12479 ent->dir->name_len & 0xFF)))
12481 pctx.dirent = ent->dir;
12482 if ((ent->dir->inode == prev->dir->inode) &&
12483 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12484 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12485 ent->dir->inode = 0;
12489 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12490 new_len = ent->dir->name_len;
12491 mutate_name(new_name, &new_len);
12492 for (j=0; j < fd->num_array; j++) {
12494 ((ent->dir->name_len & 0xFF) !=
12495 (fd->harray[j].dir->name_len & 0xFF)) ||
12496 (strncmp(new_name, fd->harray[j].dir->name,
12499 mutate_name(new_name, &new_len);
12503 new_name[new_len & 0xFF] = 0;
12504 pctx.str = new_name;
12505 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12506 memcpy(ent->dir->name, new_name, new_len & 0xFF);
12507 ent->dir->name_len = new_len;
12508 ext2fs_dirhash(fs->super->s_def_hash_version,
12510 ent->dir->name_len & 0xFF,
12511 fs->super->s_hash_seed,
12512 &ent->hash, &ent->minor_hash);
12520 static errcode_t copy_dir_entries(ext2_filsys fs,
12521 struct fill_dir_struct *fd,
12522 struct out_dir *outdir)
12526 struct hash_entry *ent;
12527 struct ext2_dir_entry *dirent;
12528 int i, rec_len, left;
12529 ext2_dirhash_t prev_hash;
12533 retval = alloc_size_dir(fs, outdir,
12534 (fd->dir_size / fs->blocksize) + 2);
12537 outdir->num = fd->compress ? 0 : 1;
12539 outdir->hashes[0] = 0;
12541 if ((retval = get_next_block(fs, outdir, &block_start)))
12543 dirent = (struct ext2_dir_entry *) block_start;
12544 left = fs->blocksize;
12545 for (i=0; i < fd->num_array; i++) {
12546 ent = fd->harray + i;
12547 if (ent->dir->inode == 0)
12549 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12550 if (rec_len > left) {
12552 dirent->rec_len += left;
12553 if ((retval = get_next_block(fs, outdir,
12558 left = fs->blocksize - offset;
12559 dirent = (struct ext2_dir_entry *) (block_start + offset);
12561 if (ent->hash == prev_hash)
12562 outdir->hashes[outdir->num-1] = ent->hash | 1;
12564 outdir->hashes[outdir->num-1] = ent->hash;
12566 dirent->inode = ent->dir->inode;
12567 dirent->name_len = ent->dir->name_len;
12568 dirent->rec_len = rec_len;
12569 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12573 dirent->rec_len += left;
12577 prev_hash = ent->hash;
12580 dirent->rec_len += left;
12586 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12587 ext2_ino_t ino, ext2_ino_t parent)
12589 struct ext2_dir_entry *dir;
12590 struct ext2_dx_root_info *root;
12591 struct ext2_dx_countlimit *limits;
12594 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12595 filetype = EXT2_FT_DIR << 8;
12597 memset(buf, 0, fs->blocksize);
12598 dir = (struct ext2_dir_entry *) buf;
12600 dir->name[0] = '.';
12601 dir->name_len = 1 | filetype;
12603 dir = (struct ext2_dir_entry *) (buf + 12);
12604 dir->inode = parent;
12605 dir->name[0] = '.';
12606 dir->name[1] = '.';
12607 dir->name_len = 2 | filetype;
12608 dir->rec_len = fs->blocksize - 12;
12610 root = (struct ext2_dx_root_info *) (buf+24);
12611 root->reserved_zero = 0;
12612 root->hash_version = fs->super->s_def_hash_version;
12613 root->info_length = 8;
12614 root->indirect_levels = 0;
12615 root->unused_flags = 0;
12617 limits = (struct ext2_dx_countlimit *) (buf+32);
12618 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12625 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12627 struct ext2_dir_entry *dir;
12628 struct ext2_dx_countlimit *limits;
12630 memset(buf, 0, fs->blocksize);
12631 dir = (struct ext2_dir_entry *) buf;
12633 dir->rec_len = fs->blocksize;
12635 limits = (struct ext2_dx_countlimit *) (buf+8);
12636 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12639 return (struct ext2_dx_entry *) limits;
12643 * This function takes the leaf nodes which have been written in
12644 * outdir, and populates the root node and any necessary interior nodes.
12646 static errcode_t calculate_tree(ext2_filsys fs,
12647 struct out_dir *outdir,
12651 struct ext2_dx_root_info *root_info;
12652 struct ext2_dx_entry *root, *dx_ent = 0;
12653 struct ext2_dx_countlimit *root_limit, *limit;
12655 char * block_start;
12656 int i, c1, c2, nblks;
12657 int limit_offset, root_offset;
12659 root_info = set_root_node(fs, outdir->buf, ino, parent);
12660 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12661 root_info->info_length;
12662 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12663 c1 = root_limit->limit;
12664 nblks = outdir->num;
12666 /* Write out the pointer blocks */
12667 if (nblks-1 <= c1) {
12668 /* Just write out the root block, and we're done */
12669 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12670 for (i=1; i < nblks; i++) {
12671 root->block = ext2fs_cpu_to_le32(i);
12674 ext2fs_cpu_to_le32(outdir->hashes[i]);
12681 root_info->indirect_levels = 1;
12682 for (i=1; i < nblks; i++) {
12687 limit->limit = limit->count =
12688 ext2fs_cpu_to_le16(limit->limit);
12689 root = (struct ext2_dx_entry *)
12690 (outdir->buf + root_offset);
12691 root->block = ext2fs_cpu_to_le32(outdir->num);
12694 ext2fs_cpu_to_le32(outdir->hashes[i]);
12695 if ((retval = get_next_block(fs, outdir,
12698 dx_ent = set_int_node(fs, block_start);
12699 limit = (struct ext2_dx_countlimit *) dx_ent;
12701 root_offset += sizeof(struct ext2_dx_entry);
12704 dx_ent->block = ext2fs_cpu_to_le32(i);
12705 if (c2 != limit->limit)
12707 ext2fs_cpu_to_le32(outdir->hashes[i]);
12711 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12712 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12714 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12715 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12716 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12721 struct write_dir_struct {
12722 struct out_dir *outdir;
12729 * Helper function which writes out a directory block.
12731 static int write_dir_block(ext2_filsys fs,
12733 e2_blkcnt_t blockcnt,
12734 blk_t ref_block EXT2FS_ATTR((unused)),
12735 int ref_offset EXT2FS_ATTR((unused)),
12738 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12742 if (*block_nr == 0)
12744 if (blockcnt >= wd->outdir->num) {
12745 e2fsck_read_bitmaps(wd->ctx);
12747 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12748 ext2fs_block_alloc_stats(fs, blk, -1);
12751 return BLOCK_CHANGED;
12756 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12757 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12759 return BLOCK_ABORT;
12763 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12764 struct out_dir *outdir,
12765 ext2_ino_t ino, int compress)
12767 struct write_dir_struct wd;
12769 struct ext2_inode inode;
12771 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12775 wd.outdir = outdir;
12780 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12781 write_dir_block, &wd);
12787 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12789 inode.i_flags &= ~EXT2_INDEX_FL;
12791 inode.i_flags |= EXT2_INDEX_FL;
12792 inode.i_size = outdir->num * fs->blocksize;
12793 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12794 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12799 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12801 ext2_filsys fs = ctx->fs;
12803 struct ext2_inode inode;
12805 struct fill_dir_struct fd;
12806 struct out_dir outdir;
12808 outdir.max = outdir.num = 0;
12811 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12815 dir_buf = malloc(inode.i_size);
12819 fd.max_array = inode.i_size / 32;
12821 fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12831 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12832 (inode.i_size / fs->blocksize) < 2)
12836 /* Read in the entire directory into memory */
12837 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12838 fill_dir_block, &fd);
12845 printf("%d entries (%d bytes) found in inode %d\n",
12846 fd.num_array, fd.dir_size, ino);
12849 /* Sort the list */
12852 qsort(fd.harray+2, fd.num_array-2,
12853 sizeof(struct hash_entry), name_cmp);
12855 qsort(fd.harray, fd.num_array,
12856 sizeof(struct hash_entry), hash_cmp);
12859 * Look for duplicates
12861 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12864 if (ctx->options & E2F_OPT_NO) {
12870 * Copy the directory entries. In a htree directory these
12871 * will become the leaf nodes.
12873 retval = copy_dir_entries(fs, &fd, &outdir);
12877 free(dir_buf); dir_buf = 0;
12879 if (!fd.compress) {
12880 /* Calculate the interior nodes */
12881 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12886 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12896 free_out_dir(&outdir);
12900 void e2fsck_rehash_directories(e2fsck_t ctx)
12902 struct problem_context pctx;
12903 #ifdef RESOURCE_TRACK
12904 struct resource_track rtrack;
12906 struct dir_info *dir;
12907 ext2_u32_iterate iter;
12910 int i, cur, max, all_dirs, dir_index, first = 1;
12912 #ifdef RESOURCE_TRACK
12913 init_resource_track(&rtrack);
12916 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12918 if (!ctx->dirs_to_hash && !all_dirs)
12921 e2fsck_get_lost_and_found(ctx, 0);
12923 clear_problem_context(&pctx);
12925 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12929 max = e2fsck_get_num_dirinfo(ctx);
12931 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12934 pctx.errcode = retval;
12935 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12938 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12942 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12946 if (!ext2fs_u32_list_iterate(iter, &ino))
12949 if (ino == ctx->lost_and_found)
12953 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12957 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12959 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12960 if (pctx.errcode) {
12961 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12962 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12964 if (ctx->progress && !ctx->progress_fd)
12965 e2fsck_simple_progress(ctx, "Rebuilding directory",
12966 100.0 * (float) (++cur) / (float) max, ino);
12968 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12970 ext2fs_u32_list_iterate_end(iter);
12972 if (ctx->dirs_to_hash)
12973 ext2fs_u32_list_free(ctx->dirs_to_hash);
12974 ctx->dirs_to_hash = 0;
12976 #ifdef RESOURCE_TRACK
12977 if (ctx->options & E2F_OPT_TIME2) {
12978 e2fsck_clear_progbar(ctx);
12979 print_resource_track("Pass 3A", &rtrack);
12985 * linux/fs/revoke.c
12987 * Journal revoke routines for the generic filesystem journaling code;
12988 * part of the ext2fs journaling system.
12990 * Revoke is the mechanism used to prevent old log records for deleted
12991 * metadata from being replayed on top of newer data using the same
12992 * blocks. The revoke mechanism is used in two separate places:
12994 * + Commit: during commit we write the entire list of the current
12995 * transaction's revoked blocks to the journal
12997 * + Recovery: during recovery we record the transaction ID of all
12998 * revoked blocks. If there are multiple revoke records in the log
12999 * for a single block, only the last one counts, and if there is a log
13000 * entry for a block beyond the last revoke, then that log entry still
13003 * We can get interactions between revokes and new log data within a
13004 * single transaction:
13006 * Block is revoked and then journaled:
13007 * The desired end result is the journaling of the new block, so we
13008 * cancel the revoke before the transaction commits.
13010 * Block is journaled and then revoked:
13011 * The revoke must take precedence over the write of the block, so we
13012 * need either to cancel the journal entry or to write the revoke
13013 * later in the log than the log block. In this case, we choose the
13014 * latter: journaling a block cancels any revoke record for that block
13015 * in the current transaction, so any revoke for that block in the
13016 * transaction must have happened after the block was journaled and so
13017 * the revoke must take precedence.
13019 * Block is revoked and then written as data:
13020 * The data write is allowed to succeed, but the revoke is _not_
13021 * cancelled. We still need to prevent old log records from
13022 * overwriting the new data. We don't even need to clear the revoke
13025 * Revoke information on buffers is a tri-state value:
13027 * RevokeValid clear: no cached revoke status, need to look it up
13028 * RevokeValid set, Revoked clear:
13029 * buffer has not been revoked, and cancel_revoke
13031 * RevokeValid set, Revoked set:
13032 * buffer has been revoked.
13035 static kmem_cache_t *revoke_record_cache;
13036 static kmem_cache_t *revoke_table_cache;
13038 /* Each revoke record represents one single revoked block. During
13039 journal replay, this involves recording the transaction ID of the
13040 last transaction to revoke this block. */
13042 struct jbd_revoke_record_s
13044 struct list_head hash;
13045 tid_t sequence; /* Used for recovery only */
13046 unsigned long blocknr;
13050 /* The revoke table is just a simple hash table of revoke records. */
13051 struct jbd_revoke_table_s
13053 /* It is conceivable that we might want a larger hash table
13054 * for recovery. Must be a power of two. */
13057 struct list_head *hash_table;
13061 /* Utility functions to maintain the revoke table */
13063 /* Borrowed from buffer.c: this is a tried and tested block hash function */
13064 static inline int hash(journal_t *journal, unsigned long block)
13066 struct jbd_revoke_table_s *table = journal->j_revoke;
13067 int hash_shift = table->hash_shift;
13069 return ((block << (hash_shift - 6)) ^
13071 (block << (hash_shift - 12))) & (table->hash_size - 1);
13074 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
13077 struct list_head *hash_list;
13078 struct jbd_revoke_record_s *record;
13080 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13084 record->sequence = seq;
13085 record->blocknr = blocknr;
13086 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13087 list_add(&record->hash, hash_list);
13094 /* Find a revoke record in the journal's hash table. */
13096 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13097 unsigned long blocknr)
13099 struct list_head *hash_list;
13100 struct jbd_revoke_record_s *record;
13102 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13104 record = (struct jbd_revoke_record_s *) hash_list->next;
13105 while (&(record->hash) != hash_list) {
13106 if (record->blocknr == blocknr)
13108 record = (struct jbd_revoke_record_s *) record->hash.next;
13113 int journal_init_revoke_caches(void)
13115 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13116 if (revoke_record_cache == 0)
13119 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13120 if (revoke_table_cache == 0) {
13121 do_cache_destroy(revoke_record_cache);
13122 revoke_record_cache = NULL;
13128 void journal_destroy_revoke_caches(void)
13130 do_cache_destroy(revoke_record_cache);
13131 revoke_record_cache = 0;
13132 do_cache_destroy(revoke_table_cache);
13133 revoke_table_cache = 0;
13136 /* Initialise the revoke table for a given journal to a given size. */
13138 int journal_init_revoke(journal_t *journal, int hash_size)
13142 J_ASSERT (journal->j_revoke == NULL);
13144 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13145 if (!journal->j_revoke)
13148 /* Check that the hash_size is a power of two */
13149 J_ASSERT ((hash_size & (hash_size-1)) == 0);
13151 journal->j_revoke->hash_size = hash_size;
13155 while((tmp >>= 1UL) != 0UL)
13157 journal->j_revoke->hash_shift = shift;
13159 journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13160 if (!journal->j_revoke->hash_table) {
13161 free(journal->j_revoke);
13162 journal->j_revoke = NULL;
13166 for (tmp = 0; tmp < hash_size; tmp++)
13167 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13172 /* Destoy a journal's revoke table. The table must already be empty! */
13174 void journal_destroy_revoke(journal_t *journal)
13176 struct jbd_revoke_table_s *table;
13177 struct list_head *hash_list;
13180 table = journal->j_revoke;
13184 for (i=0; i<table->hash_size; i++) {
13185 hash_list = &table->hash_table[i];
13186 J_ASSERT (list_empty(hash_list));
13189 free(table->hash_table);
13191 journal->j_revoke = NULL;
13195 * Revoke support for recovery.
13197 * Recovery needs to be able to:
13199 * record all revoke records, including the tid of the latest instance
13200 * of each revoke in the journal
13202 * check whether a given block in a given transaction should be replayed
13203 * (ie. has not been revoked by a revoke record in that or a subsequent
13206 * empty the revoke table after recovery.
13210 * First, setting revoke records. We create a new revoke record for
13211 * every block ever revoked in the log as we scan it for recovery, and
13212 * we update the existing records if we find multiple revokes for a
13216 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13219 struct jbd_revoke_record_s *record;
13221 record = find_revoke_record(journal, blocknr);
13223 /* If we have multiple occurences, only record the
13224 * latest sequence number in the hashed record */
13225 if (tid_gt(sequence, record->sequence))
13226 record->sequence = sequence;
13229 return insert_revoke_hash(journal, blocknr, sequence);
13233 * Test revoke records. For a given block referenced in the log, has
13234 * that block been revoked? A revoke record with a given transaction
13235 * sequence number revokes all blocks in that transaction and earlier
13236 * ones, but later transactions still need replayed.
13239 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13242 struct jbd_revoke_record_s *record;
13244 record = find_revoke_record(journal, blocknr);
13247 if (tid_gt(sequence, record->sequence))
13253 * Finally, once recovery is over, we need to clear the revoke table so
13254 * that it can be reused by the running filesystem.
13257 void journal_clear_revoke(journal_t *journal)
13260 struct list_head *hash_list;
13261 struct jbd_revoke_record_s *record;
13262 struct jbd_revoke_table_s *revoke_var;
13264 revoke_var = journal->j_revoke;
13266 for (i = 0; i < revoke_var->hash_size; i++) {
13267 hash_list = &revoke_var->hash_table[i];
13268 while (!list_empty(hash_list)) {
13269 record = (struct jbd_revoke_record_s*) hash_list->next;
13270 list_del(&record->hash);
13277 * e2fsck.c - superblock checks
13280 #define MIN_CHECK 1
13281 #define MAX_CHECK 2
13283 static void check_super_value(e2fsck_t ctx, const char *descr,
13284 unsigned long value, int flags,
13285 unsigned long min_val, unsigned long max_val)
13287 struct problem_context pctx;
13289 if (((flags & MIN_CHECK) && (value < min_val)) ||
13290 ((flags & MAX_CHECK) && (value > max_val))) {
13291 clear_problem_context(&pctx);
13294 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13295 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13300 * This routine may get stubbed out in special compilations of the
13303 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13304 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13306 return (ext2fs_get_device_size(ctx->filesystem_name,
13307 EXT2_BLOCK_SIZE(ctx->fs->super),
13308 &ctx->num_blocks));
13313 * helper function to release an inode
13315 struct process_block_struct {
13318 struct problem_context *pctx;
13320 int truncate_offset;
13321 e2_blkcnt_t truncate_block;
13322 int truncated_blocks;
13327 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13328 e2_blkcnt_t blockcnt,
13329 blk_t ref_blk EXT2FS_ATTR((unused)),
13330 int ref_offset EXT2FS_ATTR((unused)),
13333 struct process_block_struct *pb;
13335 struct problem_context *pctx;
13336 blk_t blk = *block_nr;
13339 pb = (struct process_block_struct *) priv_data;
13344 pctx->blkcount = blockcnt;
13346 if (HOLE_BLKADDR(blk))
13349 if ((blk < fs->super->s_first_data_block) ||
13350 (blk >= fs->super->s_blocks_count)) {
13351 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13354 return BLOCK_ABORT;
13357 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13358 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13363 * If we are deleting an orphan, then we leave the fields alone.
13364 * If we are truncating an orphan, then update the inode fields
13365 * and clean up any partial block data.
13367 if (pb->truncating) {
13369 * We only remove indirect blocks if they are
13370 * completely empty.
13372 if (blockcnt < 0) {
13376 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13381 limit = fs->blocksize >> 2;
13382 for (i = 0, bp = (blk_t *) pb->buf;
13383 i < limit; i++, bp++)
13388 * We don't remove direct blocks until we've reached
13389 * the truncation block.
13391 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13394 * If part of the last block needs truncating, we do
13397 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13398 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13402 memset(pb->buf + pb->truncate_offset, 0,
13403 fs->blocksize - pb->truncate_offset);
13404 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13409 pb->truncated_blocks++;
13411 retval |= BLOCK_CHANGED;
13414 ext2fs_block_alloc_stats(fs, blk, -1);
13419 * This function releases an inode. Returns 1 if an inconsistency was
13420 * found. If the inode has a link count, then it is being truncated and
13423 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13424 struct ext2_inode *inode, char *block_buf,
13425 struct problem_context *pctx)
13427 struct process_block_struct pb;
13428 ext2_filsys fs = ctx->fs;
13432 if (!ext2fs_inode_has_valid_blocks(inode))
13435 pb.buf = block_buf + 3 * ctx->fs->blocksize;
13440 if (inode->i_links_count) {
13442 pb.truncate_block = (e2_blkcnt_t)
13443 ((((long long)inode->i_size_high << 32) +
13444 inode->i_size + fs->blocksize - 1) /
13446 pb.truncate_offset = inode->i_size % fs->blocksize;
13449 pb.truncate_block = 0;
13450 pb.truncate_offset = 0;
13452 pb.truncated_blocks = 0;
13453 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13454 block_buf, release_inode_block, &pb);
13456 com_err("release_inode_blocks", retval,
13457 _("while calling ext2fs_block_iterate for inode %d"),
13464 /* Refresh the inode since ext2fs_block_iterate may have changed it */
13465 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13467 if (pb.truncated_blocks)
13468 inode->i_blocks -= pb.truncated_blocks *
13469 (fs->blocksize / 512);
13471 if (inode->i_file_acl) {
13472 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13473 block_buf, -1, &count);
13474 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13479 com_err("release_inode_blocks", retval,
13480 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13485 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13486 inode->i_file_acl = 0;
13492 * This function releases all of the orphan inodes. It returns 1 if
13493 * it hit some error, and 0 on success.
13495 static int release_orphan_inodes(e2fsck_t ctx)
13497 ext2_filsys fs = ctx->fs;
13498 ext2_ino_t ino, next_ino;
13499 struct ext2_inode inode;
13500 struct problem_context pctx;
13503 if ((ino = fs->super->s_last_orphan) == 0)
13507 * Win or lose, we won't be using the head of the orphan inode
13510 fs->super->s_last_orphan = 0;
13511 ext2fs_mark_super_dirty(fs);
13514 * If the filesystem contains errors, don't run the orphan
13515 * list, since the orphan list can't be trusted; and we're
13516 * going to be running a full e2fsck run anyway...
13518 if (fs->super->s_state & EXT2_ERROR_FS)
13521 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13522 (ino > fs->super->s_inodes_count)) {
13523 clear_problem_context(&pctx);
13525 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13529 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13530 "block iterate buffer");
13531 e2fsck_read_bitmaps(ctx);
13534 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13535 clear_problem_context(&pctx);
13537 pctx.inode = &inode;
13538 pctx.str = inode.i_links_count ? _("Truncating") :
13541 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13543 next_ino = inode.i_dtime;
13545 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13546 (next_ino > fs->super->s_inodes_count))) {
13547 pctx.ino = next_ino;
13548 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13552 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13555 if (!inode.i_links_count) {
13556 ext2fs_inode_alloc_stats2(fs, ino, -1,
13557 LINUX_S_ISDIR(inode.i_mode));
13558 inode.i_dtime = time(0);
13562 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13565 ext2fs_free_mem(&block_buf);
13568 ext2fs_free_mem(&block_buf);
13573 * Check the resize inode to make sure it is sane. We check both for
13574 * the case where on-line resizing is not enabled (in which case the
13575 * resize inode should be cleared) as well as the case where on-line
13576 * resizing is enabled.
13578 static void check_resize_inode(e2fsck_t ctx)
13580 ext2_filsys fs = ctx->fs;
13581 struct ext2_inode inode;
13582 struct problem_context pctx;
13583 int i, j, gdt_off, ind_off;
13584 blk_t blk, pblk, expect;
13585 __u32 *dind_buf = 0, *ind_buf;
13588 clear_problem_context(&pctx);
13591 * If the resize inode feature isn't set, then
13592 * s_reserved_gdt_blocks must be zero.
13594 if (!(fs->super->s_feature_compat &
13595 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13596 if (fs->super->s_reserved_gdt_blocks) {
13597 pctx.num = fs->super->s_reserved_gdt_blocks;
13598 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13600 fs->super->s_reserved_gdt_blocks = 0;
13601 ext2fs_mark_super_dirty(fs);
13606 /* Read the resizde inode */
13607 pctx.ino = EXT2_RESIZE_INO;
13608 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13610 if (fs->super->s_feature_compat &
13611 EXT2_FEATURE_COMPAT_RESIZE_INODE)
13612 ctx->flags |= E2F_FLAG_RESIZE_INODE;
13617 * If the resize inode feature isn't set, check to make sure
13618 * the resize inode is cleared; then we're done.
13620 if (!(fs->super->s_feature_compat &
13621 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13622 for (i=0; i < EXT2_N_BLOCKS; i++) {
13623 if (inode.i_block[i])
13626 if ((i < EXT2_N_BLOCKS) &&
13627 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13628 memset(&inode, 0, sizeof(inode));
13629 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13636 * The resize inode feature is enabled; check to make sure the
13637 * only block in use is the double indirect block
13639 blk = inode.i_block[EXT2_DIND_BLOCK];
13640 for (i=0; i < EXT2_N_BLOCKS; i++) {
13641 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13644 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13645 !(inode.i_mode & LINUX_S_IFREG) ||
13646 (blk < fs->super->s_first_data_block ||
13647 blk >= fs->super->s_blocks_count)) {
13648 resize_inode_invalid:
13649 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13650 memset(&inode, 0, sizeof(inode));
13651 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13653 ctx->flags |= E2F_FLAG_RESIZE_INODE;
13655 if (!(ctx->options & E2F_OPT_READONLY)) {
13656 fs->super->s_state &= ~EXT2_VALID_FS;
13657 ext2fs_mark_super_dirty(fs);
13661 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13662 "resize dind buffer");
13663 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13665 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13667 goto resize_inode_invalid;
13669 gdt_off = fs->desc_blocks;
13670 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13671 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13672 i++, gdt_off++, pblk++) {
13673 gdt_off %= fs->blocksize/4;
13674 if (dind_buf[gdt_off] != pblk)
13675 goto resize_inode_invalid;
13676 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13678 goto resize_inode_invalid;
13680 for (j = 1; j < fs->group_desc_count; j++) {
13681 if (!ext2fs_bg_has_super(fs, j))
13683 expect = pblk + (j * fs->super->s_blocks_per_group);
13684 if (ind_buf[ind_off] != expect)
13685 goto resize_inode_invalid;
13692 ext2fs_free_mem(&dind_buf);
13696 static void check_super_block(e2fsck_t ctx)
13698 ext2_filsys fs = ctx->fs;
13699 blk_t first_block, last_block;
13700 struct ext2_super_block *sb = fs->super;
13701 struct ext2_group_desc *gd;
13702 blk_t blocks_per_group = fs->super->s_blocks_per_group;
13704 int inodes_per_block;
13709 struct problem_context pctx;
13710 __u32 free_blocks = 0, free_inodes = 0;
13712 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13713 ipg_max = inodes_per_block * (blocks_per_group - 4);
13714 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13715 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13716 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13717 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13718 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13720 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13721 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13722 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13723 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13724 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13725 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13727 clear_problem_context(&pctx);
13730 * Verify the super block constants...
13732 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13734 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13736 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13737 MAX_CHECK, 0, sb->s_blocks_count);
13738 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13739 MIN_CHECK | MAX_CHECK, 0,
13740 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13741 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13742 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13743 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13744 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13746 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13747 MIN_CHECK | MAX_CHECK, 8, bpg_max);
13748 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13749 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13750 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13751 MAX_CHECK, 0, sb->s_blocks_count / 2);
13752 check_super_value(ctx, "reserved_gdt_blocks",
13753 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13755 inode_size = EXT2_INODE_SIZE(sb);
13756 check_super_value(ctx, "inode_size",
13757 inode_size, MIN_CHECK | MAX_CHECK,
13758 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13759 if (inode_size & (inode_size - 1)) {
13760 pctx.num = inode_size;
13761 pctx.str = "inode_size";
13762 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13763 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13767 if (!ctx->num_blocks) {
13768 pctx.errcode = e2fsck_get_device_size(ctx);
13769 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13770 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13771 ctx->flags |= E2F_FLAG_ABORT;
13774 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13775 (ctx->num_blocks < sb->s_blocks_count)) {
13776 pctx.blk = sb->s_blocks_count;
13777 pctx.blk2 = ctx->num_blocks;
13778 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13779 ctx->flags |= E2F_FLAG_ABORT;
13785 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13786 pctx.blk = EXT2_BLOCK_SIZE(sb);
13787 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13788 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13789 ctx->flags |= E2F_FLAG_ABORT;
13793 should_be = sb->s_frags_per_group >>
13794 (sb->s_log_block_size - sb->s_log_frag_size);
13795 if (sb->s_blocks_per_group != should_be) {
13796 pctx.blk = sb->s_blocks_per_group;
13797 pctx.blk2 = should_be;
13798 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13799 ctx->flags |= E2F_FLAG_ABORT;
13803 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13804 if (sb->s_first_data_block != should_be) {
13805 pctx.blk = sb->s_first_data_block;
13806 pctx.blk2 = should_be;
13807 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13808 ctx->flags |= E2F_FLAG_ABORT;
13812 should_be = sb->s_inodes_per_group * fs->group_desc_count;
13813 if (sb->s_inodes_count != should_be) {
13814 pctx.ino = sb->s_inodes_count;
13815 pctx.ino2 = should_be;
13816 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13817 sb->s_inodes_count = should_be;
13818 ext2fs_mark_super_dirty(fs);
13823 * Verify the group descriptors....
13825 first_block = sb->s_first_data_block;
13826 last_block = first_block + blocks_per_group;
13828 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13831 if (i == fs->group_desc_count - 1)
13832 last_block = sb->s_blocks_count;
13833 if ((gd->bg_block_bitmap < first_block) ||
13834 (gd->bg_block_bitmap >= last_block)) {
13835 pctx.blk = gd->bg_block_bitmap;
13836 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13837 gd->bg_block_bitmap = 0;
13839 if (gd->bg_block_bitmap == 0) {
13840 ctx->invalid_block_bitmap_flag[i]++;
13841 ctx->invalid_bitmaps++;
13843 if ((gd->bg_inode_bitmap < first_block) ||
13844 (gd->bg_inode_bitmap >= last_block)) {
13845 pctx.blk = gd->bg_inode_bitmap;
13846 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13847 gd->bg_inode_bitmap = 0;
13849 if (gd->bg_inode_bitmap == 0) {
13850 ctx->invalid_inode_bitmap_flag[i]++;
13851 ctx->invalid_bitmaps++;
13853 if ((gd->bg_inode_table < first_block) ||
13854 ((gd->bg_inode_table +
13855 fs->inode_blocks_per_group - 1) >= last_block)) {
13856 pctx.blk = gd->bg_inode_table;
13857 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13858 gd->bg_inode_table = 0;
13860 if (gd->bg_inode_table == 0) {
13861 ctx->invalid_inode_table_flag[i]++;
13862 ctx->invalid_bitmaps++;
13864 free_blocks += gd->bg_free_blocks_count;
13865 free_inodes += gd->bg_free_inodes_count;
13866 first_block += sb->s_blocks_per_group;
13867 last_block += sb->s_blocks_per_group;
13869 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13870 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13871 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13872 ext2fs_unmark_valid(fs);
13877 * Update the global counts from the block group counts. This
13878 * is needed for an experimental patch which eliminates
13879 * locking the entire filesystem when allocating blocks or
13880 * inodes; if the filesystem is not unmounted cleanly, the
13881 * global counts may not be accurate.
13883 if ((free_blocks != sb->s_free_blocks_count) ||
13884 (free_inodes != sb->s_free_inodes_count)) {
13885 if (ctx->options & E2F_OPT_READONLY)
13886 ext2fs_unmark_valid(fs);
13888 sb->s_free_blocks_count = free_blocks;
13889 sb->s_free_inodes_count = free_inodes;
13890 ext2fs_mark_super_dirty(fs);
13894 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13895 (sb->s_free_inodes_count > sb->s_inodes_count))
13896 ext2fs_unmark_valid(fs);
13900 * If we have invalid bitmaps, set the error state of the
13903 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13904 sb->s_state &= ~EXT2_VALID_FS;
13905 ext2fs_mark_super_dirty(fs);
13908 clear_problem_context(&pctx);
13910 #ifndef EXT2_SKIP_UUID
13912 * If the UUID field isn't assigned, assign it.
13914 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13915 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13916 uuid_generate(sb->s_uuid);
13917 ext2fs_mark_super_dirty(fs);
13918 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13924 * For the Hurd, check to see if the filetype option is set,
13925 * since it doesn't support it.
13927 if (!(ctx->options & E2F_OPT_READONLY) &&
13928 fs->super->s_creator_os == EXT2_OS_HURD &&
13929 (fs->super->s_feature_incompat &
13930 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13931 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13932 fs->super->s_feature_incompat &=
13933 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13934 ext2fs_mark_super_dirty(fs);
13940 * If we have any of the compatibility flags set, we need to have a
13941 * revision 1 filesystem. Most kernels will not check the flags on
13942 * a rev 0 filesystem and we may have corruption issues because of
13943 * the incompatible changes to the filesystem.
13945 if (!(ctx->options & E2F_OPT_READONLY) &&
13946 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13947 (fs->super->s_feature_compat ||
13948 fs->super->s_feature_ro_compat ||
13949 fs->super->s_feature_incompat) &&
13950 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13951 ext2fs_update_dynamic_rev(fs);
13952 ext2fs_mark_super_dirty(fs);
13955 check_resize_inode(ctx);
13958 * Clean up any orphan inodes, if present.
13960 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13961 fs->super->s_state &= ~EXT2_VALID_FS;
13962 ext2fs_mark_super_dirty(fs);
13966 * Move the ext3 journal file, if necessary.
13968 e2fsck_move_ext3_journal(ctx);
13973 * swapfs.c --- byte-swap an ext2 filesystem
13976 #ifdef ENABLE_SWAPFS
13978 struct swap_block_struct {
13983 struct ext2_inode *inode;
13987 * This is a helper function for block_iterate. We mark all of the
13988 * indirect and direct blocks as changed, so that block_iterate will
13991 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13996 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13998 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13999 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
14001 sb->errcode = retval;
14002 return BLOCK_ABORT;
14004 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
14006 sb->errcode = retval;
14007 return BLOCK_ABORT;
14010 if (blockcnt >= 0) {
14011 if (blockcnt < EXT2_NDIR_BLOCKS)
14013 return BLOCK_CHANGED;
14015 if (blockcnt == BLOCK_COUNT_IND) {
14016 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
14018 return BLOCK_CHANGED;
14020 if (blockcnt == BLOCK_COUNT_DIND) {
14021 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
14023 return BLOCK_CHANGED;
14025 if (blockcnt == BLOCK_COUNT_TIND) {
14026 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
14028 return BLOCK_CHANGED;
14030 return BLOCK_CHANGED;
14034 * This function is responsible for byte-swapping all of the indirect,
14035 * block pointers. It is also responsible for byte-swapping directories.
14037 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
14038 struct ext2_inode *inode)
14041 struct swap_block_struct sb;
14045 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
14048 if (LINUX_S_ISDIR(inode->i_mode))
14051 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
14054 com_err("swap_inode_blocks", retval,
14055 _("while calling ext2fs_block_iterate"));
14056 ctx->flags |= E2F_FLAG_ABORT;
14060 com_err("swap_inode_blocks", sb.errcode,
14061 _("while calling iterator function"));
14062 ctx->flags |= E2F_FLAG_ABORT;
14067 static void swap_inodes(e2fsck_t ctx)
14069 ext2_filsys fs = ctx->fs;
14072 ext2_ino_t ino = 1;
14073 char *buf, *block_buf;
14075 struct ext2_inode * inode;
14077 e2fsck_use_inode_shortcuts(ctx, 1);
14079 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
14082 com_err("swap_inodes", retval,
14083 _("while allocating inode buffer"));
14084 ctx->flags |= E2F_FLAG_ABORT;
14087 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14088 "block interate buffer");
14089 for (group = 0; group < fs->group_desc_count; group++) {
14090 retval = io_channel_read_blk(fs->io,
14091 fs->group_desc[group].bg_inode_table,
14092 fs->inode_blocks_per_group, buf);
14094 com_err("swap_inodes", retval,
14095 _("while reading inode table (group %d)"),
14097 ctx->flags |= E2F_FLAG_ABORT;
14100 inode = (struct ext2_inode *) buf;
14101 for (i=0; i < fs->super->s_inodes_per_group;
14102 i++, ino++, inode++) {
14103 ctx->stashed_ino = ino;
14104 ctx->stashed_inode = inode;
14106 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14107 ext2fs_swap_inode(fs, inode, inode, 0);
14110 * Skip deleted files.
14112 if (inode->i_links_count == 0)
14115 if (LINUX_S_ISDIR(inode->i_mode) ||
14116 ((inode->i_block[EXT2_IND_BLOCK] ||
14117 inode->i_block[EXT2_DIND_BLOCK] ||
14118 inode->i_block[EXT2_TIND_BLOCK]) &&
14119 ext2fs_inode_has_valid_blocks(inode)))
14120 swap_inode_blocks(ctx, ino, block_buf, inode);
14122 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14125 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14126 ext2fs_swap_inode(fs, inode, inode, 1);
14128 retval = io_channel_write_blk(fs->io,
14129 fs->group_desc[group].bg_inode_table,
14130 fs->inode_blocks_per_group, buf);
14132 com_err("swap_inodes", retval,
14133 _("while writing inode table (group %d)"),
14135 ctx->flags |= E2F_FLAG_ABORT;
14139 ext2fs_free_mem(&buf);
14140 ext2fs_free_mem(&block_buf);
14141 e2fsck_use_inode_shortcuts(ctx, 0);
14142 ext2fs_flush_icache(fs);
14145 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14147 * On the PowerPC, the big-endian variant of the ext2 filesystem
14148 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14149 * of each word. Thus a bitmap with only bit 0 set would be, as
14150 * a string of bytes, 00 00 00 01 00 ...
14151 * To cope with this, we byte-reverse each word of a bitmap if
14152 * we have a big-endian filesystem, that is, if we are *not*
14153 * byte-swapping other word-sized numbers.
14155 #define EXT2_BIG_ENDIAN_BITMAPS
14158 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14159 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14161 __u32 *p = (__u32 *) bmap->bitmap;
14162 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14164 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14165 *p = ext2fs_swab32(*p);
14170 #ifdef ENABLE_SWAPFS
14171 static void swap_filesys(e2fsck_t ctx)
14173 ext2_filsys fs = ctx->fs;
14174 #ifdef RESOURCE_TRACK
14175 struct resource_track rtrack;
14177 init_resource_track(&rtrack);
14180 if (!(ctx->options & E2F_OPT_PREEN))
14181 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14184 mtrace_print("Byte swap");
14187 if (fs->super->s_mnt_count) {
14188 fprintf(stderr, _("%s: the filesystem must be freshly "
14189 "checked using fsck\n"
14190 "and not mounted before trying to "
14191 "byte-swap it.\n"), ctx->device_name);
14192 ctx->flags |= E2F_FLAG_ABORT;
14195 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14196 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14197 EXT2_FLAG_SWAP_BYTES_WRITE);
14198 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14200 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14201 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14204 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14206 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14207 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14208 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14209 EXT2_FLAG_SWAP_BYTES_WRITE);
14211 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14212 e2fsck_read_bitmaps(ctx);
14213 ext2fs_swap_bitmap(fs->inode_map);
14214 ext2fs_swap_bitmap(fs->block_map);
14215 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14217 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14219 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14221 #ifdef RESOURCE_TRACK
14222 if (ctx->options & E2F_OPT_TIME2)
14223 print_resource_track(_("Byte swap"), &rtrack);
14226 #endif /* ENABLE_SWAPFS */
14231 * util.c --- miscellaneous utilities
14234 #ifdef HAVE_CONIO_H
14235 #undef HAVE_TERMIOS_H
14237 #define read_a_char() getch()
14239 #ifdef HAVE_TERMIOS_H
14240 #include <termios.h>
14245 void fatal_error(e2fsck_t ctx, const char *msg)
14248 fprintf (stderr, "e2fsck: %s\n", msg);
14249 if (ctx->fs && ctx->fs->io) {
14250 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14251 io_channel_flush(ctx->fs->io);
14253 fprintf(stderr, "e2fsck: io manager magic bad!\n");
14255 ctx->flags |= E2F_FLAG_ABORT;
14256 if (ctx->flags & E2F_FLAG_SETJMP_OK)
14257 longjmp(ctx->abort_loc, 1);
14262 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14263 const char *description)
14268 #ifdef DEBUG_ALLOCATE_MEMORY
14269 printf("Allocating %d bytes for %s...\n", size, description);
14271 ret = malloc(size);
14273 sprintf(buf, "Can't allocate %s\n", description);
14274 fatal_error(ctx, buf);
14276 memset(ret, 0, size);
14280 static char *string_copy(const char *str, int len)
14288 ret = malloc(len+1);
14290 strncpy(ret, str, len);
14296 #ifndef HAVE_CONIO_H
14297 static int read_a_char(void)
14304 if (e2fsck_global_ctx &&
14305 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14308 r = read(0, &c, 1);
14318 static int ask_yn(const char * string, int def)
14321 const char *defstr;
14322 static const char short_yes[] = "yY";
14323 static const char short_no[] = "nN";
14325 #ifdef HAVE_TERMIOS_H
14326 struct termios termios, tmp;
14328 tcgetattr (0, &termios);
14330 tmp.c_lflag &= ~(ICANON | ECHO);
14331 tmp.c_cc[VMIN] = 1;
14332 tmp.c_cc[VTIME] = 0;
14333 tcsetattr (0, TCSANOW, &tmp);
14342 printf("%s%s? ", string, defstr);
14345 if ((c = read_a_char()) == EOF)
14348 #ifdef HAVE_TERMIOS_H
14349 tcsetattr (0, TCSANOW, &termios);
14351 if (e2fsck_global_ctx &&
14352 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14354 longjmp(e2fsck_global_ctx->abort_loc, 1);
14356 puts(_("cancelled!\n"));
14359 if (strchr(short_yes, (char) c)) {
14363 else if (strchr(short_no, (char) c)) {
14367 else if ((c == ' ' || c == '\n') && (def != -1))
14374 #ifdef HAVE_TERMIOS_H
14375 tcsetattr (0, TCSANOW, &termios);
14380 int ask (e2fsck_t ctx, const char * string, int def)
14382 if (ctx->options & E2F_OPT_NO) {
14383 printf (_("%s? no\n\n"), string);
14386 if (ctx->options & E2F_OPT_YES) {
14387 printf (_("%s? yes\n\n"), string);
14390 if (ctx->options & E2F_OPT_PREEN) {
14391 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14394 return ask_yn(string, def);
14397 void e2fsck_read_bitmaps(e2fsck_t ctx)
14399 ext2_filsys fs = ctx->fs;
14402 if (ctx->invalid_bitmaps) {
14403 com_err(ctx->program_name, 0,
14404 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14406 fatal_error(ctx, 0);
14409 ehandler_operation(_("reading inode and block bitmaps"));
14410 retval = ext2fs_read_bitmaps(fs);
14411 ehandler_operation(0);
14413 com_err(ctx->program_name, retval,
14414 _("while retrying to read bitmaps for %s"),
14416 fatal_error(ctx, 0);
14420 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14422 ext2_filsys fs = ctx->fs;
14425 if (ext2fs_test_bb_dirty(fs)) {
14426 ehandler_operation(_("writing block bitmaps"));
14427 retval = ext2fs_write_block_bitmap(fs);
14428 ehandler_operation(0);
14430 com_err(ctx->program_name, retval,
14431 _("while retrying to write block bitmaps for %s"),
14433 fatal_error(ctx, 0);
14437 if (ext2fs_test_ib_dirty(fs)) {
14438 ehandler_operation(_("writing inode bitmaps"));
14439 retval = ext2fs_write_inode_bitmap(fs);
14440 ehandler_operation(0);
14442 com_err(ctx->program_name, retval,
14443 _("while retrying to write inode bitmaps for %s"),
14445 fatal_error(ctx, 0);
14450 void preenhalt(e2fsck_t ctx)
14452 ext2_filsys fs = ctx->fs;
14454 if (!(ctx->options & E2F_OPT_PREEN))
14456 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14457 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14460 fs->super->s_state |= EXT2_ERROR_FS;
14461 ext2fs_mark_super_dirty(fs);
14464 exit(FSCK_UNCORRECTED);
14467 #ifdef RESOURCE_TRACK
14468 void init_resource_track(struct resource_track *track)
14470 #ifdef HAVE_GETRUSAGE
14474 track->brk_start = sbrk(0);
14475 gettimeofday(&track->time_start, 0);
14476 #ifdef HAVE_GETRUSAGE
14478 memset(&r, 0, sizeof(struct rusage));
14480 getrusage(RUSAGE_SELF, &r);
14481 track->user_start = r.ru_utime;
14482 track->system_start = r.ru_stime;
14484 track->user_start.tv_sec = track->user_start.tv_usec = 0;
14485 track->system_start.tv_sec = track->system_start.tv_usec = 0;
14489 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14490 struct timeval *tv2)
14492 return ((tv1->tv_sec - tv2->tv_sec) +
14493 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14496 void print_resource_track(const char *desc, struct resource_track *track)
14498 #ifdef HAVE_GETRUSAGE
14501 #ifdef HAVE_MALLINFO
14502 struct mallinfo malloc_info;
14504 struct timeval time_end;
14506 gettimeofday(&time_end, 0);
14509 printf("%s: ", desc);
14511 #ifdef HAVE_MALLINFO
14512 #define kbytes(x) (((x) + 1023) / 1024)
14514 malloc_info = mallinfo();
14515 printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14516 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14517 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14519 printf(_("Memory used: %d, "),
14520 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14522 #ifdef HAVE_GETRUSAGE
14523 getrusage(RUSAGE_SELF, &r);
14525 printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14526 timeval_subtract(&time_end, &track->time_start),
14527 timeval_subtract(&r.ru_utime, &track->user_start),
14528 timeval_subtract(&r.ru_stime, &track->system_start));
14530 printf(_("elapsed time: %6.3f\n"),
14531 timeval_subtract(&time_end, &track->time_start));
14534 #endif /* RESOURCE_TRACK */
14536 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14537 struct ext2_inode * inode, const char *proc)
14541 retval = ext2fs_read_inode(ctx->fs, ino, inode);
14543 com_err("ext2fs_read_inode", retval,
14544 _("while reading inode %ld in %s"), ino, proc);
14545 fatal_error(ctx, 0);
14549 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14550 struct ext2_inode * inode, int bufsize,
14555 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14557 com_err("ext2fs_write_inode", retval,
14558 _("while writing inode %ld in %s"), ino, proc);
14559 fatal_error(ctx, 0);
14563 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14564 struct ext2_inode * inode, const char *proc)
14568 retval = ext2fs_write_inode(ctx->fs, ino, inode);
14570 com_err("ext2fs_write_inode", retval,
14571 _("while writing inode %ld in %s"), ino, proc);
14572 fatal_error(ctx, 0);
14577 void mtrace_print(char *mesg)
14579 FILE *malloc_get_mallstream();
14580 FILE *f = malloc_get_mallstream();
14583 fprintf(f, "============= %s\n", mesg);
14587 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14588 io_manager manager)
14590 struct ext2_super_block *sb;
14591 io_channel io = NULL;
14594 blk_t superblock, ret_sb = 8193;
14596 if (fs && fs->super) {
14597 ret_sb = (fs->super->s_blocks_per_group +
14598 fs->super->s_first_data_block);
14600 ctx->superblock = ret_sb;
14601 ctx->blocksize = fs->blocksize;
14607 if (ctx->blocksize) {
14608 ret_sb = ctx->blocksize * 8;
14609 if (ctx->blocksize == 1024)
14611 ctx->superblock = ret_sb;
14614 ctx->superblock = ret_sb;
14615 ctx->blocksize = 1024;
14618 if (!name || !manager)
14621 if (manager->open(name, 0, &io) != 0)
14624 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14626 sb = (struct ext2_super_block *) buf;
14628 for (blocksize = EXT2_MIN_BLOCK_SIZE;
14629 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14630 superblock = blocksize*8;
14631 if (blocksize == 1024)
14633 io_channel_set_blksize(io, blocksize);
14634 if (io_channel_read_blk(io, superblock,
14635 -SUPERBLOCK_SIZE, buf))
14637 #ifdef EXT2FS_ENABLE_SWAPFS
14638 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14639 ext2fs_swap_super(sb);
14641 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14642 ret_sb = superblock;
14644 ctx->superblock = superblock;
14645 ctx->blocksize = blocksize;
14653 io_channel_close(io);
14655 ext2fs_free_mem(&buf);
14661 * This function runs through the e2fsck passes and calls them all,
14662 * returning restart, abort, or cancel as necessary...
14664 typedef void (*pass_t)(e2fsck_t ctx);
14666 static const pass_t e2fsck_passes[] = {
14667 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14670 #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14672 static int e2fsck_run(e2fsck_t ctx)
14675 pass_t e2fsck_pass;
14677 if (setjmp(ctx->abort_loc)) {
14678 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14679 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14681 ctx->flags |= E2F_FLAG_SETJMP_OK;
14683 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14684 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14688 (void) (ctx->progress)(ctx, 0, 0, 0);
14690 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14692 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14693 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14699 * unix.c - The unix-specific code for e2fsck
14703 /* Command line options */
14705 #ifdef ENABLE_SWAPFS
14706 static int normalize_swapfs;
14708 static int cflag; /* check disk */
14709 static int show_version_only;
14710 static int verbose;
14712 static int replace_bad_blocks;
14713 static int keep_bad_blocks;
14714 static char *bad_blocks_file;
14716 #ifdef __CONFIG_JBD_DEBUG__E2FS /* Enabled by configure --enable-jfs-debug */
14717 int journal_enable_debug = -1;
14721 static void usage(e2fsck_t ctx)
14724 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14725 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14726 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal]\n"
14727 "\t\t[-E extended-options] device\n"),
14728 ctx->program_name);
14730 fprintf(stderr, _("\nEmergency help:\n"
14731 " -p Automatic repair (no questions)\n"
14732 " -n Make no changes to the filesystem\n"
14733 " -y Assume \"yes\" to all questions\n"
14734 " -c Check for bad blocks and add them to the badblock list\n"
14735 " -f Force checking even if filesystem is marked clean\n"));
14736 fprintf(stderr, _(""
14738 " -b superblock Use alternative superblock\n"
14739 " -B blocksize Force blocksize when looking for superblock\n"
14740 " -j external-journal Set location of the external journal\n"
14741 " -l bad_blocks_file Add to badblocks list\n"
14742 " -L bad_blocks_file Set badblocks list\n"
14749 #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
14751 static void show_stats(e2fsck_t ctx)
14753 ext2_filsys fs = ctx->fs;
14754 int inodes, inodes_used, blocks, blocks_used;
14756 int num_files, num_links;
14759 dir_links = 2 * ctx->fs_directory_count - 1;
14760 num_files = ctx->fs_total_count - dir_links;
14761 num_links = ctx->fs_links_count - dir_links;
14762 inodes = fs->super->s_inodes_count;
14763 inodes_used = (fs->super->s_inodes_count -
14764 fs->super->s_free_inodes_count);
14765 blocks = fs->super->s_blocks_count;
14766 blocks_used = (fs->super->s_blocks_count -
14767 fs->super->s_free_blocks_count);
14769 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14770 frag_percent = (frag_percent + 5) / 10;
14773 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14774 ctx->device_name, inodes_used, inodes,
14775 frag_percent / 10, frag_percent % 10,
14776 blocks_used, blocks);
14779 printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14780 100 * inodes_used / inodes);
14781 printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14782 P_E2("", "s", ctx->fs_fragmented),
14783 frag_percent / 10, frag_percent % 10);
14784 printf (_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14785 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14786 printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14787 (int) ((long long) 100 * blocks_used / blocks));
14788 printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14789 printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14790 printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14791 printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14792 printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14793 printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14794 printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14795 printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14796 printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14797 printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14798 printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14799 printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14802 static void check_mount(e2fsck_t ctx)
14807 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14808 &ctx->mount_flags);
14810 com_err("ext2fs_check_if_mount", retval,
14811 _("while determining whether %s is mounted."),
14812 ctx->filesystem_name);
14817 * If the filesystem isn't mounted, or it's the root filesystem
14818 * and it's mounted read-only, then everything's fine.
14820 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14821 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14822 (ctx->mount_flags & EXT2_MF_READONLY)))
14825 if (ctx->options & E2F_OPT_READONLY) {
14826 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
14830 printf(_("%s is mounted. "), ctx->filesystem_name);
14831 if (!ctx->interactive)
14832 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14833 printf(_("\n\n\007\007\007\007WARNING!!! "
14834 "Running e2fsck on a mounted filesystem may cause\n"
14835 "SEVERE filesystem damage.\007\007\007\n\n"));
14836 cont = ask_yn(_("Do you really want to continue"), -1);
14838 printf (_("check aborted.\n"));
14844 static int is_on_batt(void)
14848 char tmp[80], tmp2[80], fname[80];
14849 unsigned int acflag;
14852 f = fopen("/proc/apm", "r");
14854 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14857 return (acflag != 1);
14859 d = opendir("/proc/acpi/ac_adapter");
14861 while ((de=readdir(d)) != NULL) {
14862 if (!strncmp(".", de->d_name, 1))
14864 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14866 f = fopen(fname, "r");
14869 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14872 if (strncmp(tmp, "off-line", 8) == 0) {
14883 * This routine checks to see if a filesystem can be skipped; if so,
14884 * it will exit with E2FSCK_OK. Under some conditions it will print a
14885 * message explaining why a check is being forced.
14887 static void check_if_skip(e2fsck_t ctx)
14889 ext2_filsys fs = ctx->fs;
14890 const char *reason = NULL;
14891 unsigned int reason_arg = 0;
14893 int batt = is_on_batt();
14894 time_t now = time(0);
14896 if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14900 if ((fs->super->s_state & EXT2_ERROR_FS) ||
14901 !ext2fs_test_valid(fs))
14902 reason = _(" contains a file system with errors");
14903 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14904 reason = _(" was not cleanly unmounted");
14905 else if ((fs->super->s_max_mnt_count > 0) &&
14906 (fs->super->s_mnt_count >=
14907 (unsigned) fs->super->s_max_mnt_count)) {
14908 reason = _(" has been mounted %u times without being checked");
14909 reason_arg = fs->super->s_mnt_count;
14910 if (batt && (fs->super->s_mnt_count <
14911 (unsigned) fs->super->s_max_mnt_count*2))
14913 } else if (fs->super->s_checkinterval &&
14914 ((now - fs->super->s_lastcheck) >=
14915 fs->super->s_checkinterval)) {
14916 reason = _(" has gone %u days without being checked");
14917 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14918 if (batt && ((now - fs->super->s_lastcheck) <
14919 fs->super->s_checkinterval*2))
14923 fputs(ctx->device_name, stdout);
14924 printf(reason, reason_arg);
14925 fputs(_(", check forced.\n"), stdout);
14928 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14929 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14930 fs->super->s_inodes_count,
14931 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14932 fs->super->s_blocks_count);
14933 next_check = 100000;
14934 if (fs->super->s_max_mnt_count > 0) {
14935 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14936 if (next_check <= 0)
14939 if (fs->super->s_checkinterval &&
14940 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14942 if (next_check <= 5) {
14943 if (next_check == 1)
14944 fputs(_(" (check after next mount)"), stdout);
14946 printf(_(" (check in %ld mounts)"), next_check);
14948 fputc('\n', stdout);
14951 e2fsck_free_context(ctx);
14956 * For completion notice
14958 struct percent_tbl {
14962 static const struct percent_tbl e2fsck_tbl = {
14963 5, { 0, 70, 90, 92, 95, 100 }
14966 static char bar[128], spaces[128];
14968 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14975 if (pass > tbl->max_pass || max == 0)
14977 percent = ((float) curr) / ((float) max);
14978 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14979 + tbl->table[pass-1]);
14982 extern void e2fsck_clear_progbar(e2fsck_t ctx)
14984 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14987 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14990 ctx->flags &= ~E2F_FLAG_PROG_BAR;
14993 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14994 unsigned int dpynum)
14996 static const char spinner[] = "\\|/-";
15003 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
15007 * Calculate the new progress position. If the
15008 * percentage hasn't changed, then we skip out right
15011 fixed_percent = (int) ((10 * percent) + 0.5);
15012 if (ctx->progress_last_percent == fixed_percent)
15014 ctx->progress_last_percent = fixed_percent;
15017 * If we've already updated the spinner once within
15018 * the last 1/8th of a second, no point doing it
15021 gettimeofday(&tv, NULL);
15022 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
15023 if ((tick == ctx->progress_last_time) &&
15024 (fixed_percent != 0) && (fixed_percent != 1000))
15026 ctx->progress_last_time = tick;
15029 * Advance the spinner, and note that the progress bar
15030 * will be on the screen
15032 ctx->progress_pos = (ctx->progress_pos+1) & 3;
15033 ctx->flags |= E2F_FLAG_PROG_BAR;
15035 dpywidth = 66 - strlen(label);
15036 dpywidth = 8 * (dpywidth / 8);
15040 i = ((percent * dpywidth) + 50) / 100;
15041 printf("%s%s: |%s%s", ctx->start_meta, label,
15042 bar + (sizeof(bar) - (i+1)),
15043 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
15044 if (fixed_percent == 1000)
15045 fputc('|', stdout);
15047 fputc(spinner[ctx->progress_pos & 3], stdout);
15048 printf(" %4.1f%% ", percent);
15050 printf("%u\r", dpynum);
15052 fputs(" \r", stdout);
15053 fputs(ctx->stop_meta, stdout);
15055 if (fixed_percent == 1000)
15056 e2fsck_clear_progbar(ctx);
15062 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
15063 unsigned long cur, unsigned long max)
15071 if (ctx->progress_fd) {
15072 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
15073 write(ctx->progress_fd, buf, strlen(buf));
15075 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
15076 e2fsck_simple_progress(ctx, ctx->device_name,
15082 #define PATH_SET "PATH=/sbin"
15084 static void reserve_stdio_fds(void)
15089 fd = open("/dev/null", O_RDWR);
15093 fprintf(stderr, _("ERROR: Couldn't open "
15094 "/dev/null (%s)\n"),
15102 static void signal_progress_on(int sig EXT2FS_ATTR((unused)))
15104 e2fsck_t ctx = e2fsck_global_ctx;
15109 ctx->progress = e2fsck_update_progress;
15110 ctx->progress_fd = 0;
15113 static void signal_progress_off(int sig EXT2FS_ATTR((unused)))
15115 e2fsck_t ctx = e2fsck_global_ctx;
15120 e2fsck_clear_progbar(ctx);
15124 static void signal_cancel(int sig EXT2FS_ATTR((unused)))
15126 e2fsck_t ctx = e2fsck_global_ctx;
15129 exit(FSCK_CANCELED);
15131 ctx->flags |= E2F_FLAG_CANCEL;
15134 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15136 char *buf, *token, *next, *p, *arg;
15138 int extended_usage = 0;
15140 buf = string_copy(opts, 0);
15141 for (token = buf; token && *token; token = next) {
15142 p = strchr(token, ',');
15148 arg = strchr(token, '=');
15153 if (strcmp(token, "ea_ver") == 0) {
15158 ea_ver = strtoul(arg, &p, 0);
15160 ((ea_ver != 1) && (ea_ver != 2))) {
15162 _("Invalid EA version.\n"));
15166 ctx->ext_attr_ver = ea_ver;
15170 if (extended_usage) {
15171 bb_error_msg_and_die(
15172 "Extended options are separated by commas, "
15173 "and may take an argument which\n"
15174 "is set off by an equals ('=') sign. "
15175 "Valid raid options are:\n"
15176 "\tea_ver=<ea_version (1 or 2)\n\n");
15181 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15186 extern void *mallwatch;
15190 struct sigaction sa;
15191 char *extended_opts = 0;
15193 retval = e2fsck_allocate_context(&ctx);
15199 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15200 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15201 if (isatty(0) && isatty(1)) {
15202 ctx->interactive = 1;
15204 ctx->start_meta[0] = '\001';
15205 ctx->stop_meta[0] = '\002';
15207 memset(bar, '=', sizeof(bar)-1);
15208 memset(spaces, ' ', sizeof(spaces)-1);
15209 blkid_get_cache(&ctx->blkid, NULL);
15212 ctx->program_name = *argv;
15214 ctx->program_name = "e2fsck";
15215 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15218 ctx->progress = e2fsck_update_progress;
15219 ctx->progress_fd = atoi(optarg);
15220 if (!ctx->progress_fd)
15222 /* Validate the file descriptor to avoid disasters */
15223 fd = dup(ctx->progress_fd);
15226 _("Error validating file descriptor %d: %s\n"),
15228 error_message(errno));
15230 _("Invalid completion information file descriptor"));
15235 ctx->options |= E2F_OPT_COMPRESS_DIRS;
15238 extended_opts = optarg;
15242 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15245 _("Only one the options -p/-a, -n or -y may be specified."));
15247 ctx->options |= E2F_OPT_PREEN;
15250 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15252 ctx->options |= E2F_OPT_NO;
15255 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15257 ctx->options |= E2F_OPT_YES;
15260 #ifdef RESOURCE_TRACK
15261 if (ctx->options & E2F_OPT_TIME)
15262 ctx->options |= E2F_OPT_TIME2;
15264 ctx->options |= E2F_OPT_TIME;
15266 fprintf(stderr, _("The -t option is not "
15267 "supported on this version of e2fsck.\n"));
15272 ctx->options |= E2F_OPT_WRITECHECK;
15273 ctx->options |= E2F_OPT_CHECKBLOCKS;
15276 /* What we do by default, anyway! */
15279 ctx->use_superblock = atoi(optarg);
15280 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15283 ctx->blocksize = atoi(optarg);
15286 ctx->inode_buffer_blocks = atoi(optarg);
15289 ctx->journal_name = string_copy(optarg, 0);
15292 ctx->process_inode_size = atoi(optarg);
15295 replace_bad_blocks++;
15297 bad_blocks_file = string_copy(optarg, 0);
15300 ctx->options |= E2F_OPT_DEBUG;
15303 ctx->options |= E2F_OPT_FORCE;
15312 show_version_only = 1;
15316 mallwatch = (void *) strtol(optarg, NULL, 0);
15320 ctx->device_name = optarg;
15322 #ifdef ENABLE_SWAPFS
15324 normalize_swapfs = 1;
15331 fprintf(stderr, _("Byte-swapping filesystems "
15332 "not compiled in this version "
15342 if (show_version_only)
15344 if (optind != argc - 1)
15346 if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15347 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15348 ctx->options |= E2F_OPT_READONLY;
15349 ctx->io_options = strchr(argv[optind], '?');
15350 if (ctx->io_options)
15351 *ctx->io_options++ = 0;
15352 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15353 if (!ctx->filesystem_name) {
15354 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15356 fatal_error(ctx, 0);
15359 parse_extended_opts(ctx, extended_opts);
15362 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15364 com_err("open", errno,
15365 _("while opening %s for flushing"),
15366 ctx->filesystem_name);
15367 fatal_error(ctx, 0);
15369 if ((retval = ext2fs_sync_device(fd, 1))) {
15370 com_err("ext2fs_sync_device", retval,
15371 _("while trying to flush %s"),
15372 ctx->filesystem_name);
15373 fatal_error(ctx, 0);
15377 #ifdef ENABLE_SWAPFS
15379 if (cflag || bad_blocks_file) {
15380 fprintf(stderr, _("Incompatible options not "
15381 "allowed when byte-swapping.\n"));
15386 if (cflag && bad_blocks_file) {
15387 fprintf(stderr, _("The -c and the -l/-L options may "
15388 "not be both used at the same time.\n"));
15392 * Set up signal action
15394 memset(&sa, 0, sizeof(struct sigaction));
15395 sa.sa_handler = signal_cancel;
15396 sigaction(SIGINT, &sa, 0);
15397 sigaction(SIGTERM, &sa, 0);
15399 sa.sa_flags = SA_RESTART;
15401 e2fsck_global_ctx = ctx;
15402 sa.sa_handler = signal_progress_on;
15403 sigaction(SIGUSR1, &sa, 0);
15404 sa.sa_handler = signal_progress_off;
15405 sigaction(SIGUSR2, &sa, 0);
15407 /* Update our PATH to include /sbin if we need to run badblocks */
15409 char *oldpath = getenv("PATH");
15413 newpath = (char *) malloc(sizeof (PATH_SET) + 1 +
15416 fatal_error(ctx, "Couldn't malloc() newpath");
15417 strcpy (newpath, PATH_SET);
15418 strcat (newpath, ":");
15419 strcat (newpath, oldpath);
15424 #ifdef __CONFIG_JBD_DEBUG__E2FS
15425 if (getenv("E2FSCK_JBD_DEBUG"))
15426 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15431 static const char my_ver_string[] = E2FSPROGS_VERSION;
15432 static const char my_ver_date[] = E2FSPROGS_DATE;
15434 int e2fsck_main (int argc, char *argv[])
15437 int exit_value = FSCK_OK;
15438 ext2_filsys fs = 0;
15440 struct ext2_super_block *sb;
15441 const char *lib_ver_date;
15442 int my_ver, lib_ver;
15444 struct problem_context pctx;
15445 int flags, run_result;
15447 clear_problem_context(&pctx);
15455 setlocale(LC_MESSAGES, "");
15456 setlocale(LC_CTYPE, "");
15457 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15458 textdomain(NLS_CAT_NAME);
15460 my_ver = ext2fs_parse_version_string(my_ver_string);
15461 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15462 if (my_ver > lib_ver) {
15463 fprintf( stderr, _("Error: ext2fs library version "
15464 "out of date!\n"));
15465 show_version_only++;
15468 retval = PRS(argc, argv, &ctx);
15470 com_err("e2fsck", retval,
15471 _("while trying to initialize program"));
15474 reserve_stdio_fds();
15476 #ifdef RESOURCE_TRACK
15477 init_resource_track(&ctx->global_rtrack);
15480 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15481 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15484 if (show_version_only) {
15485 fprintf(stderr, _("\tUsing %s, %s\n"),
15486 error_message(EXT2_ET_BASE), lib_ver_date);
15492 if (!(ctx->options & E2F_OPT_PREEN) &&
15493 !(ctx->options & E2F_OPT_NO) &&
15494 !(ctx->options & E2F_OPT_YES)) {
15495 if (!ctx->interactive)
15497 _("need terminal for interactive repairs"));
15499 ctx->superblock = ctx->use_superblock;
15501 #ifdef CONFIG_TESTIO_DEBUG
15502 io_ptr = test_io_manager;
15503 test_io_backing_manager = unix_io_manager;
15505 io_ptr = unix_io_manager;
15508 if ((ctx->options & E2F_OPT_READONLY) == 0)
15509 flags |= EXT2_FLAG_RW;
15511 if (ctx->superblock && ctx->blocksize) {
15512 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15513 flags, ctx->superblock, ctx->blocksize,
15515 } else if (ctx->superblock) {
15517 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15518 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15519 retval = ext2fs_open2(ctx->filesystem_name,
15520 ctx->io_options, flags,
15521 ctx->superblock, blocksize,
15527 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15528 flags, 0, 0, io_ptr, &fs);
15529 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15530 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15531 ((retval == EXT2_ET_BAD_MAGIC) ||
15532 ((retval == 0) && ext2fs_check_desc(fs)))) {
15533 if (!fs || (fs->group_desc_count > 1)) {
15534 printf(_("%s trying backup blocks...\n"),
15535 retval ? _("Couldn't find ext2 superblock,") :
15536 _("Group descriptors look bad..."));
15537 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15544 com_err(ctx->program_name, retval, _("while trying to open %s"),
15545 ctx->filesystem_name);
15546 if (retval == EXT2_ET_REV_TOO_HIGH) {
15547 printf(_("The filesystem revision is apparently "
15548 "too high for this version of e2fsck.\n"
15549 "(Or the filesystem superblock "
15550 "is corrupt)\n\n"));
15551 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15552 } else if (retval == EXT2_ET_SHORT_READ)
15553 printf(_("Could this be a zero-length partition?\n"));
15554 else if ((retval == EPERM) || (retval == EACCES))
15555 printf(_("You must have %s access to the "
15556 "filesystem or be root\n"),
15557 (ctx->options & E2F_OPT_READONLY) ?
15559 else if (retval == ENXIO)
15560 printf(_("Possibly non-existent or swap device?\n"));
15562 else if (retval == EROFS)
15563 printf(_("Disk write-protected; use the -n option "
15564 "to do a read-only\n"
15565 "check of the device.\n"));
15568 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15569 fatal_error(ctx, 0);
15572 fs->priv_data = ctx;
15574 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15575 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15576 _("while trying to open %s"),
15577 ctx->filesystem_name);
15579 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15583 * Set the device name, which is used whenever we print error
15584 * or informational messages to the user.
15586 if (ctx->device_name == 0 &&
15587 (sb->s_volume_name[0] != 0)) {
15588 ctx->device_name = string_copy(sb->s_volume_name,
15589 sizeof(sb->s_volume_name));
15591 if (ctx->device_name == 0)
15592 ctx->device_name = ctx->filesystem_name;
15595 * Make sure the ext3 superblock fields are consistent.
15597 retval = e2fsck_check_ext3_journal(ctx);
15599 com_err(ctx->program_name, retval,
15600 _("while checking ext3 journal for %s"),
15602 fatal_error(ctx, 0);
15606 * Check to see if we need to do ext3-style recovery. If so,
15607 * do it, and then restart the fsck.
15609 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15610 if (ctx->options & E2F_OPT_READONLY) {
15611 printf(_("Warning: skipping journal recovery "
15612 "because doing a read-only filesystem "
15614 io_channel_flush(ctx->fs->io);
15616 if (ctx->flags & E2F_FLAG_RESTARTED) {
15618 * Whoops, we attempted to run the
15619 * journal twice. This should never
15620 * happen, unless the hardware or
15621 * device driver is being bogus.
15623 com_err(ctx->program_name, 0,
15624 _("unable to set superblock flags on %s\n"), ctx->device_name);
15625 fatal_error(ctx, 0);
15627 retval = e2fsck_run_ext3_journal(ctx);
15629 com_err(ctx->program_name, retval,
15630 _("while recovering ext3 journal of %s"),
15632 fatal_error(ctx, 0);
15634 ext2fs_close(ctx->fs);
15636 ctx->flags |= E2F_FLAG_RESTARTED;
15642 * Check for compatibility with the feature sets. We need to
15643 * be more stringent than ext2fs_open().
15645 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15646 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15647 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15648 "(%s)", ctx->device_name);
15651 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15652 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15653 "(%s)", ctx->device_name);
15656 #ifdef ENABLE_COMPRESSION
15657 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15658 com_err(ctx->program_name, 0,
15659 _("Warning: compression support is experimental.\n"));
15661 #ifndef ENABLE_HTREE
15662 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15663 com_err(ctx->program_name, 0,
15664 _("E2fsck not compiled with HTREE support,\n\t"
15665 "but filesystem %s has HTREE directories.\n"),
15672 * If the user specified a specific superblock, presumably the
15673 * master superblock has been trashed. So we mark the
15674 * superblock as dirty, so it can be written out.
15676 if (ctx->superblock &&
15677 !(ctx->options & E2F_OPT_READONLY))
15678 ext2fs_mark_super_dirty(fs);
15681 * We only update the master superblock because (a) paranoia;
15682 * we don't want to corrupt the backup superblocks, and (b) we
15683 * don't need to update the mount count and last checked
15684 * fields in the backup superblock (the kernel doesn't
15685 * update the backup superblocks anyway).
15687 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15689 ehandler_init(fs->io);
15691 if (ctx->superblock)
15692 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15693 ext2fs_mark_valid(fs);
15694 check_super_block(ctx);
15695 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15696 fatal_error(ctx, 0);
15697 check_if_skip(ctx);
15698 if (bad_blocks_file)
15699 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15701 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15702 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15703 fatal_error(ctx, 0);
15704 #ifdef ENABLE_SWAPFS
15705 if (normalize_swapfs) {
15706 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
15707 ext2fs_native_flag()) {
15708 fprintf(stderr, _("%s: Filesystem byte order "
15709 "already normalized.\n"), ctx->device_name);
15710 fatal_error(ctx, 0);
15715 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15716 fatal_error(ctx, 0);
15721 * Mark the system as valid, 'til proven otherwise
15723 ext2fs_mark_valid(fs);
15725 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15727 com_err(ctx->program_name, retval,
15728 _("while reading bad blocks inode"));
15730 printf(_("This doesn't bode well,"
15731 " but we'll try to go on...\n"));
15734 run_result = e2fsck_run(ctx);
15735 e2fsck_clear_progbar(ctx);
15736 if (run_result == E2F_FLAG_RESTART) {
15737 printf(_("Restarting e2fsck from the beginning...\n"));
15738 retval = e2fsck_reset_context(ctx);
15740 com_err(ctx->program_name, retval,
15741 _("while resetting context"));
15742 fatal_error(ctx, 0);
15747 if (run_result & E2F_FLAG_CANCEL) {
15748 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15749 ctx->device_name : ctx->filesystem_name);
15750 exit_value |= FSCK_CANCELED;
15752 if (run_result & E2F_FLAG_ABORT)
15753 fatal_error(ctx, _("aborted"));
15756 mtrace_print("Cleanup");
15758 if (ext2fs_test_changed(fs)) {
15759 exit_value |= FSCK_NONDESTRUCT;
15760 if (!(ctx->options & E2F_OPT_PREEN))
15761 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15763 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15764 printf(_("%s: ***** REBOOT LINUX *****\n"),
15766 exit_value |= FSCK_REBOOT;
15769 if (!ext2fs_test_valid(fs)) {
15770 printf(_("\n%s: ********** WARNING: Filesystem still has "
15771 "errors **********\n\n"), ctx->device_name);
15772 exit_value |= FSCK_UNCORRECTED;
15773 exit_value &= ~FSCK_NONDESTRUCT;
15775 if (exit_value & FSCK_CANCELED)
15776 exit_value &= ~FSCK_NONDESTRUCT;
15779 if (!(ctx->options & E2F_OPT_READONLY)) {
15780 if (ext2fs_test_valid(fs)) {
15781 if (!(sb->s_state & EXT2_VALID_FS))
15782 exit_value |= FSCK_NONDESTRUCT;
15783 sb->s_state = EXT2_VALID_FS;
15785 sb->s_state &= ~EXT2_VALID_FS;
15786 sb->s_mnt_count = 0;
15787 sb->s_lastcheck = time(NULL);
15788 ext2fs_mark_super_dirty(fs);
15792 e2fsck_write_bitmaps(ctx);
15796 free(ctx->filesystem_name);
15797 free(ctx->journal_name);
15798 e2fsck_free_context(ctx);
15800 #ifdef RESOURCE_TRACK
15801 if (ctx->options & E2F_OPT_TIME)
15802 print_resource_track(NULL, &ctx->global_rtrack);