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 * The last ext2fs revision level that this version of e2fsck is able to
85 #define E2FSCK_CURRENT_REV 1
88 * The directory information structure; stores directory information
89 * collected in earlier passes, to avoid disk i/o in fetching the
90 * directory information.
93 ext2_ino_t ino; /* Inode number */
94 ext2_ino_t dotdot; /* Parent according to '..' */
95 ext2_ino_t parent; /* Parent according to treewalk */
100 * The indexed directory information structure; stores information for
101 * directories which contain a hash tree index.
104 ext2_ino_t ino; /* Inode number */
105 int numblocks; /* number of blocks */
107 short depth; /* depth of tree */
108 struct dx_dirblock_info *dx_block; /* Array of size numblocks */
111 #define DX_DIRBLOCK_ROOT 1
112 #define DX_DIRBLOCK_LEAF 2
113 #define DX_DIRBLOCK_NODE 3
114 #define DX_DIRBLOCK_CORRUPT 4
115 #define DX_DIRBLOCK_CLEARED 8
117 struct dx_dirblock_info {
122 ext2_dirhash_t min_hash;
123 ext2_dirhash_t max_hash;
124 ext2_dirhash_t node_min_hash;
125 ext2_dirhash_t node_max_hash;
128 #define DX_FLAG_REFERENCED 1
129 #define DX_FLAG_DUP_REF 2
130 #define DX_FLAG_FIRST 4
131 #define DX_FLAG_LAST 8
133 #ifdef RESOURCE_TRACK
135 * This structure is used for keeping track of how much resources have
136 * been used for a particular pass of e2fsck.
138 struct resource_track {
139 struct timeval time_start;
140 struct timeval user_start;
141 struct timeval system_start;
149 #define E2F_OPT_READONLY 0x0001
150 #define E2F_OPT_PREEN 0x0002
151 #define E2F_OPT_YES 0x0004
152 #define E2F_OPT_NO 0x0008
153 #define E2F_OPT_TIME 0x0010
154 #define E2F_OPT_TIME2 0x0020
155 #define E2F_OPT_CHECKBLOCKS 0x0040
156 #define E2F_OPT_DEBUG 0x0080
157 #define E2F_OPT_FORCE 0x0100
158 #define E2F_OPT_WRITECHECK 0x0200
159 #define E2F_OPT_COMPRESS_DIRS 0x0400
164 #define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
165 #define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
166 #define E2F_FLAG_SIGNAL_MASK 0x0003
167 #define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
169 #define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
171 #define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
172 #define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
173 #define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */
174 #define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
175 * specified by the user */
176 #define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
177 #define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
180 * Defines for indicating the e2fsck pass number
187 #define E2F_PASS_1B 6
191 * This is the global e2fsck structure.
193 typedef struct e2fsck_struct *e2fsck_t;
196 * Define the extended attribute refcount structure
198 typedef struct ea_refcount *ext2_refcount_t;
200 struct e2fsck_struct {
202 const char *program_name;
203 char *filesystem_name;
206 int flags; /* E2fsck internal flags */
208 blk_t use_superblock; /* sb requested by user */
209 blk_t superblock; /* sb used to open fs */
210 int blocksize; /* blocksize */
211 blk_t num_blocks; /* Total number of blocks */
213 blkid_cache blkid; /* blkid cache */
217 unsigned long abort_code;
219 int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
222 ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
223 ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
224 ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
225 ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
226 ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
227 ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
229 ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
230 ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
231 ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
236 ext2_icount_t inode_count;
237 ext2_icount_t inode_link_info;
239 ext2_refcount_t refcount;
240 ext2_refcount_t refcount_extra;
243 * Array of flags indicating whether an inode bitmap, block
244 * bitmap, or inode table is invalid
246 int *invalid_inode_bitmap_flag;
247 int *invalid_block_bitmap_flag;
248 int *invalid_inode_table_flag;
249 int invalid_bitmaps; /* There are invalid bitmaps/itable */
257 * For pass1_check_directory and pass1_get_blocks
259 ext2_ino_t stashed_ino;
260 struct ext2_inode *stashed_inode;
263 * Location of the lost and found directory
265 ext2_ino_t lost_and_found;
266 int bad_lost_and_found;
269 * Directory information
273 struct dir_info *dir_info;
276 * Indexed directory information
278 int dx_dir_info_count;
279 int dx_dir_info_size;
280 struct dx_dir_info *dx_dir_info;
283 * Directories to hash
285 ext2_u32_list dirs_to_hash;
290 int process_inode_size;
291 int inode_buffer_blocks;
294 * ext3 journal support
296 io_channel journal_io;
299 #ifdef RESOURCE_TRACK
301 * For timing purposes
303 struct resource_track global_rtrack;
307 * How we display the progress update (for unix)
311 int progress_last_percent;
312 unsigned int progress_last_time;
313 int interactive; /* Are we connected directly to a tty? */
314 char start_meta[2], stop_meta[2];
317 int fs_directory_count;
318 int fs_regular_count;
319 int fs_blockdev_count;
320 int fs_chardev_count;
322 int fs_symlinks_count;
323 int fs_fast_symlinks_count;
326 int fs_badblocks_count;
327 int fs_sockets_count;
333 int fs_ext_attr_inodes;
334 int fs_ext_attr_blocks;
339 * For the use of callers of the e2fsck functions; not used by
340 * e2fsck functions themselves.
345 /* Used by the region allocation code */
346 typedef __u32 region_addr_t;
347 typedef struct region_struct *region_t;
350 * Procedure declarations
353 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
356 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
359 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
360 ext2_ino_t ino, char *buf);
363 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
364 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
365 int num, int gauranteed_size);
366 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
367 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
371 static void e2fsck_rehash_directories(e2fsck_t ctx);
374 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
375 const char *description);
376 static int ask(e2fsck_t ctx, const char * string, int def);
377 static void e2fsck_read_bitmaps(e2fsck_t ctx);
378 static void preenhalt(e2fsck_t ctx);
379 #ifdef RESOURCE_TRACK
380 static void print_resource_track(const char *desc,
381 struct resource_track *track);
382 static void init_resource_track(struct resource_track *track);
384 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
385 struct ext2_inode * inode, const char * proc);
386 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
387 struct ext2_inode * inode, const char * proc);
389 static void mtrace_print(char *mesg);
391 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
392 const char *name, io_manager manager);
395 static void e2fsck_clear_progbar(e2fsck_t ctx);
396 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
397 float percent, unsigned int dpynum);
399 * problem.h --- e2fsck problem error codes
402 typedef __u32 problem_t;
404 struct problem_context {
406 ext2_ino_t ino, ino2, dir;
407 struct ext2_inode *inode;
408 struct ext2_dir_entry *dirent;
410 e2_blkcnt_t blkcount;
417 * We define a set of "latch groups"; these are problems which are
418 * handled as a set. The user answers once for a particular latch
421 #define PR_LATCH_MASK 0x0ff0 /* Latch mask */
422 #define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
423 #define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
424 #define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
425 #define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
426 #define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
427 #define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
428 #define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
429 #define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
430 #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
432 #define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
435 * Latch group descriptor flags
437 #define PRL_YES 0x0001 /* Answer yes */
438 #define PRL_NO 0x0002 /* Answer no */
439 #define PRL_LATCHED 0x0004 /* The latch group is latched */
440 #define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
442 #define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
448 /* Block bitmap not in group */
449 #define PR_0_BB_NOT_GROUP 0x000001
451 /* Inode bitmap not in group */
452 #define PR_0_IB_NOT_GROUP 0x000002
454 /* Inode table not in group */
455 #define PR_0_ITABLE_NOT_GROUP 0x000003
457 /* Superblock corrupt */
458 #define PR_0_SB_CORRUPT 0x000004
460 /* Filesystem size is wrong */
461 #define PR_0_FS_SIZE_WRONG 0x000005
463 /* Fragments not supported */
464 #define PR_0_NO_FRAGMENTS 0x000006
466 /* Bad blocks_per_group */
467 #define PR_0_BLOCKS_PER_GROUP 0x000007
469 /* Bad first_data_block */
470 #define PR_0_FIRST_DATA_BLOCK 0x000008
472 /* Adding UUID to filesystem */
473 #define PR_0_ADD_UUID 0x000009
476 #define PR_0_RELOCATE_HINT 0x00000A
478 /* Miscellaneous superblock corruption */
479 #define PR_0_MISC_CORRUPT_SUPER 0x00000B
481 /* Error determing physical device size of filesystem */
482 #define PR_0_GETSIZE_ERROR 0x00000C
484 /* Inode count in the superblock incorrect */
485 #define PR_0_INODE_COUNT_WRONG 0x00000D
487 /* The Hurd does not support the filetype feature */
488 #define PR_0_HURD_CLEAR_FILETYPE 0x00000E
490 /* Journal inode is invalid */
491 #define PR_0_JOURNAL_BAD_INODE 0x00000F
493 /* The external journal has multiple filesystems (which we can't handle yet) */
494 #define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010
496 /* Can't find external journal */
497 #define PR_0_CANT_FIND_JOURNAL 0x000011
499 /* External journal has bad superblock */
500 #define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012
502 /* Superblock has a bad journal UUID */
503 #define PR_0_JOURNAL_BAD_UUID 0x000013
505 /* Journal has an unknown superblock type */
506 #define PR_0_JOURNAL_UNSUPP_SUPER 0x000014
508 /* Journal superblock is corrupt */
509 #define PR_0_JOURNAL_BAD_SUPER 0x000015
511 /* Journal superblock is corrupt */
512 #define PR_0_JOURNAL_HAS_JOURNAL 0x000016
514 /* Superblock has recovery flag set but no journal */
515 #define PR_0_JOURNAL_RECOVER_SET 0x000017
517 /* Journal has data, but recovery flag is clear */
518 #define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018
520 /* Ask if we should clear the journal */
521 #define PR_0_JOURNAL_RESET_JOURNAL 0x000019
523 /* Filesystem revision is 0, but feature flags are set */
524 #define PR_0_FS_REV_LEVEL 0x00001A
526 /* Clearing orphan inode */
527 #define PR_0_ORPHAN_CLEAR_INODE 0x000020
529 /* Illegal block found in orphaned inode */
530 #define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021
532 /* Already cleared block found in orphaned inode */
533 #define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022
535 /* Illegal orphan inode in superblock */
536 #define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023
538 /* Illegal inode in orphaned inode list */
539 #define PR_0_ORPHAN_ILLEGAL_INODE 0x000024
541 /* Journal has unsupported read-only feature - abort */
542 #define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025
544 /* Journal has unsupported incompatible feature - abort */
545 #define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026
547 /* Journal has unsupported version number */
548 #define PR_0_JOURNAL_UNSUPP_VERSION 0x000027
550 /* Moving journal to hidden file */
551 #define PR_0_MOVE_JOURNAL 0x000028
553 /* Error moving journal */
554 #define PR_0_ERR_MOVE_JOURNAL 0x000029
556 /* Clearing V2 journal superblock */
557 #define PR_0_CLEAR_V2_JOURNAL 0x00002A
559 /* Run journal anyway */
560 #define PR_0_JOURNAL_RUN 0x00002B
562 /* Run journal anyway by default */
563 #define PR_0_JOURNAL_RUN_DEFAULT 0x00002C
565 /* Backup journal inode blocks */
566 #define PR_0_BACKUP_JNL 0x00002D
568 /* Reserved blocks w/o resize_inode */
569 #define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E
571 /* Resize_inode not enabled, but resize inode is non-zero */
572 #define PR_0_CLEAR_RESIZE_INODE 0x00002F
574 /* Resize inode invalid */
575 #define PR_0_RESIZE_INODE_INVALID 0x000030
581 /* Pass 1: Checking inodes, blocks, and sizes */
582 #define PR_1_PASS_HEADER 0x010000
584 /* Root directory is not an inode */
585 #define PR_1_ROOT_NO_DIR 0x010001
587 /* Root directory has dtime set */
588 #define PR_1_ROOT_DTIME 0x010002
590 /* Reserved inode has bad mode */
591 #define PR_1_RESERVED_BAD_MODE 0x010003
593 /* Deleted inode has zero dtime */
594 #define PR_1_ZERO_DTIME 0x010004
596 /* Inode in use, but dtime set */
597 #define PR_1_SET_DTIME 0x010005
599 /* Zero-length directory */
600 #define PR_1_ZERO_LENGTH_DIR 0x010006
602 /* Block bitmap conflicts with some other fs block */
603 #define PR_1_BB_CONFLICT 0x010007
605 /* Inode bitmap conflicts with some other fs block */
606 #define PR_1_IB_CONFLICT 0x010008
608 /* Inode table conflicts with some other fs block */
609 #define PR_1_ITABLE_CONFLICT 0x010009
611 /* Block bitmap is on a bad block */
612 #define PR_1_BB_BAD_BLOCK 0x01000A
614 /* Inode bitmap is on a bad block */
615 #define PR_1_IB_BAD_BLOCK 0x01000B
617 /* Inode has incorrect i_size */
618 #define PR_1_BAD_I_SIZE 0x01000C
620 /* Inode has incorrect i_blocks */
621 #define PR_1_BAD_I_BLOCKS 0x01000D
623 /* Illegal block number in inode */
624 #define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
626 /* Block number overlaps fs metadata */
627 #define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F
629 /* Inode has illegal blocks (latch question) */
630 #define PR_1_INODE_BLOCK_LATCH 0x010010
632 /* Too many bad blocks in inode */
633 #define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
635 /* Illegal block number in bad block inode */
636 #define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
638 /* Bad block inode has illegal blocks (latch question) */
639 #define PR_1_INODE_BBLOCK_LATCH 0x010013
641 /* Duplicate or bad blocks in use! */
642 #define PR_1_DUP_BLOCKS_PREENSTOP 0x010014
644 /* Bad block used as bad block indirect block */
645 #define PR_1_BBINODE_BAD_METABLOCK 0x010015
647 /* Inconsistency can't be fixed prompt */
648 #define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
650 /* Bad primary block */
651 #define PR_1_BAD_PRIMARY_BLOCK 0x010017
653 /* Bad primary block prompt */
654 #define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018
656 /* Bad primary superblock */
657 #define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019
659 /* Bad primary block group descriptors */
660 #define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A
662 /* Bad superblock in group */
663 #define PR_1_BAD_SUPERBLOCK 0x01001B
665 /* Bad block group descriptors in group */
666 #define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C
668 /* Block claimed for no reason */
669 #define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D
671 /* Error allocating blocks for relocating metadata */
672 #define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E
674 /* Error allocating block buffer during relocation process */
675 #define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F
677 /* Relocating metadata group information from X to Y */
678 #define PR_1_RELOC_FROM_TO 0x010020
680 /* Relocating metatdata group information to X */
681 #define PR_1_RELOC_TO 0x010021
683 /* Block read error during relocation process */
684 #define PR_1_RELOC_READ_ERR 0x010022
686 /* Block write error during relocation process */
687 #define PR_1_RELOC_WRITE_ERR 0x010023
689 /* Error allocating inode bitmap */
690 #define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024
692 /* Error allocating block bitmap */
693 #define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025
695 /* Error allocating icount structure */
696 #define PR_1_ALLOCATE_ICOUNT 0x010026
698 /* Error allocating dbcount */
699 #define PR_1_ALLOCATE_DBCOUNT 0x010027
701 /* Error while scanning inodes */
702 #define PR_1_ISCAN_ERROR 0x010028
704 /* Error while iterating over blocks */
705 #define PR_1_BLOCK_ITERATE 0x010029
707 /* Error while storing inode count information */
708 #define PR_1_ICOUNT_STORE 0x01002A
710 /* Error while storing directory block information */
711 #define PR_1_ADD_DBLOCK 0x01002B
713 /* Error while reading inode (for clearing) */
714 #define PR_1_READ_INODE 0x01002C
716 /* Suppress messages prompt */
717 #define PR_1_SUPPRESS_MESSAGES 0x01002D
719 /* Imagic flag set on an inode when filesystem doesn't support it */
720 #define PR_1_SET_IMAGIC 0x01002F
722 /* Immutable flag set on a device or socket inode */
723 #define PR_1_SET_IMMUTABLE 0x010030
725 /* Compression flag set on a non-compressed filesystem */
726 #define PR_1_COMPR_SET 0x010031
728 /* Non-zero size on on device, fifo or socket inode */
729 #define PR_1_SET_NONZSIZE 0x010032
731 /* Filesystem revision is 0, but feature flags are set */
732 #define PR_1_FS_REV_LEVEL 0x010033
734 /* Journal inode not in use, needs clearing */
735 #define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034
737 /* Journal inode has wrong mode */
738 #define PR_1_JOURNAL_BAD_MODE 0x010035
740 /* Inode that was part of orphan linked list */
741 #define PR_1_LOW_DTIME 0x010036
743 /* Latch question which asks how to deal with low dtime inodes */
744 #define PR_1_ORPHAN_LIST_REFUGEES 0x010037
746 /* Error allocating refcount structure */
747 #define PR_1_ALLOCATE_REFCOUNT 0x010038
749 /* Error reading Extended Attribute block */
750 #define PR_1_READ_EA_BLOCK 0x010039
752 /* Invalid Extended Attribute block */
753 #define PR_1_BAD_EA_BLOCK 0x01003A
755 /* Error reading Extended Attribute block while fixing refcount -- abort */
756 #define PR_1_EXTATTR_READ_ABORT 0x01003B
758 /* Extended attribute reference count incorrect */
759 #define PR_1_EXTATTR_REFCOUNT 0x01003C
761 /* Error writing Extended Attribute block while fixing refcount */
762 #define PR_1_EXTATTR_WRITE 0x01003D
764 /* Multiple EA blocks not supported */
765 #define PR_1_EA_MULTI_BLOCK 0x01003E
767 /* Error allocating EA region allocation structure */
768 #define PR_1_EA_ALLOC_REGION 0x01003F
770 /* Error EA allocation collision */
771 #define PR_1_EA_ALLOC_COLLISION 0x010040
773 /* Bad extended attribute name */
774 #define PR_1_EA_BAD_NAME 0x010041
776 /* Bad extended attribute value */
777 #define PR_1_EA_BAD_VALUE 0x010042
779 /* Inode too big (latch question) */
780 #define PR_1_INODE_TOOBIG 0x010043
782 /* Directory too big */
783 #define PR_1_TOOBIG_DIR 0x010044
785 /* Regular file too big */
786 #define PR_1_TOOBIG_REG 0x010045
788 /* Symlink too big */
789 #define PR_1_TOOBIG_SYMLINK 0x010046
791 /* INDEX_FL flag set on a non-HTREE filesystem */
792 #define PR_1_HTREE_SET 0x010047
794 /* INDEX_FL flag set on a non-directory */
795 #define PR_1_HTREE_NODIR 0x010048
797 /* Invalid root node in HTREE directory */
798 #define PR_1_HTREE_BADROOT 0x010049
800 /* Unsupported hash version in HTREE directory */
801 #define PR_1_HTREE_HASHV 0x01004A
803 /* Incompatible flag in HTREE root node */
804 #define PR_1_HTREE_INCOMPAT 0x01004B
807 #define PR_1_HTREE_DEPTH 0x01004C
809 /* Bad block has indirect block that conflicts with filesystem block */
810 #define PR_1_BB_FS_BLOCK 0x01004D
812 /* Resize inode failed */
813 #define PR_1_RESIZE_INODE_CREATE 0x01004E
815 /* inode->i_size is too long */
816 #define PR_1_EXTRA_ISIZE 0x01004F
818 /* attribute name is too long */
819 #define PR_1_ATTR_NAME_LEN 0x010050
821 /* wrong EA value offset */
822 #define PR_1_ATTR_VALUE_OFFSET 0x010051
824 /* wrong EA blocknumber */
825 #define PR_1_ATTR_VALUE_BLOCK 0x010052
827 /* wrong EA value size */
828 #define PR_1_ATTR_VALUE_SIZE 0x010053
830 /* wrong EA hash value */
831 #define PR_1_ATTR_HASH 0x010054
837 /* Pass 1B: Rescan for duplicate/bad blocks */
838 #define PR_1B_PASS_HEADER 0x011000
840 /* Duplicate/bad block(s) header */
841 #define PR_1B_DUP_BLOCK_HEADER 0x011001
843 /* Duplicate/bad block(s) in inode */
844 #define PR_1B_DUP_BLOCK 0x011002
846 /* Duplicate/bad block(s) end */
847 #define PR_1B_DUP_BLOCK_END 0x011003
849 /* Error while scanning inodes */
850 #define PR_1B_ISCAN_ERROR 0x011004
852 /* Error allocating inode bitmap */
853 #define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
855 /* Error while iterating over blocks */
856 #define PR_1B_BLOCK_ITERATE 0x0110006
858 /* Error adjusting EA refcount */
859 #define PR_1B_ADJ_EA_REFCOUNT 0x0110007
862 /* Pass 1C: Scan directories for inodes with dup blocks. */
863 #define PR_1C_PASS_HEADER 0x012000
866 /* Pass 1D: Reconciling duplicate blocks */
867 #define PR_1D_PASS_HEADER 0x013000
869 /* File has duplicate blocks */
870 #define PR_1D_DUP_FILE 0x013001
872 /* List of files sharing duplicate blocks */
873 #define PR_1D_DUP_FILE_LIST 0x013002
875 /* File sharing blocks with filesystem metadata */
876 #define PR_1D_SHARE_METADATA 0x013003
878 /* Report of how many duplicate/bad inodes */
879 #define PR_1D_NUM_DUP_INODES 0x013004
881 /* Duplicated blocks already reassigned or cloned. */
882 #define PR_1D_DUP_BLOCKS_DEALT 0x013005
884 /* Clone duplicate/bad blocks? */
885 #define PR_1D_CLONE_QUESTION 0x013006
888 #define PR_1D_DELETE_QUESTION 0x013007
890 /* Couldn't clone file (error) */
891 #define PR_1D_CLONE_ERROR 0x013008
897 /* Pass 2: Checking directory structure */
898 #define PR_2_PASS_HEADER 0x020000
900 /* Bad inode number for '.' */
901 #define PR_2_BAD_INODE_DOT 0x020001
903 /* Directory entry has bad inode number */
904 #define PR_2_BAD_INO 0x020002
906 /* Directory entry has deleted or unused inode */
907 #define PR_2_UNUSED_INODE 0x020003
909 /* Directry entry is link to '.' */
910 #define PR_2_LINK_DOT 0x020004
912 /* Directory entry points to inode now located in a bad block */
913 #define PR_2_BB_INODE 0x020005
915 /* Directory entry contains a link to a directory */
916 #define PR_2_LINK_DIR 0x020006
918 /* Directory entry contains a link to the root directry */
919 #define PR_2_LINK_ROOT 0x020007
921 /* Directory entry has illegal characters in its name */
922 #define PR_2_BAD_NAME 0x020008
924 /* Missing '.' in directory inode */
925 #define PR_2_MISSING_DOT 0x020009
927 /* Missing '..' in directory inode */
928 #define PR_2_MISSING_DOT_DOT 0x02000A
930 /* First entry in directory inode doesn't contain '.' */
931 #define PR_2_1ST_NOT_DOT 0x02000B
933 /* Second entry in directory inode doesn't contain '..' */
934 #define PR_2_2ND_NOT_DOT_DOT 0x02000C
936 /* i_faddr should be zero */
937 #define PR_2_FADDR_ZERO 0x02000D
939 /* i_file_acl should be zero */
940 #define PR_2_FILE_ACL_ZERO 0x02000E
942 /* i_dir_acl should be zero */
943 #define PR_2_DIR_ACL_ZERO 0x02000F
945 /* i_frag should be zero */
946 #define PR_2_FRAG_ZERO 0x020010
948 /* i_fsize should be zero */
949 #define PR_2_FSIZE_ZERO 0x020011
951 /* inode has bad mode */
952 #define PR_2_BAD_MODE 0x020012
954 /* directory corrupted */
955 #define PR_2_DIR_CORRUPTED 0x020013
957 /* filename too long */
958 #define PR_2_FILENAME_LONG 0x020014
960 /* Directory inode has a missing block (hole) */
961 #define PR_2_DIRECTORY_HOLE 0x020015
963 /* '.' is not NULL terminated */
964 #define PR_2_DOT_NULL_TERM 0x020016
966 /* '..' is not NULL terminated */
967 #define PR_2_DOT_DOT_NULL_TERM 0x020017
969 /* Illegal character device in inode */
970 #define PR_2_BAD_CHAR_DEV 0x020018
972 /* Illegal block device in inode */
973 #define PR_2_BAD_BLOCK_DEV 0x020019
975 /* Duplicate '.' entry */
976 #define PR_2_DUP_DOT 0x02001A
978 /* Duplicate '..' entry */
979 #define PR_2_DUP_DOT_DOT 0x02001B
981 /* Internal error: couldn't find dir_info */
982 #define PR_2_NO_DIRINFO 0x02001C
984 /* Final rec_len is wrong */
985 #define PR_2_FINAL_RECLEN 0x02001D
987 /* Error allocating icount structure */
988 #define PR_2_ALLOCATE_ICOUNT 0x02001E
990 /* Error iterating over directory blocks */
991 #define PR_2_DBLIST_ITERATE 0x02001F
993 /* Error reading directory block */
994 #define PR_2_READ_DIRBLOCK 0x020020
996 /* Error writing directory block */
997 #define PR_2_WRITE_DIRBLOCK 0x020021
999 /* Error allocating new directory block */
1000 #define PR_2_ALLOC_DIRBOCK 0x020022
1002 /* Error deallocating inode */
1003 #define PR_2_DEALLOC_INODE 0x020023
1005 /* Directory entry for '.' is big. Split? */
1006 #define PR_2_SPLIT_DOT 0x020024
1009 #define PR_2_BAD_FIFO 0x020025
1011 /* Illegal socket */
1012 #define PR_2_BAD_SOCKET 0x020026
1014 /* Directory filetype not set */
1015 #define PR_2_SET_FILETYPE 0x020027
1017 /* Directory filetype incorrect */
1018 #define PR_2_BAD_FILETYPE 0x020028
1020 /* Directory filetype set when it shouldn't be */
1021 #define PR_2_CLEAR_FILETYPE 0x020029
1023 /* Directory filename can't be zero-length */
1024 #define PR_2_NULL_NAME 0x020030
1026 /* Invalid symlink */
1027 #define PR_2_INVALID_SYMLINK 0x020031
1029 /* i_file_acl (extended attribute) is bad */
1030 #define PR_2_FILE_ACL_BAD 0x020032
1032 /* Filesystem contains large files, but has no such flag in sb */
1033 #define PR_2_FEATURE_LARGE_FILES 0x020033
1035 /* Node in HTREE directory not referenced */
1036 #define PR_2_HTREE_NOTREF 0x020034
1038 /* Node in HTREE directory referenced twice */
1039 #define PR_2_HTREE_DUPREF 0x020035
1041 /* Node in HTREE directory has bad min hash */
1042 #define PR_2_HTREE_MIN_HASH 0x020036
1044 /* Node in HTREE directory has bad max hash */
1045 #define PR_2_HTREE_MAX_HASH 0x020037
1047 /* Clear invalid HTREE directory */
1048 #define PR_2_HTREE_CLEAR 0x020038
1050 /* Clear the htree flag forcibly */
1051 /* #define PR_2_HTREE_FCLR 0x020039 */
1053 /* Bad block in htree interior node */
1054 #define PR_2_HTREE_BADBLK 0x02003A
1056 /* Error adjusting EA refcount */
1057 #define PR_2_ADJ_EA_REFCOUNT 0x02003B
1059 /* Invalid HTREE root node */
1060 #define PR_2_HTREE_BAD_ROOT 0x02003C
1062 /* Invalid HTREE limit */
1063 #define PR_2_HTREE_BAD_LIMIT 0x02003D
1065 /* Invalid HTREE count */
1066 #define PR_2_HTREE_BAD_COUNT 0x02003E
1068 /* HTREE interior node has out-of-order hashes in table */
1069 #define PR_2_HTREE_HASH_ORDER 0x02003F
1071 /* Node in HTREE directory has bad depth */
1072 #define PR_2_HTREE_BAD_DEPTH 0x020040
1074 /* Duplicate directory entry found */
1075 #define PR_2_DUPLICATE_DIRENT 0x020041
1077 /* Non-unique filename found */
1078 #define PR_2_NON_UNIQUE_FILE 0x020042
1080 /* Duplicate directory entry found */
1081 #define PR_2_REPORT_DUP_DIRENT 0x020043
1087 /* Pass 3: Checking directory connectivity */
1088 #define PR_3_PASS_HEADER 0x030000
1090 /* Root inode not allocated */
1091 #define PR_3_NO_ROOT_INODE 0x030001
1093 /* No room in lost+found */
1094 #define PR_3_EXPAND_LF_DIR 0x030002
1096 /* Unconnected directory inode */
1097 #define PR_3_UNCONNECTED_DIR 0x030003
1099 /* /lost+found not found */
1100 #define PR_3_NO_LF_DIR 0x030004
1102 /* .. entry is incorrect */
1103 #define PR_3_BAD_DOT_DOT 0x030005
1105 /* Bad or non-existent /lost+found. Cannot reconnect */
1106 #define PR_3_NO_LPF 0x030006
1108 /* Could not expand /lost+found */
1109 #define PR_3_CANT_EXPAND_LPF 0x030007
1111 /* Could not reconnect inode */
1112 #define PR_3_CANT_RECONNECT 0x030008
1114 /* Error while trying to find /lost+found */
1115 #define PR_3_ERR_FIND_LPF 0x030009
1117 /* Error in ext2fs_new_block while creating /lost+found */
1118 #define PR_3_ERR_LPF_NEW_BLOCK 0x03000A
1120 /* Error in ext2fs_new_inode while creating /lost+found */
1121 #define PR_3_ERR_LPF_NEW_INODE 0x03000B
1123 /* Error in ext2fs_new_dir_block while creating /lost+found */
1124 #define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C
1126 /* Error while writing directory block for /lost+found */
1127 #define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D
1129 /* Error while adjusting inode count */
1130 #define PR_3_ADJUST_INODE 0x03000E
1132 /* Couldn't fix parent directory -- error */
1133 #define PR_3_FIX_PARENT_ERR 0x03000F
1135 /* Couldn't fix parent directory -- couldn't find it */
1136 #define PR_3_FIX_PARENT_NOFIND 0x030010
1138 /* Error allocating inode bitmap */
1139 #define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011
1141 /* Error creating root directory */
1142 #define PR_3_CREATE_ROOT_ERROR 0x030012
1144 /* Error creating lost and found directory */
1145 #define PR_3_CREATE_LPF_ERROR 0x030013
1147 /* Root inode is not directory; aborting */
1148 #define PR_3_ROOT_NOT_DIR_ABORT 0x030014
1150 /* Cannot proceed without a root inode. */
1151 #define PR_3_NO_ROOT_INODE_ABORT 0x030015
1153 /* Internal error: couldn't find dir_info */
1154 #define PR_3_NO_DIRINFO 0x030016
1156 /* Lost+found is not a directory */
1157 #define PR_3_LPF_NOTDIR 0x030017
1160 * Pass 3a --- rehashing diretories
1162 /* Pass 3a: Reindexing directories */
1163 #define PR_3A_PASS_HEADER 0x031000
1165 /* Error iterating over directories */
1166 #define PR_3A_OPTIMIZE_ITER 0x031001
1168 /* Error rehash directory */
1169 #define PR_3A_OPTIMIZE_DIR_ERR 0x031002
1171 /* Rehashing dir header */
1172 #define PR_3A_OPTIMIZE_DIR_HEADER 0x031003
1174 /* Rehashing directory %d */
1175 #define PR_3A_OPTIMIZE_DIR 0x031004
1177 /* Rehashing dir end */
1178 #define PR_3A_OPTIMIZE_DIR_END 0x031005
1184 /* Pass 4: Checking reference counts */
1185 #define PR_4_PASS_HEADER 0x040000
1187 /* Unattached zero-length inode */
1188 #define PR_4_ZERO_LEN_INODE 0x040001
1190 /* Unattached inode */
1191 #define PR_4_UNATTACHED_INODE 0x040002
1193 /* Inode ref count wrong */
1194 #define PR_4_BAD_REF_COUNT 0x040003
1196 /* Inconsistent inode count information cached */
1197 #define PR_4_INCONSISTENT_COUNT 0x040004
1203 /* Pass 5: Checking group summary information */
1204 #define PR_5_PASS_HEADER 0x050000
1206 /* Padding at end of inode bitmap is not set. */
1207 #define PR_5_INODE_BMAP_PADDING 0x050001
1209 /* Padding at end of block bitmap is not set. */
1210 #define PR_5_BLOCK_BMAP_PADDING 0x050002
1212 /* Block bitmap differences header */
1213 #define PR_5_BLOCK_BITMAP_HEADER 0x050003
1215 /* Block not used, but marked in bitmap */
1216 #define PR_5_BLOCK_UNUSED 0x050004
1218 /* Block used, but not marked used in bitmap */
1219 #define PR_5_BLOCK_USED 0x050005
1221 /* Block bitmap differences end */
1222 #define PR_5_BLOCK_BITMAP_END 0x050006
1224 /* Inode bitmap differences header */
1225 #define PR_5_INODE_BITMAP_HEADER 0x050007
1227 /* Inode not used, but marked in bitmap */
1228 #define PR_5_INODE_UNUSED 0x050008
1230 /* Inode used, but not marked used in bitmap */
1231 #define PR_5_INODE_USED 0x050009
1233 /* Inode bitmap differences end */
1234 #define PR_5_INODE_BITMAP_END 0x05000A
1236 /* Free inodes count for group wrong */
1237 #define PR_5_FREE_INODE_COUNT_GROUP 0x05000B
1239 /* Directories count for group wrong */
1240 #define PR_5_FREE_DIR_COUNT_GROUP 0x05000C
1242 /* Free inodes count wrong */
1243 #define PR_5_FREE_INODE_COUNT 0x05000D
1245 /* Free blocks count for group wrong */
1246 #define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E
1248 /* Free blocks count wrong */
1249 #define PR_5_FREE_BLOCK_COUNT 0x05000F
1251 /* Programming error: bitmap endpoints don't match */
1252 #define PR_5_BMAP_ENDPOINTS 0x050010
1254 /* Internal error: fudging end of bitmap */
1255 #define PR_5_FUDGE_BITMAP_ERROR 0x050011
1257 /* Error copying in replacement inode bitmap */
1258 #define PR_5_COPY_IBITMAP_ERROR 0x050012
1260 /* Error copying in replacement block bitmap */
1261 #define PR_5_COPY_BBITMAP_ERROR 0x050013
1263 /* Block range not used, but marked in bitmap */
1264 #define PR_5_BLOCK_RANGE_UNUSED 0x050014
1266 /* Block range used, but not marked used in bitmap */
1267 #define PR_5_BLOCK_RANGE_USED 0x050015
1269 /* Inode range not used, but marked in bitmap */
1270 #define PR_5_INODE_RANGE_UNUSED 0x050016
1272 /* Inode rangeused, but not marked used in bitmap */
1273 #define PR_5_INODE_RANGE_USED 0x050017
1276 * Function declarations
1278 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
1279 static int end_problem_latch(e2fsck_t ctx, int mask);
1280 static int set_latch_flags(int mask, int setflags, int clearflags);
1281 static void clear_problem_context(struct problem_context *ctx);
1284 * Dictionary Abstract Data Type
1285 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
1287 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
1295 * Blurb for inclusion into C++ translation units
1298 typedef unsigned long dictcount_t;
1299 #define DICTCOUNT_T_MAX ULONG_MAX
1302 * The dictionary is implemented as a red-black tree
1305 typedef enum { dnode_red, dnode_black } dnode_color_t;
1307 typedef struct dnode_t {
1308 struct dnode_t *dict_left;
1309 struct dnode_t *dict_right;
1310 struct dnode_t *dict_parent;
1311 dnode_color_t dict_color;
1312 const void *dict_key;
1316 typedef int (*dict_comp_t)(const void *, const void *);
1317 typedef void (*dnode_free_t)(dnode_t *);
1319 typedef struct dict_t {
1320 dnode_t dict_nilnode;
1321 dictcount_t dict_nodecount;
1322 dictcount_t dict_maxcount;
1323 dict_comp_t dict_compare;
1324 dnode_free_t dict_freenode;
1328 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
1330 typedef struct dict_load_t {
1331 dict_t *dict_dictptr;
1332 dnode_t dict_nilnode;
1335 #define dict_count(D) ((D)->dict_nodecount)
1336 #define dnode_get(N) ((N)->dict_data)
1337 #define dnode_getkey(N) ((N)->dict_key)
1342 * Compatibility header file for e2fsck which should be included
1343 * instead of linux/jfs.h
1345 * Copyright (C) 2000 Stephen C. Tweedie
1349 * Pull in the definition of the e2fsck context structure
1353 struct buffer_head {
1367 struct ext2_inode i_ext2;
1376 #define K_DEV_JOURNAL 2
1378 typedef struct kdev_s *kdev_t;
1380 #define lock_buffer(bh) do {} while(0)
1381 #define unlock_buffer(bh) do {} while(0)
1382 #define buffer_req(bh) 1
1383 #define do_readahead(journal, start) do {} while(0)
1385 static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
1391 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1394 * We use the standard libext2fs portability tricks for inline
1398 static _INLINE_ kmem_cache_t * do_cache_create(int len)
1400 kmem_cache_t *new_cache;
1402 new_cache = malloc(sizeof(*new_cache));
1404 new_cache->object_length = len;
1408 static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1414 * Now pull in the real linux/jfs.h definitions.
1416 #include "ext2fs/kernel-jbd.h"
1419 * badblocks.c --- replace/append bad blocks to the bad block inode
1422 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
1426 static void invalid_block(ext2_filsys fs FSCK_ATTR((unused)), blk_t blk)
1428 printf(_("Bad block %u out of range; ignored.\n"), blk);
1432 static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1433 int replace_bad_blocks)
1435 ext2_filsys fs = ctx->fs;
1437 badblocks_list bb_list = 0;
1441 e2fsck_read_bitmaps(ctx);
1444 * Make sure the bad block inode is sane. If there are any
1445 * illegal blocks, clear them.
1447 retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
1448 check_bb_inode_blocks, 0);
1450 com_err("ext2fs_block_iterate", retval,
1451 _("while sanity checking the bad blocks inode"));
1456 * If we're appending to the bad blocks inode, read in the
1457 * current bad blocks.
1459 if (!replace_bad_blocks) {
1460 retval = ext2fs_read_bb_inode(fs, &bb_list);
1462 com_err("ext2fs_read_bb_inode", retval,
1463 _("while reading the bad blocks inode"));
1469 * Now read in the bad blocks from the file; if
1470 * bad_blocks_file is null, then try to run the badblocks
1473 if (bad_blocks_file) {
1474 f = fopen(bad_blocks_file, "r");
1476 com_err("read_bad_blocks_file", errno,
1477 _("while trying to open %s"), bad_blocks_file);
1481 sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
1482 (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
1483 (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
1484 fs->device_name, fs->super->s_blocks_count);
1485 f = popen(buf, "r");
1487 com_err("read_bad_blocks_file", errno,
1488 _("while trying popen '%s'"), buf);
1492 retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
1493 if (bad_blocks_file)
1498 com_err("ext2fs_read_bb_FILE", retval,
1499 _("while reading in list of bad blocks from file"));
1504 * Finally, update the bad blocks from the bad_block_map
1506 retval = ext2fs_update_bb_inode(fs, bb_list);
1508 com_err("ext2fs_update_bb_inode", retval,
1509 _("while updating bad block inode"));
1513 ext2fs_badblocks_list_free(bb_list);
1517 ctx->flags |= E2F_FLAG_ABORT;
1522 static int check_bb_inode_blocks(ext2_filsys fs,
1524 int blockcnt FSCK_ATTR((unused)),
1525 void *priv_data FSCK_ATTR((unused)))
1531 * If the block number is outrageous, clear it and ignore it.
1533 if (*block_nr >= fs->super->s_blocks_count ||
1534 *block_nr < fs->super->s_first_data_block) {
1535 printf(_("Warning illegal block %u found in bad block inode. Cleared.\n"), *block_nr);
1537 return BLOCK_CHANGED;
1544 * Dictionary Abstract Data Type
1549 * These macros provide short convenient names for structure members,
1550 * which are embellished with dict_ prefixes so that they are
1551 * properly confined to the documented namespace. It's legal for a
1552 * program which uses dict to define, for instance, a macro called ``parent''.
1553 * Such a macro would interfere with the dnode_t struct definition.
1554 * In general, highly portable and reusable C modules which expose their
1555 * structures need to confine structure member names to well-defined spaces.
1556 * The resulting identifiers aren't necessarily convenient to use, nor
1557 * readable, in the implementation, however!
1560 #define left dict_left
1561 #define right dict_right
1562 #define parent dict_parent
1563 #define color dict_color
1564 #define key dict_key
1565 #define data dict_data
1567 #define nilnode dict_nilnode
1568 #define maxcount dict_maxcount
1569 #define compare dict_compare
1570 #define dupes dict_dupes
1572 #define dict_root(D) ((D)->nilnode.left)
1573 #define dict_nil(D) (&(D)->nilnode)
1574 #define DICT_DEPTH_MAX 64
1576 static void dnode_free(dnode_t *node);
1579 * Perform a ``left rotation'' adjustment on the tree. The given node P and
1580 * its right child C are rearranged so that the P instead becomes the left
1581 * child of C. The left subtree of C is inherited as the new right subtree
1582 * for P. The ordering of the keys within the tree is thus preserved.
1585 static void rotate_left(dnode_t *upper)
1587 dnode_t *lower, *lowleft, *upparent;
1589 lower = upper->right;
1590 upper->right = lowleft = lower->left;
1591 lowleft->parent = upper;
1593 lower->parent = upparent = upper->parent;
1595 /* don't need to check for root node here because root->parent is
1596 the sentinel nil node, and root->parent->left points back to root */
1598 if (upper == upparent->left) {
1599 upparent->left = lower;
1601 assert (upper == upparent->right);
1602 upparent->right = lower;
1605 lower->left = upper;
1606 upper->parent = lower;
1610 * This operation is the ``mirror'' image of rotate_left. It is
1611 * the same procedure, but with left and right interchanged.
1614 static void rotate_right(dnode_t *upper)
1616 dnode_t *lower, *lowright, *upparent;
1618 lower = upper->left;
1619 upper->left = lowright = lower->right;
1620 lowright->parent = upper;
1622 lower->parent = upparent = upper->parent;
1624 if (upper == upparent->right) {
1625 upparent->right = lower;
1627 assert (upper == upparent->left);
1628 upparent->left = lower;
1631 lower->right = upper;
1632 upper->parent = lower;
1636 * Do a postorder traversal of the tree rooted at the specified
1637 * node and free everything under it. Used by dict_free().
1640 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1644 free_nodes(dict, node->left, nil);
1645 free_nodes(dict, node->right, nil);
1646 dict->dict_freenode(node);
1650 * Verify that the tree contains the given node. This is done by
1651 * traversing all of the nodes and comparing their pointers to the
1652 * given pointer. Returns 1 if the node is found, otherwise
1653 * returns zero. It is intended for debugging purposes.
1656 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1660 || verify_dict_has_node(nil, root->left, node)
1661 || verify_dict_has_node(nil, root->right, node);
1668 * Select a different set of node allocator routines.
1671 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1673 assert (dict_count(dict) == 0);
1674 dict->dict_freenode = fr;
1678 * Free all the nodes in the dictionary by using the dictionary's
1679 * installed free routine. The dictionary is emptied.
1682 static void dict_free_nodes(dict_t *dict)
1684 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1685 free_nodes(dict, root, nil);
1686 dict->dict_nodecount = 0;
1687 dict->nilnode.left = &dict->nilnode;
1688 dict->nilnode.right = &dict->nilnode;
1692 * Initialize a user-supplied dictionary object.
1695 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1697 dict->compare = comp;
1698 dict->dict_freenode = dnode_free;
1699 dict->dict_nodecount = 0;
1700 dict->maxcount = maxcount;
1701 dict->nilnode.left = &dict->nilnode;
1702 dict->nilnode.right = &dict->nilnode;
1703 dict->nilnode.parent = &dict->nilnode;
1704 dict->nilnode.color = dnode_black;
1710 * Locate a node in the dictionary having the given key.
1711 * If the node is not found, a null a pointer is returned (rather than
1712 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
1713 * located node is returned.
1716 static dnode_t *dict_lookup(dict_t *dict, const void *key)
1718 dnode_t *root = dict_root(dict);
1719 dnode_t *nil = dict_nil(dict);
1723 /* simple binary search adapted for trees that contain duplicate keys */
1725 while (root != nil) {
1726 result = dict->compare(key, root->key);
1729 else if (result > 0)
1732 if (!dict->dupes) { /* no duplicates, return match */
1734 } else { /* could be dupes, find leftmost one */
1738 while (root != nil && dict->compare(key, root->key))
1740 } while (root != nil);
1750 * Insert a node into the dictionary. The node should have been
1751 * initialized with a data field. All other fields are ignored.
1752 * The behavior is undefined if the user attempts to insert into
1753 * a dictionary that is already full (for which the dict_isfull()
1754 * function returns true).
1757 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1759 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1760 dnode_t *parent = nil, *uncle, *grandpa;
1765 /* basic binary tree insert */
1767 while (where != nil) {
1769 result = dict->compare(key, where->key);
1770 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
1771 assert (dict->dupes || result != 0);
1773 where = where->left;
1775 where = where->right;
1778 assert (where == nil);
1781 parent->left = node;
1783 parent->right = node;
1785 node->parent = parent;
1789 dict->dict_nodecount++;
1791 /* red black adjustments */
1793 node->color = dnode_red;
1795 while (parent->color == dnode_red) {
1796 grandpa = parent->parent;
1797 if (parent == grandpa->left) {
1798 uncle = grandpa->right;
1799 if (uncle->color == dnode_red) { /* red parent, red uncle */
1800 parent->color = dnode_black;
1801 uncle->color = dnode_black;
1802 grandpa->color = dnode_red;
1804 parent = grandpa->parent;
1805 } else { /* red parent, black uncle */
1806 if (node == parent->right) {
1807 rotate_left(parent);
1809 assert (grandpa == parent->parent);
1810 /* rotation between parent and child preserves grandpa */
1812 parent->color = dnode_black;
1813 grandpa->color = dnode_red;
1814 rotate_right(grandpa);
1817 } else { /* symmetric cases: parent == parent->parent->right */
1818 uncle = grandpa->left;
1819 if (uncle->color == dnode_red) {
1820 parent->color = dnode_black;
1821 uncle->color = dnode_black;
1822 grandpa->color = dnode_red;
1824 parent = grandpa->parent;
1826 if (node == parent->left) {
1827 rotate_right(parent);
1829 assert (grandpa == parent->parent);
1831 parent->color = dnode_black;
1832 grandpa->color = dnode_red;
1833 rotate_left(grandpa);
1839 dict_root(dict)->color = dnode_black;
1844 * Allocate a node using the dictionary's allocator routine, give it
1848 static dnode_t *dnode_init(dnode_t *dnode, void *data)
1851 dnode->parent = NULL;
1853 dnode->right = NULL;
1857 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1859 dnode_t *node = malloc(sizeof(dnode_t));
1862 dnode_init(node, data);
1863 dict_insert(dict, node, key);
1870 * Return the node with the lowest (leftmost) key. If the dictionary is empty
1871 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
1874 static dnode_t *dict_first(dict_t *dict)
1876 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
1879 while ((left = root->left) != nil)
1882 return (root == nil) ? NULL : root;
1886 * Return the given node's successor node---the node which has the
1887 * next key in the the left to right ordering. If the node has
1888 * no successor, a null pointer is returned rather than a pointer to
1892 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
1894 dnode_t *nil = dict_nil(dict), *parent, *left;
1896 if (curr->right != nil) {
1898 while ((left = curr->left) != nil)
1903 parent = curr->parent;
1905 while (parent != nil && curr == parent->right) {
1907 parent = curr->parent;
1910 return (parent == nil) ? NULL : parent;
1914 static void dnode_free(dnode_t *node)
1934 * dirinfo.c --- maintains the directory information table for e2fsck.
1938 * This subroutine is called during pass1 to create a directory info
1939 * entry. During pass1, the passed-in parent is 0; it will get filled
1942 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
1944 struct dir_info *dir;
1946 ext2_ino_t num_dirs;
1948 unsigned long old_size;
1951 printf("add_dir_info for inode %lu...\n", ino);
1953 if (!ctx->dir_info) {
1954 ctx->dir_info_count = 0;
1955 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
1957 num_dirs = 1024; /* Guess */
1958 ctx->dir_info_size = num_dirs + 10;
1959 ctx->dir_info = (struct dir_info *)
1960 e2fsck_allocate_memory(ctx, ctx->dir_info_size
1961 * sizeof (struct dir_info),
1965 if (ctx->dir_info_count >= ctx->dir_info_size) {
1966 old_size = ctx->dir_info_size * sizeof(struct dir_info);
1967 ctx->dir_info_size += 10;
1968 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
1969 sizeof(struct dir_info),
1972 ctx->dir_info_size -= 10;
1978 * Normally, add_dir_info is called with each inode in
1979 * sequential order; but once in a while (like when pass 3
1980 * needs to recreate the root directory or lost+found
1981 * directory) it is called out of order. In those cases, we
1982 * need to move the dir_info entries down to make room, since
1983 * the dir_info array needs to be sorted by inode number for
1984 * get_dir_info()'s sake.
1986 if (ctx->dir_info_count &&
1987 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
1988 for (i = ctx->dir_info_count-1; i > 0; i--)
1989 if (ctx->dir_info[i-1].ino < ino)
1991 dir = &ctx->dir_info[i];
1992 if (dir->ino != ino)
1993 for (j = ctx->dir_info_count++; j > i; j--)
1994 ctx->dir_info[j] = ctx->dir_info[j-1];
1996 dir = &ctx->dir_info[ctx->dir_info_count++];
1999 dir->dotdot = parent;
2000 dir->parent = parent;
2004 * get_dir_info() --- given an inode number, try to find the directory
2005 * information entry for it.
2007 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2012 high = ctx->dir_info_count-1;
2015 if (ino == ctx->dir_info[low].ino)
2016 return &ctx->dir_info[low];
2017 if (ino == ctx->dir_info[high].ino)
2018 return &ctx->dir_info[high];
2020 while (low < high) {
2022 if (mid == low || mid == high)
2024 if (ino == ctx->dir_info[mid].ino)
2025 return &ctx->dir_info[mid];
2026 if (ino < ctx->dir_info[mid].ino)
2035 * Free the dir_info structure when it isn't needed any more.
2037 static void e2fsck_free_dir_info(e2fsck_t ctx)
2039 ext2fs_free_mem(&ctx->dir_info);
2040 ctx->dir_info_size = 0;
2041 ctx->dir_info_count = 0;
2045 * Return the count of number of directories in the dir_info structure
2047 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2049 return ctx->dir_info_count;
2053 * A simple interator function
2055 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2057 if (*control >= ctx->dir_info_count)
2060 return(ctx->dir_info + (*control)++);
2064 * dirinfo.c --- maintains the directory information table for e2fsck.
2071 * This subroutine is called during pass1 to create a directory info
2072 * entry. During pass1, the passed-in parent is 0; it will get filled
2075 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2077 struct dx_dir_info *dir;
2080 unsigned long old_size;
2083 printf("add_dx_dir_info for inode %lu...\n", ino);
2085 if (!ctx->dx_dir_info) {
2086 ctx->dx_dir_info_count = 0;
2087 ctx->dx_dir_info_size = 100; /* Guess */
2088 ctx->dx_dir_info = (struct dx_dir_info *)
2089 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
2090 * sizeof (struct dx_dir_info),
2094 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
2095 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
2096 ctx->dx_dir_info_size += 10;
2097 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
2098 sizeof(struct dx_dir_info),
2101 ctx->dx_dir_info_size -= 10;
2107 * Normally, add_dx_dir_info is called with each inode in
2108 * sequential order; but once in a while (like when pass 3
2109 * needs to recreate the root directory or lost+found
2110 * directory) it is called out of order. In those cases, we
2111 * need to move the dx_dir_info entries down to make room, since
2112 * the dx_dir_info array needs to be sorted by inode number for
2113 * get_dx_dir_info()'s sake.
2115 if (ctx->dx_dir_info_count &&
2116 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
2117 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
2118 if (ctx->dx_dir_info[i-1].ino < ino)
2120 dir = &ctx->dx_dir_info[i];
2121 if (dir->ino != ino)
2122 for (j = ctx->dx_dir_info_count++; j > i; j--)
2123 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
2125 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
2128 dir->numblocks = num_blocks;
2129 dir->hashversion = 0;
2130 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
2131 * sizeof (struct dx_dirblock_info),
2132 "dx_block info array");
2137 * get_dx_dir_info() --- given an inode number, try to find the directory
2138 * information entry for it.
2140 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2145 high = ctx->dx_dir_info_count-1;
2146 if (!ctx->dx_dir_info)
2148 if (ino == ctx->dx_dir_info[low].ino)
2149 return &ctx->dx_dir_info[low];
2150 if (ino == ctx->dx_dir_info[high].ino)
2151 return &ctx->dx_dir_info[high];
2153 while (low < high) {
2155 if (mid == low || mid == high)
2157 if (ino == ctx->dx_dir_info[mid].ino)
2158 return &ctx->dx_dir_info[mid];
2159 if (ino < ctx->dx_dir_info[mid].ino)
2168 * Free the dx_dir_info structure when it isn't needed any more.
2170 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2173 struct dx_dir_info *dir;
2175 if (ctx->dx_dir_info) {
2176 dir = ctx->dx_dir_info;
2177 for (i=0; i < ctx->dx_dir_info_count; i++) {
2178 ext2fs_free_mem(&dir->dx_block);
2180 ext2fs_free_mem(&ctx->dx_dir_info);
2182 ctx->dx_dir_info_size = 0;
2183 ctx->dx_dir_info_count = 0;
2187 * A simple interator function
2189 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2191 if (*control >= ctx->dx_dir_info_count)
2194 return(ctx->dx_dir_info + (*control)++);
2197 #endif /* ENABLE_HTREE */
2199 * e2fsck.c - a consistency checker for the new extended file system.
2204 * This function allocates an e2fsck context
2206 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2211 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
2215 memset(context, 0, sizeof(struct e2fsck_struct));
2217 context->process_inode_size = 256;
2218 context->ext_attr_ver = 2;
2224 struct ea_refcount_el {
2229 struct ea_refcount {
2233 struct ea_refcount_el *list;
2236 static void ea_refcount_free(ext2_refcount_t refcount)
2241 ext2fs_free_mem(&refcount->list);
2242 ext2fs_free_mem(&refcount);
2246 * This function resets an e2fsck context; it is called when e2fsck
2247 * needs to be restarted.
2249 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
2252 ctx->lost_and_found = 0;
2253 ctx->bad_lost_and_found = 0;
2254 ext2fs_free_inode_bitmap(ctx->inode_used_map);
2255 ctx->inode_used_map = 0;
2256 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
2257 ctx->inode_dir_map = 0;
2258 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
2259 ctx->inode_reg_map = 0;
2260 ext2fs_free_block_bitmap(ctx->block_found_map);
2261 ctx->block_found_map = 0;
2262 ext2fs_free_icount(ctx->inode_link_info);
2263 ctx->inode_link_info = 0;
2264 if (ctx->journal_io) {
2265 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2266 io_channel_close(ctx->journal_io);
2267 ctx->journal_io = 0;
2270 ext2fs_free_dblist(ctx->fs->dblist);
2271 ctx->fs->dblist = 0;
2273 e2fsck_free_dir_info(ctx);
2275 e2fsck_free_dx_dir_info(ctx);
2277 ea_refcount_free(ctx->refcount);
2279 ea_refcount_free(ctx->refcount_extra);
2280 ctx->refcount_extra = 0;
2281 ext2fs_free_block_bitmap(ctx->block_dup_map);
2282 ctx->block_dup_map = 0;
2283 ext2fs_free_block_bitmap(ctx->block_ea_map);
2284 ctx->block_ea_map = 0;
2285 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
2286 ctx->inode_bb_map = 0;
2287 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2288 ctx->inode_bad_map = 0;
2289 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
2290 ctx->inode_imagic_map = 0;
2291 ext2fs_u32_list_free(ctx->dirs_to_hash);
2292 ctx->dirs_to_hash = 0;
2295 * Clear the array of invalid meta-data flags
2297 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
2298 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
2299 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
2301 /* Clear statistic counters */
2302 ctx->fs_directory_count = 0;
2303 ctx->fs_regular_count = 0;
2304 ctx->fs_blockdev_count = 0;
2305 ctx->fs_chardev_count = 0;
2306 ctx->fs_links_count = 0;
2307 ctx->fs_symlinks_count = 0;
2308 ctx->fs_fast_symlinks_count = 0;
2309 ctx->fs_fifo_count = 0;
2310 ctx->fs_total_count = 0;
2311 ctx->fs_badblocks_count = 0;
2312 ctx->fs_sockets_count = 0;
2313 ctx->fs_ind_count = 0;
2314 ctx->fs_dind_count = 0;
2315 ctx->fs_tind_count = 0;
2316 ctx->fs_fragmented = 0;
2317 ctx->large_files = 0;
2319 /* Reset the superblock to the user's requested value */
2320 ctx->superblock = ctx->use_superblock;
2325 static void e2fsck_free_context(e2fsck_t ctx)
2330 e2fsck_reset_context(ctx);
2332 blkid_put_cache(ctx->blkid);
2334 ext2fs_free_mem(&ctx);
2342 * The strategy we use for keeping track of EA refcounts is as
2343 * follows. We keep a sorted array of first EA blocks and its
2344 * reference counts. Once the refcount has dropped to zero, it is
2345 * removed from the array to save memory space. Once the EA block is
2346 * checked, its bit is set in the block_ea_map bitmap.
2350 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2352 ext2_refcount_t refcount;
2356 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2359 memset(refcount, 0, sizeof(struct ea_refcount));
2363 refcount->size = size;
2364 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2366 printf("Refcount allocated %d entries, %d bytes.\n",
2367 refcount->size, bytes);
2369 retval = ext2fs_get_mem(bytes, &refcount->list);
2372 memset(refcount->list, 0, bytes);
2374 refcount->count = 0;
2375 refcount->cursor = 0;
2381 ea_refcount_free(refcount);
2386 * collapse_refcount() --- go through the refcount array, and get rid
2387 * of any count == zero entries
2389 static void refcount_collapse(ext2_refcount_t refcount)
2392 struct ea_refcount_el *list;
2394 list = refcount->list;
2395 for (i = 0, j = 0; i < refcount->count; i++) {
2396 if (list[i].ea_count) {
2402 #if defined(DEBUG) || defined(TEST_PROGRAM)
2403 printf("Refcount_collapse: size was %d, now %d\n",
2404 refcount->count, j);
2406 refcount->count = j;
2411 * insert_refcount_el() --- Insert a new entry into the sorted list at a
2412 * specified position.
2414 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2417 struct ea_refcount_el *el;
2422 if (refcount->count >= refcount->size) {
2423 new_size = refcount->size + 100;
2425 printf("Reallocating refcount %d entries...\n", new_size);
2427 retval = ext2fs_resize_mem((size_t) refcount->size *
2428 sizeof(struct ea_refcount_el),
2430 sizeof(struct ea_refcount_el),
2434 refcount->size = new_size;
2436 num = (int) refcount->count - pos;
2438 return 0; /* should never happen */
2440 memmove(&refcount->list[pos+1], &refcount->list[pos],
2441 sizeof(struct ea_refcount_el) * num);
2444 el = &refcount->list[pos];
2452 * get_refcount_el() --- given an block number, try to find refcount
2453 * information in the sorted list. If the create flag is set,
2454 * and we can't find an entry, create one in the sorted list.
2456 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2457 blk_t blk, int create)
2461 blk_t lowval, highval;
2463 if (!refcount || !refcount->list)
2467 high = (int) refcount->count-1;
2468 if (create && ((refcount->count == 0) ||
2469 (blk > refcount->list[high].ea_blk))) {
2470 if (refcount->count >= refcount->size)
2471 refcount_collapse(refcount);
2473 return insert_refcount_el(refcount, blk,
2474 (unsigned) refcount->count);
2476 if (refcount->count == 0)
2479 if (refcount->cursor >= refcount->count)
2480 refcount->cursor = 0;
2481 if (blk == refcount->list[refcount->cursor].ea_blk)
2482 return &refcount->list[refcount->cursor++];
2484 printf("Non-cursor get_refcount_el: %u\n", blk);
2486 while (low <= high) {
2493 /* Interpolate for efficiency */
2494 lowval = refcount->list[low].ea_blk;
2495 highval = refcount->list[high].ea_blk;
2499 else if (blk > highval)
2502 range = ((float) (blk - lowval)) /
2504 mid = low + ((int) (range * (high-low)));
2507 if (blk == refcount->list[mid].ea_blk) {
2508 refcount->cursor = mid+1;
2509 return &refcount->list[mid];
2511 if (blk < refcount->list[mid].ea_blk)
2517 * If we need to create a new entry, it should be right at
2518 * low (where high will be left at low-1).
2521 if (refcount->count >= refcount->size) {
2522 refcount_collapse(refcount);
2523 if (refcount->count < refcount->size)
2526 return insert_refcount_el(refcount, blk, low);
2532 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2534 struct ea_refcount_el *el;
2536 el = get_refcount_el(refcount, blk, 1);
2538 return EXT2_ET_NO_MEMORY;
2542 *ret = el->ea_count;
2547 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2549 struct ea_refcount_el *el;
2551 el = get_refcount_el(refcount, blk, 0);
2552 if (!el || el->ea_count == 0)
2553 return EXT2_ET_INVALID_ARGUMENT;
2558 *ret = el->ea_count;
2563 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2565 struct ea_refcount_el *el;
2568 * Get the refcount element
2570 el = get_refcount_el(refcount, blk, count ? 1 : 0);
2572 return count ? EXT2_ET_NO_MEMORY : 0;
2573 el->ea_count = count;
2577 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2579 refcount->cursor = 0;
2583 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2585 struct ea_refcount_el *list;
2588 if (refcount->cursor >= refcount->count)
2590 list = refcount->list;
2591 if (list[refcount->cursor].ea_count) {
2593 *ret = list[refcount->cursor].ea_count;
2594 return list[refcount->cursor++].ea_blk;
2602 * ehandler.c --- handle bad block errors which come up during the
2603 * course of an e2fsck session.
2607 static const char *operation;
2610 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2611 void *data, size_t size FSCK_ATTR((unused)),
2612 int actual FSCK_ATTR((unused)), errcode_t error)
2616 ext2_filsys fs = (ext2_filsys) channel->app_data;
2619 ctx = (e2fsck_t) fs->priv_data;
2622 * If more than one block was read, try reading each block
2623 * separately. We could use the actual bytes read to figure
2624 * out where to start, but we don't bother.
2628 for (i=0; i < count; i++, p += channel->block_size, block++) {
2629 error = io_channel_read_blk(channel, block,
2637 printf(_("Error reading block %lu (%s) while %s. "), block,
2638 error_message(error), operation);
2640 printf(_("Error reading block %lu (%s). "), block,
2641 error_message(error));
2643 if (ask(ctx, _("Ignore error"), 1)) {
2644 if (ask(ctx, _("Force rewrite"), 1))
2645 io_channel_write_blk(channel, block, 1, data);
2653 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2654 const void *data, size_t size FSCK_ATTR((unused)),
2655 int actual FSCK_ATTR((unused)), errcode_t error)
2659 ext2_filsys fs = (ext2_filsys) channel->app_data;
2662 ctx = (e2fsck_t) fs->priv_data;
2665 * If more than one block was written, try writing each block
2666 * separately. We could use the actual bytes read to figure
2667 * out where to start, but we don't bother.
2670 p = (const char *) data;
2671 for (i=0; i < count; i++, p += channel->block_size, block++) {
2672 error = io_channel_write_blk(channel, block,
2681 printf(_("Error writing block %lu (%s) while %s. "), block,
2682 error_message(error), operation);
2684 printf(_("Error writing block %lu (%s). "), block,
2685 error_message(error));
2687 if (ask(ctx, _("Ignore error"), 1))
2693 static inline const char *ehandler_operation(const char *op)
2695 const char *ret = operation;
2701 static void ehandler_init(io_channel channel)
2703 channel->read_error = e2fsck_handle_read_error;
2704 channel->write_error = e2fsck_handle_write_error;
2708 * journal.c --- code for handling the "ext3" journal
2710 * Copyright (C) 2000 Andreas Dilger
2711 * Copyright (C) 2000 Theodore Ts'o
2713 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2714 * Copyright (C) 1999 Red Hat Software
2716 * This file may be redistributed under the terms of the
2717 * GNU General Public License version 2 or at your discretion
2718 * any later version.
2721 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2724 #ifdef __CONFIG_JBD_DEBUG__E2FS /* Enabled by configure --enable-jfs-debug */
2725 static int bh_count = 0;
2729 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2730 * This creates a larger static binary, and a smaller binary using
2731 * shared libraries. It's also probably slightly less CPU-efficient,
2732 * which is why it's not on by default. But, it's a good way of
2733 * testing the functions in inode_io.c and fileio.c.
2737 /* Kernel compatibility functions for handling the journal. These allow us
2738 * to use the recovery.c file virtually unchanged from the kernel, so we
2739 * don't have to do much to keep kernel and user recovery in sync.
2741 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2747 struct inode *inode = journal->j_inode;
2756 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2757 &inode->i_ext2, NULL, 0, block, &pblk);
2763 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2765 struct buffer_head *bh;
2767 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2771 jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
2772 (unsigned long) blocknr, blocksize, ++bh_count);
2774 bh->b_ctx = kdev->k_ctx;
2775 if (kdev->k_dev == K_DEV_FS)
2776 bh->b_io = kdev->k_ctx->fs->io;
2778 bh->b_io = kdev->k_ctx->journal_io;
2779 bh->b_size = blocksize;
2780 bh->b_blocknr = blocknr;
2785 static void sync_blockdev(kdev_t kdev)
2789 if (kdev->k_dev == K_DEV_FS)
2790 io = kdev->k_ctx->fs->io;
2792 io = kdev->k_ctx->journal_io;
2794 io_channel_flush(io);
2797 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2800 struct buffer_head *bh;
2802 for (; nr > 0; --nr) {
2804 if (rw == READ && !bh->b_uptodate) {
2805 jfs_debug(3, "reading block %lu/%p\n",
2806 (unsigned long) bh->b_blocknr, (void *) bh);
2807 retval = io_channel_read_blk(bh->b_io,
2811 com_err(bh->b_ctx->device_name, retval,
2812 "while reading block %lu\n",
2813 (unsigned long) bh->b_blocknr);
2818 } else if (rw == WRITE && bh->b_dirty) {
2819 jfs_debug(3, "writing block %lu/%p\n",
2820 (unsigned long) bh->b_blocknr, (void *) bh);
2821 retval = io_channel_write_blk(bh->b_io,
2825 com_err(bh->b_ctx->device_name, retval,
2826 "while writing block %lu\n",
2827 (unsigned long) bh->b_blocknr);
2834 jfs_debug(3, "no-op %s for block %lu\n",
2835 rw == READ ? "read" : "write",
2836 (unsigned long) bh->b_blocknr);
2841 static inline void mark_buffer_dirty(struct buffer_head *bh)
2846 static inline void mark_buffer_clean(struct buffer_head * bh)
2851 static void brelse(struct buffer_head *bh)
2854 ll_rw_block(WRITE, 1, &bh);
2855 jfs_debug(3, "freeing block %lu/%p (total %d)\n",
2856 (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
2857 ext2fs_free_mem(&bh);
2860 static inline int buffer_uptodate(struct buffer_head *bh)
2862 return bh->b_uptodate;
2865 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2867 bh->b_uptodate = val;
2870 static void wait_on_buffer(struct buffer_head *bh)
2872 if (!bh->b_uptodate)
2873 ll_rw_block(READ, 1, &bh);
2877 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2879 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2881 /* if we had an error doing journal recovery, we need a full fsck */
2883 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2884 ext2fs_mark_super_dirty(ctx->fs);
2887 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2889 struct ext2_super_block *sb = ctx->fs->super;
2890 struct ext2_super_block jsuper;
2891 struct problem_context pctx;
2892 struct buffer_head *bh;
2893 struct inode *j_inode = NULL;
2894 struct kdev_s *dev_fs = NULL, *dev_journal;
2895 const char *journal_name = 0;
2896 journal_t *journal = NULL;
2897 errcode_t retval = 0;
2898 io_manager io_ptr = 0;
2899 unsigned long start = 0;
2901 int ext_journal = 0;
2902 int tried_backup_jnl = 0;
2905 clear_problem_context(&pctx);
2907 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2909 return EXT2_ET_NO_MEMORY;
2912 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2914 retval = EXT2_ET_NO_MEMORY;
2917 dev_journal = dev_fs+1;
2919 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2920 dev_fs->k_dev = K_DEV_FS;
2921 dev_journal->k_dev = K_DEV_JOURNAL;
2923 journal->j_dev = dev_journal;
2924 journal->j_fs_dev = dev_fs;
2925 journal->j_inode = NULL;
2926 journal->j_blocksize = ctx->fs->blocksize;
2928 if (uuid_is_null(sb->s_journal_uuid)) {
2929 if (!sb->s_journal_inum)
2930 return EXT2_ET_BAD_INODE_NUM;
2931 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2934 retval = EXT2_ET_NO_MEMORY;
2938 j_inode->i_ctx = ctx;
2939 j_inode->i_ino = sb->s_journal_inum;
2941 if ((retval = ext2fs_read_inode(ctx->fs,
2943 &j_inode->i_ext2))) {
2945 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
2948 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
2949 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
2951 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
2952 j_inode->i_ext2.i_links_count = 1;
2953 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
2956 if (!j_inode->i_ext2.i_links_count ||
2957 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
2958 retval = EXT2_ET_NO_JOURNAL;
2959 goto try_backup_journal;
2961 if (j_inode->i_ext2.i_size / journal->j_blocksize <
2962 JFS_MIN_JOURNAL_BLOCKS) {
2963 retval = EXT2_ET_JOURNAL_TOO_SMALL;
2964 goto try_backup_journal;
2966 for (i=0; i < EXT2_N_BLOCKS; i++) {
2967 blk = j_inode->i_ext2.i_block[i];
2969 if (i < EXT2_NDIR_BLOCKS) {
2970 retval = EXT2_ET_JOURNAL_TOO_SMALL;
2971 goto try_backup_journal;
2975 if (blk < sb->s_first_data_block ||
2976 blk >= sb->s_blocks_count) {
2977 retval = EXT2_ET_BAD_BLOCK_NUM;
2978 goto try_backup_journal;
2981 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
2984 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
2990 io_ptr = inode_io_manager;
2992 journal->j_inode = j_inode;
2993 ctx->journal_io = ctx->fs->io;
2994 if ((retval = journal_bmap(journal, 0, &start)) != 0)
2999 if (!ctx->journal_name) {
3002 uuid_unparse(sb->s_journal_uuid, uuid);
3003 ctx->journal_name = blkid_get_devname(ctx->blkid,
3005 if (!ctx->journal_name)
3006 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
3008 journal_name = ctx->journal_name;
3010 if (!journal_name) {
3011 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
3012 return EXT2_ET_LOAD_EXT_JOURNAL;
3015 jfs_debug(1, "Using journal file %s\n", journal_name);
3016 io_ptr = unix_io_manager;
3020 test_io_backing_manager = io_ptr;
3021 io_ptr = test_io_manager;
3023 #ifndef USE_INODE_IO
3026 retval = io_ptr->open(journal_name, IO_FLAG_RW,
3031 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
3034 if (ctx->fs->blocksize == 1024)
3036 bh = getblk(dev_journal, start, ctx->fs->blocksize);
3038 retval = EXT2_ET_NO_MEMORY;
3041 ll_rw_block(READ, 1, &bh);
3042 if ((retval = bh->b_err) != 0)
3044 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
3047 #ifdef EXT2FS_ENABLE_SWAPFS
3048 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
3049 ext2fs_swap_super(&jsuper);
3051 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
3052 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
3053 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
3054 retval = EXT2_ET_LOAD_EXT_JOURNAL;
3057 /* Make sure the journal UUID is correct */
3058 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
3059 sizeof(jsuper.s_uuid))) {
3060 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
3061 retval = EXT2_ET_LOAD_EXT_JOURNAL;
3065 journal->j_maxlen = jsuper.s_blocks_count;
3069 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
3070 retval = EXT2_ET_NO_MEMORY;
3074 journal->j_sb_buffer = bh;
3075 journal->j_superblock = (journal_superblock_t *)bh->b_data;
3078 ext2fs_free_mem(&j_inode);
3081 *ret_journal = journal;
3085 ext2fs_free_mem(&dev_fs);
3086 ext2fs_free_mem(&j_inode);
3087 ext2fs_free_mem(&journal);
3092 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
3093 struct problem_context *pctx)
3095 struct ext2_super_block *sb = ctx->fs->super;
3096 int recover = ctx->fs->super->s_feature_incompat &
3097 EXT3_FEATURE_INCOMPAT_RECOVER;
3098 int has_journal = ctx->fs->super->s_feature_compat &
3099 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3101 if (has_journal || sb->s_journal_inum) {
3102 /* The journal inode is bogus, remove and force full fsck */
3103 pctx->ino = sb->s_journal_inum;
3104 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
3105 if (has_journal && sb->s_journal_inum)
3106 printf("*** ext3 journal has been deleted - "
3107 "filesystem is now ext2 only ***\n\n");
3108 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3109 sb->s_journal_inum = 0;
3110 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
3111 e2fsck_clear_recover(ctx, 1);
3114 return EXT2_ET_BAD_INODE_NUM;
3115 } else if (recover) {
3116 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
3117 e2fsck_clear_recover(ctx, 1);
3120 return EXT2_ET_UNSUPP_FEATURE;
3125 #define V1_SB_SIZE 0x0024
3126 static void clear_v2_journal_fields(journal_t *journal)
3128 e2fsck_t ctx = journal->j_dev->k_ctx;
3129 struct problem_context pctx;
3131 clear_problem_context(&pctx);
3133 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
3136 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
3137 ctx->fs->blocksize-V1_SB_SIZE);
3138 mark_buffer_dirty(journal->j_sb_buffer);
3142 static errcode_t e2fsck_journal_load(journal_t *journal)
3144 e2fsck_t ctx = journal->j_dev->k_ctx;
3145 journal_superblock_t *jsb;
3146 struct buffer_head *jbh = journal->j_sb_buffer;
3147 struct problem_context pctx;
3149 clear_problem_context(&pctx);
3151 ll_rw_block(READ, 1, &jbh);
3153 com_err(ctx->device_name, jbh->b_err,
3154 _("reading journal superblock\n"));
3158 jsb = journal->j_superblock;
3159 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
3160 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
3161 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3163 switch (ntohl(jsb->s_header.h_blocktype)) {
3164 case JFS_SUPERBLOCK_V1:
3165 journal->j_format_version = 1;
3166 if (jsb->s_feature_compat ||
3167 jsb->s_feature_incompat ||
3168 jsb->s_feature_ro_compat ||
3170 clear_v2_journal_fields(journal);
3173 case JFS_SUPERBLOCK_V2:
3174 journal->j_format_version = 2;
3175 if (ntohl(jsb->s_nr_users) > 1 &&
3176 uuid_is_null(ctx->fs->super->s_journal_uuid))
3177 clear_v2_journal_fields(journal);
3178 if (ntohl(jsb->s_nr_users) > 1) {
3179 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
3180 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3185 * These should never appear in a journal super block, so if
3186 * they do, the journal is badly corrupted.
3188 case JFS_DESCRIPTOR_BLOCK:
3189 case JFS_COMMIT_BLOCK:
3190 case JFS_REVOKE_BLOCK:
3191 return EXT2_ET_CORRUPT_SUPERBLOCK;
3193 /* If we don't understand the superblock major type, but there
3194 * is a magic number, then it is likely to be a new format we
3195 * just don't understand, so leave it alone. */
3197 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3200 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
3201 return EXT2_ET_UNSUPP_FEATURE;
3203 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
3204 return EXT2_ET_RO_UNSUPP_FEATURE;
3206 /* We have now checked whether we know enough about the journal
3207 * format to be able to proceed safely, so any other checks that
3208 * fail we should attempt to recover from. */
3209 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
3210 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3211 _("%s: no valid journal superblock found\n"),
3213 return EXT2_ET_CORRUPT_SUPERBLOCK;
3216 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
3217 journal->j_maxlen = ntohl(jsb->s_maxlen);
3218 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
3219 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3220 _("%s: journal too short\n"),
3222 return EXT2_ET_CORRUPT_SUPERBLOCK;
3225 journal->j_tail_sequence = ntohl(jsb->s_sequence);
3226 journal->j_transaction_sequence = journal->j_tail_sequence;
3227 journal->j_tail = ntohl(jsb->s_start);
3228 journal->j_first = ntohl(jsb->s_first);
3229 journal->j_last = ntohl(jsb->s_maxlen);
3234 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
3245 /* Leave a valid existing V1 superblock signature alone.
3246 * Anything unrecognisable we overwrite with a new V2
3249 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
3250 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
3251 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
3252 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
3255 /* Zero out everything else beyond the superblock header */
3257 p = ((char *) jsb) + sizeof(journal_header_t);
3258 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
3260 jsb->s_blocksize = htonl(ctx->fs->blocksize);
3261 jsb->s_maxlen = htonl(journal->j_maxlen);
3262 jsb->s_first = htonl(1);
3264 /* Initialize the journal sequence number so that there is "no"
3265 * chance we will find old "valid" transactions in the journal.
3266 * This avoids the need to zero the whole journal (slow to do,
3267 * and risky when we are just recovering the filesystem).
3269 uuid_generate(u.uuid);
3270 for (i = 0; i < 4; i ++)
3271 new_seq ^= u.val[i];
3272 jsb->s_sequence = htonl(new_seq);
3274 mark_buffer_dirty(journal->j_sb_buffer);
3275 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
3278 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
3280 struct problem_context *pctx)
3282 struct ext2_super_block *sb = ctx->fs->super;
3283 int recover = ctx->fs->super->s_feature_incompat &
3284 EXT3_FEATURE_INCOMPAT_RECOVER;
3286 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
3287 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
3288 e2fsck_journal_reset_super(ctx, journal->j_superblock,
3290 journal->j_transaction_sequence = 1;
3291 e2fsck_clear_recover(ctx, recover);
3294 return EXT2_ET_CORRUPT_SUPERBLOCK;
3295 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
3296 return EXT2_ET_CORRUPT_SUPERBLOCK;
3301 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
3302 int reset, int drop)
3304 journal_superblock_t *jsb;
3307 mark_buffer_clean(journal->j_sb_buffer);
3308 else if (!(ctx->options & E2F_OPT_READONLY)) {
3309 jsb = journal->j_superblock;
3310 jsb->s_sequence = htonl(journal->j_transaction_sequence);
3312 jsb->s_start = 0; /* this marks the journal as empty */
3313 mark_buffer_dirty(journal->j_sb_buffer);
3315 brelse(journal->j_sb_buffer);
3317 if (ctx->journal_io) {
3318 if (ctx->fs && ctx->fs->io != ctx->journal_io)
3319 io_channel_close(ctx->journal_io);
3320 ctx->journal_io = 0;
3323 #ifndef USE_INODE_IO
3324 ext2fs_free_mem(&journal->j_inode);
3326 ext2fs_free_mem(&journal->j_fs_dev);
3327 ext2fs_free_mem(&journal);
3331 * This function makes sure that the superblock fields regarding the
3332 * journal are consistent.
3334 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
3336 struct ext2_super_block *sb = ctx->fs->super;
3338 int recover = ctx->fs->super->s_feature_incompat &
3339 EXT3_FEATURE_INCOMPAT_RECOVER;
3340 struct problem_context pctx;
3342 int reset = 0, force_fsck = 0;
3345 /* If we don't have any journal features, don't do anything more */
3346 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3347 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
3348 uuid_is_null(sb->s_journal_uuid))
3351 clear_problem_context(&pctx);
3352 pctx.num = sb->s_journal_inum;
3354 retval = e2fsck_get_journal(ctx, &journal);
3356 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3357 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3358 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3359 (retval == EXT2_ET_NO_JOURNAL))
3360 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3364 retval = e2fsck_journal_load(journal);
3366 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3367 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3368 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3370 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3371 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3373 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3374 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3375 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3377 e2fsck_journal_release(ctx, journal, 0, 1);
3382 * We want to make the flags consistent here. We will not leave with
3383 * needs_recovery set but has_journal clear. We can't get in a loop
3384 * with -y, -n, or -p, only if a user isn't making up their mind.
3387 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3388 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3390 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3392 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3393 goto no_has_journal;
3395 * Need a full fsck if we are releasing a
3396 * journal stored on a reserved inode.
3398 force_fsck = recover ||
3399 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3400 /* Clear all of the journal fields */
3401 sb->s_journal_inum = 0;
3402 sb->s_journal_dev = 0;
3403 memset(sb->s_journal_uuid, 0,
3404 sizeof(sb->s_journal_uuid));
3405 e2fsck_clear_recover(ctx, force_fsck);
3406 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3407 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3408 ext2fs_mark_super_dirty(ctx->fs);
3412 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3413 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3414 journal->j_superblock->s_start != 0) {
3415 /* Print status information */
3416 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3417 if (ctx->superblock)
3418 problem = PR_0_JOURNAL_RUN_DEFAULT;
3420 problem = PR_0_JOURNAL_RUN;
3421 if (fix_problem(ctx, problem, &pctx)) {
3422 ctx->options |= E2F_OPT_FORCE;
3423 sb->s_feature_incompat |=
3424 EXT3_FEATURE_INCOMPAT_RECOVER;
3425 ext2fs_mark_super_dirty(ctx->fs);
3426 } else if (fix_problem(ctx,
3427 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3429 sb->s_state &= ~EXT2_VALID_FS;
3430 ext2fs_mark_super_dirty(ctx->fs);
3433 * If the user answers no to the above question, we
3434 * ignore the fact that journal apparently has data;
3435 * accidentally replaying over valid data would be far
3436 * worse than skipping a questionable recovery.
3438 * XXX should we abort with a fatal error here? What
3439 * will the ext3 kernel code do if a filesystem with
3440 * !NEEDS_RECOVERY but with a non-zero
3441 * journal->j_superblock->s_start is mounted?
3445 e2fsck_journal_release(ctx, journal, reset, 0);
3449 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3454 journal_init_revoke_caches();
3455 retval = e2fsck_get_journal(ctx, &journal);
3459 retval = e2fsck_journal_load(journal);
3463 retval = journal_init_revoke(journal, 1024);
3467 retval = -journal_recover(journal);
3471 if (journal->j_superblock->s_errno) {
3472 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3473 ext2fs_mark_super_dirty(ctx->fs);
3474 journal->j_superblock->s_errno = 0;
3475 mark_buffer_dirty(journal->j_sb_buffer);
3479 journal_destroy_revoke(journal);
3480 journal_destroy_revoke_caches();
3481 e2fsck_journal_release(ctx, journal, 1, 0);
3485 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3487 io_manager io_ptr = ctx->fs->io->manager;
3488 int blocksize = ctx->fs->blocksize;
3489 errcode_t retval, recover_retval;
3491 printf(_("%s: recovering journal\n"), ctx->device_name);
3492 if (ctx->options & E2F_OPT_READONLY) {
3493 printf(_("%s: won't do journal recovery while read-only\n"),
3495 return EXT2_ET_FILE_RO;
3498 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3499 ext2fs_flush(ctx->fs); /* Force out any modifications */
3501 recover_retval = recover_ext3_journal(ctx);
3504 * Reload the filesystem context to get up-to-date data from disk
3505 * because journal recovery will change the filesystem under us.
3507 ext2fs_close(ctx->fs);
3508 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3509 ctx->superblock, blocksize, io_ptr,
3513 com_err(ctx->program_name, retval,
3514 _("while trying to re-open %s"),
3516 fatal_error(ctx, 0);
3518 ctx->fs->priv_data = ctx;
3520 /* Set the superblock flags */
3521 e2fsck_clear_recover(ctx, recover_retval);
3522 return recover_retval;
3526 * This function will move the journal inode from a visible file in
3527 * the filesystem directory hierarchy to the reserved inode if necessary.
3529 static const char * const journal_names[] = {
3530 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3532 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3534 struct ext2_super_block *sb = ctx->fs->super;
3535 struct problem_context pctx;
3536 struct ext2_inode inode;
3537 ext2_filsys fs = ctx->fs;
3540 const char * const * cpp;
3541 int group, mount_flags;
3543 clear_problem_context(&pctx);
3546 * If the filesystem is opened read-only, or there is no
3547 * journal, then do nothing.
3549 if ((ctx->options & E2F_OPT_READONLY) ||
3550 (sb->s_journal_inum == 0) ||
3551 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3555 * Read in the journal inode
3557 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3561 * If it's necessary to backup the journal inode, do so.
3563 if ((sb->s_jnl_backup_type == 0) ||
3564 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3565 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3566 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3567 memcpy(sb->s_jnl_blocks, inode.i_block,
3569 sb->s_jnl_blocks[16] = inode.i_size;
3570 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3571 ext2fs_mark_super_dirty(fs);
3572 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3577 * If the journal is already the hidden inode, then do nothing
3579 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3583 * The journal inode had better have only one link and not be readable.
3585 if (inode.i_links_count != 1)
3589 * If the filesystem is mounted, or we can't tell whether
3590 * or not it's mounted, do nothing.
3592 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3593 if (retval || (mount_flags & EXT2_MF_MOUNTED))
3597 * If we can't find the name of the journal inode, then do
3600 for (cpp = journal_names; *cpp; cpp++) {
3601 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3602 strlen(*cpp), 0, &ino);
3603 if ((retval == 0) && (ino == sb->s_journal_inum))
3609 /* We need the inode bitmap to be loaded */
3610 retval = ext2fs_read_bitmaps(fs);
3615 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3619 * OK, we've done all the checks, let's actually move the
3620 * journal inode. Errors at this point mean we need to force
3621 * an ext2 filesystem check.
3623 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3625 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3627 sb->s_journal_inum = EXT2_JOURNAL_INO;
3628 ext2fs_mark_super_dirty(fs);
3629 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3630 inode.i_links_count = 0;
3631 inode.i_dtime = time(0);
3632 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3635 group = ext2fs_group_of_ino(fs, ino);
3636 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3637 ext2fs_mark_ib_dirty(fs);
3638 fs->group_desc[group].bg_free_inodes_count++;
3639 fs->super->s_free_inodes_count++;
3643 pctx.errcode = retval;
3644 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3645 fs->super->s_state &= ~EXT2_VALID_FS;
3646 ext2fs_mark_super_dirty(fs);
3651 * message.c --- print e2fsck messages (with compression)
3653 * print_e2fsck_message() prints a message to the user, using
3654 * compression techniques and expansions of abbreviations.
3656 * The following % expansions are supported:
3658 * %b <blk> block number
3659 * %B <blkcount> integer
3660 * %c <blk2> block number
3661 * %Di <dirent>->ino inode number
3662 * %Dn <dirent>->name string
3663 * %Dr <dirent>->rec_len
3664 * %Dl <dirent>->name_len
3665 * %Dt <dirent>->filetype
3666 * %d <dir> inode number
3667 * %g <group> integer
3668 * %i <ino> inode number
3669 * %Is <inode> -> i_size
3670 * %IS <inode> -> i_extra_isize
3671 * %Ib <inode> -> i_blocks
3672 * %Il <inode> -> i_links_count
3673 * %Im <inode> -> i_mode
3674 * %IM <inode> -> i_mtime
3675 * %IF <inode> -> i_faddr
3676 * %If <inode> -> i_file_acl
3677 * %Id <inode> -> i_dir_acl
3678 * %Iu <inode> -> i_uid
3679 * %Ig <inode> -> i_gid
3680 * %j <ino2> inode number
3681 * %m <com_err error message>
3683 * %p ext2fs_get_pathname of directory <ino>
3684 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
3685 * the containing directory. (If dirent is NULL
3686 * then return the pathname of directory <ino2>)
3687 * %q ext2fs_get_pathname of directory <dir>
3688 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
3689 * the containing directory.
3690 * %s <str> miscellaneous string
3691 * %S backup superblock
3692 * %X <num> hexadecimal format
3694 * The following '@' expansions are supported:
3696 * @a extended attribute
3697 * @A error allocating
3701 * @C conflicts with some other fs block
3705 * @E Entry '%Dn' in %p (%i)
3707 * @F for @i %i (%Q) is
3709 * @h HTREE directory inode
3727 * This structure defines the abbreviations used by the text strings
3728 * below. The first character in the string is the index letter. An
3729 * abbreviation of the form '@<i>' is expanded by looking up the index
3730 * letter <i> in the table below.
3732 static const char * const abbrevs[] = {
3733 N_("aextended attribute"),
3734 N_("Aerror allocating"),
3738 N_("Cconflicts with some other fs @b"),
3745 N_("E@e '%Dn' in %p (%i)"),
3747 N_("Ffor @i %i (%Q) is"),
3765 * Give more user friendly names to the "special" inodes.
3767 #define num_special_inodes 11
3768 static const char * const special_inode_name[] =
3770 N_("<The NULL inode>"), /* 0 */
3771 N_("<The bad blocks inode>"), /* 1 */
3773 N_("<The ACL index inode>"), /* 3 */
3774 N_("<The ACL data inode>"), /* 4 */
3775 N_("<The boot loader inode>"), /* 5 */
3776 N_("<The undelete directory inode>"), /* 6 */
3777 N_("<The group descriptor inode>"), /* 7 */
3778 N_("<The journal inode>"), /* 8 */
3779 N_("<Reserved inode 9>"), /* 9 */
3780 N_("<Reserved inode 10>"), /* 10 */
3784 * This function does "safe" printing. It will convert non-printable
3785 * ASCII characters using '^' and M- notation.
3787 static void safe_print(const char *cp, int len)
3797 fputs("M-", stdout);
3800 if ((ch < 32) || (ch == 0x7f)) {
3802 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3810 * This function prints a pathname, using the ext2fs_get_pathname
3813 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3818 if (!dir && (ino < num_special_inodes)) {
3819 fputs(_(special_inode_name[ino]), stdout);
3823 retval = ext2fs_get_pathname(fs, dir, ino, &path);
3825 fputs("???", stdout);
3827 safe_print(path, -1);
3828 ext2fs_free_mem(&path);
3832 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3833 struct problem_context *pctx, int first);
3835 * This function handles the '@' expansion. We allow recursive
3836 * expansion; an @ expression can contain further '@' and '%'
3839 static void expand_at_expression(e2fsck_t ctx, char ch,
3840 struct problem_context *pctx,
3843 const char * const *cpp;
3846 /* Search for the abbreviation */
3847 for (cpp = abbrevs; *cpp; cpp++) {
3853 if (*first && islower(*str)) {
3855 fputc(toupper(*str++), stdout);
3857 print_e2fsck_message(ctx, str, pctx, *first);
3863 * This function expands '%IX' expressions
3865 static void expand_inode_expression(char ch,
3866 struct problem_context *ctx)
3868 struct ext2_inode *inode;
3869 struct ext2_inode_large *large_inode;
3874 if (!ctx || !ctx->inode)
3878 large_inode = (struct ext2_inode_large *) inode;
3882 if (LINUX_S_ISDIR(inode->i_mode))
3883 printf("%u", inode->i_size);
3885 #ifdef EXT2_NO_64_TYPE
3886 if (inode->i_size_high)
3887 printf("0x%x%08x", inode->i_size_high,
3890 printf("%u", inode->i_size);
3892 printf("%llu", (inode->i_size |
3893 ((__u64) inode->i_size_high << 32)));
3898 printf("%u", large_inode->i_extra_isize);
3901 printf("%u", inode->i_blocks);
3904 printf("%d", inode->i_links_count);
3907 printf("0%o", inode->i_mode);
3910 /* The diet libc doesn't respect the TZ environemnt variable */
3912 time_str = getenv("TZ");
3915 do_gmt = !strcmp(time_str, "GMT");
3918 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3919 printf("%.24s", time_str);
3922 printf("%u", inode->i_faddr);
3925 printf("%u", inode->i_file_acl);
3928 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3929 inode->i_dir_acl : 0));
3932 printf("%d", (inode->i_uid |
3933 (inode->osd2.linux2.l_i_uid_high << 16)));
3936 printf("%d", (inode->i_gid |
3937 (inode->osd2.linux2.l_i_gid_high << 16)));
3941 printf("%%I%c", ch);
3947 * This function expands '%dX' expressions
3949 static _INLINE_ void expand_dirent_expression(char ch,
3950 struct problem_context *ctx)
3952 struct ext2_dir_entry *dirent;
3955 if (!ctx || !ctx->dirent)
3958 dirent = ctx->dirent;
3962 printf("%u", dirent->inode);
3965 len = dirent->name_len & 0xFF;
3966 if (len > EXT2_NAME_LEN)
3967 len = EXT2_NAME_LEN;
3968 if (len > dirent->rec_len)
3969 len = dirent->rec_len;
3970 safe_print(dirent->name, len);
3973 printf("%u", dirent->rec_len);
3976 printf("%u", dirent->name_len & 0xFF);
3979 printf("%u", dirent->name_len >> 8);
3983 printf("%%D%c", ch);
3988 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
3989 struct problem_context *ctx)
3999 printf("%u", ctx->blk);
4002 #ifdef EXT2_NO_64_TYPE
4003 printf("%d", ctx->blkcount);
4005 printf("%lld", ctx->blkcount);
4009 printf("%u", ctx->blk2);
4012 printf("%u", ctx->dir);
4015 printf("%d", ctx->group);
4018 printf("%u", ctx->ino);
4021 printf("%u", ctx->ino2);
4024 printf("%s", error_message(ctx->errcode));
4027 #ifdef EXT2_NO_64_TYPE
4028 printf("%u", ctx->num);
4030 printf("%llu", ctx->num);
4034 print_pathname(fs, ctx->ino, 0);
4037 print_pathname(fs, ctx->ino2,
4038 ctx->dirent ? ctx->dirent->inode : 0);
4041 print_pathname(fs, ctx->dir, 0);
4044 print_pathname(fs, ctx->dir, ctx->ino);
4047 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4050 printf("%s", ctx->str ? ctx->str : "NULL");
4053 #ifdef EXT2_NO_64_TYPE
4054 printf("0x%x", ctx->num);
4056 printf("0x%llx", ctx->num);
4067 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4068 struct problem_context *pctx, int first)
4070 ext2_filsys fs = ctx->fs;
4074 e2fsck_clear_progbar(ctx);
4075 for (cp = msg; *cp; cp++) {
4078 expand_at_expression(ctx, *cp, pctx, &first);
4079 } else if (cp[0] == '%' && cp[1] == 'I') {
4081 expand_inode_expression(*cp, pctx);
4082 } else if (cp[0] == '%' && cp[1] == 'D') {
4084 expand_dirent_expression(*cp, pctx);
4085 } else if ((cp[0] == '%')) {
4087 expand_percent_expression(fs, *cp, pctx);
4089 for (i=0; cp[i]; i++)
4090 if ((cp[i] == '@') || cp[i] == '%')
4092 printf("%.*s", i, cp);
4101 * region.c --- code which manages allocations within a region.
4105 region_addr_t start;
4107 struct region_el *next;
4110 struct region_struct {
4113 struct region_el *allocated;
4116 static region_t region_create(region_addr_t min, region_addr_t max)
4120 region = malloc(sizeof(struct region_struct));
4123 memset(region, 0, sizeof(struct region_struct));
4129 static void region_free(region_t region)
4131 struct region_el *r, *next;
4133 for (r = region->allocated; r; r = next) {
4137 memset(region, 0, sizeof(struct region_struct));
4141 static int region_allocate(region_t region, region_addr_t start, int n)
4143 struct region_el *r, *new_region, *prev, *next;
4147 if ((start < region->min) || (end > region->max))
4153 * Search through the linked list. If we find that it
4154 * conflicts witih something that's already allocated, return
4155 * 1; if we can find an existing region which we can grow, do
4156 * so. Otherwise, stop when we find the appropriate place
4157 * insert a new region element into the linked list.
4159 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4160 if (((start >= r->start) && (start < r->end)) ||
4161 ((end > r->start) && (end <= r->end)) ||
4162 ((start <= r->start) && (end >= r->end)))
4164 if (end == r->start) {
4168 if (start == r->end) {
4169 if ((next = r->next)) {
4170 if (end > next->start)
4172 if (end == next->start) {
4174 r->next = next->next;
4182 if (start < r->start)
4186 * Insert a new region element structure into the linked list
4188 new_region = malloc(sizeof(struct region_el));
4191 new_region->start = start;
4192 new_region->end = start + n;
4193 new_region->next = r;
4195 prev->next = new_region;
4197 region->allocated = new_region;
4202 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4204 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4205 * and applies the following tests to each inode:
4207 * - The mode field of the inode must be legal.
4208 * - The size and block count fields of the inode are correct.
4209 * - A data block must not be used by another inode
4211 * Pass 1 also gathers the collects the following information:
4213 * - A bitmap of which inodes are in use. (inode_used_map)
4214 * - A bitmap of which inodes are directories. (inode_dir_map)
4215 * - A bitmap of which inodes are regular files. (inode_reg_map)
4216 * - A bitmap of which inodes have bad fields. (inode_bad_map)
4217 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
4218 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
4219 * - A bitmap of which blocks are in use. (block_found_map)
4220 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
4221 * - The data blocks of the directory inodes. (dir_map)
4223 * Pass 1 is designed to stash away enough information so that the
4224 * other passes should not need to read in the inode information
4225 * during the normal course of a filesystem check. (Althogh if an
4226 * inconsistency is detected, other passes may need to read in an
4229 * Note that pass 1B will be invoked if there are any duplicate blocks
4234 static int process_block(ext2_filsys fs, blk_t *blocknr,
4235 e2_blkcnt_t blockcnt, blk_t ref_blk,
4236 int ref_offset, void *priv_data);
4237 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4238 e2_blkcnt_t blockcnt, blk_t ref_blk,
4239 int ref_offset, void *priv_data);
4240 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4242 static void mark_table_blocks(e2fsck_t ctx);
4243 static void alloc_bb_map(e2fsck_t ctx);
4244 static void alloc_imagic_map(e2fsck_t ctx);
4245 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4246 static void handle_fs_bad_blocks(e2fsck_t ctx);
4247 static void process_inodes(e2fsck_t ctx, char *block_buf);
4248 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4249 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4250 dgrp_t group, void * priv_data);
4251 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4252 char *block_buf, int adjust_sign);
4253 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4255 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4256 struct ext2_inode * inode, int bufsize,
4259 struct process_block_struct_1 {
4261 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
4262 fragmented:1, compressed:1, bbcheck:1;
4265 e2_blkcnt_t last_block;
4266 int num_illegal_blocks;
4267 blk_t previous_block;
4268 struct ext2_inode *inode;
4269 struct problem_context *pctx;
4270 ext2fs_block_bitmap fs_meta_blocks;
4274 struct process_inode_block {
4276 struct ext2_inode inode;
4279 struct scan_callback_struct {
4285 * For the inodes to process list.
4287 static struct process_inode_block *inodes_to_process;
4288 static int process_inode_count;
4290 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4291 EXT2_MIN_BLOCK_LOG_SIZE + 1];
4294 * Free all memory allocated by pass1 in preparation for restarting
4297 static void unwind_pass1(void)
4299 ext2fs_free_mem(&inodes_to_process);
4303 * Check to make sure a device inode is real. Returns 1 if the device
4304 * checks out, 0 if not.
4306 * Note: this routine is now also used to check FIFO's and Sockets,
4307 * since they have the same requirement; the i_block fields should be
4311 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4316 * If i_blocks is non-zero, or the index flag is set, then
4317 * this is a bogus device/fifo/socket
4319 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4320 (inode->i_flags & EXT2_INDEX_FL))
4324 * We should be able to do the test below all the time, but
4325 * because the kernel doesn't forcibly clear the device
4326 * inode's additional i_block fields, there are some rare
4327 * occasions when a legitimate device inode will have non-zero
4328 * additional i_block fields. So for now, we only complain
4329 * when the immutable flag is set, which should never happen
4330 * for devices. (And that's when the problem is caused, since
4331 * you can't set or clear immutable flags for devices.) Once
4332 * the kernel has been fixed we can change this...
4334 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4335 for (i=4; i < EXT2_N_BLOCKS; i++)
4336 if (inode->i_block[i])
4343 * Check to make sure a symlink inode is real. Returns 1 if the symlink
4344 * checks out, 0 if not.
4347 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4353 if ((inode->i_size_high || inode->i_size == 0) ||
4354 (inode->i_flags & EXT2_INDEX_FL))
4357 blocks = ext2fs_inode_data_blocks(fs, inode);
4359 if ((inode->i_size >= fs->blocksize) ||
4360 (blocks != fs->blocksize >> 9) ||
4361 (inode->i_block[0] < fs->super->s_first_data_block) ||
4362 (inode->i_block[0] >= fs->super->s_blocks_count))
4365 for (i = 1; i < EXT2_N_BLOCKS; i++)
4366 if (inode->i_block[i])
4369 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4372 len = strnlen(buf, fs->blocksize);
4373 if (len == fs->blocksize)
4376 if (inode->i_size >= sizeof(inode->i_block))
4379 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4380 if (len == sizeof(inode->i_block))
4383 if (len != inode->i_size)
4389 * If the immutable (or append-only) flag is set on the inode, offer
4392 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4393 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4395 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4398 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4401 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4402 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4406 * If device, fifo or socket, check size is zero -- if not offer to
4409 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4411 struct ext2_inode *inode = pctx->inode;
4413 if ((inode->i_size == 0) && (inode->i_size_high == 0))
4416 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4420 inode->i_size_high = 0;
4421 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4424 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4426 struct ext2_super_block *sb = ctx->fs->super;
4427 struct ext2_inode_large *inode;
4428 struct ext2_ext_attr_entry *entry;
4430 int storage_size, remain, offs;
4433 inode = (struct ext2_inode_large *) pctx->inode;
4434 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4435 inode->i_extra_isize;
4436 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4437 inode->i_extra_isize + sizeof(__u32);
4438 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4439 entry = (struct ext2_ext_attr_entry *) start;
4441 /* scan all entry's headers first */
4443 /* take finish entry 0UL into account */
4444 remain = storage_size - sizeof(__u32);
4447 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4449 /* header eats this space */
4450 remain -= sizeof(struct ext2_ext_attr_entry);
4452 /* is attribute name valid? */
4453 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4454 pctx->num = entry->e_name_len;
4455 problem = PR_1_ATTR_NAME_LEN;
4459 /* attribute len eats this space */
4460 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4462 /* check value size */
4463 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4464 pctx->num = entry->e_value_size;
4465 problem = PR_1_ATTR_VALUE_SIZE;
4469 /* check value placement */
4470 if (entry->e_value_offs +
4471 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4472 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4473 pctx->num = entry->e_value_offs;
4474 problem = PR_1_ATTR_VALUE_OFFSET;
4478 /* e_value_block must be 0 in inode's ea */
4479 if (entry->e_value_block != 0) {
4480 pctx->num = entry->e_value_block;
4481 problem = PR_1_ATTR_VALUE_BLOCK;
4485 /* e_hash must be 0 in inode's ea */
4486 if (entry->e_hash != 0) {
4487 pctx->num = entry->e_hash;
4488 problem = PR_1_ATTR_HASH;
4492 remain -= entry->e_value_size;
4493 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4495 entry = EXT2_EXT_ATTR_NEXT(entry);
4499 * it seems like a corruption. it's very unlikely we could repair
4500 * EA(s) in automatic fashion -bzzz
4503 problem = PR_1_ATTR_HASH;
4505 if (problem == 0 || !fix_problem(ctx, problem, pctx))
4508 /* simple remove all possible EA(s) */
4509 *((__u32 *)start) = 0UL;
4510 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4511 EXT2_INODE_SIZE(sb), "pass1");
4514 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4516 struct ext2_super_block *sb = ctx->fs->super;
4517 struct ext2_inode_large *inode;
4521 inode = (struct ext2_inode_large *) pctx->inode;
4522 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4523 /* this isn't large inode. so, nothing to check */
4528 printf("inode #%u, i_extra_size %d\n", pctx->ino,
4529 inode->i_extra_isize);
4531 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4532 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4533 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4535 * For now we will allow i_extra_isize to be 0, but really
4536 * implementations should never allow i_extra_isize to be 0
4538 if (inode->i_extra_isize &&
4539 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4540 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4542 inode->i_extra_isize = min;
4543 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4544 EXT2_INODE_SIZE(sb), "pass1");
4548 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4549 inode->i_extra_isize);
4550 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4551 /* it seems inode has an extended attribute(s) in body */
4552 check_ea_in_inode(ctx, pctx);
4556 static void e2fsck_pass1(e2fsck_t ctx)
4560 ext2_filsys fs = ctx->fs;
4562 struct ext2_inode *inode;
4563 ext2_inode_scan scan;
4565 #ifdef RESOURCE_TRACK
4566 struct resource_track rtrack;
4568 unsigned char frag, fsize;
4569 struct problem_context pctx;
4570 struct scan_callback_struct scan_struct;
4571 struct ext2_super_block *sb = ctx->fs->super;
4573 int busted_fs_time = 0;
4576 #ifdef RESOURCE_TRACK
4577 init_resource_track(&rtrack);
4579 clear_problem_context(&pctx);
4581 if (!(ctx->options & E2F_OPT_PREEN))
4582 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4584 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4585 !(ctx->options & E2F_OPT_NO)) {
4586 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4587 ctx->dirs_to_hash = 0;
4591 mtrace_print("Pass 1");
4594 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4596 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4597 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4598 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4599 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4600 max_sizes = (max_sizes * (1UL << i)) - 1;
4601 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4605 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4608 * Allocate bitmaps structures
4610 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4611 &ctx->inode_used_map);
4614 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4615 ctx->flags |= E2F_FLAG_ABORT;
4618 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4619 _("directory inode map"), &ctx->inode_dir_map);
4622 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4623 ctx->flags |= E2F_FLAG_ABORT;
4626 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4627 _("regular file inode map"), &ctx->inode_reg_map);
4630 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4631 ctx->flags |= E2F_FLAG_ABORT;
4634 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4635 &ctx->block_found_map);
4638 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4639 ctx->flags |= E2F_FLAG_ABORT;
4642 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4643 &ctx->inode_link_info);
4645 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4646 ctx->flags |= E2F_FLAG_ABORT;
4649 inode_size = EXT2_INODE_SIZE(fs->super);
4650 inode = (struct ext2_inode *)
4651 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4653 inodes_to_process = (struct process_inode_block *)
4654 e2fsck_allocate_memory(ctx,
4655 (ctx->process_inode_size *
4656 sizeof(struct process_inode_block)),
4657 "array of inodes to process");
4658 process_inode_count = 0;
4660 pctx.errcode = ext2fs_init_dblist(fs, 0);
4662 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4663 ctx->flags |= E2F_FLAG_ABORT;
4668 * If the last orphan field is set, clear it, since the pass1
4669 * processing will automatically find and clear the orphans.
4670 * In the future, we may want to try using the last_orphan
4671 * linked list ourselves, but for now, we clear it so that the
4672 * ext3 mount code won't get confused.
4674 if (!(ctx->options & E2F_OPT_READONLY)) {
4675 if (fs->super->s_last_orphan) {
4676 fs->super->s_last_orphan = 0;
4677 ext2fs_mark_super_dirty(fs);
4681 mark_table_blocks(ctx);
4682 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4683 "block interate buffer");
4684 e2fsck_use_inode_shortcuts(ctx, 1);
4685 ehandler_operation(_("doing inode scan"));
4686 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4689 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4690 ctx->flags |= E2F_FLAG_ABORT;
4693 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4694 ctx->stashed_inode = inode;
4695 scan_struct.ctx = ctx;
4696 scan_struct.block_buf = block_buf;
4697 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4699 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4701 if (fs->super->s_wtime < fs->super->s_inodes_count)
4705 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4707 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4709 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4710 if (!ctx->inode_bb_map)
4712 ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4713 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4717 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4718 ctx->flags |= E2F_FLAG_ABORT;
4725 ctx->stashed_ino = ino;
4726 if (inode->i_links_count) {
4727 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4728 ino, inode->i_links_count);
4730 pctx.num = inode->i_links_count;
4731 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4732 ctx->flags |= E2F_FLAG_ABORT;
4736 if (ino == EXT2_BAD_INO) {
4737 struct process_block_struct_1 pb;
4739 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4740 &pb.fs_meta_blocks);
4743 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4744 ctx->flags |= E2F_FLAG_ABORT;
4747 pb.ino = EXT2_BAD_INO;
4748 pb.num_blocks = pb.last_block = 0;
4749 pb.num_illegal_blocks = 0;
4750 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4751 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4755 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4756 block_buf, process_bad_block, &pb);
4757 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4759 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4760 ctx->flags |= E2F_FLAG_ABORT;
4764 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4765 ctx->flags |= E2F_FLAG_ABORT;
4768 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4769 clear_problem_context(&pctx);
4771 } else if (ino == EXT2_ROOT_INO) {
4773 * Make sure the root inode is a directory; if
4774 * not, offer to clear it. It will be
4775 * regnerated in pass #3.
4777 if (!LINUX_S_ISDIR(inode->i_mode)) {
4778 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4779 inode->i_dtime = time(0);
4780 inode->i_links_count = 0;
4781 ext2fs_icount_store(ctx->inode_link_info,
4783 e2fsck_write_inode(ctx, ino, inode,
4789 * If dtime is set, offer to clear it. mke2fs
4790 * version 0.2b created filesystems with the
4791 * dtime field set for the root and lost+found
4792 * directories. We won't worry about
4793 * /lost+found, since that can be regenerated
4794 * easily. But we will fix the root directory
4795 * as a special case.
4797 if (inode->i_dtime && inode->i_links_count) {
4798 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4800 e2fsck_write_inode(ctx, ino, inode,
4804 } else if (ino == EXT2_JOURNAL_INO) {
4805 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4806 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4807 if (!LINUX_S_ISREG(inode->i_mode) &&
4808 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4810 inode->i_mode = LINUX_S_IFREG;
4811 e2fsck_write_inode(ctx, ino, inode,
4814 check_blocks(ctx, &pctx, block_buf);
4817 if ((inode->i_links_count || inode->i_blocks ||
4818 inode->i_blocks || inode->i_block[0]) &&
4819 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4821 memset(inode, 0, inode_size);
4822 ext2fs_icount_store(ctx->inode_link_info,
4824 e2fsck_write_inode_full(ctx, ino, inode,
4825 inode_size, "pass1");
4827 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4830 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4831 if (ino == EXT2_BOOT_LOADER_INO) {
4832 if (LINUX_S_ISDIR(inode->i_mode))
4833 problem = PR_1_RESERVED_BAD_MODE;
4834 } else if (ino == EXT2_RESIZE_INO) {
4835 if (inode->i_mode &&
4836 !LINUX_S_ISREG(inode->i_mode))
4837 problem = PR_1_RESERVED_BAD_MODE;
4839 if (inode->i_mode != 0)
4840 problem = PR_1_RESERVED_BAD_MODE;
4843 if (fix_problem(ctx, problem, &pctx)) {
4845 e2fsck_write_inode(ctx, ino, inode,
4849 check_blocks(ctx, &pctx, block_buf);
4853 * Check for inodes who might have been part of the
4854 * orphaned list linked list. They should have gotten
4855 * dealt with by now, unless the list had somehow been
4858 * FIXME: In the future, inodes which are still in use
4859 * (and which are therefore) pending truncation should
4860 * be handled specially. Right now we just clear the
4861 * dtime field, and the normal e2fsck handling of
4862 * inodes where i_size and the inode blocks are
4863 * inconsistent is to fix i_size, instead of releasing
4864 * the extra blocks. This won't catch the inodes that
4865 * was at the end of the orphan list, but it's better
4866 * than nothing. The right answer is that there
4867 * shouldn't be any bugs in the orphan list handling. :-)
4869 if (inode->i_dtime && !busted_fs_time &&
4870 inode->i_dtime < ctx->fs->super->s_inodes_count) {
4871 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4872 inode->i_dtime = inode->i_links_count ?
4874 e2fsck_write_inode(ctx, ino, inode,
4880 * This code assumes that deleted inodes have
4881 * i_links_count set to 0.
4883 if (!inode->i_links_count) {
4884 if (!inode->i_dtime && inode->i_mode) {
4885 if (fix_problem(ctx,
4886 PR_1_ZERO_DTIME, &pctx)) {
4887 inode->i_dtime = time(0);
4888 e2fsck_write_inode(ctx, ino, inode,
4895 * n.b. 0.3c ext2fs code didn't clear i_links_count for
4896 * deleted files. Oops.
4898 * Since all new ext2 implementations get this right,
4899 * we now assume that the case of non-zero
4900 * i_links_count and non-zero dtime means that we
4901 * should keep the file, not delete it.
4904 if (inode->i_dtime) {
4905 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4907 e2fsck_write_inode(ctx, ino, inode, "pass1");
4911 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4912 switch (fs->super->s_creator_os) {
4914 frag = inode->osd2.linux2.l_i_frag;
4915 fsize = inode->osd2.linux2.l_i_fsize;
4918 frag = inode->osd2.hurd2.h_i_frag;
4919 fsize = inode->osd2.hurd2.h_i_fsize;
4922 frag = inode->osd2.masix2.m_i_frag;
4923 fsize = inode->osd2.masix2.m_i_fsize;
4929 if (inode->i_faddr || frag || fsize ||
4930 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4931 mark_inode_bad(ctx, ino);
4932 if (inode->i_flags & EXT2_IMAGIC_FL) {
4934 if (!ctx->inode_imagic_map)
4935 alloc_imagic_map(ctx);
4936 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4939 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4940 inode->i_flags &= ~EXT2_IMAGIC_FL;
4941 e2fsck_write_inode(ctx, ino,
4947 check_inode_extra_space(ctx, &pctx);
4949 if (LINUX_S_ISDIR(inode->i_mode)) {
4950 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
4951 e2fsck_add_dir_info(ctx, ino, 0);
4952 ctx->fs_directory_count++;
4953 } else if (LINUX_S_ISREG (inode->i_mode)) {
4954 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
4955 ctx->fs_regular_count++;
4956 } else if (LINUX_S_ISCHR (inode->i_mode) &&
4957 e2fsck_pass1_check_device_inode(fs, inode)) {
4958 check_immutable(ctx, &pctx);
4959 check_size(ctx, &pctx);
4960 ctx->fs_chardev_count++;
4961 } else if (LINUX_S_ISBLK (inode->i_mode) &&
4962 e2fsck_pass1_check_device_inode(fs, inode)) {
4963 check_immutable(ctx, &pctx);
4964 check_size(ctx, &pctx);
4965 ctx->fs_blockdev_count++;
4966 } else if (LINUX_S_ISLNK (inode->i_mode) &&
4967 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
4968 check_immutable(ctx, &pctx);
4969 ctx->fs_symlinks_count++;
4970 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
4971 ctx->fs_fast_symlinks_count++;
4972 check_blocks(ctx, &pctx, block_buf);
4976 else if (LINUX_S_ISFIFO (inode->i_mode) &&
4977 e2fsck_pass1_check_device_inode(fs, inode)) {
4978 check_immutable(ctx, &pctx);
4979 check_size(ctx, &pctx);
4980 ctx->fs_fifo_count++;
4981 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
4982 e2fsck_pass1_check_device_inode(fs, inode)) {
4983 check_immutable(ctx, &pctx);
4984 check_size(ctx, &pctx);
4985 ctx->fs_sockets_count++;
4987 mark_inode_bad(ctx, ino);
4988 if (inode->i_block[EXT2_IND_BLOCK])
4989 ctx->fs_ind_count++;
4990 if (inode->i_block[EXT2_DIND_BLOCK])
4991 ctx->fs_dind_count++;
4992 if (inode->i_block[EXT2_TIND_BLOCK])
4993 ctx->fs_tind_count++;
4994 if (inode->i_block[EXT2_IND_BLOCK] ||
4995 inode->i_block[EXT2_DIND_BLOCK] ||
4996 inode->i_block[EXT2_TIND_BLOCK] ||
4997 inode->i_file_acl) {
4998 inodes_to_process[process_inode_count].ino = ino;
4999 inodes_to_process[process_inode_count].inode = *inode;
5000 process_inode_count++;
5002 check_blocks(ctx, &pctx, block_buf);
5004 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5007 if (process_inode_count >= ctx->process_inode_size) {
5008 process_inodes(ctx, block_buf);
5010 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5014 process_inodes(ctx, block_buf);
5015 ext2fs_close_inode_scan(scan);
5016 ehandler_operation(0);
5019 * If any extended attribute blocks' reference counts need to
5020 * be adjusted, either up (ctx->refcount_extra), or down
5021 * (ctx->refcount), then fix them.
5023 if (ctx->refcount) {
5024 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5025 ea_refcount_free(ctx->refcount);
5028 if (ctx->refcount_extra) {
5029 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5031 ea_refcount_free(ctx->refcount_extra);
5032 ctx->refcount_extra = 0;
5035 if (ctx->invalid_bitmaps)
5036 handle_fs_bad_blocks(ctx);
5038 /* We don't need the block_ea_map any more */
5039 ext2fs_free_block_bitmap(ctx->block_ea_map);
5040 ctx->block_ea_map = 0;
5042 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5043 ext2fs_block_bitmap save_bmap;
5045 save_bmap = fs->block_map;
5046 fs->block_map = ctx->block_found_map;
5047 clear_problem_context(&pctx);
5048 pctx.errcode = ext2fs_create_resize_inode(fs);
5050 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5051 /* Should never get here */
5052 ctx->flags |= E2F_FLAG_ABORT;
5055 fs->block_map = save_bmap;
5056 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5059 if (ctx->flags & E2F_FLAG_RESTART) {
5061 * Only the master copy of the superblock and block
5062 * group descriptors are going to be written during a
5063 * restart, so set the superblock to be used to be the
5064 * master superblock.
5066 ctx->use_superblock = 0;
5071 if (ctx->block_dup_map) {
5072 if (ctx->options & E2F_OPT_PREEN) {
5073 clear_problem_context(&pctx);
5074 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5076 e2fsck_pass1_dupblocks(ctx, block_buf);
5078 ext2fs_free_mem(&inodes_to_process);
5080 e2fsck_use_inode_shortcuts(ctx, 0);
5082 ext2fs_free_mem(&block_buf);
5083 ext2fs_free_mem(&inode);
5085 #ifdef RESOURCE_TRACK
5086 if (ctx->options & E2F_OPT_TIME2) {
5087 e2fsck_clear_progbar(ctx);
5088 print_resource_track(_("Pass 1"), &rtrack);
5094 * When the inode_scan routines call this callback at the end of the
5095 * glock group, call process_inodes.
5097 static errcode_t scan_callback(ext2_filsys fs,
5098 ext2_inode_scan scan FSCK_ATTR((unused)),
5099 dgrp_t group, void * priv_data)
5101 struct scan_callback_struct *scan_struct;
5104 scan_struct = (struct scan_callback_struct *) priv_data;
5105 ctx = scan_struct->ctx;
5107 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5110 if ((ctx->progress)(ctx, 1, group+1,
5111 ctx->fs->group_desc_count))
5112 return EXT2_ET_CANCEL_REQUESTED;
5118 * Process the inodes in the "inodes to process" list.
5120 static void process_inodes(e2fsck_t ctx, char *block_buf)
5123 struct ext2_inode *old_stashed_inode;
5124 ext2_ino_t old_stashed_ino;
5125 const char *old_operation;
5127 struct problem_context pctx;
5130 printf("begin process_inodes: ");
5132 if (process_inode_count == 0)
5134 old_operation = ehandler_operation(0);
5135 old_stashed_inode = ctx->stashed_inode;
5136 old_stashed_ino = ctx->stashed_ino;
5137 qsort(inodes_to_process, process_inode_count,
5138 sizeof(struct process_inode_block), process_inode_cmp);
5139 clear_problem_context(&pctx);
5140 for (i=0; i < process_inode_count; i++) {
5141 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5142 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5145 printf("%u ", pctx.ino);
5147 sprintf(buf, _("reading indirect blocks of inode %u"),
5149 ehandler_operation(buf);
5150 check_blocks(ctx, &pctx, block_buf);
5151 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5154 ctx->stashed_inode = old_stashed_inode;
5155 ctx->stashed_ino = old_stashed_ino;
5156 process_inode_count = 0;
5158 printf("end process inodes\n");
5160 ehandler_operation(old_operation);
5163 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5165 const struct process_inode_block *ib_a =
5166 (const struct process_inode_block *) a;
5167 const struct process_inode_block *ib_b =
5168 (const struct process_inode_block *) b;
5171 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5172 ib_b->inode.i_block[EXT2_IND_BLOCK]);
5174 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5179 * Mark an inode as being bad in some what
5181 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5183 struct problem_context pctx;
5185 if (!ctx->inode_bad_map) {
5186 clear_problem_context(&pctx);
5188 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5189 _("bad inode map"), &ctx->inode_bad_map);
5192 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5193 /* Should never get here */
5194 ctx->flags |= E2F_FLAG_ABORT;
5198 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5203 * This procedure will allocate the inode "bb" (badblock) map table
5205 static void alloc_bb_map(e2fsck_t ctx)
5207 struct problem_context pctx;
5209 clear_problem_context(&pctx);
5210 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5211 _("inode in bad block map"),
5212 &ctx->inode_bb_map);
5215 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5216 /* Should never get here */
5217 ctx->flags |= E2F_FLAG_ABORT;
5223 * This procedure will allocate the inode imagic table
5225 static void alloc_imagic_map(e2fsck_t ctx)
5227 struct problem_context pctx;
5229 clear_problem_context(&pctx);
5230 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5231 _("imagic inode map"),
5232 &ctx->inode_imagic_map);
5235 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5236 /* Should never get here */
5237 ctx->flags |= E2F_FLAG_ABORT;
5243 * Marks a block as in use, setting the dup_map if it's been set
5244 * already. Called by process_block and process_bad_block.
5246 * WARNING: Assumes checks have already been done to make sure block
5247 * is valid. This is true in both process_block and process_bad_block.
5249 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5251 struct problem_context pctx;
5253 clear_problem_context(&pctx);
5255 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5256 if (!ctx->block_dup_map) {
5257 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5258 _("multiply claimed block map"),
5259 &ctx->block_dup_map);
5262 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5264 /* Should never get here */
5265 ctx->flags |= E2F_FLAG_ABORT;
5269 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5271 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5276 * Adjust the extended attribute block's reference counts at the end
5277 * of pass 1, either by subtracting out references for EA blocks that
5278 * are still referenced in ctx->refcount, or by adding references for
5279 * EA blocks that had extra references as accounted for in
5280 * ctx->refcount_extra.
5282 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5283 char *block_buf, int adjust_sign)
5285 struct ext2_ext_attr_header *header;
5286 struct problem_context pctx;
5287 ext2_filsys fs = ctx->fs;
5292 clear_problem_context(&pctx);
5294 ea_refcount_intr_begin(refcount);
5296 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5299 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5301 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5304 header = (struct ext2_ext_attr_header *) block_buf;
5305 pctx.blkcount = header->h_refcount;
5306 should_be = header->h_refcount + adjust_sign * count;
5307 pctx.num = should_be;
5308 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5309 header->h_refcount = should_be;
5310 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5313 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5321 * Handle processing the extended attribute blocks
5323 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5326 ext2_filsys fs = ctx->fs;
5327 ext2_ino_t ino = pctx->ino;
5328 struct ext2_inode *inode = pctx->inode;
5331 struct ext2_ext_attr_header *header;
5332 struct ext2_ext_attr_entry *entry;
5336 blk = inode->i_file_acl;
5341 * If the Extended attribute flag isn't set, then a non-zero
5342 * file acl means that the inode is corrupted.
5344 * Or if the extended attribute block is an invalid block,
5345 * then the inode is also corrupted.
5347 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5348 (blk < fs->super->s_first_data_block) ||
5349 (blk >= fs->super->s_blocks_count)) {
5350 mark_inode_bad(ctx, ino);
5354 /* If ea bitmap hasn't been allocated, create it */
5355 if (!ctx->block_ea_map) {
5356 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5357 _("ext attr block map"),
5358 &ctx->block_ea_map);
5359 if (pctx->errcode) {
5361 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5362 ctx->flags |= E2F_FLAG_ABORT;
5367 /* Create the EA refcount structure if necessary */
5368 if (!ctx->refcount) {
5369 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5370 if (pctx->errcode) {
5372 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5373 ctx->flags |= E2F_FLAG_ABORT;
5379 /* Debugging text */
5380 printf("Inode %u has EA block %u\n", ino, blk);
5383 /* Have we seen this EA block before? */
5384 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5385 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5387 /* Ooops, this EA was referenced more than it stated */
5388 if (!ctx->refcount_extra) {
5389 pctx->errcode = ea_refcount_create(0,
5390 &ctx->refcount_extra);
5391 if (pctx->errcode) {
5393 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5394 ctx->flags |= E2F_FLAG_ABORT;
5398 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5403 * OK, we haven't seen this EA block yet. So we need to
5407 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5408 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5410 header = (struct ext2_ext_attr_header *) block_buf;
5411 pctx->blk = inode->i_file_acl;
5412 if (((ctx->ext_attr_ver == 1) &&
5413 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5414 ((ctx->ext_attr_ver == 2) &&
5415 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5416 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5420 if (header->h_blocks != 1) {
5421 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5425 region = region_create(0, fs->blocksize);
5427 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5428 ctx->flags |= E2F_FLAG_ABORT;
5431 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5432 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5436 entry = (struct ext2_ext_attr_entry *)(header+1);
5437 end = block_buf + fs->blocksize;
5438 while ((char *)entry < end && *(__u32 *)entry) {
5439 if (region_allocate(region, (char *)entry - (char *)header,
5440 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5441 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5444 if ((ctx->ext_attr_ver == 1 &&
5445 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5446 (ctx->ext_attr_ver == 2 &&
5447 entry->e_name_index == 0)) {
5448 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5451 if (entry->e_value_block != 0) {
5452 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5455 if (entry->e_value_size &&
5456 region_allocate(region, entry->e_value_offs,
5457 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5458 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5461 entry = EXT2_EXT_ATTR_NEXT(entry);
5463 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5464 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5467 region_free(region);
5469 count = header->h_refcount - 1;
5471 ea_refcount_store(ctx->refcount, blk, count);
5472 mark_block_used(ctx, blk);
5473 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5478 inode->i_file_acl = 0;
5479 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5483 /* Returns 1 if bad htree, 0 if OK */
5484 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5485 ext2_ino_t ino FSCK_ATTR((unused)),
5486 struct ext2_inode *inode,
5489 struct ext2_dx_root_info *root;
5490 ext2_filsys fs = ctx->fs;
5494 if ((!LINUX_S_ISDIR(inode->i_mode) &&
5495 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5496 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5497 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5500 blk = inode->i_block[0];
5502 (blk < fs->super->s_first_data_block) ||
5503 (blk >= fs->super->s_blocks_count)) &&
5504 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5507 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5508 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5511 /* XXX should check that beginning matches a directory */
5512 root = (struct ext2_dx_root_info *) (block_buf + 24);
5514 if ((root->reserved_zero || root->info_length < 8) &&
5515 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5518 pctx->num = root->hash_version;
5519 if ((root->hash_version != EXT2_HASH_LEGACY) &&
5520 (root->hash_version != EXT2_HASH_HALF_MD4) &&
5521 (root->hash_version != EXT2_HASH_TEA) &&
5522 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5525 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5526 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5529 pctx->num = root->indirect_levels;
5530 if ((root->indirect_levels > 1) &&
5531 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5538 * This subroutine is called on each inode to account for all of the
5539 * blocks used by that inode.
5541 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5544 ext2_filsys fs = ctx->fs;
5545 struct process_block_struct_1 pb;
5546 ext2_ino_t ino = pctx->ino;
5547 struct ext2_inode *inode = pctx->inode;
5549 int dirty_inode = 0;
5555 pb.num_illegal_blocks = 0;
5556 pb.suppress = 0; pb.clear = 0;
5559 pb.previous_block = 0;
5560 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5561 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5562 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5569 if (inode->i_flags & EXT2_COMPRBLK_FL) {
5570 if (fs->super->s_feature_incompat &
5571 EXT2_FEATURE_INCOMPAT_COMPRESSION)
5574 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5575 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5581 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5584 if (ext2fs_inode_has_valid_blocks(inode))
5585 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5586 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5587 block_buf, process_block, &pb);
5588 end_problem_latch(ctx, PR_LATCH_BLOCK);
5589 end_problem_latch(ctx, PR_LATCH_TOOBIG);
5590 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5593 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5595 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5596 ctx->fs_fragmented++;
5599 inode->i_links_count = 0;
5600 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5601 inode->i_dtime = time(0);
5603 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5604 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5605 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5607 * The inode was probably partially accounted for
5608 * before processing was aborted, so we need to
5609 * restart the pass 1 scan.
5611 ctx->flags |= E2F_FLAG_RESTART;
5615 if (inode->i_flags & EXT2_INDEX_FL) {
5616 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5617 inode->i_flags &= ~EXT2_INDEX_FL;
5621 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5625 if (ctx->dirs_to_hash && pb.is_dir &&
5626 !(inode->i_flags & EXT2_INDEX_FL) &&
5627 ((inode->i_size / fs->blocksize) >= 3))
5628 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5630 if (!pb.num_blocks && pb.is_dir) {
5631 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5632 inode->i_links_count = 0;
5633 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5634 inode->i_dtime = time(0);
5636 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5637 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5638 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5639 ctx->fs_directory_count--;
5644 pb.num_blocks *= (fs->blocksize / 512);
5646 printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5647 ino, inode->i_size, pb.last_block, inode->i_blocks,
5651 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5652 if (nblock > (pb.last_block + 1))
5654 else if (nblock < (pb.last_block + 1)) {
5655 if (((pb.last_block + 1) - nblock) >
5656 fs->super->s_prealloc_dir_blocks)
5660 size = EXT2_I_SIZE(inode);
5661 if ((pb.last_block >= 0) &&
5662 (size < (__u64) pb.last_block * fs->blocksize))
5664 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5667 /* i_size for symlinks is checked elsewhere */
5668 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5669 pctx->num = (pb.last_block+1) * fs->blocksize;
5670 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5671 inode->i_size = pctx->num;
5672 if (!LINUX_S_ISDIR(inode->i_mode))
5673 inode->i_size_high = pctx->num >> 32;
5678 if (LINUX_S_ISREG(inode->i_mode) &&
5679 (inode->i_size_high || inode->i_size & 0x80000000UL))
5681 if (pb.num_blocks != inode->i_blocks) {
5682 pctx->num = pb.num_blocks;
5683 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5684 inode->i_blocks = pb.num_blocks;
5691 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5696 * Helper function called by process block when an illegal block is
5697 * found. It returns a description about why the block is illegal
5699 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5703 static char problem[80];
5705 super = fs->super->s_first_data_block;
5706 strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5707 if (block < super) {
5708 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5710 } else if (block >= fs->super->s_blocks_count) {
5711 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5714 for (i = 0; i < fs->group_desc_count; i++) {
5715 if (block == super) {
5716 sprintf(problem, "is the superblock in group %d", i);
5719 if (block > super &&
5720 block <= (super + fs->desc_blocks)) {
5721 sprintf(problem, "is in the group descriptors "
5725 if (block == fs->group_desc[i].bg_block_bitmap) {
5726 sprintf(problem, "is the block bitmap of group %d", i);
5729 if (block == fs->group_desc[i].bg_inode_bitmap) {
5730 sprintf(problem, "is the inode bitmap of group %d", i);
5733 if (block >= fs->group_desc[i].bg_inode_table &&
5734 (block < fs->group_desc[i].bg_inode_table
5735 + fs->inode_blocks_per_group)) {
5736 sprintf(problem, "is in the inode table of group %d",
5740 super += fs->super->s_blocks_per_group;
5747 * This is a helper function for check_blocks().
5749 static int process_block(ext2_filsys fs,
5751 e2_blkcnt_t blockcnt,
5752 blk_t ref_block FSCK_ATTR((unused)),
5753 int ref_offset FSCK_ATTR((unused)),
5756 struct process_block_struct_1 *p;
5757 struct problem_context *pctx;
5758 blk_t blk = *block_nr;
5763 p = (struct process_block_struct_1 *) priv_data;
5767 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5768 /* todo: Check that the comprblk_fl is high, that the
5769 blkaddr pattern looks right (all non-holes up to
5770 first EXT2FS_COMPRESSED_BLKADDR, then all
5771 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5772 that the feature_incompat bit is high, and that the
5773 inode is a regular file. If we're doing a "full
5774 check" (a concept introduced to e2fsck by e2compr,
5775 meaning that we look at data blocks as well as
5776 metadata) then call some library routine that
5777 checks the compressed data. I'll have to think
5778 about this, because one particularly important
5779 problem to be able to fix is to recalculate the
5780 cluster size if necessary. I think that perhaps
5781 we'd better do most/all e2compr-specific checks
5782 separately, after the non-e2compr checks. If not
5783 doing a full check, it may be useful to test that
5784 the personality is linux; e.g. if it isn't then
5785 perhaps this really is just an illegal block. */
5790 if (p->is_dir == 0) {
5792 * Should never happen, since only directories
5793 * get called with BLOCK_FLAG_HOLE
5796 printf("process_block() called with blk == 0, "
5797 "blockcnt=%d, inode %lu???\n",
5804 if (blockcnt * fs->blocksize < p->inode->i_size) {
5806 printf("Missing block (#%d) in directory inode %lu!\n",
5815 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5820 * Simplistic fragmentation check. We merely require that the
5821 * file be contiguous. (Which can never be true for really
5822 * big files that are greater than a block group.)
5824 if (!HOLE_BLKADDR(p->previous_block)) {
5825 if (p->previous_block+1 != blk)
5828 p->previous_block = blk;
5830 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5831 problem = PR_1_TOOBIG_DIR;
5832 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5833 problem = PR_1_TOOBIG_REG;
5834 if (!p->is_dir && !p->is_reg && blockcnt > 0)
5835 problem = PR_1_TOOBIG_SYMLINK;
5837 if (blk < fs->super->s_first_data_block ||
5838 blk >= fs->super->s_blocks_count)
5839 problem = PR_1_ILLEGAL_BLOCK_NUM;
5842 p->num_illegal_blocks++;
5843 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5844 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5848 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5850 set_latch_flags(PR_LATCH_BLOCK,
5855 pctx->blkcount = blockcnt;
5856 if (fix_problem(ctx, problem, pctx)) {
5857 blk = *block_nr = 0;
5858 ret_code = BLOCK_CHANGED;
5864 if (p->ino == EXT2_RESIZE_INO) {
5866 * The resize inode has already be sanity checked
5867 * during pass #0 (the superblock checks). All we
5868 * have to do is mark the double indirect block as
5869 * being in use; all of the other blocks are handled
5870 * by mark_table_blocks()).
5872 if (blockcnt == BLOCK_COUNT_DIND)
5873 mark_block_used(ctx, blk);
5875 mark_block_used(ctx, blk);
5878 p->last_block = blockcnt;
5880 if (p->is_dir && (blockcnt >= 0)) {
5881 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5883 if (pctx->errcode) {
5885 pctx->num = blockcnt;
5886 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5887 /* Should never get here */
5888 ctx->flags |= E2F_FLAG_ABORT;
5895 static int process_bad_block(ext2_filsys fs,
5897 e2_blkcnt_t blockcnt,
5898 blk_t ref_block FSCK_ATTR((unused)),
5899 int ref_offset FSCK_ATTR((unused)),
5902 struct process_block_struct_1 *p;
5903 blk_t blk = *block_nr;
5906 struct problem_context *pctx;
5910 * Note: This function processes blocks for the bad blocks
5911 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
5917 p = (struct process_block_struct_1 *) priv_data;
5921 pctx->ino = EXT2_BAD_INO;
5923 pctx->blkcount = blockcnt;
5925 if ((blk < fs->super->s_first_data_block) ||
5926 (blk >= fs->super->s_blocks_count)) {
5927 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5929 return BLOCK_CHANGED;
5935 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5937 if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5939 return BLOCK_CHANGED;
5941 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5944 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5947 return BLOCK_CHANGED;
5949 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5952 mark_block_used(ctx, blk);
5956 printf ("DEBUG: Marking %u as bad.\n", blk);
5958 ctx->fs_badblocks_count++;
5960 * If the block is not used, then mark it as used and return.
5961 * If it is already marked as found, this must mean that
5962 * there's an overlap between the filesystem table blocks
5963 * (bitmaps and inode table) and the bad block list.
5965 if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
5966 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
5970 * Try to find the where the filesystem block was used...
5972 first_block = fs->super->s_first_data_block;
5974 for (i = 0; i < fs->group_desc_count; i++ ) {
5977 if (!ext2fs_bg_has_super(fs, i))
5979 if (blk == first_block) {
5981 if (fix_problem(ctx,
5982 PR_1_BAD_PRIMARY_SUPERBLOCK,
5985 return BLOCK_CHANGED;
5989 fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
5992 if ((blk > first_block) &&
5993 (blk <= first_block + fs->desc_blocks)) {
5995 pctx->blk = *block_nr;
5996 if (fix_problem(ctx,
5997 PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
5999 return BLOCK_CHANGED;
6003 fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6007 if (blk == fs->group_desc[i].bg_block_bitmap) {
6008 if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6009 ctx->invalid_block_bitmap_flag[i]++;
6010 ctx->invalid_bitmaps++;
6014 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6015 if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6016 ctx->invalid_inode_bitmap_flag[i]++;
6017 ctx->invalid_bitmaps++;
6021 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6022 (blk < (fs->group_desc[i].bg_inode_table +
6023 fs->inode_blocks_per_group))) {
6025 * If there are bad blocks in the inode table,
6026 * the inode scan code will try to do
6027 * something reasonable automatically.
6031 first_block += fs->super->s_blocks_per_group;
6034 * If we've gotten to this point, then the only
6035 * possibility is that the bad block inode meta data
6036 * is using a bad block.
6038 if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6039 (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6040 (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6042 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6044 return BLOCK_CHANGED;
6046 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6053 /* Warn user that the block wasn't claimed */
6054 fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6059 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6060 const char *name, int num, blk_t *new_block)
6062 ext2_filsys fs = ctx->fs;
6063 blk_t old_block = *new_block;
6066 struct problem_context pctx;
6068 clear_problem_context(&pctx);
6071 pctx.blk = old_block;
6074 pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6075 first_block + fs->super->s_blocks_per_group,
6076 num, ctx->block_found_map, new_block);
6079 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6080 ext2fs_unmark_valid(fs);
6083 pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6085 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6086 ext2fs_unmark_valid(fs);
6089 ext2fs_mark_super_dirty(fs);
6090 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6091 pctx.blk2 = *new_block;
6092 fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6093 PR_1_RELOC_TO), &pctx);
6095 for (i = 0; i < num; i++) {
6097 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6099 pctx.errcode = io_channel_read_blk(fs->io,
6100 old_block + i, 1, buf);
6102 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6104 memset(buf, 0, fs->blocksize);
6106 pctx.blk = (*new_block) + i;
6107 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6110 fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6112 ext2fs_free_mem(&buf);
6116 * This routine gets called at the end of pass 1 if bad blocks are
6117 * detected in the superblock, group descriptors, inode_bitmaps, or
6118 * block bitmaps. At this point, all of the blocks have been mapped
6119 * out, so we can try to allocate new block(s) to replace the bad
6122 static void handle_fs_bad_blocks(e2fsck_t ctx)
6124 ext2_filsys fs = ctx->fs;
6126 int first_block = fs->super->s_first_data_block;
6128 for (i = 0; i < fs->group_desc_count; i++) {
6129 if (ctx->invalid_block_bitmap_flag[i]) {
6130 new_table_block(ctx, first_block, i, _("block bitmap"),
6131 1, &fs->group_desc[i].bg_block_bitmap);
6133 if (ctx->invalid_inode_bitmap_flag[i]) {
6134 new_table_block(ctx, first_block, i, _("inode bitmap"),
6135 1, &fs->group_desc[i].bg_inode_bitmap);
6137 if (ctx->invalid_inode_table_flag[i]) {
6138 new_table_block(ctx, first_block, i, _("inode table"),
6139 fs->inode_blocks_per_group,
6140 &fs->group_desc[i].bg_inode_table);
6141 ctx->flags |= E2F_FLAG_RESTART;
6143 first_block += fs->super->s_blocks_per_group;
6145 ctx->invalid_bitmaps = 0;
6149 * This routine marks all blocks which are used by the superblock,
6150 * group descriptors, inode bitmaps, and block bitmaps.
6152 static void mark_table_blocks(e2fsck_t ctx)
6154 ext2_filsys fs = ctx->fs;
6158 struct problem_context pctx;
6160 clear_problem_context(&pctx);
6162 block = fs->super->s_first_data_block;
6163 for (i = 0; i < fs->group_desc_count; i++) {
6166 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6169 * Mark the blocks used for the inode table
6171 if (fs->group_desc[i].bg_inode_table) {
6172 for (j = 0, b = fs->group_desc[i].bg_inode_table;
6173 j < fs->inode_blocks_per_group;
6175 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6178 if (fix_problem(ctx,
6179 PR_1_ITABLE_CONFLICT, &pctx)) {
6180 ctx->invalid_inode_table_flag[i]++;
6181 ctx->invalid_bitmaps++;
6184 ext2fs_mark_block_bitmap(ctx->block_found_map,
6191 * Mark block used for the block bitmap
6193 if (fs->group_desc[i].bg_block_bitmap) {
6194 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6195 fs->group_desc[i].bg_block_bitmap)) {
6196 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6197 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6198 ctx->invalid_block_bitmap_flag[i]++;
6199 ctx->invalid_bitmaps++;
6202 ext2fs_mark_block_bitmap(ctx->block_found_map,
6203 fs->group_desc[i].bg_block_bitmap);
6208 * Mark block used for the inode bitmap
6210 if (fs->group_desc[i].bg_inode_bitmap) {
6211 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6212 fs->group_desc[i].bg_inode_bitmap)) {
6213 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6214 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6215 ctx->invalid_inode_bitmap_flag[i]++;
6216 ctx->invalid_bitmaps++;
6219 ext2fs_mark_block_bitmap(ctx->block_found_map,
6220 fs->group_desc[i].bg_inode_bitmap);
6223 block += fs->super->s_blocks_per_group;
6228 * Thes subroutines short circuits ext2fs_get_blocks and
6229 * ext2fs_check_directory; we use them since we already have the inode
6230 * structure, so there's no point in letting the ext2fs library read
6233 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6236 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6239 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6240 return EXT2_ET_CALLBACK_NOTHANDLED;
6242 for (i=0; i < EXT2_N_BLOCKS; i++)
6243 blocks[i] = ctx->stashed_inode->i_block[i];
6247 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6248 struct ext2_inode *inode)
6250 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6252 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6253 return EXT2_ET_CALLBACK_NOTHANDLED;
6254 *inode = *ctx->stashed_inode;
6258 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6259 struct ext2_inode *inode)
6261 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6263 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6264 *ctx->stashed_inode = *inode;
6265 return EXT2_ET_CALLBACK_NOTHANDLED;
6268 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6270 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6272 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6273 return EXT2_ET_CALLBACK_NOTHANDLED;
6275 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6276 return EXT2_ET_NO_DIRECTORY;
6280 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6282 ext2_filsys fs = ctx->fs;
6285 fs->get_blocks = pass1_get_blocks;
6286 fs->check_directory = pass1_check_directory;
6287 fs->read_inode = pass1_read_inode;
6288 fs->write_inode = pass1_write_inode;
6289 ctx->stashed_ino = 0;
6292 fs->check_directory = 0;
6294 fs->write_inode = 0;
6299 * pass1b.c --- Pass #1b of e2fsck
6301 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
6302 * only invoked if pass 1 discovered blocks which are in use by more
6305 * Pass1B scans the data blocks of all the inodes again, generating a
6306 * complete list of duplicate blocks and which inodes have claimed
6309 * Pass1C does a tree-traversal of the filesystem, to determine the
6310 * parent directories of these inodes. This step is necessary so that
6311 * e2fsck can print out the pathnames of affected inodes.
6313 * Pass1D is a reconciliation pass. For each inode with duplicate
6314 * blocks, the user is prompted if s/he would like to clone the file
6315 * (so that the file gets a fresh copy of the duplicated blocks) or
6316 * simply to delete the file.
6321 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6322 #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
6323 #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
6325 /* Define an extension to the ext2 library's block count information */
6326 #define BLOCK_COUNT_EXTATTR (-5)
6330 struct block_el *next;
6335 struct inode_el *next;
6340 struct inode_el *inode_list;
6344 * This structure stores information about a particular inode which
6345 * is sharing blocks with other inodes. This information is collected
6346 * to display to the user, so that the user knows what files he or she
6347 * is dealing with, when trying to decide how to resolve the conflict
6348 * of multiply-claimed blocks.
6353 struct ext2_inode inode;
6354 struct block_el *block_list;
6357 static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
6358 e2_blkcnt_t blockcnt, blk_t ref_blk,
6359 int ref_offset, void *priv_data);
6360 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6361 struct dup_inode *dp, char *block_buf);
6362 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6363 struct dup_inode *dp, char* block_buf);
6364 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6366 static void pass1b(e2fsck_t ctx, char *block_buf);
6367 static void pass1c(e2fsck_t ctx, char *block_buf);
6368 static void pass1d(e2fsck_t ctx, char *block_buf);
6370 static int dup_inode_count = 0;
6372 static dict_t blk_dict, ino_dict;
6374 static ext2fs_inode_bitmap inode_dup_map;
6376 static int dict_int_cmp(const void *a, const void *b)
6387 * Add a duplicate block record
6389 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6390 struct ext2_inode *inode)
6393 struct dup_block *db;
6394 struct dup_inode *di;
6395 struct block_el *blk_el;
6396 struct inode_el *ino_el;
6398 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6400 db = (struct dup_block *) dnode_get(n);
6402 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6403 sizeof(struct dup_block), "duplicate block header");
6406 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6408 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6409 sizeof(struct inode_el), "inode element");
6410 ino_el->inode = ino;
6411 ino_el->next = db->inode_list;
6412 db->inode_list = ino_el;
6415 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6417 di = (struct dup_inode *) dnode_get(n);
6419 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6420 sizeof(struct dup_inode), "duplicate inode header");
6421 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6422 di->num_dupblocks = 0;
6425 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6427 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6428 sizeof(struct block_el), "block element");
6429 blk_el->block = blk;
6430 blk_el->next = di->block_list;
6431 di->block_list = blk_el;
6432 di->num_dupblocks++;
6436 * Free a duplicate inode record
6438 static void inode_dnode_free(dnode_t *node)
6440 struct dup_inode *di;
6441 struct block_el *p, *next;
6443 di = (struct dup_inode *) dnode_get(node);
6444 for (p = di->block_list; p; p = next) {
6452 * Free a duplicate block record
6454 static void block_dnode_free(dnode_t *node)
6456 struct dup_block *db;
6457 struct inode_el *p, *next;
6459 db = (struct dup_block *) dnode_get(node);
6460 for (p = db->inode_list; p; p = next) {
6469 * Main procedure for handling duplicate blocks
6471 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6473 ext2_filsys fs = ctx->fs;
6474 struct problem_context pctx;
6476 clear_problem_context(&pctx);
6478 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6479 _("multiply claimed inode map"), &inode_dup_map);
6481 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6482 ctx->flags |= E2F_FLAG_ABORT;
6486 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6487 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6488 dict_set_allocator(&ino_dict, inode_dnode_free);
6489 dict_set_allocator(&blk_dict, block_dnode_free);
6491 pass1b(ctx, block_buf);
6492 pass1c(ctx, block_buf);
6493 pass1d(ctx, block_buf);
6496 * Time to free all of the accumulated data structures that we
6497 * don't need anymore.
6499 dict_free_nodes(&ino_dict);
6500 dict_free_nodes(&blk_dict);
6504 * Scan the inodes looking for inodes that contain duplicate blocks.
6506 struct process_block_struct_1b {
6510 struct ext2_inode *inode;
6511 struct problem_context *pctx;
6514 static void pass1b(e2fsck_t ctx, char *block_buf)
6516 ext2_filsys fs = ctx->fs;
6518 struct ext2_inode inode;
6519 ext2_inode_scan scan;
6520 struct process_block_struct_1b pb;
6521 struct problem_context pctx;
6523 clear_problem_context(&pctx);
6525 if (!(ctx->options & E2F_OPT_PREEN))
6526 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6527 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6530 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6531 ctx->flags |= E2F_FLAG_ABORT;
6534 ctx->stashed_inode = &inode;
6537 pctx.str = "pass1b";
6539 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6540 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6543 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6544 ctx->flags |= E2F_FLAG_ABORT;
6549 pctx.ino = ctx->stashed_ino = ino;
6550 if ((ino != EXT2_BAD_INO) &&
6551 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6558 if (ext2fs_inode_has_valid_blocks(&inode) ||
6559 (ino == EXT2_BAD_INO))
6560 pctx.errcode = ext2fs_block_iterate2(fs, ino,
6561 0, block_buf, process_pass1b_block, &pb);
6562 if (inode.i_file_acl)
6563 process_pass1b_block(fs, &inode.i_file_acl,
6564 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6565 if (pb.dup_blocks) {
6566 end_problem_latch(ctx, PR_LATCH_DBLOCK);
6567 if (ino >= EXT2_FIRST_INODE(fs->super) ||
6568 ino == EXT2_ROOT_INO)
6572 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6574 ext2fs_close_inode_scan(scan);
6575 e2fsck_use_inode_shortcuts(ctx, 0);
6578 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6580 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6581 blk_t ref_blk FSCK_ATTR((unused)),
6582 int ref_offset FSCK_ATTR((unused)),
6585 struct process_block_struct_1b *p;
6588 if (HOLE_BLKADDR(*block_nr))
6590 p = (struct process_block_struct_1b *) priv_data;
6593 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6596 /* OK, this is a duplicate block */
6597 if (p->ino != EXT2_BAD_INO) {
6598 p->pctx->blk = *block_nr;
6599 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6602 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6604 add_dupe(ctx, p->ino, *block_nr, p->inode);
6610 * Pass 1c: Scan directories for inodes with duplicate blocks. This
6611 * is used so that we can print pathnames when prompting the user for
6614 struct search_dir_struct {
6616 ext2_ino_t first_inode;
6617 ext2_ino_t max_inode;
6620 static int search_dirent_proc(ext2_ino_t dir, int entry,
6621 struct ext2_dir_entry *dirent,
6622 int offset FSCK_ATTR((unused)),
6623 int blocksize FSCK_ATTR((unused)),
6624 char *buf FSCK_ATTR((unused)),
6627 struct search_dir_struct *sd;
6628 struct dup_inode *p;
6631 sd = (struct search_dir_struct *) priv_data;
6633 if (dirent->inode > sd->max_inode)
6634 /* Should abort this inode, but not everything */
6637 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6638 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6641 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6644 p = (struct dup_inode *) dnode_get(n);
6648 return(sd->count ? 0 : DIRENT_ABORT);
6652 static void pass1c(e2fsck_t ctx, char *block_buf)
6654 ext2_filsys fs = ctx->fs;
6655 struct search_dir_struct sd;
6656 struct problem_context pctx;
6658 clear_problem_context(&pctx);
6660 if (!(ctx->options & E2F_OPT_PREEN))
6661 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6664 * Search through all directories to translate inodes to names
6665 * (by searching for the containing directory for that inode.)
6667 sd.count = dup_inode_count;
6668 sd.first_inode = EXT2_FIRST_INODE(fs->super);
6669 sd.max_inode = fs->super->s_inodes_count;
6670 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6671 search_dirent_proc, &sd);
6674 static void pass1d(e2fsck_t ctx, char *block_buf)
6676 ext2_filsys fs = ctx->fs;
6677 struct dup_inode *p, *t;
6678 struct dup_block *q;
6679 ext2_ino_t *shared, ino;
6684 struct problem_context pctx;
6689 clear_problem_context(&pctx);
6691 if (!(ctx->options & E2F_OPT_PREEN))
6692 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6693 e2fsck_read_bitmaps(ctx);
6695 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6696 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6697 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6698 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6699 "Shared inode list");
6700 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6701 p = (struct dup_inode *) dnode_get(n);
6704 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6705 if (ino == EXT2_BAD_INO)
6709 * Find all of the inodes which share blocks with this
6710 * one. First we find all of the duplicate blocks
6711 * belonging to this inode, and then search each block
6712 * get the list of inodes, and merge them together.
6714 for (s = p->block_list; s; s = s->next) {
6715 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6717 continue; /* Should never happen... */
6718 q = (struct dup_block *) dnode_get(m);
6721 if (check_if_fs_block(ctx, s->block)) {
6727 * Add all inodes used by this block to the
6728 * shared[] --- which is a unique list, so
6729 * if an inode is already in shared[], don't
6732 for (r = q->inode_list; r; r = r->next) {
6733 if (r->inode == ino)
6735 for (i = 0; i < shared_len; i++)
6736 if (shared[i] == r->inode)
6738 if (i == shared_len) {
6739 shared[shared_len++] = r->inode;
6745 * Report the inode that we are working on
6747 pctx.inode = &p->inode;
6750 pctx.blkcount = p->num_dupblocks;
6751 pctx.num = meta_data ? shared_len+1 : shared_len;
6752 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6757 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6759 for (i = 0; i < shared_len; i++) {
6760 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6762 continue; /* should never happen */
6763 t = (struct dup_inode *) dnode_get(m);
6765 * Report the inode that we are sharing with
6767 pctx.inode = &t->inode;
6768 pctx.ino = shared[i];
6770 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6773 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6776 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6777 pctx.errcode = clone_file(ctx, ino, p, block_buf);
6779 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6783 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6784 delete_file(ctx, ino, p, block_buf);
6786 ext2fs_unmark_valid(fs);
6788 ext2fs_free_mem(&shared);
6792 * Drop the refcount on the dup_block structure, and clear the entry
6793 * in the block_dup_map if appropriate.
6795 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6798 if (p->num_bad <= 0 ||
6799 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6800 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6803 static int delete_file_block(ext2_filsys fs,
6805 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6806 blk_t ref_block FSCK_ATTR((unused)),
6807 int ref_offset FSCK_ATTR((unused)),
6810 struct process_block_struct_1b *pb;
6811 struct dup_block *p;
6815 pb = (struct process_block_struct_1b *) priv_data;
6818 if (HOLE_BLKADDR(*block_nr))
6821 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6822 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6824 p = (struct dup_block *) dnode_get(n);
6825 decrement_badcount(ctx, *block_nr, p);
6827 com_err("delete_file_block", 0,
6828 _("internal error; can't find dup_blk for %d\n"),
6831 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6832 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6838 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6839 struct dup_inode *dp, char* block_buf)
6841 ext2_filsys fs = ctx->fs;
6842 struct process_block_struct_1b pb;
6843 struct ext2_inode inode;
6844 struct problem_context pctx;
6847 clear_problem_context(&pctx);
6848 pctx.ino = pb.ino = ino;
6849 pb.dup_blocks = dp->num_dupblocks;
6851 pctx.str = "delete_file";
6853 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6854 if (ext2fs_inode_has_valid_blocks(&inode))
6855 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6856 delete_file_block, &pb);
6858 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6859 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6860 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6861 if (ctx->inode_bad_map)
6862 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6863 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6865 /* Inode may have changed by block_iterate, so reread it */
6866 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6867 inode.i_links_count = 0;
6868 inode.i_dtime = time(0);
6869 if (inode.i_file_acl &&
6870 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6872 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6873 block_buf, -1, &count);
6874 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6879 pctx.blk = inode.i_file_acl;
6880 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6883 * If the count is zero, then arrange to have the
6884 * block deleted. If the block is in the block_dup_map,
6885 * also call delete_file_block since it will take care
6886 * of keeping the accounting straight.
6889 ext2fs_test_block_bitmap(ctx->block_dup_map,
6891 delete_file_block(fs, &inode.i_file_acl,
6892 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6894 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6897 struct clone_struct {
6904 static int clone_file_block(ext2_filsys fs,
6906 e2_blkcnt_t blockcnt,
6907 blk_t ref_block FSCK_ATTR((unused)),
6908 int ref_offset FSCK_ATTR((unused)),
6911 struct dup_block *p;
6914 struct clone_struct *cs = (struct clone_struct *) priv_data;
6920 if (HOLE_BLKADDR(*block_nr))
6923 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6924 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6926 p = (struct dup_block *) dnode_get(n);
6927 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6930 cs->errcode = retval;
6933 if (cs->dir && (blockcnt >= 0)) {
6934 retval = ext2fs_set_dir_block(fs->dblist,
6935 cs->dir, new_block, blockcnt);
6937 cs->errcode = retval;
6942 printf("Cloning block %u to %u\n", *block_nr,
6945 retval = io_channel_read_blk(fs->io, *block_nr, 1,
6948 cs->errcode = retval;
6951 retval = io_channel_write_blk(fs->io, new_block, 1,
6954 cs->errcode = retval;
6957 decrement_badcount(ctx, *block_nr, p);
6958 *block_nr = new_block;
6959 ext2fs_mark_block_bitmap(ctx->block_found_map,
6961 ext2fs_mark_block_bitmap(fs->block_map, new_block);
6962 return BLOCK_CHANGED;
6964 com_err("clone_file_block", 0,
6965 _("internal error; can't find dup_blk for %d\n"),
6971 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6972 struct dup_inode *dp, char* block_buf)
6974 ext2_filsys fs = ctx->fs;
6976 struct clone_struct cs;
6977 struct problem_context pctx;
6980 struct inode_el *ino_el;
6981 struct dup_block *db;
6982 struct dup_inode *di;
6984 clear_problem_context(&pctx);
6988 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
6992 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
6996 pctx.str = "clone_file";
6997 if (ext2fs_inode_has_valid_blocks(&dp->inode))
6998 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6999 clone_file_block, &cs);
7000 ext2fs_mark_bb_dirty(fs);
7002 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7003 retval = pctx.errcode;
7007 com_err("clone_file", cs.errcode,
7008 _("returned from clone_file_block"));
7009 retval = cs.errcode;
7012 /* The inode may have changed on disk, so we have to re-read it */
7013 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7014 blk = dp->inode.i_file_acl;
7015 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7016 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7018 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7020 * If we cloned the EA block, find all other inodes
7021 * which refered to that EA block, and modify
7022 * them to point to the new EA block.
7024 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7025 db = (struct dup_block *) dnode_get(n);
7026 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7027 if (ino_el->inode == ino)
7029 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7030 di = (struct dup_inode *) dnode_get(n);
7031 if (di->inode.i_file_acl == blk) {
7032 di->inode.i_file_acl = dp->inode.i_file_acl;
7033 e2fsck_write_inode(ctx, ino_el->inode,
7034 &di->inode, "clone file EA");
7035 decrement_badcount(ctx, blk, db);
7041 ext2fs_free_mem(&cs.buf);
7046 * This routine returns 1 if a block overlaps with one of the superblocks,
7047 * group descriptors, inode bitmaps, or block bitmaps.
7049 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7051 ext2_filsys fs = ctx->fs;
7055 block = fs->super->s_first_data_block;
7056 for (i = 0; i < fs->group_desc_count; i++) {
7058 /* Check superblocks/block group descriptros */
7059 if (ext2fs_bg_has_super(fs, i)) {
7060 if (test_block >= block &&
7061 (test_block <= block + fs->desc_blocks))
7065 /* Check the inode table */
7066 if ((fs->group_desc[i].bg_inode_table) &&
7067 (test_block >= fs->group_desc[i].bg_inode_table) &&
7068 (test_block < (fs->group_desc[i].bg_inode_table +
7069 fs->inode_blocks_per_group)))
7072 /* Check the bitmap blocks */
7073 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7074 (test_block == fs->group_desc[i].bg_inode_bitmap))
7077 block += fs->super->s_blocks_per_group;
7082 * pass2.c --- check directory structure
7084 * Pass 2 of e2fsck iterates through all active directory inodes, and
7085 * applies to following tests to each directory entry in the directory
7086 * blocks in the inodes:
7088 * - The length of the directory entry (rec_len) should be at
7089 * least 8 bytes, and no more than the remaining space
7090 * left in the directory block.
7091 * - The length of the name in the directory entry (name_len)
7092 * should be less than (rec_len - 8).
7093 * - The inode number in the directory entry should be within
7095 * - The inode number should refer to a in-use inode.
7096 * - The first entry should be '.', and its inode should be
7097 * the inode of the directory.
7098 * - The second entry should be '..'.
7100 * To minimize disk seek time, the directory blocks are processed in
7101 * sorted order of block numbers.
7103 * Pass 2 also collects the following information:
7104 * - The inode numbers of the subdirectories for each directory.
7106 * Pass 2 relies on the following information from previous passes:
7107 * - The directory information collected in pass 1.
7108 * - The inode_used_map bitmap
7109 * - The inode_bad_map bitmap
7110 * - The inode_dir_map bitmap
7112 * Pass 2 frees the following data structures
7113 * - The inode_bad_map bitmap
7114 * - The inode_reg_map bitmap
7117 /* #define DX_DEBUG */
7120 * Keeps track of how many times an inode is referenced.
7122 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7123 static int check_dir_block(ext2_filsys fs,
7124 struct ext2_db_entry *dir_blocks_info,
7126 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7127 struct problem_context *pctx);
7128 static int update_dir_block(ext2_filsys fs,
7130 e2_blkcnt_t blockcnt,
7134 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7135 static int htree_depth(struct dx_dir_info *dx_dir,
7136 struct dx_dirblock_info *dx_db);
7137 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7139 struct check_dir_struct {
7141 struct problem_context pctx;
7146 static void e2fsck_pass2(e2fsck_t ctx)
7148 struct ext2_super_block *sb = ctx->fs->super;
7149 struct problem_context pctx;
7150 ext2_filsys fs = ctx->fs;
7152 #ifdef RESOURCE_TRACK
7153 struct resource_track rtrack;
7155 struct dir_info *dir;
7156 struct check_dir_struct cd;
7157 struct dx_dir_info *dx_dir;
7158 struct dx_dirblock_info *dx_db, *dx_parent;
7164 #ifdef RESOURCE_TRACK
7165 init_resource_track(&rtrack);
7168 clear_problem_context(&cd.pctx);
7171 mtrace_print("Pass 2");
7174 if (!(ctx->options & E2F_OPT_PREEN))
7175 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7177 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7178 0, ctx->inode_link_info,
7180 if (cd.pctx.errcode) {
7181 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7182 ctx->flags |= E2F_FLAG_ABORT;
7185 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7186 "directory scan buffer");
7189 * Set up the parent pointer for the root directory, if
7190 * present. (If the root directory is not present, we will
7191 * create it in pass 3.)
7193 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7195 dir->parent = EXT2_ROOT_INO;
7200 cd.max = ext2fs_dblist_count(fs->dblist);
7203 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7205 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7206 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7208 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7210 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7212 if (cd.pctx.errcode) {
7213 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7214 ctx->flags |= E2F_FLAG_ABORT;
7219 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7220 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7222 if (dx_dir->numblocks == 0)
7224 clear_problem_context(&pctx);
7226 pctx.dir = dx_dir->ino;
7227 dx_db = dx_dir->dx_block;
7228 if (dx_db->flags & DX_FLAG_REFERENCED)
7229 dx_db->flags |= DX_FLAG_DUP_REF;
7231 dx_db->flags |= DX_FLAG_REFERENCED;
7233 * Find all of the first and last leaf blocks, and
7234 * update their parent's min and max hash values
7236 for (b=0, dx_db = dx_dir->dx_block;
7237 b < dx_dir->numblocks;
7239 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7240 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7242 dx_parent = &dx_dir->dx_block[dx_db->parent];
7244 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7246 if (dx_db->flags & DX_FLAG_FIRST)
7247 dx_parent->min_hash = dx_db->min_hash;
7249 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7251 if (dx_db->flags & DX_FLAG_LAST)
7252 dx_parent->max_hash = dx_db->max_hash;
7255 for (b=0, dx_db = dx_dir->dx_block;
7256 b < dx_dir->numblocks;
7259 pctx.group = dx_db->parent;
7261 if (!(dx_db->flags & DX_FLAG_FIRST) &&
7262 (dx_db->min_hash < dx_db->node_min_hash)) {
7263 pctx.blk = dx_db->min_hash;
7264 pctx.blk2 = dx_db->node_min_hash;
7265 code = PR_2_HTREE_MIN_HASH;
7266 fix_problem(ctx, code, &pctx);
7269 if (dx_db->type == DX_DIRBLOCK_LEAF) {
7270 depth = htree_depth(dx_dir, dx_db);
7271 if (depth != dx_dir->depth) {
7272 code = PR_2_HTREE_BAD_DEPTH;
7273 fix_problem(ctx, code, &pctx);
7278 * This test doesn't apply for the root block
7282 (dx_db->max_hash > dx_db->node_max_hash)) {
7283 pctx.blk = dx_db->max_hash;
7284 pctx.blk2 = dx_db->node_max_hash;
7285 code = PR_2_HTREE_MAX_HASH;
7286 fix_problem(ctx, code, &pctx);
7289 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7290 code = PR_2_HTREE_NOTREF;
7291 fix_problem(ctx, code, &pctx);
7293 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7294 code = PR_2_HTREE_DUPREF;
7295 fix_problem(ctx, code, &pctx);
7301 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7302 clear_htree(ctx, dx_dir->ino);
7303 dx_dir->numblocks = 0;
7307 ext2fs_free_mem(&buf);
7308 ext2fs_free_dblist(fs->dblist);
7310 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7311 ctx->inode_bad_map = 0;
7312 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7313 ctx->inode_reg_map = 0;
7315 clear_problem_context(&pctx);
7316 if (ctx->large_files) {
7317 if (!(sb->s_feature_ro_compat &
7318 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7319 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7320 sb->s_feature_ro_compat |=
7321 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7322 ext2fs_mark_super_dirty(fs);
7324 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7325 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7326 ext2fs_update_dynamic_rev(fs);
7327 ext2fs_mark_super_dirty(fs);
7329 } else if (!ctx->large_files &&
7330 (sb->s_feature_ro_compat &
7331 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7332 if (fs->flags & EXT2_FLAG_RW) {
7333 sb->s_feature_ro_compat &=
7334 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7335 ext2fs_mark_super_dirty(fs);
7339 #ifdef RESOURCE_TRACK
7340 if (ctx->options & E2F_OPT_TIME2) {
7341 e2fsck_clear_progbar(ctx);
7342 print_resource_track(_("Pass 2"), &rtrack);
7347 #define MAX_DEPTH 32000
7348 static int htree_depth(struct dx_dir_info *dx_dir,
7349 struct dx_dirblock_info *dx_db)
7353 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7354 dx_db = &dx_dir->dx_block[dx_db->parent];
7360 static int dict_de_cmp(const void *a, const void *b)
7362 const struct ext2_dir_entry *de_a, *de_b;
7365 de_a = (const struct ext2_dir_entry *) a;
7366 a_len = de_a->name_len & 0xFF;
7367 de_b = (const struct ext2_dir_entry *) b;
7368 b_len = de_b->name_len & 0xFF;
7371 return (a_len - b_len);
7373 return strncmp(de_a->name, de_b->name, a_len);
7377 * This is special sort function that makes sure that directory blocks
7378 * with a dirblock of zero are sorted to the beginning of the list.
7379 * This guarantees that the root node of the htree directories are
7380 * processed first, so we know what hash version to use.
7382 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7384 const struct ext2_db_entry *db_a =
7385 (const struct ext2_db_entry *) a;
7386 const struct ext2_db_entry *db_b =
7387 (const struct ext2_db_entry *) b;
7389 if (db_a->blockcnt && !db_b->blockcnt)
7392 if (!db_a->blockcnt && db_b->blockcnt)
7395 if (db_a->blk != db_b->blk)
7396 return (int) (db_a->blk - db_b->blk);
7398 if (db_a->ino != db_b->ino)
7399 return (int) (db_a->ino - db_b->ino);
7401 return (int) (db_a->blockcnt - db_b->blockcnt);
7406 * Make sure the first entry in the directory is '.', and that the
7407 * directory entry is sane.
7409 static int check_dot(e2fsck_t ctx,
7410 struct ext2_dir_entry *dirent,
7411 ext2_ino_t ino, struct problem_context *pctx)
7413 struct ext2_dir_entry *nextdir;
7420 problem = PR_2_MISSING_DOT;
7421 else if (((dirent->name_len & 0xFF) != 1) ||
7422 (dirent->name[0] != '.'))
7423 problem = PR_2_1ST_NOT_DOT;
7424 else if (dirent->name[1] != '\0')
7425 problem = PR_2_DOT_NULL_TERM;
7428 if (fix_problem(ctx, problem, pctx)) {
7429 if (dirent->rec_len < 12)
7430 dirent->rec_len = 12;
7431 dirent->inode = ino;
7432 dirent->name_len = 1;
7433 dirent->name[0] = '.';
7434 dirent->name[1] = '\0';
7439 if (dirent->inode != ino) {
7440 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7441 dirent->inode = ino;
7445 if (dirent->rec_len > 12) {
7446 new_len = dirent->rec_len - 12;
7449 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7450 nextdir = (struct ext2_dir_entry *)
7451 ((char *) dirent + 12);
7452 dirent->rec_len = 12;
7453 nextdir->rec_len = new_len;
7455 nextdir->name_len = 0;
7464 * Make sure the second entry in the directory is '..', and that the
7465 * directory entry is sane. We do not check the inode number of '..'
7466 * here; this gets done in pass 3.
7468 static int check_dotdot(e2fsck_t ctx,
7469 struct ext2_dir_entry *dirent,
7470 struct dir_info *dir, struct problem_context *pctx)
7475 problem = PR_2_MISSING_DOT_DOT;
7476 else if (((dirent->name_len & 0xFF) != 2) ||
7477 (dirent->name[0] != '.') ||
7478 (dirent->name[1] != '.'))
7479 problem = PR_2_2ND_NOT_DOT_DOT;
7480 else if (dirent->name[2] != '\0')
7481 problem = PR_2_DOT_DOT_NULL_TERM;
7484 if (fix_problem(ctx, problem, pctx)) {
7485 if (dirent->rec_len < 12)
7486 dirent->rec_len = 12;
7488 * Note: we don't have the parent inode just
7489 * yet, so we will fill it in with the root
7490 * inode. This will get fixed in pass 3.
7492 dirent->inode = EXT2_ROOT_INO;
7493 dirent->name_len = 2;
7494 dirent->name[0] = '.';
7495 dirent->name[1] = '.';
7496 dirent->name[2] = '\0';
7501 dir->dotdot = dirent->inode;
7506 * Check to make sure a directory entry doesn't contain any illegal
7509 static int check_name(e2fsck_t ctx,
7510 struct ext2_dir_entry *dirent,
7511 struct problem_context *pctx)
7517 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7518 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7520 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7523 dirent->name[i] = '.';
7532 * Check the directory filetype (if present)
7536 * Given a mode, return the ext2 file type
7538 static int ext2_file_type(unsigned int mode)
7540 if (LINUX_S_ISREG(mode))
7541 return EXT2_FT_REG_FILE;
7543 if (LINUX_S_ISDIR(mode))
7546 if (LINUX_S_ISCHR(mode))
7547 return EXT2_FT_CHRDEV;
7549 if (LINUX_S_ISBLK(mode))
7550 return EXT2_FT_BLKDEV;
7552 if (LINUX_S_ISLNK(mode))
7553 return EXT2_FT_SYMLINK;
7555 if (LINUX_S_ISFIFO(mode))
7556 return EXT2_FT_FIFO;
7558 if (LINUX_S_ISSOCK(mode))
7559 return EXT2_FT_SOCK;
7564 static _INLINE_ int check_filetype(e2fsck_t ctx,
7565 struct ext2_dir_entry *dirent,
7566 struct problem_context *pctx)
7568 int filetype = dirent->name_len >> 8;
7569 int should_be = EXT2_FT_UNKNOWN;
7570 struct ext2_inode inode;
7572 if (!(ctx->fs->super->s_feature_incompat &
7573 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7574 if (filetype == 0 ||
7575 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7577 dirent->name_len = dirent->name_len & 0xFF;
7581 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7582 should_be = EXT2_FT_DIR;
7583 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7585 should_be = EXT2_FT_REG_FILE;
7586 } else if (ctx->inode_bad_map &&
7587 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7591 e2fsck_read_inode(ctx, dirent->inode, &inode,
7593 should_be = ext2_file_type(inode.i_mode);
7595 if (filetype == should_be)
7597 pctx->num = should_be;
7599 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7603 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7608 static void parse_int_node(ext2_filsys fs,
7609 struct ext2_db_entry *db,
7610 struct check_dir_struct *cd,
7611 struct dx_dir_info *dx_dir,
7614 struct ext2_dx_root_info *root;
7615 struct ext2_dx_entry *ent;
7616 struct ext2_dx_countlimit *limit;
7617 struct dx_dirblock_info *dx_db;
7618 int i, expect_limit, count;
7620 ext2_dirhash_t min_hash = 0xffffffff;
7621 ext2_dirhash_t max_hash = 0;
7622 ext2_dirhash_t hash = 0, prev_hash;
7624 if (db->blockcnt == 0) {
7625 root = (struct ext2_dx_root_info *) (block_buf + 24);
7628 printf("Root node dump:\n");
7629 printf("\t Reserved zero: %d\n", root->reserved_zero);
7630 printf("\t Hash Version: %d\n", root->hash_version);
7631 printf("\t Info length: %d\n", root->info_length);
7632 printf("\t Indirect levels: %d\n", root->indirect_levels);
7633 printf("\t Flags: %d\n", root->unused_flags);
7636 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7638 ent = (struct ext2_dx_entry *) (block_buf+8);
7640 limit = (struct ext2_dx_countlimit *) ent;
7643 printf("Number of entries (count): %d\n",
7644 ext2fs_le16_to_cpu(limit->count));
7645 printf("Number of entries (limit): %d\n",
7646 ext2fs_le16_to_cpu(limit->limit));
7649 count = ext2fs_le16_to_cpu(limit->count);
7650 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7651 sizeof(struct ext2_dx_entry);
7652 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7653 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7654 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7655 goto clear_and_exit;
7657 if (count > expect_limit) {
7658 cd->pctx.num = count;
7659 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7660 goto clear_and_exit;
7661 count = expect_limit;
7664 for (i=0; i < count; i++) {
7666 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7668 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7669 hash, ext2fs_le32_to_cpu(ent[i].block));
7671 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7672 /* Check to make sure the block is valid */
7673 if (blk > (blk_t) dx_dir->numblocks) {
7675 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7677 goto clear_and_exit;
7679 if (hash < prev_hash &&
7680 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7681 goto clear_and_exit;
7682 dx_db = &dx_dir->dx_block[blk];
7683 if (dx_db->flags & DX_FLAG_REFERENCED) {
7684 dx_db->flags |= DX_FLAG_DUP_REF;
7686 dx_db->flags |= DX_FLAG_REFERENCED;
7687 dx_db->parent = db->blockcnt;
7689 if (hash < min_hash)
7691 if (hash > max_hash)
7693 dx_db->node_min_hash = hash;
7695 dx_db->node_max_hash =
7696 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7698 dx_db->node_max_hash = 0xfffffffe;
7699 dx_db->flags |= DX_FLAG_LAST;
7702 dx_db->flags |= DX_FLAG_FIRST;
7705 printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7706 db->blockcnt, min_hash, max_hash);
7708 dx_db = &dx_dir->dx_block[db->blockcnt];
7709 dx_db->min_hash = min_hash;
7710 dx_db->max_hash = max_hash;
7714 clear_htree(cd->ctx, cd->pctx.ino);
7715 dx_dir->numblocks = 0;
7717 #endif /* ENABLE_HTREE */
7720 * Given a busted directory, try to salvage it somehow.
7723 static void salvage_directory(ext2_filsys fs,
7724 struct ext2_dir_entry *dirent,
7725 struct ext2_dir_entry *prev,
7726 unsigned int *offset)
7728 char *cp = (char *) dirent;
7729 int left = fs->blocksize - *offset - dirent->rec_len;
7730 int name_len = dirent->name_len & 0xFF;
7733 * Special case of directory entry of size 8: copy what's left
7734 * of the directory block up to cover up the invalid hole.
7736 if ((left >= 12) && (dirent->rec_len == 8)) {
7737 memmove(cp, cp+8, left);
7738 memset(cp + left, 0, 8);
7742 * If the directory entry overruns the end of the directory
7743 * block, and the name is small enough to fit, then adjust the
7747 (name_len + 8 <= dirent->rec_len + left) &&
7748 dirent->inode <= fs->super->s_inodes_count &&
7749 strnlen(dirent->name, name_len) == name_len) {
7750 dirent->rec_len += left;
7754 * If the directory entry is a multiple of four, so it is
7755 * valid, let the previous directory entry absorb the invalid
7758 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7759 prev->rec_len += dirent->rec_len;
7760 *offset += dirent->rec_len;
7764 * Default salvage method --- kill all of the directory
7765 * entries for the rest of the block. We will either try to
7766 * absorb it into the previous directory entry, or create a
7767 * new empty directory entry the rest of the directory block.
7770 prev->rec_len += fs->blocksize - *offset;
7771 *offset = fs->blocksize;
7773 dirent->rec_len = fs->blocksize - *offset;
7774 dirent->name_len = 0;
7779 static int check_dir_block(ext2_filsys fs,
7780 struct ext2_db_entry *db,
7783 struct dir_info *subdir, *dir;
7784 struct dx_dir_info *dx_dir;
7786 struct dx_dirblock_info *dx_db = 0;
7787 #endif /* ENABLE_HTREE */
7788 struct ext2_dir_entry *dirent, *prev;
7789 ext2_dirhash_t hash;
7790 unsigned int offset = 0;
7791 int dir_modified = 0;
7793 blk_t block_nr = db->blk;
7794 ext2_ino_t ino = db->ino;
7796 struct check_dir_struct *cd;
7800 struct ext2_dx_root_info *root;
7801 struct ext2_dx_countlimit *limit;
7802 static dict_t de_dict;
7803 struct problem_context pctx;
7806 cd = (struct check_dir_struct *) priv_data;
7810 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7811 return DIRENT_ABORT;
7813 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7814 return DIRENT_ABORT;
7817 * Make sure the inode is still in use (could have been
7818 * deleted in the duplicate/bad blocks pass.
7820 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7824 cd->pctx.blk = block_nr;
7825 cd->pctx.blkcount = db->blockcnt;
7827 cd->pctx.dirent = 0;
7831 if (allocate_dir_block(ctx, db, &cd->pctx))
7841 if (ctx->dirs_to_hash &&
7842 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7846 printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7850 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7851 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7852 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7853 if (cd->pctx.errcode) {
7854 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7855 ctx->flags |= E2F_FLAG_ABORT;
7856 return DIRENT_ABORT;
7858 memset(buf, 0, fs->blocksize);
7861 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7862 if (dx_dir && dx_dir->numblocks) {
7863 if (db->blockcnt >= dx_dir->numblocks) {
7864 printf("XXX should never happen!!!\n");
7867 dx_db = &dx_dir->dx_block[db->blockcnt];
7868 dx_db->type = DX_DIRBLOCK_LEAF;
7869 dx_db->phys = block_nr;
7870 dx_db->min_hash = ~0;
7871 dx_db->max_hash = 0;
7873 dirent = (struct ext2_dir_entry *) buf;
7874 limit = (struct ext2_dx_countlimit *) (buf+8);
7875 if (db->blockcnt == 0) {
7876 root = (struct ext2_dx_root_info *) (buf + 24);
7877 dx_db->type = DX_DIRBLOCK_ROOT;
7878 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7879 if ((root->reserved_zero ||
7880 root->info_length < 8 ||
7881 root->indirect_levels > 1) &&
7882 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7883 clear_htree(ctx, ino);
7884 dx_dir->numblocks = 0;
7887 dx_dir->hashversion = root->hash_version;
7888 dx_dir->depth = root->indirect_levels + 1;
7889 } else if ((dirent->inode == 0) &&
7890 (dirent->rec_len == fs->blocksize) &&
7891 (dirent->name_len == 0) &&
7892 (ext2fs_le16_to_cpu(limit->limit) ==
7893 ((fs->blocksize-8) /
7894 sizeof(struct ext2_dx_entry))))
7895 dx_db->type = DX_DIRBLOCK_NODE;
7897 #endif /* ENABLE_HTREE */
7899 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7903 dirent = (struct ext2_dir_entry *) (buf + offset);
7904 cd->pctx.dirent = dirent;
7905 cd->pctx.num = offset;
7906 if (((offset + dirent->rec_len) > fs->blocksize) ||
7907 (dirent->rec_len < 12) ||
7908 ((dirent->rec_len % 4) != 0) ||
7909 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7910 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7911 salvage_directory(fs, dirent, prev, &offset);
7915 goto abort_free_dict;
7917 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7918 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7919 dirent->name_len = EXT2_NAME_LEN;
7924 if (dot_state == 0) {
7925 if (check_dot(ctx, dirent, ino, &cd->pctx))
7927 } else if (dot_state == 1) {
7928 dir = e2fsck_get_dir_info(ctx, ino);
7930 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7931 goto abort_free_dict;
7933 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7935 } else if (dirent->inode == ino) {
7936 problem = PR_2_LINK_DOT;
7937 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7947 * Make sure the inode listed is a legal one.
7949 if (((dirent->inode != EXT2_ROOT_INO) &&
7950 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
7951 (dirent->inode > fs->super->s_inodes_count)) {
7952 problem = PR_2_BAD_INO;
7953 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
7956 * If the inode is unused, offer to clear it.
7958 problem = PR_2_UNUSED_INODE;
7959 } else if (ctx->inode_bb_map &&
7960 (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
7963 * If the inode is in a bad block, offer to
7966 problem = PR_2_BB_INODE;
7967 } else if ((dot_state > 1) &&
7968 ((dirent->name_len & 0xFF) == 1) &&
7969 (dirent->name[0] == '.')) {
7971 * If there's a '.' entry in anything other
7972 * than the first directory entry, it's a
7973 * duplicate entry that should be removed.
7975 problem = PR_2_DUP_DOT;
7976 } else if ((dot_state > 1) &&
7977 ((dirent->name_len & 0xFF) == 2) &&
7978 (dirent->name[0] == '.') &&
7979 (dirent->name[1] == '.')) {
7981 * If there's a '..' entry in anything other
7982 * than the second directory entry, it's a
7983 * duplicate entry that should be removed.
7985 problem = PR_2_DUP_DOT_DOT;
7986 } else if ((dot_state > 1) &&
7987 (dirent->inode == EXT2_ROOT_INO)) {
7989 * Don't allow links to the root directory.
7990 * We check this specially to make sure we
7991 * catch this error case even if the root
7992 * directory hasn't been created yet.
7994 problem = PR_2_LINK_ROOT;
7995 } else if ((dot_state > 1) &&
7996 (dirent->name_len & 0xFF) == 0) {
7998 * Don't allow zero-length directory names.
8000 problem = PR_2_NULL_NAME;
8004 if (fix_problem(ctx, problem, &cd->pctx)) {
8009 ext2fs_unmark_valid(fs);
8010 if (problem == PR_2_BAD_INO)
8016 * If the inode was marked as having bad fields in
8017 * pass1, process it and offer to fix/clear it.
8018 * (We wait until now so that we can display the
8019 * pathname to the user.)
8021 if (ctx->inode_bad_map &&
8022 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8024 if (e2fsck_process_bad_inode(ctx, ino,
8026 buf + fs->blocksize)) {
8031 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8032 return DIRENT_ABORT;
8035 if (check_name(ctx, dirent, &cd->pctx))
8038 if (check_filetype(ctx, dirent, &cd->pctx))
8043 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8044 (dirent->name_len & 0xFF),
8045 fs->super->s_hash_seed, &hash, 0);
8046 if (hash < dx_db->min_hash)
8047 dx_db->min_hash = hash;
8048 if (hash > dx_db->max_hash)
8049 dx_db->max_hash = hash;
8054 * If this is a directory, then mark its parent in its
8055 * dir_info structure. If the parent field is already
8056 * filled in, then this directory has more than one
8057 * hard link. We assume the first link is correct,
8058 * and ask the user if he/she wants to clear this one.
8060 if ((dot_state > 1) &&
8061 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8063 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8065 cd->pctx.ino = dirent->inode;
8066 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8067 goto abort_free_dict;
8069 if (subdir->parent) {
8070 cd->pctx.ino2 = subdir->parent;
8071 if (fix_problem(ctx, PR_2_LINK_DIR,
8079 subdir->parent = ino;
8084 } else if (dict_lookup(&de_dict, dirent)) {
8085 clear_problem_context(&pctx);
8087 pctx.dirent = dirent;
8088 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8089 if (!ctx->dirs_to_hash)
8090 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8091 if (ctx->dirs_to_hash)
8092 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8095 dict_alloc_insert(&de_dict, dirent, dirent);
8097 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8100 ctx->fs_links_count++;
8101 ctx->fs_total_count++;
8104 offset += dirent->rec_len;
8106 } while (offset < fs->blocksize);
8113 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8114 db->blockcnt, dx_db->type,
8115 dx_db->min_hash, dx_db->max_hash);
8117 cd->pctx.dir = cd->pctx.ino;
8118 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8119 (dx_db->type == DX_DIRBLOCK_NODE))
8120 parse_int_node(fs, db, cd, dx_dir, buf);
8122 #endif /* ENABLE_HTREE */
8123 if (offset != fs->blocksize) {
8124 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8125 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8126 dirent->rec_len = cd->pctx.num;
8131 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8132 if (cd->pctx.errcode) {
8133 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8135 goto abort_free_dict;
8137 ext2fs_mark_changed(fs);
8139 dict_free_nodes(&de_dict);
8142 dict_free_nodes(&de_dict);
8143 ctx->flags |= E2F_FLAG_ABORT;
8144 return DIRENT_ABORT;
8148 * This function is called to deallocate a block, and is an interator
8149 * functioned called by deallocate inode via ext2fs_iterate_block().
8151 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8152 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
8153 blk_t ref_block FSCK_ATTR((unused)),
8154 int ref_offset FSCK_ATTR((unused)),
8157 e2fsck_t ctx = (e2fsck_t) priv_data;
8159 if (HOLE_BLKADDR(*block_nr))
8161 if ((*block_nr < fs->super->s_first_data_block) ||
8162 (*block_nr >= fs->super->s_blocks_count))
8164 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8165 ext2fs_block_alloc_stats(fs, *block_nr, -1);
8170 * This fuction deallocates an inode
8172 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8174 ext2_filsys fs = ctx->fs;
8175 struct ext2_inode inode;
8176 struct problem_context pctx;
8179 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8180 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8181 inode.i_links_count = 0;
8182 inode.i_dtime = time(0);
8183 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8184 clear_problem_context(&pctx);
8188 * Fix up the bitmaps...
8190 e2fsck_read_bitmaps(ctx);
8191 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8192 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8193 if (ctx->inode_bad_map)
8194 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8195 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8197 if (inode.i_file_acl &&
8198 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8199 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8200 block_buf, -1, &count);
8201 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8206 pctx.blk = inode.i_file_acl;
8207 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8208 ctx->flags |= E2F_FLAG_ABORT;
8212 ext2fs_unmark_block_bitmap(ctx->block_found_map,
8214 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8216 inode.i_file_acl = 0;
8219 if (!ext2fs_inode_has_valid_blocks(&inode))
8222 if (LINUX_S_ISREG(inode.i_mode) &&
8223 (inode.i_size_high || inode.i_size & 0x80000000UL))
8226 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8227 deallocate_inode_block, ctx);
8229 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8230 ctx->flags |= E2F_FLAG_ABORT;
8236 * This fuction clears the htree flag on an inode
8238 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8240 struct ext2_inode inode;
8242 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8243 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8244 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8245 if (ctx->dirs_to_hash)
8246 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8250 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8251 ext2_ino_t ino, char *buf)
8253 ext2_filsys fs = ctx->fs;
8254 struct ext2_inode inode;
8255 int inode_modified = 0;
8257 unsigned char *frag, *fsize;
8258 struct problem_context pctx;
8261 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8263 clear_problem_context(&pctx);
8266 pctx.inode = &inode;
8268 if (inode.i_file_acl &&
8269 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8270 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8271 inode.i_file_acl = 0;
8272 #ifdef EXT2FS_ENABLE_SWAPFS
8274 * This is a special kludge to deal with long symlinks
8275 * on big endian systems. i_blocks had already been
8276 * decremented earlier in pass 1, but since i_file_acl
8277 * hadn't yet been cleared, ext2fs_read_inode()
8278 * assumed that the file was short symlink and would
8279 * not have byte swapped i_block[0]. Hence, we have
8280 * to byte-swap it here.
8282 if (LINUX_S_ISLNK(inode.i_mode) &&
8283 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8284 (inode.i_blocks == fs->blocksize >> 9))
8285 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8291 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8292 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8293 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8294 !(LINUX_S_ISSOCK(inode.i_mode)))
8295 problem = PR_2_BAD_MODE;
8296 else if (LINUX_S_ISCHR(inode.i_mode)
8297 && !e2fsck_pass1_check_device_inode(fs, &inode))
8298 problem = PR_2_BAD_CHAR_DEV;
8299 else if (LINUX_S_ISBLK(inode.i_mode)
8300 && !e2fsck_pass1_check_device_inode(fs, &inode))
8301 problem = PR_2_BAD_BLOCK_DEV;
8302 else if (LINUX_S_ISFIFO(inode.i_mode)
8303 && !e2fsck_pass1_check_device_inode(fs, &inode))
8304 problem = PR_2_BAD_FIFO;
8305 else if (LINUX_S_ISSOCK(inode.i_mode)
8306 && !e2fsck_pass1_check_device_inode(fs, &inode))
8307 problem = PR_2_BAD_SOCKET;
8308 else if (LINUX_S_ISLNK(inode.i_mode)
8309 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8310 problem = PR_2_INVALID_SYMLINK;
8314 if (fix_problem(ctx, problem, &pctx)) {
8315 deallocate_inode(ctx, ino, 0);
8316 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8324 if (inode.i_faddr) {
8325 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8332 switch (fs->super->s_creator_os) {
8334 frag = &inode.osd2.linux2.l_i_frag;
8335 fsize = &inode.osd2.linux2.l_i_fsize;
8338 frag = &inode.osd2.hurd2.h_i_frag;
8339 fsize = &inode.osd2.hurd2.h_i_fsize;
8342 frag = &inode.osd2.masix2.m_i_frag;
8343 fsize = &inode.osd2.masix2.m_i_fsize;
8348 if (frag && *frag) {
8350 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8357 if (fsize && *fsize) {
8359 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8367 if (inode.i_file_acl &&
8368 ((inode.i_file_acl < fs->super->s_first_data_block) ||
8369 (inode.i_file_acl >= fs->super->s_blocks_count))) {
8370 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8371 inode.i_file_acl = 0;
8376 if (inode.i_dir_acl &&
8377 LINUX_S_ISDIR(inode.i_mode)) {
8378 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8379 inode.i_dir_acl = 0;
8386 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8388 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8394 * allocate_dir_block --- this function allocates a new directory
8395 * block for a particular inode; this is done if a directory has
8396 * a "hole" in it, or if a directory has a illegal block number
8397 * that was zeroed out and now needs to be replaced.
8399 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8400 struct problem_context *pctx)
8402 ext2_filsys fs = ctx->fs;
8405 struct ext2_inode inode;
8407 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8411 * Read the inode and block bitmaps in; we'll be messing with
8414 e2fsck_read_bitmaps(ctx);
8417 * First, find a free block
8419 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8420 if (pctx->errcode) {
8421 pctx->str = "ext2fs_new_block";
8422 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8425 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8426 ext2fs_mark_block_bitmap(fs->block_map, blk);
8427 ext2fs_mark_bb_dirty(fs);
8430 * Now let's create the actual data block for the inode
8433 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8435 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8436 EXT2_ROOT_INO, &block);
8438 if (pctx->errcode) {
8439 pctx->str = "ext2fs_new_dir_block";
8440 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8444 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8445 ext2fs_free_mem(&block);
8446 if (pctx->errcode) {
8447 pctx->str = "ext2fs_write_dir_block";
8448 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8453 * Update the inode block count
8455 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8456 inode.i_blocks += fs->blocksize / 512;
8457 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8458 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8459 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8462 * Finally, update the block pointers for the inode
8465 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8466 0, update_dir_block, db);
8467 if (pctx->errcode) {
8468 pctx->str = "ext2fs_block_iterate";
8469 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8477 * This is a helper function for allocate_dir_block().
8479 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8481 e2_blkcnt_t blockcnt,
8482 blk_t ref_block FSCK_ATTR((unused)),
8483 int ref_offset FSCK_ATTR((unused)),
8486 struct ext2_db_entry *db;
8488 db = (struct ext2_db_entry *) priv_data;
8489 if (db->blockcnt == (int) blockcnt) {
8490 *block_nr = db->blk;
8491 return BLOCK_CHANGED;
8497 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8499 * Pass #3 assures that all directories are connected to the
8500 * filesystem tree, using the following algorithm:
8502 * First, the root directory is checked to make sure it exists; if
8503 * not, e2fsck will offer to create a new one. It is then marked as
8506 * Then, pass3 interates over all directory inodes; for each directory
8507 * it attempts to trace up the filesystem tree, using dirinfo.parent
8508 * until it reaches a directory which has been marked "done". If it
8509 * can not do so, then the directory must be disconnected, and e2fsck
8510 * will offer to reconnect it to /lost+found. While it is chasing
8511 * parent pointers up the filesystem tree, if pass3 sees a directory
8512 * twice, then it has detected a filesystem loop, and it will again
8513 * offer to reconnect the directory to /lost+found in to break the
8516 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8517 * reconnect inodes to /lost+found; this subroutine is also used by
8518 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
8519 * is responsible for creating /lost+found if it does not exist.
8521 * Pass 3 frees the following data structures:
8522 * - The dirinfo directory information cache.
8525 static void check_root(e2fsck_t ctx);
8526 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8527 struct problem_context *pctx);
8528 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8530 static ext2fs_inode_bitmap inode_loop_detect;
8531 static ext2fs_inode_bitmap inode_done_map;
8533 static void e2fsck_pass3(e2fsck_t ctx)
8535 ext2_filsys fs = ctx->fs;
8537 #ifdef RESOURCE_TRACK
8538 struct resource_track rtrack;
8540 struct problem_context pctx;
8541 struct dir_info *dir;
8542 unsigned long maxdirs, count;
8544 #ifdef RESOURCE_TRACK
8545 init_resource_track(&rtrack);
8548 clear_problem_context(&pctx);
8551 mtrace_print("Pass 3");
8554 if (!(ctx->options & E2F_OPT_PREEN))
8555 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8558 * Allocate some bitmaps to do loop detection.
8560 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8564 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8565 ctx->flags |= E2F_FLAG_ABORT;
8568 #ifdef RESOURCE_TRACK
8569 if (ctx->options & E2F_OPT_TIME) {
8570 e2fsck_clear_progbar(ctx);
8571 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8576 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8579 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8581 maxdirs = e2fsck_get_num_dirinfo(ctx);
8585 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8588 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8589 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8591 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8593 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8594 if (check_directory(ctx, dir, &pctx))
8599 * Force the creation of /lost+found if not present
8601 if ((ctx->flags & E2F_OPT_READONLY) == 0)
8602 e2fsck_get_lost_and_found(ctx, 1);
8605 * If there are any directories that need to be indexed or
8606 * optimized, do it here.
8608 e2fsck_rehash_directories(ctx);
8611 e2fsck_free_dir_info(ctx);
8612 ext2fs_free_inode_bitmap(inode_loop_detect);
8613 inode_loop_detect = 0;
8614 ext2fs_free_inode_bitmap(inode_done_map);
8617 #ifdef RESOURCE_TRACK
8618 if (ctx->options & E2F_OPT_TIME2) {
8619 e2fsck_clear_progbar(ctx);
8620 print_resource_track(_("Pass 3"), &rtrack);
8626 * This makes sure the root inode is present; if not, we ask if the
8627 * user wants us to create it. Not creating it is a fatal error.
8629 static void check_root(e2fsck_t ctx)
8631 ext2_filsys fs = ctx->fs;
8633 struct ext2_inode inode;
8635 struct problem_context pctx;
8637 clear_problem_context(&pctx);
8639 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8641 * If the root inode is not a directory, die here. The
8642 * user must have answered 'no' in pass1 when we
8643 * offered to clear it.
8645 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8647 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8648 ctx->flags |= E2F_FLAG_ABORT;
8653 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8654 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8655 ctx->flags |= E2F_FLAG_ABORT;
8659 e2fsck_read_bitmaps(ctx);
8662 * First, find a free block
8664 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8666 pctx.str = "ext2fs_new_block";
8667 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8668 ctx->flags |= E2F_FLAG_ABORT;
8671 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8672 ext2fs_mark_block_bitmap(fs->block_map, blk);
8673 ext2fs_mark_bb_dirty(fs);
8676 * Now let's create the actual data block for the inode
8678 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8681 pctx.str = "ext2fs_new_dir_block";
8682 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8683 ctx->flags |= E2F_FLAG_ABORT;
8687 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8689 pctx.str = "ext2fs_write_dir_block";
8690 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8691 ctx->flags |= E2F_FLAG_ABORT;
8694 ext2fs_free_mem(&block);
8697 * Set up the inode structure
8699 memset(&inode, 0, sizeof(inode));
8700 inode.i_mode = 040755;
8701 inode.i_size = fs->blocksize;
8702 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8703 inode.i_links_count = 2;
8704 inode.i_blocks = fs->blocksize / 512;
8705 inode.i_block[0] = blk;
8708 * Write out the inode.
8710 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8712 pctx.str = "ext2fs_write_inode";
8713 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8714 ctx->flags |= E2F_FLAG_ABORT;
8719 * Miscellaneous bookkeeping...
8721 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8722 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8723 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8725 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8726 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8727 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8728 ext2fs_mark_ib_dirty(fs);
8732 * This subroutine is responsible for making sure that a particular
8733 * directory is connected to the root; if it isn't we trace it up as
8734 * far as we can go, and then offer to connect the resulting parent to
8735 * the lost+found. We have to do loop detection; if we ever discover
8736 * a loop, we treat that as a disconnected directory and offer to
8737 * reparent it to lost+found.
8739 * However, loop detection is expensive, because for very large
8740 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8741 * is non-trivial. Loops in filesystems are also a rare error case,
8742 * and we shouldn't optimize for error cases. So we try two passes of
8743 * the algorithm. The first time, we ignore loop detection and merely
8744 * increment a counter; if the counter exceeds some extreme threshold,
8745 * then we try again with the loop detection bitmap enabled.
8747 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8748 struct problem_context *pctx)
8750 ext2_filsys fs = ctx->fs;
8751 struct dir_info *p = dir;
8752 int loop_pass = 0, parent_count = 0;
8759 * Mark this inode as being "done"; by the time we
8760 * return from this function, the inode we either be
8761 * verified as being connected to the directory tree,
8762 * or we will have offered to reconnect this to
8765 * If it was marked done already, then we've reached a
8766 * parent we've already checked.
8768 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8772 * If this directory doesn't have a parent, or we've
8773 * seen the parent once already, then offer to
8774 * reparent it to lost+found
8778 (ext2fs_test_inode_bitmap(inode_loop_detect,
8781 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8782 if (e2fsck_reconnect_file(ctx, pctx->ino))
8783 ext2fs_unmark_valid(fs);
8785 p = e2fsck_get_dir_info(ctx, pctx->ino);
8786 p->parent = ctx->lost_and_found;
8787 fix_dotdot(ctx, p, ctx->lost_and_found);
8792 p = e2fsck_get_dir_info(ctx, p->parent);
8794 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8798 ext2fs_mark_inode_bitmap(inode_loop_detect,
8800 } else if (parent_count++ > 2048) {
8802 * If we've run into a path depth that's
8803 * greater than 2048, try again with the inode
8804 * loop bitmap turned on and start from the
8808 if (inode_loop_detect)
8809 ext2fs_clear_inode_bitmap(inode_loop_detect);
8811 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8812 if (pctx->errcode) {
8815 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8816 ctx->flags |= E2F_FLAG_ABORT;
8825 * Make sure that .. and the parent directory are the same;
8826 * offer to fix it if not.
8828 if (dir->parent != dir->dotdot) {
8829 pctx->ino = dir->ino;
8830 pctx->ino2 = dir->dotdot;
8831 pctx->dir = dir->parent;
8832 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8833 fix_dotdot(ctx, dir, dir->parent);
8839 * This routine gets the lost_and_found inode, making it a directory
8842 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8844 ext2_filsys fs = ctx->fs;
8848 struct ext2_inode inode;
8850 static const char name[] = "lost+found";
8851 struct problem_context pctx;
8852 struct dir_info *dirinfo;
8854 if (ctx->lost_and_found)
8855 return ctx->lost_and_found;
8857 clear_problem_context(&pctx);
8859 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8860 sizeof(name)-1, 0, &ino);
8864 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8865 ctx->lost_and_found = ino;
8869 /* Lost+found isn't a directory! */
8873 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8876 /* OK, unlink the old /lost+found file. */
8877 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8879 pctx.str = "ext2fs_unlink";
8880 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8883 dirinfo = e2fsck_get_dir_info(ctx, ino);
8885 dirinfo->parent = 0;
8886 e2fsck_adjust_inode_count(ctx, ino, -1);
8887 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8888 pctx.errcode = retval;
8889 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8891 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8895 * Read the inode and block bitmaps in; we'll be messing with
8898 e2fsck_read_bitmaps(ctx);
8901 * First, find a free block
8903 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8905 pctx.errcode = retval;
8906 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8909 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8910 ext2fs_block_alloc_stats(fs, blk, +1);
8913 * Next find a free inode.
8915 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8916 ctx->inode_used_map, &ino);
8918 pctx.errcode = retval;
8919 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8922 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8923 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8924 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8927 * Now let's create the actual data block for the inode
8929 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8931 pctx.errcode = retval;
8932 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8936 retval = ext2fs_write_dir_block(fs, blk, block);
8937 ext2fs_free_mem(&block);
8939 pctx.errcode = retval;
8940 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
8945 * Set up the inode structure
8947 memset(&inode, 0, sizeof(inode));
8948 inode.i_mode = 040700;
8949 inode.i_size = fs->blocksize;
8950 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8951 inode.i_links_count = 2;
8952 inode.i_blocks = fs->blocksize / 512;
8953 inode.i_block[0] = blk;
8956 * Next, write out the inode.
8958 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
8960 pctx.str = "ext2fs_write_inode";
8961 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8965 * Finally, create the directory link
8967 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
8969 pctx.str = "ext2fs_link";
8970 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8975 * Miscellaneous bookkeeping that needs to be kept straight.
8977 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
8978 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
8979 ext2fs_icount_store(ctx->inode_count, ino, 2);
8980 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
8981 ctx->lost_and_found = ino;
8983 printf("/lost+found created; inode #%lu\n", ino);
8989 * This routine will connect a file to lost+found
8991 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
8993 ext2_filsys fs = ctx->fs;
8996 struct problem_context pctx;
8997 struct ext2_inode inode;
9000 clear_problem_context(&pctx);
9003 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9004 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9005 ctx->bad_lost_and_found++;
9007 if (ctx->bad_lost_and_found) {
9008 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9012 sprintf(name, "#%u", ino);
9013 if (ext2fs_read_inode(fs, ino, &inode) == 0)
9014 file_type = ext2_file_type(inode.i_mode);
9015 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9016 if (retval == EXT2_ET_DIR_NO_SPACE) {
9017 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9019 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9022 pctx.errcode = retval;
9023 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9026 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9030 pctx.errcode = retval;
9031 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9034 e2fsck_adjust_inode_count(ctx, ino, 1);
9040 * Utility routine to adjust the inode counts on an inode.
9042 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9044 ext2_filsys fs = ctx->fs;
9046 struct ext2_inode inode;
9051 retval = ext2fs_read_inode(fs, ino, &inode);
9056 printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9057 inode.i_links_count);
9061 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9062 if (inode.i_links_count == (__u16) ~0)
9064 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9065 inode.i_links_count++;
9066 } else if (adj == -1) {
9067 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9068 if (inode.i_links_count == 0)
9070 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9071 inode.i_links_count--;
9074 retval = ext2fs_write_inode(fs, ino, &inode);
9082 * Fix parent --- this routine fixes up the parent of a directory.
9084 struct fix_dotdot_struct {
9091 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9092 int offset FSCK_ATTR((unused)),
9093 int blocksize FSCK_ATTR((unused)),
9094 char *buf FSCK_ATTR((unused)),
9097 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9099 struct problem_context pctx;
9101 if ((dirent->name_len & 0xFF) != 2)
9103 if (strncmp(dirent->name, "..", 2))
9106 clear_problem_context(&pctx);
9108 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9110 pctx.errcode = retval;
9111 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9113 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9115 pctx.errcode = retval;
9116 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9118 dirent->inode = fp->parent;
9121 return DIRENT_ABORT | DIRENT_CHANGED;
9124 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9126 ext2_filsys fs = ctx->fs;
9128 struct fix_dotdot_struct fp;
9129 struct problem_context pctx;
9137 printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9140 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9141 0, fix_dotdot_proc, &fp);
9142 if (retval || !fp.done) {
9143 clear_problem_context(&pctx);
9144 pctx.ino = dir->ino;
9145 pctx.errcode = retval;
9146 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9147 PR_3_FIX_PARENT_NOFIND, &pctx);
9148 ext2fs_unmark_valid(fs);
9150 dir->dotdot = parent;
9156 * These routines are responsible for expanding a /lost+found if it is
9160 struct expand_dir_struct {
9162 int guaranteed_size;
9169 static int expand_dir_proc(ext2_filsys fs,
9171 e2_blkcnt_t blockcnt,
9172 blk_t ref_block FSCK_ATTR((unused)),
9173 int ref_offset FSCK_ATTR((unused)),
9176 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9178 static blk_t last_blk = 0;
9185 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9189 es->last_block = blockcnt;
9191 last_blk = *blocknr;
9194 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9201 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9207 retval = ext2fs_write_dir_block(fs, new_blk, block);
9209 retval = ext2fs_get_mem(fs->blocksize, &block);
9214 memset(block, 0, fs->blocksize);
9215 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9221 ext2fs_free_mem(&block);
9223 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9224 ext2fs_block_alloc_stats(fs, new_blk, +1);
9228 return (BLOCK_CHANGED | BLOCK_ABORT);
9230 return BLOCK_CHANGED;
9233 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9234 int num, int guaranteed_size)
9236 ext2_filsys fs = ctx->fs;
9238 struct expand_dir_struct es;
9239 struct ext2_inode inode;
9241 if (!(fs->flags & EXT2_FLAG_RW))
9242 return EXT2_ET_RO_FILSYS;
9245 * Read the inode and block bitmaps in; we'll be messing with
9248 e2fsck_read_bitmaps(ctx);
9250 retval = ext2fs_check_directory(fs, dir);
9255 es.guaranteed_size = guaranteed_size;
9261 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9262 0, expand_dir_proc, &es);
9268 * Update the size and block count fields in the inode.
9270 retval = ext2fs_read_inode(fs, dir, &inode);
9274 inode.i_size = (es.last_block + 1) * fs->blocksize;
9275 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9277 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9283 * pass4.c -- pass #4 of e2fsck: Check reference counts
9285 * Pass 4 frees the following data structures:
9286 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
9287 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
9291 * This routine is called when an inode is not connected to the
9294 * This subroutine returns 1 then the caller shouldn't bother with the
9295 * rest of the pass 4 tests.
9297 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9299 ext2_filsys fs = ctx->fs;
9300 struct ext2_inode inode;
9301 struct problem_context pctx;
9303 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9304 clear_problem_context(&pctx);
9306 pctx.inode = &inode;
9309 * Offer to delete any zero-length files that does not have
9310 * blocks. If there is an EA block, it might have useful
9311 * information, so we won't prompt to delete it, but let it be
9312 * reconnected to lost+found.
9314 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9315 LINUX_S_ISDIR(inode.i_mode))) {
9316 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9317 ext2fs_icount_store(ctx->inode_link_info, i, 0);
9318 inode.i_links_count = 0;
9319 inode.i_dtime = time(0);
9320 e2fsck_write_inode(ctx, i, &inode,
9321 "disconnect_inode");
9323 * Fix up the bitmaps...
9325 e2fsck_read_bitmaps(ctx);
9326 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9327 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9328 ext2fs_inode_alloc_stats2(fs, i, -1,
9329 LINUX_S_ISDIR(inode.i_mode));
9335 * Prompt to reconnect.
9337 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9338 if (e2fsck_reconnect_file(ctx, i))
9339 ext2fs_unmark_valid(fs);
9342 * If we don't attach the inode, then skip the
9343 * i_links_test since there's no point in trying to
9344 * force i_links_count to zero.
9346 ext2fs_unmark_valid(fs);
9353 static void e2fsck_pass4(e2fsck_t ctx)
9355 ext2_filsys fs = ctx->fs;
9357 struct ext2_inode inode;
9358 #ifdef RESOURCE_TRACK
9359 struct resource_track rtrack;
9361 struct problem_context pctx;
9362 __u16 link_count, link_counted;
9364 int group, maxgroup;
9366 #ifdef RESOURCE_TRACK
9367 init_resource_track(&rtrack);
9371 mtrace_print("Pass 4");
9374 clear_problem_context(&pctx);
9376 if (!(ctx->options & E2F_OPT_PREEN))
9377 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9380 maxgroup = fs->group_desc_count;
9382 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9385 for (i=1; i <= fs->super->s_inodes_count; i++) {
9386 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9388 if ((i % fs->super->s_inodes_per_group) == 0) {
9391 if ((ctx->progress)(ctx, 4, group, maxgroup))
9394 if (i == EXT2_BAD_INO ||
9395 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9397 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9398 (ctx->inode_imagic_map &&
9399 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9400 (ctx->inode_bb_map &&
9401 ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9403 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9404 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9405 if (link_counted == 0) {
9407 buf = e2fsck_allocate_memory(ctx,
9408 fs->blocksize, "bad_inode buffer");
9409 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9411 if (disconnect_inode(ctx, i))
9413 ext2fs_icount_fetch(ctx->inode_link_info, i,
9415 ext2fs_icount_fetch(ctx->inode_count, i,
9418 if (link_counted != link_count) {
9419 e2fsck_read_inode(ctx, i, &inode, "pass4");
9421 pctx.inode = &inode;
9422 if (link_count != inode.i_links_count) {
9423 pctx.num = link_count;
9425 PR_4_INCONSISTENT_COUNT, &pctx);
9427 pctx.num = link_counted;
9428 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9429 inode.i_links_count = link_counted;
9430 e2fsck_write_inode(ctx, i, &inode, "pass4");
9434 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9435 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9436 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9437 ctx->inode_bb_map = 0;
9438 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9439 ctx->inode_imagic_map = 0;
9440 ext2fs_free_mem(&buf);
9441 #ifdef RESOURCE_TRACK
9442 if (ctx->options & E2F_OPT_TIME2) {
9443 e2fsck_clear_progbar(ctx);
9444 print_resource_track(_("Pass 4"), &rtrack);
9450 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9453 #define NO_BLK ((blk_t) -1)
9455 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9456 struct problem_context *pctx)
9459 case PR_5_BLOCK_UNUSED:
9460 if (pctx->blk == pctx->blk2)
9463 problem = PR_5_BLOCK_RANGE_UNUSED;
9465 case PR_5_BLOCK_USED:
9466 if (pctx->blk == pctx->blk2)
9469 problem = PR_5_BLOCK_RANGE_USED;
9471 case PR_5_INODE_UNUSED:
9472 if (pctx->ino == pctx->ino2)
9475 problem = PR_5_INODE_RANGE_UNUSED;
9477 case PR_5_INODE_USED:
9478 if (pctx->ino == pctx->ino2)
9481 problem = PR_5_INODE_RANGE_USED;
9484 fix_problem(ctx, problem, pctx);
9485 pctx->blk = pctx->blk2 = NO_BLK;
9486 pctx->ino = pctx->ino2 = 0;
9489 static void check_block_bitmaps(e2fsck_t ctx)
9491 ext2_filsys fs = ctx->fs;
9495 unsigned int blocks = 0;
9496 unsigned int free_blocks = 0;
9499 struct problem_context pctx;
9500 int problem, save_problem, fixit, had_problem;
9503 clear_problem_context(&pctx);
9504 free_array = (int *) e2fsck_allocate_memory(ctx,
9505 fs->group_desc_count * sizeof(int), "free block count array");
9507 if ((fs->super->s_first_data_block <
9508 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9509 (fs->super->s_blocks_count-1 >
9510 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9512 pctx.blk = fs->super->s_first_data_block;
9513 pctx.blk2 = fs->super->s_blocks_count -1;
9514 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9515 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9516 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9518 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9522 if ((fs->super->s_first_data_block <
9523 ext2fs_get_block_bitmap_start(fs->block_map)) ||
9524 (fs->super->s_blocks_count-1 >
9525 ext2fs_get_block_bitmap_end(fs->block_map))) {
9527 pctx.blk = fs->super->s_first_data_block;
9528 pctx.blk2 = fs->super->s_blocks_count -1;
9529 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9530 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9531 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9533 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9540 pctx.blk = pctx.blk2 = NO_BLK;
9541 for (i = fs->super->s_first_data_block;
9542 i < fs->super->s_blocks_count;
9544 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9545 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9547 if (actual == bitmap)
9550 if (!actual && bitmap) {
9552 * Block not used, but marked in use in the bitmap.
9554 problem = PR_5_BLOCK_UNUSED;
9557 * Block used, but not marked in use in the bitmap.
9559 problem = PR_5_BLOCK_USED;
9561 if (pctx.blk == NO_BLK) {
9562 pctx.blk = pctx.blk2 = i;
9563 save_problem = problem;
9565 if ((problem == save_problem) &&
9569 print_bitmap_problem(ctx, save_problem, &pctx);
9570 pctx.blk = pctx.blk2 = i;
9571 save_problem = problem;
9574 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9583 if ((blocks == fs->super->s_blocks_per_group) ||
9584 (i == fs->super->s_blocks_count-1)) {
9585 free_array[group] = group_free;
9590 if ((ctx->progress)(ctx, 5, group,
9591 fs->group_desc_count*2))
9595 if (pctx.blk != NO_BLK)
9596 print_bitmap_problem(ctx, save_problem, &pctx);
9598 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9601 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9604 ext2fs_free_block_bitmap(fs->block_map);
9605 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9608 clear_problem_context(&pctx);
9609 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9610 ctx->flags |= E2F_FLAG_ABORT;
9613 ext2fs_set_bitmap_padding(fs->block_map);
9614 ext2fs_mark_bb_dirty(fs);
9616 /* Redo the counts */
9617 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9618 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9620 } else if (fixit == 0)
9621 ext2fs_unmark_valid(fs);
9623 for (i = 0; i < fs->group_desc_count; i++) {
9624 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9626 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9627 pctx.blk2 = free_array[i];
9629 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9631 fs->group_desc[i].bg_free_blocks_count =
9633 ext2fs_mark_super_dirty(fs);
9635 ext2fs_unmark_valid(fs);
9638 if (free_blocks != fs->super->s_free_blocks_count) {
9640 pctx.blk = fs->super->s_free_blocks_count;
9641 pctx.blk2 = free_blocks;
9643 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9644 fs->super->s_free_blocks_count = free_blocks;
9645 ext2fs_mark_super_dirty(fs);
9647 ext2fs_unmark_valid(fs);
9649 ext2fs_free_mem(&free_array);
9652 static void check_inode_bitmaps(e2fsck_t ctx)
9654 ext2_filsys fs = ctx->fs;
9656 unsigned int free_inodes = 0;
9660 unsigned int inodes = 0;
9665 struct problem_context pctx;
9666 int problem, save_problem, fixit, had_problem;
9668 clear_problem_context(&pctx);
9669 free_array = (int *) e2fsck_allocate_memory(ctx,
9670 fs->group_desc_count * sizeof(int), "free inode count array");
9672 dir_array = (int *) e2fsck_allocate_memory(ctx,
9673 fs->group_desc_count * sizeof(int), "directory count array");
9675 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9676 (fs->super->s_inodes_count >
9677 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9680 pctx.blk2 = fs->super->s_inodes_count;
9681 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9682 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9683 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9685 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9688 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9689 (fs->super->s_inodes_count >
9690 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9693 pctx.blk2 = fs->super->s_inodes_count;
9694 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9695 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9696 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9698 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9705 pctx.ino = pctx.ino2 = 0;
9706 for (i = 1; i <= fs->super->s_inodes_count; i++) {
9707 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9708 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9710 if (actual == bitmap)
9713 if (!actual && bitmap) {
9715 * Inode wasn't used, but marked in bitmap
9717 problem = PR_5_INODE_UNUSED;
9718 } else /* if (actual && !bitmap) */ {
9720 * Inode used, but not in bitmap
9722 problem = PR_5_INODE_USED;
9724 if (pctx.ino == 0) {
9725 pctx.ino = pctx.ino2 = i;
9726 save_problem = problem;
9728 if ((problem == save_problem) &&
9732 print_bitmap_problem(ctx, save_problem, &pctx);
9733 pctx.ino = pctx.ino2 = i;
9734 save_problem = problem;
9737 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9745 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9749 if ((inodes == fs->super->s_inodes_per_group) ||
9750 (i == fs->super->s_inodes_count)) {
9751 free_array[group] = group_free;
9752 dir_array[group] = dirs_count;
9758 if ((ctx->progress)(ctx, 5,
9759 group + fs->group_desc_count,
9760 fs->group_desc_count*2))
9765 print_bitmap_problem(ctx, save_problem, &pctx);
9768 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9771 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9774 ext2fs_free_inode_bitmap(fs->inode_map);
9775 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9778 clear_problem_context(&pctx);
9779 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9780 ctx->flags |= E2F_FLAG_ABORT;
9783 ext2fs_set_bitmap_padding(fs->inode_map);
9784 ext2fs_mark_ib_dirty(fs);
9787 inodes = 0; free_inodes = 0; group_free = 0;
9788 dirs_count = 0; group = 0;
9789 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9790 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9792 } else if (fixit == 0)
9793 ext2fs_unmark_valid(fs);
9795 for (i = 0; i < fs->group_desc_count; i++) {
9796 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9798 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9799 pctx.ino2 = free_array[i];
9800 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9802 fs->group_desc[i].bg_free_inodes_count =
9804 ext2fs_mark_super_dirty(fs);
9806 ext2fs_unmark_valid(fs);
9808 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9810 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9811 pctx.ino2 = dir_array[i];
9813 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9815 fs->group_desc[i].bg_used_dirs_count =
9817 ext2fs_mark_super_dirty(fs);
9819 ext2fs_unmark_valid(fs);
9822 if (free_inodes != fs->super->s_free_inodes_count) {
9824 pctx.ino = fs->super->s_free_inodes_count;
9825 pctx.ino2 = free_inodes;
9827 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9828 fs->super->s_free_inodes_count = free_inodes;
9829 ext2fs_mark_super_dirty(fs);
9831 ext2fs_unmark_valid(fs);
9833 ext2fs_free_mem(&free_array);
9834 ext2fs_free_mem(&dir_array);
9837 static void check_inode_end(e2fsck_t ctx)
9839 ext2_filsys fs = ctx->fs;
9840 ext2_ino_t end, save_inodes_count, i;
9841 struct problem_context pctx;
9843 clear_problem_context(&pctx);
9845 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9846 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9847 &save_inodes_count);
9850 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9851 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9854 if (save_inodes_count == end)
9857 for (i = save_inodes_count + 1; i <= end; i++) {
9858 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9859 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9860 for (i = save_inodes_count + 1; i <= end; i++)
9861 ext2fs_mark_inode_bitmap(fs->inode_map,
9863 ext2fs_mark_ib_dirty(fs);
9865 ext2fs_unmark_valid(fs);
9870 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9871 save_inodes_count, 0);
9874 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9875 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9880 static void check_block_end(e2fsck_t ctx)
9882 ext2_filsys fs = ctx->fs;
9883 blk_t end, save_blocks_count, i;
9884 struct problem_context pctx;
9886 clear_problem_context(&pctx);
9888 end = fs->block_map->start +
9889 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9890 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9891 &save_blocks_count);
9894 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9895 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9898 if (save_blocks_count == end)
9901 for (i = save_blocks_count + 1; i <= end; i++) {
9902 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9903 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9904 for (i = save_blocks_count + 1; i <= end; i++)
9905 ext2fs_mark_block_bitmap(fs->block_map,
9907 ext2fs_mark_bb_dirty(fs);
9909 ext2fs_unmark_valid(fs);
9914 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9915 save_blocks_count, 0);
9918 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9919 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9924 static void e2fsck_pass5(e2fsck_t ctx)
9926 #ifdef RESOURCE_TRACK
9927 struct resource_track rtrack;
9929 struct problem_context pctx;
9932 mtrace_print("Pass 5");
9935 #ifdef RESOURCE_TRACK
9936 init_resource_track(&rtrack);
9939 clear_problem_context(&pctx);
9941 if (!(ctx->options & E2F_OPT_PREEN))
9942 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9945 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9948 e2fsck_read_bitmaps(ctx);
9950 check_block_bitmaps(ctx);
9951 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9953 check_inode_bitmaps(ctx);
9954 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9956 check_inode_end(ctx);
9957 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9959 check_block_end(ctx);
9960 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9963 ext2fs_free_inode_bitmap(ctx->inode_used_map);
9964 ctx->inode_used_map = 0;
9965 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9966 ctx->inode_dir_map = 0;
9967 ext2fs_free_block_bitmap(ctx->block_found_map);
9968 ctx->block_found_map = 0;
9970 #ifdef RESOURCE_TRACK
9971 if (ctx->options & E2F_OPT_TIME2) {
9972 e2fsck_clear_progbar(ctx);
9973 print_resource_track(_("Pass 5"), &rtrack);
9979 * problem.c --- report filesystem problems to the user
9982 #define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
9983 #define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
9984 #define PR_NO_DEFAULT 0x000004 /* Default to no */
9985 #define PR_MSG_ONLY 0x000008 /* Print message only */
9987 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
9989 #define PR_FATAL 0x001000 /* Fatal error */
9990 #define PR_AFTER_CODE 0x002000 /* After asking the first question, */
9992 #define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
9993 #define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
9994 #define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
9995 #define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
9996 #define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
9999 #define PROMPT_NONE 0
10000 #define PROMPT_FIX 1
10001 #define PROMPT_CLEAR 2
10002 #define PROMPT_RELOCATE 3
10003 #define PROMPT_ALLOCATE 4
10004 #define PROMPT_EXPAND 5
10005 #define PROMPT_CONNECT 6
10006 #define PROMPT_CREATE 7
10007 #define PROMPT_SALVAGE 8
10008 #define PROMPT_TRUNCATE 9
10009 #define PROMPT_CLEAR_INODE 10
10010 #define PROMPT_ABORT 11
10011 #define PROMPT_SPLIT 12
10012 #define PROMPT_CONTINUE 13
10013 #define PROMPT_CLONE 14
10014 #define PROMPT_DELETE 15
10015 #define PROMPT_SUPPRESS 16
10016 #define PROMPT_UNLINK 17
10017 #define PROMPT_CLEAR_HTREE 18
10018 #define PROMPT_RECREATE 19
10019 #define PROMPT_NULL 20
10021 struct e2fsck_problem {
10022 problem_t e2p_code;
10023 const char * e2p_description;
10026 problem_t second_code;
10029 struct latch_descr {
10031 problem_t question;
10032 problem_t end_message;
10037 * These are the prompts which are used to ask the user if they want
10038 * to fix a problem.
10040 static const char * const prompt[] = {
10041 N_("(no prompt)"), /* 0 */
10043 N_("Clear"), /* 2 */
10044 N_("Relocate"), /* 3 */
10045 N_("Allocate"), /* 4 */
10046 N_("Expand"), /* 5 */
10047 N_("Connect to /lost+found"), /* 6 */
10048 N_("Create"), /* 7 */
10049 N_("Salvage"), /* 8 */
10050 N_("Truncate"), /* 9 */
10051 N_("Clear inode"), /* 10 */
10052 N_("Abort"), /* 11 */
10053 N_("Split"), /* 12 */
10054 N_("Continue"), /* 13 */
10055 N_("Clone duplicate/bad blocks"), /* 14 */
10056 N_("Delete file"), /* 15 */
10057 N_("Suppress messages"),/* 16 */
10058 N_("Unlink"), /* 17 */
10059 N_("Clear HTree index"),/* 18 */
10060 N_("Recreate"), /* 19 */
10065 * These messages are printed when we are preen mode and we will be
10066 * automatically fixing the problem.
10068 static const char * const preen_msg[] = {
10069 N_("(NONE)"), /* 0 */
10070 N_("FIXED"), /* 1 */
10071 N_("CLEARED"), /* 2 */
10072 N_("RELOCATED"), /* 3 */
10073 N_("ALLOCATED"), /* 4 */
10074 N_("EXPANDED"), /* 5 */
10075 N_("RECONNECTED"), /* 6 */
10076 N_("CREATED"), /* 7 */
10077 N_("SALVAGED"), /* 8 */
10078 N_("TRUNCATED"), /* 9 */
10079 N_("INODE CLEARED"), /* 10 */
10080 N_("ABORTED"), /* 11 */
10081 N_("SPLIT"), /* 12 */
10082 N_("CONTINUING"), /* 13 */
10083 N_("DUPLICATE/BAD BLOCKS CLONED"), /* 14 */
10084 N_("FILE DELETED"), /* 15 */
10085 N_("SUPPRESSED"), /* 16 */
10086 N_("UNLINKED"), /* 17 */
10087 N_("HTREE INDEX CLEARED"),/* 18 */
10088 N_("WILL RECREATE"), /* 19 */
10092 static const struct e2fsck_problem problem_table[] = {
10094 /* Pre-Pass 1 errors */
10096 /* Block bitmap not in group */
10097 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
10098 PROMPT_RELOCATE, PR_LATCH_RELOC },
10100 /* Inode bitmap not in group */
10101 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
10102 PROMPT_RELOCATE, PR_LATCH_RELOC },
10104 /* Inode table not in group */
10105 { PR_0_ITABLE_NOT_GROUP,
10106 N_("@i table for @g %g is not in @g. (@b %b)\n"
10107 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10108 PROMPT_RELOCATE, PR_LATCH_RELOC },
10110 /* Superblock corrupt */
10112 N_("\nThe @S could not be read or does not describe a correct ext2\n"
10113 "@f. If the @v is valid and it really contains an ext2\n"
10114 "@f (and not swap or ufs or something else), then the @S\n"
10115 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10116 " e2fsck -b %S <@v>\n\n"),
10117 PROMPT_NONE, PR_FATAL },
10119 /* Filesystem size is wrong */
10120 { PR_0_FS_SIZE_WRONG,
10121 N_("The @f size (according to the @S) is %b @bs\n"
10122 "The physical size of the @v is %c @bs\n"
10123 "Either the @S or the partition table is likely to be corrupt!\n"),
10126 /* Fragments not supported */
10127 { PR_0_NO_FRAGMENTS,
10128 N_("@S @b_size = %b, fragsize = %c.\n"
10129 "This version of e2fsck does not support fragment sizes different\n"
10130 "from the @b size.\n"),
10131 PROMPT_NONE, PR_FATAL },
10133 /* Bad blocks_per_group */
10134 { PR_0_BLOCKS_PER_GROUP,
10135 N_("@S @bs_per_group = %b, should have been %c\n"),
10136 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10138 /* Bad first_data_block */
10139 { PR_0_FIRST_DATA_BLOCK,
10140 N_("@S first_data_@b = %b, should have been %c\n"),
10141 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10143 /* Adding UUID to filesystem */
10145 N_("@f did not have a UUID; generating one.\n\n"),
10148 /* Relocate hint */
10149 { PR_0_RELOCATE_HINT,
10150 N_("Note: if there is several inode or block bitmap blocks\n"
10151 "which require relocation, or one part of the inode table\n"
10152 "which must be moved, you may wish to try running e2fsck\n"
10153 "with the '-b %S' option first. The problem may lie only\n"
10154 "with the primary block group descriptor, and the backup\n"
10155 "block group descriptor may be OK.\n\n"),
10156 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10158 /* Miscellaneous superblock corruption */
10159 { PR_0_MISC_CORRUPT_SUPER,
10160 N_("Corruption found in @S. (%s = %N).\n"),
10161 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10163 /* Error determing physical device size of filesystem */
10164 { PR_0_GETSIZE_ERROR,
10165 N_("Error determining size of the physical @v: %m\n"),
10166 PROMPT_NONE, PR_FATAL },
10168 /* Inode count in superblock is incorrect */
10169 { PR_0_INODE_COUNT_WRONG,
10170 N_("@i count in @S is %i, should be %j.\n"),
10173 { PR_0_HURD_CLEAR_FILETYPE,
10174 N_("The Hurd does not support the filetype feature.\n"),
10177 /* Journal inode is invalid */
10178 { PR_0_JOURNAL_BAD_INODE,
10179 N_("@S has a bad ext3 @j (@i %i).\n"),
10180 PROMPT_CLEAR, PR_PREEN_OK },
10182 /* The external journal has (unsupported) multiple filesystems */
10183 { PR_0_JOURNAL_UNSUPP_MULTIFS,
10184 N_("External @j has multiple @f users (unsupported).\n"),
10185 PROMPT_NONE, PR_FATAL },
10187 /* Can't find external journal */
10188 { PR_0_CANT_FIND_JOURNAL,
10189 N_("Can't find external @j\n"),
10190 PROMPT_NONE, PR_FATAL },
10192 /* External journal has bad superblock */
10193 { PR_0_EXT_JOURNAL_BAD_SUPER,
10194 N_("External @j has bad @S\n"),
10195 PROMPT_NONE, PR_FATAL },
10197 /* Superblock has a bad journal UUID */
10198 { PR_0_JOURNAL_BAD_UUID,
10199 N_("External @j does not support this @f\n"),
10200 PROMPT_NONE, PR_FATAL },
10202 /* Journal has an unknown superblock type */
10203 { PR_0_JOURNAL_UNSUPP_SUPER,
10204 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10205 "It is likely that your copy of e2fsck is old and/or doesn't "
10206 "support this @j format.\n"
10207 "It is also possible the @j @S is corrupt.\n"),
10208 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10210 /* Journal superblock is corrupt */
10211 { PR_0_JOURNAL_BAD_SUPER,
10212 N_("Ext3 @j @S is corrupt.\n"),
10213 PROMPT_FIX, PR_PREEN_OK },
10215 /* Superblock flag should be cleared */
10216 { PR_0_JOURNAL_HAS_JOURNAL,
10217 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10218 PROMPT_CLEAR, PR_PREEN_OK },
10220 /* Superblock flag is incorrect */
10221 { PR_0_JOURNAL_RECOVER_SET,
10222 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10223 PROMPT_CLEAR, PR_PREEN_OK },
10225 /* Journal has data, but recovery flag is clear */
10226 { PR_0_JOURNAL_RECOVERY_CLEAR,
10227 N_("ext3 recovery flag clear, but @j has data.\n"),
10230 /* Ask if we should clear the journal */
10231 { PR_0_JOURNAL_RESET_JOURNAL,
10233 PROMPT_NULL, PR_PREEN_NOMSG },
10235 /* Ask if we should run the journal anyway */
10236 { PR_0_JOURNAL_RUN,
10237 N_("Run @j anyway"),
10240 /* Run the journal by default */
10241 { PR_0_JOURNAL_RUN_DEFAULT,
10242 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10245 /* Clearing orphan inode */
10246 { PR_0_ORPHAN_CLEAR_INODE,
10247 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10250 /* Illegal block found in orphaned inode */
10251 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10252 N_("@I @b #%B (%b) found in @o @i %i.\n"),
10255 /* Already cleared block found in orphaned inode */
10256 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10257 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10260 /* Illegal orphan inode in superblock */
10261 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10262 N_("@I @o @i %i in @S.\n"),
10265 /* Illegal inode in orphaned inode list */
10266 { PR_0_ORPHAN_ILLEGAL_INODE,
10267 N_("@I @i %i in @o @i list.\n"),
10270 /* Filesystem revision is 0, but feature flags are set */
10271 { PR_0_FS_REV_LEVEL,
10272 "@f has feature flag(s) set, but is a revision 0 @f. ",
10273 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10275 /* Journal superblock has an unknown read-only feature flag set */
10276 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10277 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10280 /* Journal superblock has an unknown incompatible feature flag set */
10281 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10282 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10285 /* Journal has unsupported version number */
10286 { PR_0_JOURNAL_UNSUPP_VERSION,
10287 N_("@j version not supported by this e2fsck.\n"),
10290 /* Moving journal to hidden file */
10291 { PR_0_MOVE_JOURNAL,
10292 N_("Moving @j from /%s to hidden inode.\n\n"),
10295 /* Error moving journal to hidden file */
10296 { PR_0_ERR_MOVE_JOURNAL,
10297 N_("Error moving @j: %m\n\n"),
10300 /* Clearing V2 journal superblock */
10301 { PR_0_CLEAR_V2_JOURNAL,
10302 N_("Found invalid V2 @j @S fields (from V1 journal).\n"
10303 "Clearing fields beyond the V1 @j @S...\n\n"),
10306 /* Backup journal inode blocks */
10308 N_("Backing up @j @i @b information.\n\n"),
10311 /* Reserved blocks w/o resize_inode */
10312 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10313 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10314 "is %N; @s zero. "),
10317 /* Resize_inode not enabled, but resize inode is non-zero */
10318 { PR_0_CLEAR_RESIZE_INODE,
10319 N_("Resize_@i not enabled, but the resize inode is non-zero. "),
10322 /* Resize inode invalid */
10323 { PR_0_RESIZE_INODE_INVALID,
10324 N_("Resize @i not valid. "),
10325 PROMPT_RECREATE, 0 },
10327 /* Pass 1 errors */
10329 /* Pass 1: Checking inodes, blocks, and sizes */
10330 { PR_1_PASS_HEADER,
10331 N_("Pass 1: Checking @is, @bs, and sizes\n"),
10334 /* Root directory is not an inode */
10335 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
10338 /* Root directory has dtime set */
10340 N_("@r has dtime set (probably due to old mke2fs). "),
10341 PROMPT_FIX, PR_PREEN_OK },
10343 /* Reserved inode has bad mode */
10344 { PR_1_RESERVED_BAD_MODE,
10345 N_("Reserved @i %i %Q has bad mode. "),
10346 PROMPT_CLEAR, PR_PREEN_OK },
10348 /* Deleted inode has zero dtime */
10350 N_("@D @i %i has zero dtime. "),
10351 PROMPT_FIX, PR_PREEN_OK },
10353 /* Inode in use, but dtime set */
10355 N_("@i %i is in use, but has dtime set. "),
10356 PROMPT_FIX, PR_PREEN_OK },
10358 /* Zero-length directory */
10359 { PR_1_ZERO_LENGTH_DIR,
10360 N_("@i %i is a @z @d. "),
10361 PROMPT_CLEAR, PR_PREEN_OK },
10363 /* Block bitmap conflicts with some other fs block */
10364 { PR_1_BB_CONFLICT,
10365 N_("@g %g's @b @B at %b @C.\n"),
10366 PROMPT_RELOCATE, 0 },
10368 /* Inode bitmap conflicts with some other fs block */
10369 { PR_1_IB_CONFLICT,
10370 N_("@g %g's @i @B at %b @C.\n"),
10371 PROMPT_RELOCATE, 0 },
10373 /* Inode table conflicts with some other fs block */
10374 { PR_1_ITABLE_CONFLICT,
10375 N_("@g %g's @i table at %b @C.\n"),
10376 PROMPT_RELOCATE, 0 },
10378 /* Block bitmap is on a bad block */
10379 { PR_1_BB_BAD_BLOCK,
10380 N_("@g %g's @b @B (%b) is bad. "),
10381 PROMPT_RELOCATE, 0 },
10383 /* Inode bitmap is on a bad block */
10384 { PR_1_IB_BAD_BLOCK,
10385 N_("@g %g's @i @B (%b) is bad. "),
10386 PROMPT_RELOCATE, 0 },
10388 /* Inode has incorrect i_size */
10390 N_("@i %i, i_size is %Is, @s %N. "),
10391 PROMPT_FIX, PR_PREEN_OK },
10393 /* Inode has incorrect i_blocks */
10394 { PR_1_BAD_I_BLOCKS,
10395 N_("@i %i, i_@bs is %Ib, @s %N. "),
10396 PROMPT_FIX, PR_PREEN_OK },
10398 /* Illegal blocknumber in inode */
10399 { PR_1_ILLEGAL_BLOCK_NUM,
10400 N_("@I @b #%B (%b) in @i %i. "),
10401 PROMPT_CLEAR, PR_LATCH_BLOCK },
10403 /* Block number overlaps fs metadata */
10404 { PR_1_BLOCK_OVERLAPS_METADATA,
10405 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
10406 PROMPT_CLEAR, PR_LATCH_BLOCK },
10408 /* Inode has illegal blocks (latch question) */
10409 { PR_1_INODE_BLOCK_LATCH,
10410 N_("@i %i has illegal @b(s). "),
10413 /* Too many bad blocks in inode */
10414 { PR_1_TOO_MANY_BAD_BLOCKS,
10415 N_("Too many illegal @bs in @i %i.\n"),
10416 PROMPT_CLEAR_INODE, PR_NO_OK },
10418 /* Illegal block number in bad block inode */
10419 { PR_1_BB_ILLEGAL_BLOCK_NUM,
10420 N_("@I @b #%B (%b) in bad @b @i. "),
10421 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10423 /* Bad block inode has illegal blocks (latch question) */
10424 { PR_1_INODE_BBLOCK_LATCH,
10425 N_("Bad @b @i has illegal @b(s). "),
10428 /* Duplicate or bad blocks in use! */
10429 { PR_1_DUP_BLOCKS_PREENSTOP,
10430 N_("Duplicate or bad @b in use!\n"),
10433 /* Bad block used as bad block indirect block */
10434 { PR_1_BBINODE_BAD_METABLOCK,
10435 N_("Bad @b %b used as bad @b @i indirect @b. "),
10436 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10438 /* Inconsistency can't be fixed prompt */
10439 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10440 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
10441 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10443 PROMPT_CONTINUE, PR_PREEN_NOMSG },
10445 /* Bad primary block */
10446 { PR_1_BAD_PRIMARY_BLOCK,
10447 N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10448 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10450 /* Bad primary block prompt */
10451 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10452 N_("You can clear the this @b (and hope for the best) from the\n"
10453 "bad @b list and hope that @b is really OK, but there are no\n"
10454 "guarantees.\n\n"),
10455 PROMPT_CLEAR, PR_PREEN_NOMSG },
10457 /* Bad primary superblock */
10458 { PR_1_BAD_PRIMARY_SUPERBLOCK,
10459 N_("The primary @S (%b) is on the bad @b list.\n"),
10460 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10462 /* Bad primary block group descriptors */
10463 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10464 N_("Block %b in the primary @g descriptors "
10465 "is on the bad @b list\n"),
10466 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10468 /* Bad superblock in group */
10469 { PR_1_BAD_SUPERBLOCK,
10470 N_("Warning: Group %g's @S (%b) is bad.\n"),
10471 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10473 /* Bad block group descriptors in group */
10474 { PR_1_BAD_GROUP_DESCRIPTORS,
10475 N_("Warning: Group %g's copy of the @g descriptors has a bad "
10477 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10479 /* Block claimed for no reason */
10480 { PR_1_PROGERR_CLAIMED_BLOCK,
10481 N_("Programming error? @b #%b claimed for no reason in "
10482 "process_bad_@b.\n"),
10483 PROMPT_NONE, PR_PREEN_OK },
10485 /* Error allocating blocks for relocating metadata */
10486 { PR_1_RELOC_BLOCK_ALLOCATE,
10487 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10488 PROMPT_NONE, PR_PREEN_OK },
10490 /* Error allocating block buffer during relocation process */
10491 { PR_1_RELOC_MEMORY_ALLOCATE,
10492 N_("@A @b buffer for relocating %s\n"),
10493 PROMPT_NONE, PR_PREEN_OK },
10495 /* Relocating metadata group information from X to Y */
10496 { PR_1_RELOC_FROM_TO,
10497 N_("Relocating @g %g's %s from %b to %c...\n"),
10498 PROMPT_NONE, PR_PREEN_OK },
10500 /* Relocating metatdata group information to X */
10502 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10503 PROMPT_NONE, PR_PREEN_OK },
10505 /* Block read error during relocation process */
10506 { PR_1_RELOC_READ_ERR,
10507 N_("Warning: could not read @b %b of %s: %m\n"),
10508 PROMPT_NONE, PR_PREEN_OK },
10510 /* Block write error during relocation process */
10511 { PR_1_RELOC_WRITE_ERR,
10512 N_("Warning: could not write @b %b for %s: %m\n"),
10513 PROMPT_NONE, PR_PREEN_OK },
10515 /* Error allocating inode bitmap */
10516 { PR_1_ALLOCATE_IBITMAP_ERROR,
10517 "@A @i @B (%N): %m\n",
10518 PROMPT_NONE, PR_FATAL },
10520 /* Error allocating block bitmap */
10521 { PR_1_ALLOCATE_BBITMAP_ERROR,
10522 "@A @b @B (%N): %m\n",
10523 PROMPT_NONE, PR_FATAL },
10525 /* Error allocating icount structure */
10526 { PR_1_ALLOCATE_ICOUNT,
10527 N_("@A icount link information: %m\n"),
10528 PROMPT_NONE, PR_FATAL },
10530 /* Error allocating dbcount */
10531 { PR_1_ALLOCATE_DBCOUNT,
10532 N_("@A @d @b array: %m\n"),
10533 PROMPT_NONE, PR_FATAL },
10535 /* Error while scanning inodes */
10536 { PR_1_ISCAN_ERROR,
10537 N_("Error while scanning @is (%i): %m\n"),
10538 PROMPT_NONE, PR_FATAL },
10540 /* Error while iterating over blocks */
10541 { PR_1_BLOCK_ITERATE,
10542 N_("Error while iterating over @bs in @i %i: %m\n"),
10543 PROMPT_NONE, PR_FATAL },
10545 /* Error while storing inode count information */
10546 { PR_1_ICOUNT_STORE,
10547 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10548 PROMPT_NONE, PR_FATAL },
10550 /* Error while storing directory block information */
10552 N_("Error storing @d @b information "
10553 "(@i=%i, @b=%b, num=%N): %m\n"),
10554 PROMPT_NONE, PR_FATAL },
10556 /* Error while reading inode (for clearing) */
10558 N_("Error reading @i %i: %m\n"),
10559 PROMPT_NONE, PR_FATAL },
10561 /* Suppress messages prompt */
10562 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10564 /* Imagic flag set on an inode when filesystem doesn't support it */
10566 N_("@i %i has imagic flag set. "),
10569 /* Immutable flag set on a device or socket inode */
10570 { PR_1_SET_IMMUTABLE,
10571 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10572 "or append-only flag set. "),
10573 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10575 /* Compression flag set on an inode when filesystem doesn't support it */
10577 N_("@i %i has @cion flag set on @f without @cion support. "),
10580 /* Non-zero size for device, fifo or socket inode */
10581 { PR_1_SET_NONZSIZE,
10582 "Special (@v/socket/fifo) @i %i has non-zero size. ",
10583 PROMPT_FIX, PR_PREEN_OK },
10585 /* Filesystem revision is 0, but feature flags are set */
10586 { PR_1_FS_REV_LEVEL,
10587 "@f has feature flag(s) set, but is a revision 0 @f. ",
10588 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10590 /* Journal inode is not in use, but contains data */
10591 { PR_1_JOURNAL_INODE_NOT_CLEAR,
10592 "@j @i is not in use, but contains data. ",
10593 PROMPT_CLEAR, PR_PREEN_OK },
10595 /* Journal has bad mode */
10596 { PR_1_JOURNAL_BAD_MODE,
10597 N_("@j is not regular file. "),
10598 PROMPT_FIX, PR_PREEN_OK },
10600 /* Deal with inodes that were part of orphan linked list */
10602 N_("@i %i was part of the orphaned @i list. "),
10603 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10605 /* Deal with inodes that were part of corrupted orphan linked
10606 list (latch question) */
10607 { PR_1_ORPHAN_LIST_REFUGEES,
10608 N_("@is that were part of a corrupted orphan linked list found. "),
10611 /* Error allocating refcount structure */
10612 { PR_1_ALLOCATE_REFCOUNT,
10613 "@A refcount structure (%N): %m\n",
10614 PROMPT_NONE, PR_FATAL },
10616 /* Error reading extended attribute block */
10617 { PR_1_READ_EA_BLOCK,
10618 N_("Error reading @a @b %b for @i %i. "),
10621 /* Invalid extended attribute block */
10622 { PR_1_BAD_EA_BLOCK,
10623 N_("@i %i has a bad @a @b %b. "),
10626 /* Error reading Extended Attribute block while fixing refcount */
10627 { PR_1_EXTATTR_READ_ABORT,
10628 N_("Error reading @a @b %b (%m). "),
10631 /* Extended attribute reference count incorrect */
10632 { PR_1_EXTATTR_REFCOUNT,
10633 N_("@a @b %b has reference count %B, should be %N. "),
10636 /* Error writing Extended Attribute block while fixing refcount */
10637 { PR_1_EXTATTR_WRITE,
10638 N_("Error writing @a @b %b (%m). "),
10641 /* Multiple EA blocks not supported */
10642 { PR_1_EA_MULTI_BLOCK,
10643 N_("@a @b %b has h_blocks > 1. "),
10646 /* Error allocating EA region allocation structure */
10647 { PR_1_EA_ALLOC_REGION,
10648 N_("Error allocating @a @b %b. "),
10651 /* Error EA allocation collision */
10652 { PR_1_EA_ALLOC_COLLISION,
10653 N_("@a @b %b is corrupt (allocation collision). "),
10656 /* Bad extended attribute name */
10657 { PR_1_EA_BAD_NAME,
10658 N_("@a @b %b is corrupt (invalid name). "),
10661 /* Bad extended attribute value */
10662 { PR_1_EA_BAD_VALUE,
10663 N_("@a @b %b is corrupt (invalid value). "),
10666 /* Inode too big (latch question) */
10667 { PR_1_INODE_TOOBIG,
10668 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
10670 /* Directory too big */
10672 N_("@b #%B (%b) causes @d to be too big. "),
10673 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10675 /* Regular file too big */
10677 N_("@b #%B (%b) causes file to be too big. "),
10678 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10680 /* Symlink too big */
10681 { PR_1_TOOBIG_SYMLINK,
10682 N_("@b #%B (%b) causes symlink to be too big. "),
10683 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10685 /* INDEX_FL flag set on a non-HTREE filesystem */
10687 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10688 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10690 /* INDEX_FL flag set on a non-directory */
10691 { PR_1_HTREE_NODIR,
10692 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10693 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10695 /* Invalid root node in HTREE directory */
10696 { PR_1_HTREE_BADROOT,
10697 N_("@h %i has an invalid root node.\n"),
10698 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10700 /* Unsupported hash version in HTREE directory */
10701 { PR_1_HTREE_HASHV,
10702 N_("@h %i has an unsupported hash version (%N)\n"),
10703 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10705 /* Incompatible flag in HTREE root node */
10706 { PR_1_HTREE_INCOMPAT,
10707 N_("@h %i uses an incompatible htree root node flag.\n"),
10708 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10710 /* HTREE too deep */
10711 { PR_1_HTREE_DEPTH,
10712 N_("@h %i has a tree depth (%N) which is too big\n"),
10713 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10715 /* Bad block has indirect block that conflicts with filesystem block */
10716 { PR_1_BB_FS_BLOCK,
10717 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10719 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10721 /* Resize inode failed */
10722 { PR_1_RESIZE_INODE_CREATE,
10723 N_("Resize @i (re)creation failed: %m."),
10726 /* invalid inode->i_extra_isize */
10727 { PR_1_EXTRA_ISIZE,
10728 N_("@i %i has a extra size (%IS) which is invalid\n"),
10729 PROMPT_FIX, PR_PREEN_OK },
10731 /* invalid ea entry->e_name_len */
10732 { PR_1_ATTR_NAME_LEN,
10733 N_("@a in @i %i has a namelen (%N) which is invalid\n"),
10734 PROMPT_CLEAR, PR_PREEN_OK },
10736 /* invalid ea entry->e_value_size */
10737 { PR_1_ATTR_VALUE_SIZE,
10738 N_("@a in @i %i has a value size (%N) which is invalid\n"),
10739 PROMPT_CLEAR, PR_PREEN_OK },
10741 /* invalid ea entry->e_value_offs */
10742 { PR_1_ATTR_VALUE_OFFSET,
10743 N_("@a in @i %i has a value offset (%N) which is invalid\n"),
10744 PROMPT_CLEAR, PR_PREEN_OK },
10746 /* invalid ea entry->e_value_block */
10747 { PR_1_ATTR_VALUE_BLOCK,
10748 N_("@a in @i %i has a value block (%N) which is invalid (must be 0)\n"),
10749 PROMPT_CLEAR, PR_PREEN_OK },
10751 /* invalid ea entry->e_hash */
10753 N_("@a in @i %i has a hash (%N) which is invalid (must be 0)\n"),
10754 PROMPT_CLEAR, PR_PREEN_OK },
10756 /* Pass 1b errors */
10758 /* Pass 1B: Rescan for duplicate/bad blocks */
10759 { PR_1B_PASS_HEADER,
10760 N_("Duplicate @bs found... invoking duplicate @b passes.\n"
10761 "Pass 1B: Rescan for duplicate/bad @bs\n"),
10764 /* Duplicate/bad block(s) header */
10765 { PR_1B_DUP_BLOCK_HEADER,
10766 N_("Duplicate/bad @b(s) in @i %i:"),
10769 /* Duplicate/bad block(s) in inode */
10772 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10774 /* Duplicate/bad block(s) end */
10775 { PR_1B_DUP_BLOCK_END,
10777 PROMPT_NONE, PR_PREEN_NOHDR },
10779 /* Error while scanning inodes */
10780 { PR_1B_ISCAN_ERROR,
10781 N_("Error while scanning inodes (%i): %m\n"),
10782 PROMPT_NONE, PR_FATAL },
10784 /* Error allocating inode bitmap */
10785 { PR_1B_ALLOCATE_IBITMAP_ERROR,
10786 N_("@A @i @B (inode_dup_map): %m\n"),
10787 PROMPT_NONE, PR_FATAL },
10789 /* Error while iterating over blocks */
10790 { PR_1B_BLOCK_ITERATE,
10791 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10794 /* Error adjusting EA refcount */
10795 { PR_1B_ADJ_EA_REFCOUNT,
10796 N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
10800 /* Pass 1C: Scan directories for inodes with dup blocks. */
10801 { PR_1C_PASS_HEADER,
10802 N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
10806 /* Pass 1D: Reconciling duplicate blocks */
10807 { PR_1D_PASS_HEADER,
10808 N_("Pass 1D: Reconciling duplicate @bs\n"),
10811 /* File has duplicate blocks */
10813 N_("File %Q (@i #%i, mod time %IM) \n"
10814 " has %B duplicate @b(s), shared with %N file(s):\n"),
10817 /* List of files sharing duplicate blocks */
10818 { PR_1D_DUP_FILE_LIST,
10819 N_("\t%Q (@i #%i, mod time %IM)\n"),
10822 /* File sharing blocks with filesystem metadata */
10823 { PR_1D_SHARE_METADATA,
10824 N_("\t<@f metadata>\n"),
10827 /* Report of how many duplicate/bad inodes */
10828 { PR_1D_NUM_DUP_INODES,
10829 N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
10832 /* Duplicated blocks already reassigned or cloned. */
10833 { PR_1D_DUP_BLOCKS_DEALT,
10834 N_("Duplicated @bs already reassigned or cloned.\n\n"),
10837 /* Clone duplicate/bad blocks? */
10838 { PR_1D_CLONE_QUESTION,
10839 "", PROMPT_CLONE, PR_NO_OK },
10842 { PR_1D_DELETE_QUESTION,
10843 "", PROMPT_DELETE, 0 },
10845 /* Couldn't clone file (error) */
10846 { PR_1D_CLONE_ERROR,
10847 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10849 /* Pass 2 errors */
10851 /* Pass 2: Checking directory structure */
10852 { PR_2_PASS_HEADER,
10853 N_("Pass 2: Checking @d structure\n"),
10856 /* Bad inode number for '.' */
10857 { PR_2_BAD_INODE_DOT,
10858 N_("Bad @i number for '.' in @d @i %i.\n"),
10861 /* Directory entry has bad inode number */
10863 N_("@E has bad @i #: %Di.\n"),
10866 /* Directory entry has deleted or unused inode */
10867 { PR_2_UNUSED_INODE,
10868 N_("@E has @D/unused @i %Di. "),
10869 PROMPT_CLEAR, PR_PREEN_OK },
10871 /* Directry entry is link to '.' */
10873 N_("@E @L to '.' "),
10876 /* Directory entry points to inode now located in a bad block */
10878 N_("@E points to @i (%Di) located in a bad @b.\n"),
10881 /* Directory entry contains a link to a directory */
10883 N_("@E @L to @d %P (%Di).\n"),
10886 /* Directory entry contains a link to the root directry */
10888 N_("@E @L to the @r.\n"),
10891 /* Directory entry has illegal characters in its name */
10893 N_("@E has illegal characters in its name.\n"),
10896 /* Missing '.' in directory inode */
10897 { PR_2_MISSING_DOT,
10898 N_("Missing '.' in @d @i %i.\n"),
10901 /* Missing '..' in directory inode */
10902 { PR_2_MISSING_DOT_DOT,
10903 N_("Missing '..' in @d @i %i.\n"),
10906 /* First entry in directory inode doesn't contain '.' */
10907 { PR_2_1ST_NOT_DOT,
10908 N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
10911 /* Second entry in directory inode doesn't contain '..' */
10912 { PR_2_2ND_NOT_DOT_DOT,
10913 N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
10916 /* i_faddr should be zero */
10918 N_("i_faddr @F %IF, @s zero.\n"),
10921 /* i_file_acl should be zero */
10922 { PR_2_FILE_ACL_ZERO,
10923 N_("i_file_acl @F %If, @s zero.\n"),
10926 /* i_dir_acl should be zero */
10927 { PR_2_DIR_ACL_ZERO,
10928 N_("i_dir_acl @F %Id, @s zero.\n"),
10931 /* i_frag should be zero */
10933 N_("i_frag @F %N, @s zero.\n"),
10936 /* i_fsize should be zero */
10938 N_("i_fsize @F %N, @s zero.\n"),
10941 /* inode has bad mode */
10943 N_("@i %i (%Q) has a bad mode (%Im).\n"),
10946 /* directory corrupted */
10947 { PR_2_DIR_CORRUPTED,
10948 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
10949 PROMPT_SALVAGE, 0 },
10951 /* filename too long */
10952 { PR_2_FILENAME_LONG,
10953 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
10954 PROMPT_TRUNCATE, 0 },
10956 /* Directory inode has a missing block (hole) */
10957 { PR_2_DIRECTORY_HOLE,
10958 N_("@d @i %i has an unallocated @b #%B. "),
10959 PROMPT_ALLOCATE, 0 },
10961 /* '.' is not NULL terminated */
10962 { PR_2_DOT_NULL_TERM,
10963 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
10966 /* '..' is not NULL terminated */
10967 { PR_2_DOT_DOT_NULL_TERM,
10968 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
10971 /* Illegal character device inode */
10972 { PR_2_BAD_CHAR_DEV,
10973 N_("@i %i (%Q) is an @I character @v.\n"),
10976 /* Illegal block device inode */
10977 { PR_2_BAD_BLOCK_DEV,
10978 N_("@i %i (%Q) is an @I @b @v.\n"),
10981 /* Duplicate '.' entry */
10983 N_("@E is duplicate '.' @e.\n"),
10986 /* Duplicate '..' entry */
10987 { PR_2_DUP_DOT_DOT,
10988 N_("@E is duplicate '..' @e.\n"),
10991 /* Internal error: couldn't find dir_info */
10993 N_("Internal error: couldn't find dir_info for %i.\n"),
10994 PROMPT_NONE, PR_FATAL },
10996 /* Final rec_len is wrong */
10997 { PR_2_FINAL_RECLEN,
10998 N_("@E has rec_len of %Dr, should be %N.\n"),
11001 /* Error allocating icount structure */
11002 { PR_2_ALLOCATE_ICOUNT,
11003 N_("@A icount structure: %m\n"),
11004 PROMPT_NONE, PR_FATAL },
11006 /* Error iterating over directory blocks */
11007 { PR_2_DBLIST_ITERATE,
11008 N_("Error iterating over @d @bs: %m\n"),
11009 PROMPT_NONE, PR_FATAL },
11011 /* Error reading directory block */
11012 { PR_2_READ_DIRBLOCK,
11013 N_("Error reading @d @b %b (@i %i): %m\n"),
11014 PROMPT_CONTINUE, 0 },
11016 /* Error writing directory block */
11017 { PR_2_WRITE_DIRBLOCK,
11018 N_("Error writing @d @b %b (@i %i): %m\n"),
11019 PROMPT_CONTINUE, 0 },
11021 /* Error allocating new directory block */
11022 { PR_2_ALLOC_DIRBOCK,
11023 N_("@A new @d @b for @i %i (%s): %m\n"),
11026 /* Error deallocating inode */
11027 { PR_2_DEALLOC_INODE,
11028 N_("Error deallocating @i %i: %m\n"),
11029 PROMPT_NONE, PR_FATAL },
11031 /* Directory entry for '.' is big. Split? */
11033 N_("@d @e for '.' is big. "),
11034 PROMPT_SPLIT, PR_NO_OK },
11036 /* Illegal FIFO inode */
11038 N_("@i %i (%Q) is an @I FIFO.\n"),
11041 /* Illegal socket inode */
11043 N_("@i %i (%Q) is an @I socket.\n"),
11046 /* Directory filetype not set */
11047 { PR_2_SET_FILETYPE,
11048 N_("Setting filetype for @E to %N.\n"),
11049 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11051 /* Directory filetype incorrect */
11052 { PR_2_BAD_FILETYPE,
11053 N_("@E has an incorrect filetype (was %Dt, should be %N).\n"),
11056 /* Directory filetype set on filesystem */
11057 { PR_2_CLEAR_FILETYPE,
11058 N_("@E has filetype set.\n"),
11059 PROMPT_CLEAR, PR_PREEN_OK },
11061 /* Directory filename is null */
11063 N_("@E has a zero-length name.\n"),
11066 /* Invalid symlink */
11067 { PR_2_INVALID_SYMLINK,
11068 N_("Symlink %Q (@i #%i) is invalid.\n"),
11071 /* i_file_acl (extended attribute block) is bad */
11072 { PR_2_FILE_ACL_BAD,
11073 N_("@a @b @F invalid (%If).\n"),
11076 /* Filesystem contains large files, but has no such flag in sb */
11077 { PR_2_FEATURE_LARGE_FILES,
11078 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11081 /* Node in HTREE directory not referenced */
11082 { PR_2_HTREE_NOTREF,
11083 N_("@p @h %d: node (%B) not referenced\n"),
11086 /* Node in HTREE directory referenced twice */
11087 { PR_2_HTREE_DUPREF,
11088 N_("@p @h %d: node (%B) referenced twice\n"),
11091 /* Node in HTREE directory has bad min hash */
11092 { PR_2_HTREE_MIN_HASH,
11093 N_("@p @h %d: node (%B) has bad min hash\n"),
11096 /* Node in HTREE directory has bad max hash */
11097 { PR_2_HTREE_MAX_HASH,
11098 N_("@p @h %d: node (%B) has bad max hash\n"),
11101 /* Clear invalid HTREE directory */
11102 { PR_2_HTREE_CLEAR,
11103 N_("Invalid @h %d (%q). "), PROMPT_CLEAR, 0 },
11105 /* Bad block in htree interior node */
11106 { PR_2_HTREE_BADBLK,
11107 N_("@p @h %d (%q): bad @b number %b.\n"),
11108 PROMPT_CLEAR_HTREE, 0 },
11110 /* Error adjusting EA refcount */
11111 { PR_2_ADJ_EA_REFCOUNT,
11112 N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
11113 PROMPT_NONE, PR_FATAL },
11115 /* Invalid HTREE root node */
11116 { PR_2_HTREE_BAD_ROOT,
11117 N_("@p @h %d: root node is invalid\n"),
11118 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11120 /* Invalid HTREE limit */
11121 { PR_2_HTREE_BAD_LIMIT,
11122 N_("@p @h %d: node (%B) has bad limit (%N)\n"),
11123 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11125 /* Invalid HTREE count */
11126 { PR_2_HTREE_BAD_COUNT,
11127 N_("@p @h %d: node (%B) has bad count (%N)\n"),
11128 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11130 /* HTREE interior node has out-of-order hashes in table */
11131 { PR_2_HTREE_HASH_ORDER,
11132 N_("@p @h %d: node (%B) has an unordered hash table\n"),
11133 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11135 /* Node in HTREE directory has bad depth */
11136 { PR_2_HTREE_BAD_DEPTH,
11137 N_("@p @h %d: node (%B) has bad depth\n"),
11140 /* Duplicate directory entry found */
11141 { PR_2_DUPLICATE_DIRENT,
11142 N_("Duplicate @E found. "),
11145 /* Non-unique filename found */
11146 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11147 N_("@E has a non-unique filename.\nRename to %s"),
11150 /* Duplicate directory entry found */
11151 { PR_2_REPORT_DUP_DIRENT,
11152 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11155 /* Pass 3 errors */
11157 /* Pass 3: Checking directory connectivity */
11158 { PR_3_PASS_HEADER,
11159 N_("Pass 3: Checking @d connectivity\n"),
11162 /* Root inode not allocated */
11163 { PR_3_NO_ROOT_INODE,
11164 N_("@r not allocated. "),
11165 PROMPT_ALLOCATE, 0 },
11167 /* No room in lost+found */
11168 { PR_3_EXPAND_LF_DIR,
11169 N_("No room in @l @d. "),
11170 PROMPT_EXPAND, 0 },
11172 /* Unconnected directory inode */
11173 { PR_3_UNCONNECTED_DIR,
11174 N_("Unconnected @d @i %i (%p)\n"),
11175 PROMPT_CONNECT, 0 },
11177 /* /lost+found not found */
11179 N_("/@l not found. "),
11180 PROMPT_CREATE, PR_PREEN_OK },
11182 /* .. entry is incorrect */
11183 { PR_3_BAD_DOT_DOT,
11184 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11187 /* Bad or non-existent /lost+found. Cannot reconnect */
11189 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
11192 /* Could not expand /lost+found */
11193 { PR_3_CANT_EXPAND_LPF,
11194 N_("Could not expand /@l: %m\n"),
11197 /* Could not reconnect inode */
11198 { PR_3_CANT_RECONNECT,
11199 N_("Could not reconnect %i: %m\n"),
11202 /* Error while trying to find /lost+found */
11203 { PR_3_ERR_FIND_LPF,
11204 N_("Error while trying to find /@l: %m\n"),
11207 /* Error in ext2fs_new_block while creating /lost+found */
11208 { PR_3_ERR_LPF_NEW_BLOCK,
11209 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11212 /* Error in ext2fs_new_inode while creating /lost+found */
11213 { PR_3_ERR_LPF_NEW_INODE,
11214 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11217 /* Error in ext2fs_new_dir_block while creating /lost+found */
11218 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11219 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11222 /* Error while writing directory block for /lost+found */
11223 { PR_3_ERR_LPF_WRITE_BLOCK,
11224 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11227 /* Error while adjusting inode count */
11228 { PR_3_ADJUST_INODE,
11229 N_("Error while adjusting @i count on @i %i\n"),
11232 /* Couldn't fix parent directory -- error */
11233 { PR_3_FIX_PARENT_ERR,
11234 N_("Couldn't fix parent of @i %i: %m\n\n"),
11237 /* Couldn't fix parent directory -- couldn't find it */
11238 { PR_3_FIX_PARENT_NOFIND,
11239 N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
11242 /* Error allocating inode bitmap */
11243 { PR_3_ALLOCATE_IBITMAP_ERROR,
11244 N_("@A @i @B (%N): %m\n"),
11245 PROMPT_NONE, PR_FATAL },
11247 /* Error creating root directory */
11248 { PR_3_CREATE_ROOT_ERROR,
11249 N_("Error creating root @d (%s): %m\n"),
11250 PROMPT_NONE, PR_FATAL },
11252 /* Error creating lost and found directory */
11253 { PR_3_CREATE_LPF_ERROR,
11254 N_("Error creating /@l @d (%s): %m\n"),
11255 PROMPT_NONE, PR_FATAL },
11257 /* Root inode is not directory; aborting */
11258 { PR_3_ROOT_NOT_DIR_ABORT,
11259 N_("@r is not a @d; aborting.\n"),
11260 PROMPT_NONE, PR_FATAL },
11262 /* Cannot proceed without a root inode. */
11263 { PR_3_NO_ROOT_INODE_ABORT,
11264 N_("Cannot proceed without a @r.\n"),
11265 PROMPT_NONE, PR_FATAL },
11267 /* Internal error: couldn't find dir_info */
11269 N_("Internal error: couldn't find dir_info for %i.\n"),
11270 PROMPT_NONE, PR_FATAL },
11272 /* Lost+found not a directory */
11274 N_("/@l is not a @d (ino=%i)\n"),
11275 PROMPT_UNLINK, 0 },
11277 /* Pass 3A Directory Optimization */
11279 /* Pass 3A: Optimizing directories */
11280 { PR_3A_PASS_HEADER,
11281 N_("Pass 3A: Optimizing directories\n"),
11282 PROMPT_NONE, PR_PREEN_NOMSG },
11284 /* Error iterating over directories */
11285 { PR_3A_OPTIMIZE_ITER,
11286 N_("Failed to create dirs_to_hash iterator: %m"),
11289 /* Error rehash directory */
11290 { PR_3A_OPTIMIZE_DIR_ERR,
11291 N_("Failed to optimize directory %q (%d): %m"),
11294 /* Rehashing dir header */
11295 { PR_3A_OPTIMIZE_DIR_HEADER,
11296 N_("Optimizing directories: "),
11297 PROMPT_NONE, PR_MSG_ONLY },
11299 /* Rehashing directory %d */
11300 { PR_3A_OPTIMIZE_DIR,
11302 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11304 /* Rehashing dir end */
11305 { PR_3A_OPTIMIZE_DIR_END,
11307 PROMPT_NONE, PR_PREEN_NOHDR },
11309 /* Pass 4 errors */
11311 /* Pass 4: Checking reference counts */
11312 { PR_4_PASS_HEADER,
11313 N_("Pass 4: Checking reference counts\n"),
11316 /* Unattached zero-length inode */
11317 { PR_4_ZERO_LEN_INODE,
11319 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11321 /* Unattached inode */
11322 { PR_4_UNATTACHED_INODE,
11324 PROMPT_CONNECT, 0 },
11326 /* Inode ref count wrong */
11327 { PR_4_BAD_REF_COUNT,
11328 N_("@i %i ref count is %Il, @s %N. "),
11329 PROMPT_FIX, PR_PREEN_OK },
11331 { PR_4_INCONSISTENT_COUNT,
11332 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11333 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11334 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
11335 "They should be the same!\n"),
11338 /* Pass 5 errors */
11340 /* Pass 5: Checking group summary information */
11341 { PR_5_PASS_HEADER,
11342 N_("Pass 5: Checking @g summary information\n"),
11345 /* Padding at end of inode bitmap is not set. */
11346 { PR_5_INODE_BMAP_PADDING,
11347 N_("Padding at end of @i @B is not set. "),
11348 PROMPT_FIX, PR_PREEN_OK },
11350 /* Padding at end of block bitmap is not set. */
11351 { PR_5_BLOCK_BMAP_PADDING,
11352 N_("Padding at end of @b @B is not set. "),
11353 PROMPT_FIX, PR_PREEN_OK },
11355 /* Block bitmap differences header */
11356 { PR_5_BLOCK_BITMAP_HEADER,
11357 N_("@b @B differences: "),
11358 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11360 /* Block not used, but marked in bitmap */
11361 { PR_5_BLOCK_UNUSED,
11363 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11365 /* Block used, but not marked used in bitmap */
11368 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11370 /* Block bitmap differences end */
11371 { PR_5_BLOCK_BITMAP_END,
11373 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11375 /* Inode bitmap differences header */
11376 { PR_5_INODE_BITMAP_HEADER,
11377 N_("@i @B differences: "),
11378 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11380 /* Inode not used, but marked in bitmap */
11381 { PR_5_INODE_UNUSED,
11383 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11385 /* Inode used, but not marked used in bitmap */
11388 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11390 /* Inode bitmap differences end */
11391 { PR_5_INODE_BITMAP_END,
11393 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11395 /* Free inodes count for group wrong */
11396 { PR_5_FREE_INODE_COUNT_GROUP,
11397 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11398 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11400 /* Directories count for group wrong */
11401 { PR_5_FREE_DIR_COUNT_GROUP,
11402 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11403 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11405 /* Free inodes count wrong */
11406 { PR_5_FREE_INODE_COUNT,
11407 N_("Free @is count wrong (%i, counted=%j).\n"),
11408 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11410 /* Free blocks count for group wrong */
11411 { PR_5_FREE_BLOCK_COUNT_GROUP,
11412 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11413 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11415 /* Free blocks count wrong */
11416 { PR_5_FREE_BLOCK_COUNT,
11417 N_("Free @bs count wrong (%b, counted=%c).\n"),
11418 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11420 /* Programming error: bitmap endpoints don't match */
11421 { PR_5_BMAP_ENDPOINTS,
11422 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11423 "match calculated @B endpoints (%i, %j)\n"),
11424 PROMPT_NONE, PR_FATAL },
11426 /* Internal error: fudging end of bitmap */
11427 { PR_5_FUDGE_BITMAP_ERROR,
11428 N_("Internal error: fudging end of bitmap (%N)\n"),
11429 PROMPT_NONE, PR_FATAL },
11431 /* Error copying in replacement inode bitmap */
11432 { PR_5_COPY_IBITMAP_ERROR,
11433 "Error copying in replacement @i @B: %m\n",
11434 PROMPT_NONE, PR_FATAL },
11436 /* Error copying in replacement block bitmap */
11437 { PR_5_COPY_BBITMAP_ERROR,
11438 "Error copying in replacement @b @B: %m\n",
11439 PROMPT_NONE, PR_FATAL },
11441 /* Block range not used, but marked in bitmap */
11442 { PR_5_BLOCK_RANGE_UNUSED,
11444 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11446 /* Block range used, but not marked used in bitmap */
11447 { PR_5_BLOCK_RANGE_USED,
11449 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11451 /* Inode range not used, but marked in bitmap */
11452 { PR_5_INODE_RANGE_UNUSED,
11454 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11456 /* Inode range used, but not marked used in bitmap */
11457 { PR_5_INODE_RANGE_USED,
11459 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11465 * This is the latch flags register. It allows several problems to be
11466 * "latched" together. This means that the user has to answer but one
11467 * question for the set of problems, and all of the associated
11468 * problems will be either fixed or not fixed.
11470 static struct latch_descr pr_latch_info[] = {
11471 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11472 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11473 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11474 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11475 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11476 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11477 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11478 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11479 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11483 static const struct e2fsck_problem *find_problem(problem_t code)
11487 for (i=0; problem_table[i].e2p_code; i++) {
11488 if (problem_table[i].e2p_code == code)
11489 return &problem_table[i];
11494 static struct latch_descr *find_latch(int code)
11498 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11499 if (pr_latch_info[i].latch_code == code)
11500 return &pr_latch_info[i];
11505 int end_problem_latch(e2fsck_t ctx, int mask)
11507 struct latch_descr *ldesc;
11508 struct problem_context pctx;
11511 ldesc = find_latch(mask);
11512 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11513 clear_problem_context(&pctx);
11514 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11516 ldesc->flags &= ~(PRL_VARIABLE);
11520 int set_latch_flags(int mask, int setflags, int clearflags)
11522 struct latch_descr *ldesc;
11524 ldesc = find_latch(mask);
11527 ldesc->flags |= setflags;
11528 ldesc->flags &= ~clearflags;
11532 void clear_problem_context(struct problem_context *ctx)
11534 memset(ctx, 0, sizeof(struct problem_context));
11535 ctx->blkcount = -1;
11539 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11541 ext2_filsys fs = ctx->fs;
11542 const struct e2fsck_problem *ptr;
11543 struct latch_descr *ldesc = 0;
11544 const char *message;
11545 int def_yn, answer, ans;
11546 int print_answer = 0;
11549 ptr = find_problem(code);
11551 printf(_("Unhandled error code (0x%x)!\n"), code);
11555 if ((ptr->flags & PR_NO_DEFAULT) ||
11556 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11557 (ctx->options & E2F_OPT_NO))
11561 * Do special latch processing. This is where we ask the
11562 * latch question, if it exists
11564 if (ptr->flags & PR_LATCH_MASK) {
11565 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11566 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11567 ans = fix_problem(ctx, ldesc->question, pctx);
11569 ldesc->flags |= PRL_YES;
11571 ldesc->flags |= PRL_NO;
11572 ldesc->flags |= PRL_LATCHED;
11574 if (ldesc->flags & PRL_SUPPRESS)
11577 if ((ptr->flags & PR_PREEN_NOMSG) &&
11578 (ctx->options & E2F_OPT_PREEN))
11580 if ((ptr->flags & PR_NO_NOMSG) &&
11581 (ctx->options & E2F_OPT_NO))
11584 message = ptr->e2p_description;
11585 if ((ctx->options & E2F_OPT_PREEN) &&
11586 !(ptr->flags & PR_PREEN_NOHDR)) {
11587 printf("%s: ", ctx->device_name ?
11588 ctx->device_name : ctx->filesystem_name);
11591 print_e2fsck_message(ctx, _(message), pctx, 1);
11593 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11596 if (ptr->flags & PR_FATAL)
11597 fatal_error(ctx, 0);
11599 if (ptr->prompt == PROMPT_NONE) {
11600 if (ptr->flags & PR_NOCOLLATE)
11605 if (ctx->options & E2F_OPT_PREEN) {
11607 if (!(ptr->flags & PR_PREEN_NOMSG))
11609 } else if ((ptr->flags & PR_LATCH_MASK) &&
11610 (ldesc->flags & (PRL_YES | PRL_NO))) {
11613 if (ldesc->flags & PRL_YES)
11618 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11619 if (!answer && !(ptr->flags & PR_NO_OK))
11620 ext2fs_unmark_valid(fs);
11623 printf("%s.\n", answer ?
11624 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11628 if ((ptr->prompt == PROMPT_ABORT) && answer)
11629 fatal_error(ctx, 0);
11631 if (ptr->flags & PR_AFTER_CODE)
11632 answer = fix_problem(ctx, ptr->second_code, pctx);
11638 * linux/fs/recovery.c
11640 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11644 * Maintain information about the progress of the recovery job, so that
11645 * the different passes can carry information between them.
11647 struct recovery_info
11649 tid_t start_transaction;
11650 tid_t end_transaction;
11654 int nr_revoke_hits;
11657 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11658 static int do_one_pass(journal_t *journal,
11659 struct recovery_info *info, enum passtype pass);
11660 static int scan_revoke_records(journal_t *, struct buffer_head *,
11661 tid_t, struct recovery_info *);
11664 * Read a block from the journal
11667 static int jread(struct buffer_head **bhp, journal_t *journal,
11668 unsigned int offset)
11671 unsigned long blocknr;
11672 struct buffer_head *bh;
11676 J_ASSERT (offset < journal->j_maxlen);
11678 err = journal_bmap(journal, offset, &blocknr);
11681 printk (KERN_ERR "JBD: bad block at offset %u\n",
11686 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11690 if (!buffer_uptodate(bh)) {
11691 /* If this is a brand new buffer, start readahead.
11692 Otherwise, we assume we are already reading it. */
11693 if (!buffer_req(bh))
11694 do_readahead(journal, offset);
11695 wait_on_buffer(bh);
11698 if (!buffer_uptodate(bh)) {
11699 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11711 * Count the number of in-use tags in a journal descriptor block.
11714 static int count_tags(struct buffer_head *bh, int size)
11717 journal_block_tag_t * tag;
11720 tagp = &bh->b_data[sizeof(journal_header_t)];
11722 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11723 tag = (journal_block_tag_t *) tagp;
11726 tagp += sizeof(journal_block_tag_t);
11727 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11730 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11738 /* Make sure we wrap around the log correctly! */
11739 #define wrap(journal, var) \
11741 if (var >= (journal)->j_last) \
11742 var -= ((journal)->j_last - (journal)->j_first); \
11746 * int journal_recover(journal_t *journal) - recovers a on-disk journal
11747 * @journal: the journal to recover
11749 * The primary function for recovering the log contents when mounting a
11750 * journaled device.
11752 * Recovery is done in three passes. In the first pass, we look for the
11753 * end of the log. In the second, we assemble the list of revoke
11754 * blocks. In the third and final pass, we replay any un-revoked blocks
11757 int journal_recover(journal_t *journal)
11760 journal_superblock_t * sb;
11762 struct recovery_info info;
11764 memset(&info, 0, sizeof(info));
11765 sb = journal->j_superblock;
11768 * The journal superblock's s_start field (the current log head)
11769 * is always zero if, and only if, the journal was cleanly
11773 if (!sb->s_start) {
11774 jbd_debug(1, "No recovery required, last transaction %d\n",
11775 ntohl(sb->s_sequence));
11776 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11780 err = do_one_pass(journal, &info, PASS_SCAN);
11782 err = do_one_pass(journal, &info, PASS_REVOKE);
11784 err = do_one_pass(journal, &info, PASS_REPLAY);
11786 jbd_debug(0, "JBD: recovery, exit status %d, "
11787 "recovered transactions %u to %u\n",
11788 err, info.start_transaction, info.end_transaction);
11789 jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11790 info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11792 /* Restart the log at the next transaction ID, thus invalidating
11793 * any existing commit records in the log. */
11794 journal->j_transaction_sequence = ++info.end_transaction;
11796 journal_clear_revoke(journal);
11797 sync_blockdev(journal->j_fs_dev);
11801 static int do_one_pass(journal_t *journal,
11802 struct recovery_info *info, enum passtype pass)
11804 unsigned int first_commit_ID, next_commit_ID;
11805 unsigned long next_log_block;
11806 int err, success = 0;
11807 journal_superblock_t * sb;
11808 journal_header_t * tmp;
11809 struct buffer_head * bh;
11810 unsigned int sequence;
11813 /* Precompute the maximum metadata descriptors in a descriptor block */
11814 int MAX_BLOCKS_PER_DESC;
11815 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11816 / sizeof(journal_block_tag_t));
11819 * First thing is to establish what we expect to find in the log
11820 * (in terms of transaction IDs), and where (in terms of log
11821 * block offsets): query the superblock.
11824 sb = journal->j_superblock;
11825 next_commit_ID = ntohl(sb->s_sequence);
11826 next_log_block = ntohl(sb->s_start);
11828 first_commit_ID = next_commit_ID;
11829 if (pass == PASS_SCAN)
11830 info->start_transaction = first_commit_ID;
11832 jbd_debug(1, "Starting recovery pass %d\n", pass);
11835 * Now we walk through the log, transaction by transaction,
11836 * making sure that each transaction has a commit block in the
11837 * expected place. Each complete transaction gets replayed back
11838 * into the main filesystem.
11844 journal_block_tag_t * tag;
11845 struct buffer_head * obh;
11846 struct buffer_head * nbh;
11848 /* If we already know where to stop the log traversal,
11849 * check right now that we haven't gone past the end of
11852 if (pass != PASS_SCAN)
11853 if (tid_geq(next_commit_ID, info->end_transaction))
11856 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11857 next_commit_ID, next_log_block, journal->j_last);
11859 /* Skip over each chunk of the transaction looking
11860 * either the next descriptor block or the final commit
11863 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11864 err = jread(&bh, journal, next_log_block);
11869 wrap(journal, next_log_block);
11871 /* What kind of buffer is it?
11873 * If it is a descriptor block, check that it has the
11874 * expected sequence number. Otherwise, we're all done
11877 tmp = (journal_header_t *)bh->b_data;
11879 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11884 blocktype = ntohl(tmp->h_blocktype);
11885 sequence = ntohl(tmp->h_sequence);
11886 jbd_debug(3, "Found magic %d, sequence %d\n",
11887 blocktype, sequence);
11889 if (sequence != next_commit_ID) {
11894 /* OK, we have a valid descriptor block which matches
11895 * all of the sequence number checks. What are we going
11896 * to do with it? That depends on the pass... */
11898 switch(blocktype) {
11899 case JFS_DESCRIPTOR_BLOCK:
11900 /* If it is a valid descriptor block, replay it
11901 * in pass REPLAY; otherwise, just skip over the
11902 * blocks it describes. */
11903 if (pass != PASS_REPLAY) {
11905 count_tags(bh, journal->j_blocksize);
11906 wrap(journal, next_log_block);
11911 /* A descriptor block: we can now write all of
11912 * the data blocks. Yay, useful work is finally
11913 * getting done here! */
11915 tagp = &bh->b_data[sizeof(journal_header_t)];
11916 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11917 <= journal->j_blocksize) {
11918 unsigned long io_block;
11920 tag = (journal_block_tag_t *) tagp;
11921 flags = ntohl(tag->t_flags);
11923 io_block = next_log_block++;
11924 wrap(journal, next_log_block);
11925 err = jread(&obh, journal, io_block);
11927 /* Recover what we can, but
11928 * report failure at the end. */
11931 "JBD: IO error %d recovering "
11932 "block %ld in log\n",
11935 unsigned long blocknr;
11937 J_ASSERT(obh != NULL);
11938 blocknr = ntohl(tag->t_blocknr);
11940 /* If the block has been
11941 * revoked, then we're all done
11943 if (journal_test_revoke
11947 ++info->nr_revoke_hits;
11951 /* Find a buffer for the new
11952 * data being restored */
11953 nbh = getblk(journal->j_fs_dev,
11955 journal->j_blocksize);
11958 "JBD: Out of memory "
11959 "during recovery.\n");
11967 memcpy(nbh->b_data, obh->b_data,
11968 journal->j_blocksize);
11969 if (flags & JFS_FLAG_ESCAPE) {
11970 *((unsigned int *)bh->b_data) =
11971 htonl(JFS_MAGIC_NUMBER);
11974 BUFFER_TRACE(nbh, "marking dirty");
11975 mark_buffer_uptodate(nbh, 1);
11976 mark_buffer_dirty(nbh);
11977 BUFFER_TRACE(nbh, "marking uptodate");
11978 ++info->nr_replays;
11979 /* ll_rw_block(WRITE, 1, &nbh); */
11980 unlock_buffer(nbh);
11986 tagp += sizeof(journal_block_tag_t);
11987 if (!(flags & JFS_FLAG_SAME_UUID))
11990 if (flags & JFS_FLAG_LAST_TAG)
11997 case JFS_COMMIT_BLOCK:
11998 /* Found an expected commit block: not much to
11999 * do other than move on to the next sequence
12005 case JFS_REVOKE_BLOCK:
12006 /* If we aren't in the REVOKE pass, then we can
12007 * just skip over this block. */
12008 if (pass != PASS_REVOKE) {
12013 err = scan_revoke_records(journal, bh,
12014 next_commit_ID, info);
12021 jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12029 * We broke out of the log scan loop: either we came to the
12030 * known end of the log or we found an unexpected block in the
12031 * log. If the latter happened, then we know that the "current"
12032 * transaction marks the end of the valid log.
12035 if (pass == PASS_SCAN)
12036 info->end_transaction = next_commit_ID;
12038 /* It's really bad news if different passes end up at
12039 * different places (but possible due to IO errors). */
12040 if (info->end_transaction != next_commit_ID) {
12041 printk (KERN_ERR "JBD: recovery pass %d ended at "
12042 "transaction %u, expected %u\n",
12043 pass, next_commit_ID, info->end_transaction);
12056 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12058 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12059 tid_t sequence, struct recovery_info *info)
12061 journal_revoke_header_t *header;
12064 header = (journal_revoke_header_t *) bh->b_data;
12065 offset = sizeof(journal_revoke_header_t);
12066 max = ntohl(header->r_count);
12068 while (offset < max) {
12069 unsigned long blocknr;
12072 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12074 err = journal_set_revoke(journal, blocknr, sequence);
12077 ++info->nr_revokes;
12084 * rehash.c --- rebuild hash tree directories
12086 * This algorithm is designed for simplicity of implementation and to
12087 * pack the directory as much as possible. It however requires twice
12088 * as much memory as the size of the directory. The maximum size
12089 * directory supported using a 4k blocksize is roughly a gigabyte, and
12090 * so there may very well be problems with machines that don't have
12091 * virtual memory, and obscenely large directories.
12093 * An alternate algorithm which is much more disk intensive could be
12094 * written, and probably will need to be written in the future. The
12095 * design goals of such an algorithm are: (a) use (roughly) constant
12096 * amounts of memory, no matter how large the directory, (b) the
12097 * directory must be safe at all times, even if e2fsck is interrupted
12098 * in the middle, (c) we must use minimal amounts of extra disk
12099 * blocks. This pretty much requires an incremental approach, where
12100 * we are reading from one part of the directory, and inserting into
12101 * the front half. So the algorithm will have to keep track of a
12102 * moving block boundary between the new tree and the old tree, and
12103 * files will need to be moved from the old directory and inserted
12104 * into the new tree. If the new directory requires space which isn't
12105 * yet available, blocks from the beginning part of the old directory
12106 * may need to be moved to the end of the directory to make room for
12109 * --------------------------------------------------------
12110 * | new tree | | old tree |
12111 * --------------------------------------------------------
12113 * tail new head old
12115 * This is going to be a pain in the tuckus to implement, and will
12116 * require a lot more disk accesses. So I'm going to skip it for now;
12117 * it's only really going to be an issue for really, really big
12118 * filesystems (when we reach the level of tens of millions of files
12119 * in a single directory). It will probably be easier to simply
12120 * require that e2fsck use VM first.
12123 struct fill_dir_struct {
12125 struct ext2_inode *inode;
12128 struct hash_entry *harray;
12129 int max_array, num_array;
12135 struct hash_entry {
12136 ext2_dirhash_t hash;
12137 ext2_dirhash_t minor_hash;
12138 struct ext2_dir_entry *dir;
12145 ext2_dirhash_t *hashes;
12148 static int fill_dir_block(ext2_filsys fs,
12150 e2_blkcnt_t blockcnt,
12151 blk_t ref_block FSCK_ATTR((unused)),
12152 int ref_offset FSCK_ATTR((unused)),
12155 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
12156 struct hash_entry *new_array, *ent;
12157 struct ext2_dir_entry *dirent;
12159 unsigned int offset, dir_offset;
12164 offset = blockcnt * fs->blocksize;
12165 if (offset + fs->blocksize > fd->inode->i_size) {
12166 fd->err = EXT2_ET_DIR_CORRUPTED;
12167 return BLOCK_ABORT;
12169 dir = (fd->buf+offset);
12170 if (HOLE_BLKADDR(*block_nr)) {
12171 memset(dir, 0, fs->blocksize);
12172 dirent = (struct ext2_dir_entry *) dir;
12173 dirent->rec_len = fs->blocksize;
12175 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12177 return BLOCK_ABORT;
12179 /* While the directory block is "hot", index it. */
12181 while (dir_offset < fs->blocksize) {
12182 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12183 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12184 (dirent->rec_len < 8) ||
12185 ((dirent->rec_len % 4) != 0) ||
12186 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12187 fd->err = EXT2_ET_DIR_CORRUPTED;
12188 return BLOCK_ABORT;
12190 dir_offset += dirent->rec_len;
12191 if (dirent->inode == 0)
12193 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12194 (dirent->name[0] == '.'))
12196 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12197 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12198 fd->parent = dirent->inode;
12201 if (fd->num_array >= fd->max_array) {
12202 new_array = realloc(fd->harray,
12203 sizeof(struct hash_entry) * (fd->max_array+500));
12206 return BLOCK_ABORT;
12208 fd->harray = new_array;
12209 fd->max_array += 500;
12211 ent = fd->harray + fd->num_array++;
12213 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12215 ent->hash = ent->minor_hash = 0;
12217 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12219 dirent->name_len & 0xFF,
12220 fs->super->s_hash_seed,
12221 &ent->hash, &ent->minor_hash);
12223 return BLOCK_ABORT;
12230 /* Used for sorting the hash entry */
12231 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12233 const struct hash_entry *he_a = (const struct hash_entry *) a;
12234 const struct hash_entry *he_b = (const struct hash_entry *) b;
12238 min_len = he_a->dir->name_len;
12239 if (min_len > he_b->dir->name_len)
12240 min_len = he_b->dir->name_len;
12242 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12244 if (he_a->dir->name_len > he_b->dir->name_len)
12246 else if (he_a->dir->name_len < he_b->dir->name_len)
12249 ret = he_b->dir->inode - he_a->dir->inode;
12254 /* Used for sorting the hash entry */
12255 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12257 const struct hash_entry *he_a = (const struct hash_entry *) a;
12258 const struct hash_entry *he_b = (const struct hash_entry *) b;
12261 if (he_a->hash > he_b->hash)
12263 else if (he_a->hash < he_b->hash)
12266 if (he_a->minor_hash > he_b->minor_hash)
12268 else if (he_a->minor_hash < he_b->minor_hash)
12271 ret = name_cmp(a, b);
12276 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12282 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12285 outdir->buf = new_mem;
12286 new_mem = realloc(outdir->hashes,
12287 blocks * sizeof(ext2_dirhash_t));
12290 outdir->hashes = new_mem;
12292 outdir->buf = malloc(blocks * fs->blocksize);
12293 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12296 outdir->max = blocks;
12300 static void free_out_dir(struct out_dir *outdir)
12303 free(outdir->hashes);
12308 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12313 if (outdir->num >= outdir->max) {
12314 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12318 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12319 memset(*ret, 0, fs->blocksize);
12324 * This function is used to make a unique filename. We do this by
12325 * appending ~0, and then incrementing the number. However, we cannot
12326 * expand the length of the filename beyond the padding available in
12327 * the directory entry.
12329 static void mutate_name(char *str, __u16 *len)
12332 __u16 l = *len & 0xFF, h = *len & 0xff00;
12335 * First check to see if it looks the name has been mutated
12338 for (i = l-1; i > 0; i--) {
12339 if (!isdigit(str[i]))
12342 if ((i == l-1) || (str[i] != '~')) {
12343 if (((l-1) & 3) < 2)
12352 for (i = l-1; i >= 0; i--) {
12353 if (isdigit(str[i])) {
12365 else if (str[0] == 'Z') {
12370 } else if (i > 0) {
12383 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12385 struct fill_dir_struct *fd)
12387 struct problem_context pctx;
12388 struct hash_entry *ent, *prev;
12391 char new_name[256];
12394 clear_problem_context(&pctx);
12397 for (i=1; i < fd->num_array; i++) {
12398 ent = fd->harray + i;
12400 if (!ent->dir->inode ||
12401 ((ent->dir->name_len & 0xFF) !=
12402 (prev->dir->name_len & 0xFF)) ||
12403 (strncmp(ent->dir->name, prev->dir->name,
12404 ent->dir->name_len & 0xFF)))
12406 pctx.dirent = ent->dir;
12407 if ((ent->dir->inode == prev->dir->inode) &&
12408 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12409 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12410 ent->dir->inode = 0;
12414 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12415 new_len = ent->dir->name_len;
12416 mutate_name(new_name, &new_len);
12417 for (j=0; j < fd->num_array; j++) {
12419 ((ent->dir->name_len & 0xFF) !=
12420 (fd->harray[j].dir->name_len & 0xFF)) ||
12421 (strncmp(new_name, fd->harray[j].dir->name,
12424 mutate_name(new_name, &new_len);
12428 new_name[new_len & 0xFF] = 0;
12429 pctx.str = new_name;
12430 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12431 memcpy(ent->dir->name, new_name, new_len & 0xFF);
12432 ent->dir->name_len = new_len;
12433 ext2fs_dirhash(fs->super->s_def_hash_version,
12435 ent->dir->name_len & 0xFF,
12436 fs->super->s_hash_seed,
12437 &ent->hash, &ent->minor_hash);
12445 static errcode_t copy_dir_entries(ext2_filsys fs,
12446 struct fill_dir_struct *fd,
12447 struct out_dir *outdir)
12451 struct hash_entry *ent;
12452 struct ext2_dir_entry *dirent;
12453 int i, rec_len, left;
12454 ext2_dirhash_t prev_hash;
12458 retval = alloc_size_dir(fs, outdir,
12459 (fd->dir_size / fs->blocksize) + 2);
12462 outdir->num = fd->compress ? 0 : 1;
12464 outdir->hashes[0] = 0;
12466 if ((retval = get_next_block(fs, outdir, &block_start)))
12468 dirent = (struct ext2_dir_entry *) block_start;
12469 left = fs->blocksize;
12470 for (i=0; i < fd->num_array; i++) {
12471 ent = fd->harray + i;
12472 if (ent->dir->inode == 0)
12474 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12475 if (rec_len > left) {
12477 dirent->rec_len += left;
12478 if ((retval = get_next_block(fs, outdir,
12483 left = fs->blocksize - offset;
12484 dirent = (struct ext2_dir_entry *) (block_start + offset);
12486 if (ent->hash == prev_hash)
12487 outdir->hashes[outdir->num-1] = ent->hash | 1;
12489 outdir->hashes[outdir->num-1] = ent->hash;
12491 dirent->inode = ent->dir->inode;
12492 dirent->name_len = ent->dir->name_len;
12493 dirent->rec_len = rec_len;
12494 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12498 dirent->rec_len += left;
12502 prev_hash = ent->hash;
12505 dirent->rec_len += left;
12511 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12512 ext2_ino_t ino, ext2_ino_t parent)
12514 struct ext2_dir_entry *dir;
12515 struct ext2_dx_root_info *root;
12516 struct ext2_dx_countlimit *limits;
12519 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12520 filetype = EXT2_FT_DIR << 8;
12522 memset(buf, 0, fs->blocksize);
12523 dir = (struct ext2_dir_entry *) buf;
12525 dir->name[0] = '.';
12526 dir->name_len = 1 | filetype;
12528 dir = (struct ext2_dir_entry *) (buf + 12);
12529 dir->inode = parent;
12530 dir->name[0] = '.';
12531 dir->name[1] = '.';
12532 dir->name_len = 2 | filetype;
12533 dir->rec_len = fs->blocksize - 12;
12535 root = (struct ext2_dx_root_info *) (buf+24);
12536 root->reserved_zero = 0;
12537 root->hash_version = fs->super->s_def_hash_version;
12538 root->info_length = 8;
12539 root->indirect_levels = 0;
12540 root->unused_flags = 0;
12542 limits = (struct ext2_dx_countlimit *) (buf+32);
12543 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12550 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12552 struct ext2_dir_entry *dir;
12553 struct ext2_dx_countlimit *limits;
12555 memset(buf, 0, fs->blocksize);
12556 dir = (struct ext2_dir_entry *) buf;
12558 dir->rec_len = fs->blocksize;
12560 limits = (struct ext2_dx_countlimit *) (buf+8);
12561 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12564 return (struct ext2_dx_entry *) limits;
12568 * This function takes the leaf nodes which have been written in
12569 * outdir, and populates the root node and any necessary interior nodes.
12571 static errcode_t calculate_tree(ext2_filsys fs,
12572 struct out_dir *outdir,
12576 struct ext2_dx_root_info *root_info;
12577 struct ext2_dx_entry *root, *dx_ent = 0;
12578 struct ext2_dx_countlimit *root_limit, *limit;
12580 char * block_start;
12581 int i, c1, c2, nblks;
12582 int limit_offset, root_offset;
12584 root_info = set_root_node(fs, outdir->buf, ino, parent);
12585 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12586 root_info->info_length;
12587 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12588 c1 = root_limit->limit;
12589 nblks = outdir->num;
12591 /* Write out the pointer blocks */
12592 if (nblks-1 <= c1) {
12593 /* Just write out the root block, and we're done */
12594 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12595 for (i=1; i < nblks; i++) {
12596 root->block = ext2fs_cpu_to_le32(i);
12599 ext2fs_cpu_to_le32(outdir->hashes[i]);
12606 root_info->indirect_levels = 1;
12607 for (i=1; i < nblks; i++) {
12612 limit->limit = limit->count =
12613 ext2fs_cpu_to_le16(limit->limit);
12614 root = (struct ext2_dx_entry *)
12615 (outdir->buf + root_offset);
12616 root->block = ext2fs_cpu_to_le32(outdir->num);
12619 ext2fs_cpu_to_le32(outdir->hashes[i]);
12620 if ((retval = get_next_block(fs, outdir,
12623 dx_ent = set_int_node(fs, block_start);
12624 limit = (struct ext2_dx_countlimit *) dx_ent;
12626 root_offset += sizeof(struct ext2_dx_entry);
12629 dx_ent->block = ext2fs_cpu_to_le32(i);
12630 if (c2 != limit->limit)
12632 ext2fs_cpu_to_le32(outdir->hashes[i]);
12636 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12637 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12639 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12640 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12641 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12646 struct write_dir_struct {
12647 struct out_dir *outdir;
12654 * Helper function which writes out a directory block.
12656 static int write_dir_block(ext2_filsys fs,
12658 e2_blkcnt_t blockcnt,
12659 blk_t ref_block FSCK_ATTR((unused)),
12660 int ref_offset FSCK_ATTR((unused)),
12663 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12667 if (*block_nr == 0)
12669 if (blockcnt >= wd->outdir->num) {
12670 e2fsck_read_bitmaps(wd->ctx);
12672 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12673 ext2fs_block_alloc_stats(fs, blk, -1);
12676 return BLOCK_CHANGED;
12681 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12682 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12684 return BLOCK_ABORT;
12688 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12689 struct out_dir *outdir,
12690 ext2_ino_t ino, int compress)
12692 struct write_dir_struct wd;
12694 struct ext2_inode inode;
12696 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12700 wd.outdir = outdir;
12705 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12706 write_dir_block, &wd);
12712 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12714 inode.i_flags &= ~EXT2_INDEX_FL;
12716 inode.i_flags |= EXT2_INDEX_FL;
12717 inode.i_size = outdir->num * fs->blocksize;
12718 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12719 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12724 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12726 ext2_filsys fs = ctx->fs;
12728 struct ext2_inode inode;
12730 struct fill_dir_struct fd;
12731 struct out_dir outdir;
12733 outdir.max = outdir.num = 0;
12736 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12740 dir_buf = malloc(inode.i_size);
12744 fd.max_array = inode.i_size / 32;
12746 fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12756 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12757 (inode.i_size / fs->blocksize) < 2)
12761 /* Read in the entire directory into memory */
12762 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12763 fill_dir_block, &fd);
12770 printf("%d entries (%d bytes) found in inode %d\n",
12771 fd.num_array, fd.dir_size, ino);
12774 /* Sort the list */
12777 qsort(fd.harray+2, fd.num_array-2,
12778 sizeof(struct hash_entry), name_cmp);
12780 qsort(fd.harray, fd.num_array,
12781 sizeof(struct hash_entry), hash_cmp);
12784 * Look for duplicates
12786 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12789 if (ctx->options & E2F_OPT_NO) {
12795 * Copy the directory entries. In a htree directory these
12796 * will become the leaf nodes.
12798 retval = copy_dir_entries(fs, &fd, &outdir);
12802 free(dir_buf); dir_buf = 0;
12804 if (!fd.compress) {
12805 /* Calculate the interior nodes */
12806 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12811 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12817 free_out_dir(&outdir);
12821 void e2fsck_rehash_directories(e2fsck_t ctx)
12823 struct problem_context pctx;
12824 #ifdef RESOURCE_TRACK
12825 struct resource_track rtrack;
12827 struct dir_info *dir;
12828 ext2_u32_iterate iter;
12831 int i, cur, max, all_dirs, dir_index, first = 1;
12833 #ifdef RESOURCE_TRACK
12834 init_resource_track(&rtrack);
12837 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12839 if (!ctx->dirs_to_hash && !all_dirs)
12842 e2fsck_get_lost_and_found(ctx, 0);
12844 clear_problem_context(&pctx);
12846 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12850 max = e2fsck_get_num_dirinfo(ctx);
12852 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12855 pctx.errcode = retval;
12856 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12859 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12863 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12867 if (!ext2fs_u32_list_iterate(iter, &ino))
12870 if (ino == ctx->lost_and_found)
12874 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12878 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12880 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12881 if (pctx.errcode) {
12882 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12883 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12885 if (ctx->progress && !ctx->progress_fd)
12886 e2fsck_simple_progress(ctx, "Rebuilding directory",
12887 100.0 * (float) (++cur) / (float) max, ino);
12889 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12891 ext2fs_u32_list_iterate_end(iter);
12893 ext2fs_u32_list_free(ctx->dirs_to_hash);
12894 ctx->dirs_to_hash = 0;
12896 #ifdef RESOURCE_TRACK
12897 if (ctx->options & E2F_OPT_TIME2) {
12898 e2fsck_clear_progbar(ctx);
12899 print_resource_track("Pass 3A", &rtrack);
12905 * linux/fs/revoke.c
12907 * Journal revoke routines for the generic filesystem journaling code;
12908 * part of the ext2fs journaling system.
12910 * Revoke is the mechanism used to prevent old log records for deleted
12911 * metadata from being replayed on top of newer data using the same
12912 * blocks. The revoke mechanism is used in two separate places:
12914 * + Commit: during commit we write the entire list of the current
12915 * transaction's revoked blocks to the journal
12917 * + Recovery: during recovery we record the transaction ID of all
12918 * revoked blocks. If there are multiple revoke records in the log
12919 * for a single block, only the last one counts, and if there is a log
12920 * entry for a block beyond the last revoke, then that log entry still
12923 * We can get interactions between revokes and new log data within a
12924 * single transaction:
12926 * Block is revoked and then journaled:
12927 * The desired end result is the journaling of the new block, so we
12928 * cancel the revoke before the transaction commits.
12930 * Block is journaled and then revoked:
12931 * The revoke must take precedence over the write of the block, so we
12932 * need either to cancel the journal entry or to write the revoke
12933 * later in the log than the log block. In this case, we choose the
12934 * latter: journaling a block cancels any revoke record for that block
12935 * in the current transaction, so any revoke for that block in the
12936 * transaction must have happened after the block was journaled and so
12937 * the revoke must take precedence.
12939 * Block is revoked and then written as data:
12940 * The data write is allowed to succeed, but the revoke is _not_
12941 * cancelled. We still need to prevent old log records from
12942 * overwriting the new data. We don't even need to clear the revoke
12945 * Revoke information on buffers is a tri-state value:
12947 * RevokeValid clear: no cached revoke status, need to look it up
12948 * RevokeValid set, Revoked clear:
12949 * buffer has not been revoked, and cancel_revoke
12951 * RevokeValid set, Revoked set:
12952 * buffer has been revoked.
12955 static kmem_cache_t *revoke_record_cache;
12956 static kmem_cache_t *revoke_table_cache;
12958 /* Each revoke record represents one single revoked block. During
12959 journal replay, this involves recording the transaction ID of the
12960 last transaction to revoke this block. */
12962 struct jbd_revoke_record_s
12964 struct list_head hash;
12965 tid_t sequence; /* Used for recovery only */
12966 unsigned long blocknr;
12970 /* The revoke table is just a simple hash table of revoke records. */
12971 struct jbd_revoke_table_s
12973 /* It is conceivable that we might want a larger hash table
12974 * for recovery. Must be a power of two. */
12977 struct list_head *hash_table;
12981 /* Utility functions to maintain the revoke table */
12983 /* Borrowed from buffer.c: this is a tried and tested block hash function */
12984 static inline int hash(journal_t *journal, unsigned long block)
12986 struct jbd_revoke_table_s *table = journal->j_revoke;
12987 int hash_shift = table->hash_shift;
12989 return ((block << (hash_shift - 6)) ^
12991 (block << (hash_shift - 12))) & (table->hash_size - 1);
12994 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
12997 struct list_head *hash_list;
12998 struct jbd_revoke_record_s *record;
13000 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13004 record->sequence = seq;
13005 record->blocknr = blocknr;
13006 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13007 list_add(&record->hash, hash_list);
13014 /* Find a revoke record in the journal's hash table. */
13016 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13017 unsigned long blocknr)
13019 struct list_head *hash_list;
13020 struct jbd_revoke_record_s *record;
13022 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13024 record = (struct jbd_revoke_record_s *) hash_list->next;
13025 while (&(record->hash) != hash_list) {
13026 if (record->blocknr == blocknr)
13028 record = (struct jbd_revoke_record_s *) record->hash.next;
13033 int journal_init_revoke_caches(void)
13035 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13036 if (revoke_record_cache == 0)
13039 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13040 if (revoke_table_cache == 0) {
13041 do_cache_destroy(revoke_record_cache);
13042 revoke_record_cache = NULL;
13048 void journal_destroy_revoke_caches(void)
13050 do_cache_destroy(revoke_record_cache);
13051 revoke_record_cache = 0;
13052 do_cache_destroy(revoke_table_cache);
13053 revoke_table_cache = 0;
13056 /* Initialise the revoke table for a given journal to a given size. */
13058 int journal_init_revoke(journal_t *journal, int hash_size)
13062 J_ASSERT (journal->j_revoke == NULL);
13064 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13065 if (!journal->j_revoke)
13068 /* Check that the hash_size is a power of two */
13069 J_ASSERT ((hash_size & (hash_size-1)) == 0);
13071 journal->j_revoke->hash_size = hash_size;
13075 while((tmp >>= 1UL) != 0UL)
13077 journal->j_revoke->hash_shift = shift;
13079 journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13080 if (!journal->j_revoke->hash_table) {
13081 free(journal->j_revoke);
13082 journal->j_revoke = NULL;
13086 for (tmp = 0; tmp < hash_size; tmp++)
13087 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13092 /* Destoy a journal's revoke table. The table must already be empty! */
13094 void journal_destroy_revoke(journal_t *journal)
13096 struct jbd_revoke_table_s *table;
13097 struct list_head *hash_list;
13100 table = journal->j_revoke;
13104 for (i=0; i<table->hash_size; i++) {
13105 hash_list = &table->hash_table[i];
13106 J_ASSERT (list_empty(hash_list));
13109 free(table->hash_table);
13111 journal->j_revoke = NULL;
13115 * Revoke support for recovery.
13117 * Recovery needs to be able to:
13119 * record all revoke records, including the tid of the latest instance
13120 * of each revoke in the journal
13122 * check whether a given block in a given transaction should be replayed
13123 * (ie. has not been revoked by a revoke record in that or a subsequent
13126 * empty the revoke table after recovery.
13130 * First, setting revoke records. We create a new revoke record for
13131 * every block ever revoked in the log as we scan it for recovery, and
13132 * we update the existing records if we find multiple revokes for a
13136 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13139 struct jbd_revoke_record_s *record;
13141 record = find_revoke_record(journal, blocknr);
13143 /* If we have multiple occurences, only record the
13144 * latest sequence number in the hashed record */
13145 if (tid_gt(sequence, record->sequence))
13146 record->sequence = sequence;
13149 return insert_revoke_hash(journal, blocknr, sequence);
13153 * Test revoke records. For a given block referenced in the log, has
13154 * that block been revoked? A revoke record with a given transaction
13155 * sequence number revokes all blocks in that transaction and earlier
13156 * ones, but later transactions still need replayed.
13159 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13162 struct jbd_revoke_record_s *record;
13164 record = find_revoke_record(journal, blocknr);
13167 if (tid_gt(sequence, record->sequence))
13173 * Finally, once recovery is over, we need to clear the revoke table so
13174 * that it can be reused by the running filesystem.
13177 void journal_clear_revoke(journal_t *journal)
13180 struct list_head *hash_list;
13181 struct jbd_revoke_record_s *record;
13182 struct jbd_revoke_table_s *revoke_var;
13184 revoke_var = journal->j_revoke;
13186 for (i = 0; i < revoke_var->hash_size; i++) {
13187 hash_list = &revoke_var->hash_table[i];
13188 while (!list_empty(hash_list)) {
13189 record = (struct jbd_revoke_record_s*) hash_list->next;
13190 list_del(&record->hash);
13197 * e2fsck.c - superblock checks
13200 #define MIN_CHECK 1
13201 #define MAX_CHECK 2
13203 static void check_super_value(e2fsck_t ctx, const char *descr,
13204 unsigned long value, int flags,
13205 unsigned long min_val, unsigned long max_val)
13207 struct problem_context pctx;
13209 if (((flags & MIN_CHECK) && (value < min_val)) ||
13210 ((flags & MAX_CHECK) && (value > max_val))) {
13211 clear_problem_context(&pctx);
13214 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13215 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13220 * This routine may get stubbed out in special compilations of the
13223 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13224 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13226 return (ext2fs_get_device_size(ctx->filesystem_name,
13227 EXT2_BLOCK_SIZE(ctx->fs->super),
13228 &ctx->num_blocks));
13233 * helper function to release an inode
13235 struct process_block_struct {
13238 struct problem_context *pctx;
13240 int truncate_offset;
13241 e2_blkcnt_t truncate_block;
13242 int truncated_blocks;
13247 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13248 e2_blkcnt_t blockcnt,
13249 blk_t ref_blk FSCK_ATTR((unused)),
13250 int ref_offset FSCK_ATTR((unused)),
13253 struct process_block_struct *pb;
13255 struct problem_context *pctx;
13256 blk_t blk = *block_nr;
13259 pb = (struct process_block_struct *) priv_data;
13264 pctx->blkcount = blockcnt;
13266 if (HOLE_BLKADDR(blk))
13269 if ((blk < fs->super->s_first_data_block) ||
13270 (blk >= fs->super->s_blocks_count)) {
13271 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13274 return BLOCK_ABORT;
13277 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13278 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13283 * If we are deleting an orphan, then we leave the fields alone.
13284 * If we are truncating an orphan, then update the inode fields
13285 * and clean up any partial block data.
13287 if (pb->truncating) {
13289 * We only remove indirect blocks if they are
13290 * completely empty.
13292 if (blockcnt < 0) {
13296 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13301 limit = fs->blocksize >> 2;
13302 for (i = 0, bp = (blk_t *) pb->buf;
13303 i < limit; i++, bp++)
13308 * We don't remove direct blocks until we've reached
13309 * the truncation block.
13311 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13314 * If part of the last block needs truncating, we do
13317 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13318 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13322 memset(pb->buf + pb->truncate_offset, 0,
13323 fs->blocksize - pb->truncate_offset);
13324 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13329 pb->truncated_blocks++;
13331 retval |= BLOCK_CHANGED;
13334 ext2fs_block_alloc_stats(fs, blk, -1);
13339 * This function releases an inode. Returns 1 if an inconsistency was
13340 * found. If the inode has a link count, then it is being truncated and
13343 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13344 struct ext2_inode *inode, char *block_buf,
13345 struct problem_context *pctx)
13347 struct process_block_struct pb;
13348 ext2_filsys fs = ctx->fs;
13352 if (!ext2fs_inode_has_valid_blocks(inode))
13355 pb.buf = block_buf + 3 * ctx->fs->blocksize;
13360 if (inode->i_links_count) {
13362 pb.truncate_block = (e2_blkcnt_t)
13363 ((((long long)inode->i_size_high << 32) +
13364 inode->i_size + fs->blocksize - 1) /
13366 pb.truncate_offset = inode->i_size % fs->blocksize;
13369 pb.truncate_block = 0;
13370 pb.truncate_offset = 0;
13372 pb.truncated_blocks = 0;
13373 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13374 block_buf, release_inode_block, &pb);
13376 com_err("release_inode_blocks", retval,
13377 _("while calling ext2fs_block_iterate for inode %d"),
13384 /* Refresh the inode since ext2fs_block_iterate may have changed it */
13385 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13387 if (pb.truncated_blocks)
13388 inode->i_blocks -= pb.truncated_blocks *
13389 (fs->blocksize / 512);
13391 if (inode->i_file_acl) {
13392 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13393 block_buf, -1, &count);
13394 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13399 com_err("release_inode_blocks", retval,
13400 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13405 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13406 inode->i_file_acl = 0;
13412 * This function releases all of the orphan inodes. It returns 1 if
13413 * it hit some error, and 0 on success.
13415 static int release_orphan_inodes(e2fsck_t ctx)
13417 ext2_filsys fs = ctx->fs;
13418 ext2_ino_t ino, next_ino;
13419 struct ext2_inode inode;
13420 struct problem_context pctx;
13423 if ((ino = fs->super->s_last_orphan) == 0)
13427 * Win or lose, we won't be using the head of the orphan inode
13430 fs->super->s_last_orphan = 0;
13431 ext2fs_mark_super_dirty(fs);
13434 * If the filesystem contains errors, don't run the orphan
13435 * list, since the orphan list can't be trusted; and we're
13436 * going to be running a full e2fsck run anyway...
13438 if (fs->super->s_state & EXT2_ERROR_FS)
13441 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13442 (ino > fs->super->s_inodes_count)) {
13443 clear_problem_context(&pctx);
13445 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13449 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13450 "block iterate buffer");
13451 e2fsck_read_bitmaps(ctx);
13454 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13455 clear_problem_context(&pctx);
13457 pctx.inode = &inode;
13458 pctx.str = inode.i_links_count ? _("Truncating") :
13461 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13463 next_ino = inode.i_dtime;
13465 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13466 (next_ino > fs->super->s_inodes_count))) {
13467 pctx.ino = next_ino;
13468 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13472 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13475 if (!inode.i_links_count) {
13476 ext2fs_inode_alloc_stats2(fs, ino, -1,
13477 LINUX_S_ISDIR(inode.i_mode));
13478 inode.i_dtime = time(0);
13482 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13485 ext2fs_free_mem(&block_buf);
13488 ext2fs_free_mem(&block_buf);
13493 * Check the resize inode to make sure it is sane. We check both for
13494 * the case where on-line resizing is not enabled (in which case the
13495 * resize inode should be cleared) as well as the case where on-line
13496 * resizing is enabled.
13498 static void check_resize_inode(e2fsck_t ctx)
13500 ext2_filsys fs = ctx->fs;
13501 struct ext2_inode inode;
13502 struct problem_context pctx;
13503 int i, j, gdt_off, ind_off;
13504 blk_t blk, pblk, expect;
13505 __u32 *dind_buf = 0, *ind_buf;
13508 clear_problem_context(&pctx);
13511 * If the resize inode feature isn't set, then
13512 * s_reserved_gdt_blocks must be zero.
13514 if (!(fs->super->s_feature_compat &
13515 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13516 if (fs->super->s_reserved_gdt_blocks) {
13517 pctx.num = fs->super->s_reserved_gdt_blocks;
13518 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13520 fs->super->s_reserved_gdt_blocks = 0;
13521 ext2fs_mark_super_dirty(fs);
13526 /* Read the resizde inode */
13527 pctx.ino = EXT2_RESIZE_INO;
13528 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13530 if (fs->super->s_feature_compat &
13531 EXT2_FEATURE_COMPAT_RESIZE_INODE)
13532 ctx->flags |= E2F_FLAG_RESIZE_INODE;
13537 * If the resize inode feature isn't set, check to make sure
13538 * the resize inode is cleared; then we're done.
13540 if (!(fs->super->s_feature_compat &
13541 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13542 for (i=0; i < EXT2_N_BLOCKS; i++) {
13543 if (inode.i_block[i])
13546 if ((i < EXT2_N_BLOCKS) &&
13547 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13548 memset(&inode, 0, sizeof(inode));
13549 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13556 * The resize inode feature is enabled; check to make sure the
13557 * only block in use is the double indirect block
13559 blk = inode.i_block[EXT2_DIND_BLOCK];
13560 for (i=0; i < EXT2_N_BLOCKS; i++) {
13561 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13564 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13565 !(inode.i_mode & LINUX_S_IFREG) ||
13566 (blk < fs->super->s_first_data_block ||
13567 blk >= fs->super->s_blocks_count)) {
13568 resize_inode_invalid:
13569 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13570 memset(&inode, 0, sizeof(inode));
13571 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13573 ctx->flags |= E2F_FLAG_RESIZE_INODE;
13575 if (!(ctx->options & E2F_OPT_READONLY)) {
13576 fs->super->s_state &= ~EXT2_VALID_FS;
13577 ext2fs_mark_super_dirty(fs);
13581 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13582 "resize dind buffer");
13583 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13585 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13587 goto resize_inode_invalid;
13589 gdt_off = fs->desc_blocks;
13590 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13591 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13592 i++, gdt_off++, pblk++) {
13593 gdt_off %= fs->blocksize/4;
13594 if (dind_buf[gdt_off] != pblk)
13595 goto resize_inode_invalid;
13596 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13598 goto resize_inode_invalid;
13600 for (j = 1; j < fs->group_desc_count; j++) {
13601 if (!ext2fs_bg_has_super(fs, j))
13603 expect = pblk + (j * fs->super->s_blocks_per_group);
13604 if (ind_buf[ind_off] != expect)
13605 goto resize_inode_invalid;
13611 ext2fs_free_mem(&dind_buf);
13615 static void check_super_block(e2fsck_t ctx)
13617 ext2_filsys fs = ctx->fs;
13618 blk_t first_block, last_block;
13619 struct ext2_super_block *sb = fs->super;
13620 struct ext2_group_desc *gd;
13621 blk_t blocks_per_group = fs->super->s_blocks_per_group;
13623 int inodes_per_block;
13628 struct problem_context pctx;
13629 __u32 free_blocks = 0, free_inodes = 0;
13631 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13632 ipg_max = inodes_per_block * (blocks_per_group - 4);
13633 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13634 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13635 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13636 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13637 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13639 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13640 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13641 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13642 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13643 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13644 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13646 clear_problem_context(&pctx);
13649 * Verify the super block constants...
13651 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13653 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13655 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13656 MAX_CHECK, 0, sb->s_blocks_count);
13657 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13658 MIN_CHECK | MAX_CHECK, 0,
13659 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13660 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13661 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13662 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13663 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13665 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13666 MIN_CHECK | MAX_CHECK, 8, bpg_max);
13667 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13668 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13669 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13670 MAX_CHECK, 0, sb->s_blocks_count / 2);
13671 check_super_value(ctx, "reserved_gdt_blocks",
13672 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13674 inode_size = EXT2_INODE_SIZE(sb);
13675 check_super_value(ctx, "inode_size",
13676 inode_size, MIN_CHECK | MAX_CHECK,
13677 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13678 if (inode_size & (inode_size - 1)) {
13679 pctx.num = inode_size;
13680 pctx.str = "inode_size";
13681 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13682 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13686 if (!ctx->num_blocks) {
13687 pctx.errcode = e2fsck_get_device_size(ctx);
13688 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13689 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13690 ctx->flags |= E2F_FLAG_ABORT;
13693 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13694 (ctx->num_blocks < sb->s_blocks_count)) {
13695 pctx.blk = sb->s_blocks_count;
13696 pctx.blk2 = ctx->num_blocks;
13697 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13698 ctx->flags |= E2F_FLAG_ABORT;
13704 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13705 pctx.blk = EXT2_BLOCK_SIZE(sb);
13706 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13707 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13708 ctx->flags |= E2F_FLAG_ABORT;
13712 should_be = sb->s_frags_per_group >>
13713 (sb->s_log_block_size - sb->s_log_frag_size);
13714 if (sb->s_blocks_per_group != should_be) {
13715 pctx.blk = sb->s_blocks_per_group;
13716 pctx.blk2 = should_be;
13717 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13718 ctx->flags |= E2F_FLAG_ABORT;
13722 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13723 if (sb->s_first_data_block != should_be) {
13724 pctx.blk = sb->s_first_data_block;
13725 pctx.blk2 = should_be;
13726 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13727 ctx->flags |= E2F_FLAG_ABORT;
13731 should_be = sb->s_inodes_per_group * fs->group_desc_count;
13732 if (sb->s_inodes_count != should_be) {
13733 pctx.ino = sb->s_inodes_count;
13734 pctx.ino2 = should_be;
13735 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13736 sb->s_inodes_count = should_be;
13737 ext2fs_mark_super_dirty(fs);
13742 * Verify the group descriptors....
13744 first_block = sb->s_first_data_block;
13745 last_block = first_block + blocks_per_group;
13747 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13750 if (i == fs->group_desc_count - 1)
13751 last_block = sb->s_blocks_count;
13752 if ((gd->bg_block_bitmap < first_block) ||
13753 (gd->bg_block_bitmap >= last_block)) {
13754 pctx.blk = gd->bg_block_bitmap;
13755 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13756 gd->bg_block_bitmap = 0;
13758 if (gd->bg_block_bitmap == 0) {
13759 ctx->invalid_block_bitmap_flag[i]++;
13760 ctx->invalid_bitmaps++;
13762 if ((gd->bg_inode_bitmap < first_block) ||
13763 (gd->bg_inode_bitmap >= last_block)) {
13764 pctx.blk = gd->bg_inode_bitmap;
13765 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13766 gd->bg_inode_bitmap = 0;
13768 if (gd->bg_inode_bitmap == 0) {
13769 ctx->invalid_inode_bitmap_flag[i]++;
13770 ctx->invalid_bitmaps++;
13772 if ((gd->bg_inode_table < first_block) ||
13773 ((gd->bg_inode_table +
13774 fs->inode_blocks_per_group - 1) >= last_block)) {
13775 pctx.blk = gd->bg_inode_table;
13776 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13777 gd->bg_inode_table = 0;
13779 if (gd->bg_inode_table == 0) {
13780 ctx->invalid_inode_table_flag[i]++;
13781 ctx->invalid_bitmaps++;
13783 free_blocks += gd->bg_free_blocks_count;
13784 free_inodes += gd->bg_free_inodes_count;
13785 first_block += sb->s_blocks_per_group;
13786 last_block += sb->s_blocks_per_group;
13788 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13789 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13790 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13791 ext2fs_unmark_valid(fs);
13796 * Update the global counts from the block group counts. This
13797 * is needed for an experimental patch which eliminates
13798 * locking the entire filesystem when allocating blocks or
13799 * inodes; if the filesystem is not unmounted cleanly, the
13800 * global counts may not be accurate.
13802 if ((free_blocks != sb->s_free_blocks_count) ||
13803 (free_inodes != sb->s_free_inodes_count)) {
13804 if (ctx->options & E2F_OPT_READONLY)
13805 ext2fs_unmark_valid(fs);
13807 sb->s_free_blocks_count = free_blocks;
13808 sb->s_free_inodes_count = free_inodes;
13809 ext2fs_mark_super_dirty(fs);
13813 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13814 (sb->s_free_inodes_count > sb->s_inodes_count))
13815 ext2fs_unmark_valid(fs);
13819 * If we have invalid bitmaps, set the error state of the
13822 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13823 sb->s_state &= ~EXT2_VALID_FS;
13824 ext2fs_mark_super_dirty(fs);
13827 clear_problem_context(&pctx);
13829 #ifndef EXT2_SKIP_UUID
13831 * If the UUID field isn't assigned, assign it.
13833 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13834 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13835 uuid_generate(sb->s_uuid);
13836 ext2fs_mark_super_dirty(fs);
13837 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13843 * For the Hurd, check to see if the filetype option is set,
13844 * since it doesn't support it.
13846 if (!(ctx->options & E2F_OPT_READONLY) &&
13847 fs->super->s_creator_os == EXT2_OS_HURD &&
13848 (fs->super->s_feature_incompat &
13849 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13850 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13851 fs->super->s_feature_incompat &=
13852 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13853 ext2fs_mark_super_dirty(fs);
13859 * If we have any of the compatibility flags set, we need to have a
13860 * revision 1 filesystem. Most kernels will not check the flags on
13861 * a rev 0 filesystem and we may have corruption issues because of
13862 * the incompatible changes to the filesystem.
13864 if (!(ctx->options & E2F_OPT_READONLY) &&
13865 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13866 (fs->super->s_feature_compat ||
13867 fs->super->s_feature_ro_compat ||
13868 fs->super->s_feature_incompat) &&
13869 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13870 ext2fs_update_dynamic_rev(fs);
13871 ext2fs_mark_super_dirty(fs);
13874 check_resize_inode(ctx);
13877 * Clean up any orphan inodes, if present.
13879 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13880 fs->super->s_state &= ~EXT2_VALID_FS;
13881 ext2fs_mark_super_dirty(fs);
13885 * Move the ext3 journal file, if necessary.
13887 e2fsck_move_ext3_journal(ctx);
13892 * swapfs.c --- byte-swap an ext2 filesystem
13895 #ifdef ENABLE_SWAPFS
13897 struct swap_block_struct {
13902 struct ext2_inode *inode;
13906 * This is a helper function for block_iterate. We mark all of the
13907 * indirect and direct blocks as changed, so that block_iterate will
13910 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13915 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13917 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13918 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13920 sb->errcode = retval;
13921 return BLOCK_ABORT;
13923 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13925 sb->errcode = retval;
13926 return BLOCK_ABORT;
13929 if (blockcnt >= 0) {
13930 if (blockcnt < EXT2_NDIR_BLOCKS)
13932 return BLOCK_CHANGED;
13934 if (blockcnt == BLOCK_COUNT_IND) {
13935 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
13937 return BLOCK_CHANGED;
13939 if (blockcnt == BLOCK_COUNT_DIND) {
13940 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
13942 return BLOCK_CHANGED;
13944 if (blockcnt == BLOCK_COUNT_TIND) {
13945 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
13947 return BLOCK_CHANGED;
13949 return BLOCK_CHANGED;
13953 * This function is responsible for byte-swapping all of the indirect,
13954 * block pointers. It is also responsible for byte-swapping directories.
13956 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
13957 struct ext2_inode *inode)
13960 struct swap_block_struct sb;
13964 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
13967 if (LINUX_S_ISDIR(inode->i_mode))
13970 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
13973 com_err("swap_inode_blocks", retval,
13974 _("while calling ext2fs_block_iterate"));
13975 ctx->flags |= E2F_FLAG_ABORT;
13979 com_err("swap_inode_blocks", sb.errcode,
13980 _("while calling iterator function"));
13981 ctx->flags |= E2F_FLAG_ABORT;
13986 static void swap_inodes(e2fsck_t ctx)
13988 ext2_filsys fs = ctx->fs;
13991 ext2_ino_t ino = 1;
13992 char *buf, *block_buf;
13994 struct ext2_inode * inode;
13996 e2fsck_use_inode_shortcuts(ctx, 1);
13998 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
14001 com_err("swap_inodes", retval,
14002 _("while allocating inode buffer"));
14003 ctx->flags |= E2F_FLAG_ABORT;
14006 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14007 "block interate buffer");
14008 for (group = 0; group < fs->group_desc_count; group++) {
14009 retval = io_channel_read_blk(fs->io,
14010 fs->group_desc[group].bg_inode_table,
14011 fs->inode_blocks_per_group, buf);
14013 com_err("swap_inodes", retval,
14014 _("while reading inode table (group %d)"),
14016 ctx->flags |= E2F_FLAG_ABORT;
14019 inode = (struct ext2_inode *) buf;
14020 for (i=0; i < fs->super->s_inodes_per_group;
14021 i++, ino++, inode++) {
14022 ctx->stashed_ino = ino;
14023 ctx->stashed_inode = inode;
14025 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14026 ext2fs_swap_inode(fs, inode, inode, 0);
14029 * Skip deleted files.
14031 if (inode->i_links_count == 0)
14034 if (LINUX_S_ISDIR(inode->i_mode) ||
14035 ((inode->i_block[EXT2_IND_BLOCK] ||
14036 inode->i_block[EXT2_DIND_BLOCK] ||
14037 inode->i_block[EXT2_TIND_BLOCK]) &&
14038 ext2fs_inode_has_valid_blocks(inode)))
14039 swap_inode_blocks(ctx, ino, block_buf, inode);
14041 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14044 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14045 ext2fs_swap_inode(fs, inode, inode, 1);
14047 retval = io_channel_write_blk(fs->io,
14048 fs->group_desc[group].bg_inode_table,
14049 fs->inode_blocks_per_group, buf);
14051 com_err("swap_inodes", retval,
14052 _("while writing inode table (group %d)"),
14054 ctx->flags |= E2F_FLAG_ABORT;
14058 ext2fs_free_mem(&buf);
14059 ext2fs_free_mem(&block_buf);
14060 e2fsck_use_inode_shortcuts(ctx, 0);
14061 ext2fs_flush_icache(fs);
14064 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14066 * On the PowerPC, the big-endian variant of the ext2 filesystem
14067 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14068 * of each word. Thus a bitmap with only bit 0 set would be, as
14069 * a string of bytes, 00 00 00 01 00 ...
14070 * To cope with this, we byte-reverse each word of a bitmap if
14071 * we have a big-endian filesystem, that is, if we are *not*
14072 * byte-swapping other word-sized numbers.
14074 #define EXT2_BIG_ENDIAN_BITMAPS
14077 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14078 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14080 __u32 *p = (__u32 *) bmap->bitmap;
14081 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14083 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14084 *p = ext2fs_swab32(*p);
14089 #ifdef ENABLE_SWAPFS
14090 static void swap_filesys(e2fsck_t ctx)
14092 ext2_filsys fs = ctx->fs;
14093 #ifdef RESOURCE_TRACK
14094 struct resource_track rtrack;
14096 init_resource_track(&rtrack);
14099 if (!(ctx->options & E2F_OPT_PREEN))
14100 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14103 mtrace_print("Byte swap");
14106 if (fs->super->s_mnt_count) {
14107 fprintf(stderr, _("%s: the filesystem must be freshly "
14108 "checked using fsck\n"
14109 "and not mounted before trying to "
14110 "byte-swap it.\n"), ctx->device_name);
14111 ctx->flags |= E2F_FLAG_ABORT;
14114 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14115 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14116 EXT2_FLAG_SWAP_BYTES_WRITE);
14117 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14119 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14120 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14123 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14125 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14126 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14127 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14128 EXT2_FLAG_SWAP_BYTES_WRITE);
14130 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14131 e2fsck_read_bitmaps(ctx);
14132 ext2fs_swap_bitmap(fs->inode_map);
14133 ext2fs_swap_bitmap(fs->block_map);
14134 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14136 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14138 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14140 #ifdef RESOURCE_TRACK
14141 if (ctx->options & E2F_OPT_TIME2)
14142 print_resource_track(_("Byte swap"), &rtrack);
14145 #endif /* ENABLE_SWAPFS */
14150 * util.c --- miscellaneous utilities
14153 #ifdef HAVE_CONIO_H
14154 #undef HAVE_TERMIOS_H
14156 #define read_a_char() getch()
14158 #ifdef HAVE_TERMIOS_H
14159 #include <termios.h>
14164 void fatal_error(e2fsck_t ctx, const char *msg)
14167 fprintf (stderr, "e2fsck: %s\n", msg);
14168 if (ctx->fs && ctx->fs->io) {
14169 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14170 io_channel_flush(ctx->fs->io);
14172 fprintf(stderr, "e2fsck: io manager magic bad!\n");
14174 ctx->flags |= E2F_FLAG_ABORT;
14175 if (ctx->flags & E2F_FLAG_SETJMP_OK)
14176 longjmp(ctx->abort_loc, 1);
14181 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14182 const char *description)
14187 #ifdef DEBUG_ALLOCATE_MEMORY
14188 printf("Allocating %d bytes for %s...\n", size, description);
14190 ret = malloc(size);
14192 sprintf(buf, "Can't allocate %s\n", description);
14193 fatal_error(ctx, buf);
14195 memset(ret, 0, size);
14199 static char *string_copy(const char *str, int len)
14207 ret = malloc(len+1);
14209 strncpy(ret, str, len);
14215 #ifndef HAVE_CONIO_H
14216 static int read_a_char(void)
14223 if (e2fsck_global_ctx &&
14224 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14227 r = read(0, &c, 1);
14237 static int ask_yn(const char * string, int def)
14240 const char *defstr;
14241 static const char short_yes[] = "yY";
14242 static const char short_no[] = "nN";
14244 #ifdef HAVE_TERMIOS_H
14245 struct termios termios, tmp;
14247 tcgetattr (0, &termios);
14249 tmp.c_lflag &= ~(ICANON | ECHO);
14250 tmp.c_cc[VMIN] = 1;
14251 tmp.c_cc[VTIME] = 0;
14252 tcsetattr (0, TCSANOW, &tmp);
14261 printf("%s%s? ", string, defstr);
14264 if ((c = read_a_char()) == EOF)
14267 #ifdef HAVE_TERMIOS_H
14268 tcsetattr (0, TCSANOW, &termios);
14270 if (e2fsck_global_ctx &&
14271 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14273 longjmp(e2fsck_global_ctx->abort_loc, 1);
14275 puts(_("cancelled!\n"));
14278 if (strchr(short_yes, (char) c)) {
14282 else if (strchr(short_no, (char) c)) {
14286 else if ((c == ' ' || c == '\n') && (def != -1))
14293 #ifdef HAVE_TERMIOS_H
14294 tcsetattr (0, TCSANOW, &termios);
14299 int ask (e2fsck_t ctx, const char * string, int def)
14301 if (ctx->options & E2F_OPT_NO) {
14302 printf (_("%s? no\n\n"), string);
14305 if (ctx->options & E2F_OPT_YES) {
14306 printf (_("%s? yes\n\n"), string);
14309 if (ctx->options & E2F_OPT_PREEN) {
14310 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14313 return ask_yn(string, def);
14316 void e2fsck_read_bitmaps(e2fsck_t ctx)
14318 ext2_filsys fs = ctx->fs;
14321 if (ctx->invalid_bitmaps) {
14322 com_err(ctx->program_name, 0,
14323 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14325 fatal_error(ctx, 0);
14328 ehandler_operation(_("reading inode and block bitmaps"));
14329 retval = ext2fs_read_bitmaps(fs);
14330 ehandler_operation(0);
14332 com_err(ctx->program_name, retval,
14333 _("while retrying to read bitmaps for %s"),
14335 fatal_error(ctx, 0);
14339 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14341 ext2_filsys fs = ctx->fs;
14344 if (ext2fs_test_bb_dirty(fs)) {
14345 ehandler_operation(_("writing block bitmaps"));
14346 retval = ext2fs_write_block_bitmap(fs);
14347 ehandler_operation(0);
14349 com_err(ctx->program_name, retval,
14350 _("while retrying to write block bitmaps for %s"),
14352 fatal_error(ctx, 0);
14356 if (ext2fs_test_ib_dirty(fs)) {
14357 ehandler_operation(_("writing inode bitmaps"));
14358 retval = ext2fs_write_inode_bitmap(fs);
14359 ehandler_operation(0);
14361 com_err(ctx->program_name, retval,
14362 _("while retrying to write inode bitmaps for %s"),
14364 fatal_error(ctx, 0);
14369 void preenhalt(e2fsck_t ctx)
14371 ext2_filsys fs = ctx->fs;
14373 if (!(ctx->options & E2F_OPT_PREEN))
14375 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14376 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14379 fs->super->s_state |= EXT2_ERROR_FS;
14380 ext2fs_mark_super_dirty(fs);
14383 exit(EXIT_UNCORRECTED);
14386 #ifdef RESOURCE_TRACK
14387 void init_resource_track(struct resource_track *track)
14389 #ifdef HAVE_GETRUSAGE
14393 track->brk_start = sbrk(0);
14394 gettimeofday(&track->time_start, 0);
14395 #ifdef HAVE_GETRUSAGE
14397 memset(&r, 0, sizeof(struct rusage));
14399 getrusage(RUSAGE_SELF, &r);
14400 track->user_start = r.ru_utime;
14401 track->system_start = r.ru_stime;
14403 track->user_start.tv_sec = track->user_start.tv_usec = 0;
14404 track->system_start.tv_sec = track->system_start.tv_usec = 0;
14408 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14409 struct timeval *tv2)
14411 return ((tv1->tv_sec - tv2->tv_sec) +
14412 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14415 void print_resource_track(const char *desc, struct resource_track *track)
14417 #ifdef HAVE_GETRUSAGE
14420 #ifdef HAVE_MALLINFO
14421 struct mallinfo malloc_info;
14423 struct timeval time_end;
14425 gettimeofday(&time_end, 0);
14428 printf("%s: ", desc);
14430 #ifdef HAVE_MALLINFO
14431 #define kbytes(x) (((x) + 1023) / 1024)
14433 malloc_info = mallinfo();
14434 printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14435 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14436 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14438 printf(_("Memory used: %d, "),
14439 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14441 #ifdef HAVE_GETRUSAGE
14442 getrusage(RUSAGE_SELF, &r);
14444 printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14445 timeval_subtract(&time_end, &track->time_start),
14446 timeval_subtract(&r.ru_utime, &track->user_start),
14447 timeval_subtract(&r.ru_stime, &track->system_start));
14449 printf(_("elapsed time: %6.3f\n"),
14450 timeval_subtract(&time_end, &track->time_start));
14453 #endif /* RESOURCE_TRACK */
14455 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14456 struct ext2_inode * inode, const char *proc)
14460 retval = ext2fs_read_inode(ctx->fs, ino, inode);
14462 com_err("ext2fs_read_inode", retval,
14463 _("while reading inode %ld in %s"), ino, proc);
14464 fatal_error(ctx, 0);
14468 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14469 struct ext2_inode * inode, int bufsize,
14474 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14476 com_err("ext2fs_write_inode", retval,
14477 _("while writing inode %ld in %s"), ino, proc);
14478 fatal_error(ctx, 0);
14482 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14483 struct ext2_inode * inode, const char *proc)
14487 retval = ext2fs_write_inode(ctx->fs, ino, inode);
14489 com_err("ext2fs_write_inode", retval,
14490 _("while writing inode %ld in %s"), ino, proc);
14491 fatal_error(ctx, 0);
14496 void mtrace_print(char *mesg)
14498 FILE *malloc_get_mallstream();
14499 FILE *f = malloc_get_mallstream();
14502 fprintf(f, "============= %s\n", mesg);
14506 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14507 io_manager manager)
14509 struct ext2_super_block *sb;
14510 io_channel io = NULL;
14513 blk_t superblock, ret_sb = 8193;
14515 if (fs && fs->super) {
14516 ret_sb = (fs->super->s_blocks_per_group +
14517 fs->super->s_first_data_block);
14519 ctx->superblock = ret_sb;
14520 ctx->blocksize = fs->blocksize;
14526 if (ctx->blocksize) {
14527 ret_sb = ctx->blocksize * 8;
14528 if (ctx->blocksize == 1024)
14530 ctx->superblock = ret_sb;
14533 ctx->superblock = ret_sb;
14534 ctx->blocksize = 1024;
14537 if (!name || !manager)
14540 if (manager->open(name, 0, &io) != 0)
14543 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14545 sb = (struct ext2_super_block *) buf;
14547 for (blocksize = EXT2_MIN_BLOCK_SIZE;
14548 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14549 superblock = blocksize*8;
14550 if (blocksize == 1024)
14552 io_channel_set_blksize(io, blocksize);
14553 if (io_channel_read_blk(io, superblock,
14554 -SUPERBLOCK_SIZE, buf))
14556 #ifdef EXT2FS_ENABLE_SWAPFS
14557 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14558 ext2fs_swap_super(sb);
14560 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14561 ret_sb = superblock;
14563 ctx->superblock = superblock;
14564 ctx->blocksize = blocksize;
14572 io_channel_close(io);
14573 ext2fs_free_mem(&buf);
14579 * This function runs through the e2fsck passes and calls them all,
14580 * returning restart, abort, or cancel as necessary...
14582 typedef void (*pass_t)(e2fsck_t ctx);
14584 static const pass_t e2fsck_passes[] = {
14585 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14588 #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14590 static int e2fsck_run(e2fsck_t ctx)
14593 pass_t e2fsck_pass;
14595 if (setjmp(ctx->abort_loc)) {
14596 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14597 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14599 ctx->flags |= E2F_FLAG_SETJMP_OK;
14601 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14602 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14606 (void) (ctx->progress)(ctx, 0, 0, 0);
14608 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14610 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14611 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14617 * unix.c - The unix-specific code for e2fsck
14621 /* Command line options */
14623 #ifdef ENABLE_SWAPFS
14624 static int normalize_swapfs;
14626 static int cflag; /* check disk */
14627 static int show_version_only;
14628 static int verbose;
14630 static int replace_bad_blocks;
14631 static int keep_bad_blocks;
14632 static char *bad_blocks_file;
14634 #ifdef __CONFIG_JBD_DEBUG__E2FS /* Enabled by configure --enable-jfs-debug */
14635 int journal_enable_debug = -1;
14639 static void usage(e2fsck_t ctx)
14642 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14643 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14644 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal]\n"
14645 "\t\t[-E extended-options] device\n"),
14646 ctx->program_name);
14648 fprintf(stderr, _("\nEmergency help:\n"
14649 " -p Automatic repair (no questions)\n"
14650 " -n Make no changes to the filesystem\n"
14651 " -y Assume \"yes\" to all questions\n"
14652 " -c Check for bad blocks and add them to the badblock list\n"
14653 " -f Force checking even if filesystem is marked clean\n"));
14654 fprintf(stderr, _(""
14656 " -b superblock Use alternative superblock\n"
14657 " -B blocksize Force blocksize when looking for superblock\n"
14658 " -j external-journal Set location of the external journal\n"
14659 " -l bad_blocks_file Add to badblocks list\n"
14660 " -L bad_blocks_file Set badblocks list\n"
14667 #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
14669 static void show_stats(e2fsck_t ctx)
14671 ext2_filsys fs = ctx->fs;
14672 int inodes, inodes_used, blocks, blocks_used;
14674 int num_files, num_links;
14677 dir_links = 2 * ctx->fs_directory_count - 1;
14678 num_files = ctx->fs_total_count - dir_links;
14679 num_links = ctx->fs_links_count - dir_links;
14680 inodes = fs->super->s_inodes_count;
14681 inodes_used = (fs->super->s_inodes_count -
14682 fs->super->s_free_inodes_count);
14683 blocks = fs->super->s_blocks_count;
14684 blocks_used = (fs->super->s_blocks_count -
14685 fs->super->s_free_blocks_count);
14687 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14688 frag_percent = (frag_percent + 5) / 10;
14691 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14692 ctx->device_name, inodes_used, inodes,
14693 frag_percent / 10, frag_percent % 10,
14694 blocks_used, blocks);
14697 printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14698 100 * inodes_used / inodes);
14699 printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14700 P_E2("", "s", ctx->fs_fragmented),
14701 frag_percent / 10, frag_percent % 10);
14702 printf (_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14703 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14704 printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14705 (int) ((long long) 100 * blocks_used / blocks));
14706 printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14707 printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14708 printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14709 printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14710 printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14711 printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14712 printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14713 printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14714 printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14715 printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14716 printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14717 printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14720 static void check_mount(e2fsck_t ctx)
14725 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14726 &ctx->mount_flags);
14728 com_err("ext2fs_check_if_mount", retval,
14729 _("while determining whether %s is mounted."),
14730 ctx->filesystem_name);
14735 * If the filesystem isn't mounted, or it's the root filesystem
14736 * and it's mounted read-only, then everything's fine.
14738 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14739 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14740 (ctx->mount_flags & EXT2_MF_READONLY)))
14743 if (ctx->options & E2F_OPT_READONLY) {
14744 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
14748 printf(_("%s is mounted. "), ctx->filesystem_name);
14749 if (!ctx->interactive)
14750 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14751 printf(_("\n\n\007\007\007\007WARNING!!! "
14752 "Running e2fsck on a mounted filesystem may cause\n"
14753 "SEVERE filesystem damage.\007\007\007\n\n"));
14754 cont = ask_yn(_("Do you really want to continue"), -1);
14756 printf (_("check aborted.\n"));
14762 static int is_on_batt(void)
14766 char tmp[80], tmp2[80], fname[80];
14767 unsigned int acflag;
14770 f = fopen("/proc/apm", "r");
14772 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14775 return (acflag != 1);
14777 d = opendir("/proc/acpi/ac_adapter");
14779 while ((de=readdir(d)) != NULL) {
14780 if (!strncmp(".", de->d_name, 1))
14782 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14784 f = fopen(fname, "r");
14787 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14790 if (strncmp(tmp, "off-line", 8) == 0) {
14801 * This routine checks to see if a filesystem can be skipped; if so,
14802 * it will exit with EXIT_OK. Under some conditions it will print a
14803 * message explaining why a check is being forced.
14805 static void check_if_skip(e2fsck_t ctx)
14807 ext2_filsys fs = ctx->fs;
14808 const char *reason = NULL;
14809 unsigned int reason_arg = 0;
14811 int batt = is_on_batt();
14812 time_t now = time(0);
14814 if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14818 if ((fs->super->s_state & EXT2_ERROR_FS) ||
14819 !ext2fs_test_valid(fs))
14820 reason = _(" contains a file system with errors");
14821 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14822 reason = _(" was not cleanly unmounted");
14823 else if ((fs->super->s_max_mnt_count > 0) &&
14824 (fs->super->s_mnt_count >=
14825 (unsigned) fs->super->s_max_mnt_count)) {
14826 reason = _(" has been mounted %u times without being checked");
14827 reason_arg = fs->super->s_mnt_count;
14828 if (batt && (fs->super->s_mnt_count <
14829 (unsigned) fs->super->s_max_mnt_count*2))
14831 } else if (fs->super->s_checkinterval &&
14832 ((now - fs->super->s_lastcheck) >=
14833 fs->super->s_checkinterval)) {
14834 reason = _(" has gone %u days without being checked");
14835 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14836 if (batt && ((now - fs->super->s_lastcheck) <
14837 fs->super->s_checkinterval*2))
14841 fputs(ctx->device_name, stdout);
14842 printf(reason, reason_arg);
14843 fputs(_(", check forced.\n"), stdout);
14846 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14847 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14848 fs->super->s_inodes_count,
14849 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14850 fs->super->s_blocks_count);
14851 next_check = 100000;
14852 if (fs->super->s_max_mnt_count > 0) {
14853 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14854 if (next_check <= 0)
14857 if (fs->super->s_checkinterval &&
14858 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14860 if (next_check <= 5) {
14861 if (next_check == 1)
14862 fputs(_(" (check after next mount)"), stdout);
14864 printf(_(" (check in %ld mounts)"), next_check);
14866 fputc('\n', stdout);
14869 e2fsck_free_context(ctx);
14874 * For completion notice
14876 struct percent_tbl {
14880 static const struct percent_tbl e2fsck_tbl = {
14881 5, { 0, 70, 90, 92, 95, 100 }
14884 static char bar[128], spaces[128];
14886 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14893 if (pass > tbl->max_pass || max == 0)
14895 percent = ((float) curr) / ((float) max);
14896 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14897 + tbl->table[pass-1]);
14900 extern void e2fsck_clear_progbar(e2fsck_t ctx)
14902 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14905 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14908 ctx->flags &= ~E2F_FLAG_PROG_BAR;
14911 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14912 unsigned int dpynum)
14914 static const char spinner[] = "\\|/-";
14921 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14925 * Calculate the new progress position. If the
14926 * percentage hasn't changed, then we skip out right
14929 fixed_percent = (int) ((10 * percent) + 0.5);
14930 if (ctx->progress_last_percent == fixed_percent)
14932 ctx->progress_last_percent = fixed_percent;
14935 * If we've already updated the spinner once within
14936 * the last 1/8th of a second, no point doing it
14939 gettimeofday(&tv, NULL);
14940 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
14941 if ((tick == ctx->progress_last_time) &&
14942 (fixed_percent != 0) && (fixed_percent != 1000))
14944 ctx->progress_last_time = tick;
14947 * Advance the spinner, and note that the progress bar
14948 * will be on the screen
14950 ctx->progress_pos = (ctx->progress_pos+1) & 3;
14951 ctx->flags |= E2F_FLAG_PROG_BAR;
14953 dpywidth = 66 - strlen(label);
14954 dpywidth = 8 * (dpywidth / 8);
14958 i = ((percent * dpywidth) + 50) / 100;
14959 printf("%s%s: |%s%s", ctx->start_meta, label,
14960 bar + (sizeof(bar) - (i+1)),
14961 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
14962 if (fixed_percent == 1000)
14963 fputc('|', stdout);
14965 fputc(spinner[ctx->progress_pos & 3], stdout);
14966 printf(" %4.1f%% ", percent);
14968 printf("%u\r", dpynum);
14970 fputs(" \r", stdout);
14971 fputs(ctx->stop_meta, stdout);
14973 if (fixed_percent == 1000)
14974 e2fsck_clear_progbar(ctx);
14980 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
14981 unsigned long cur, unsigned long max)
14989 if (ctx->progress_fd) {
14990 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
14991 write(ctx->progress_fd, buf, strlen(buf));
14993 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
14994 e2fsck_simple_progress(ctx, ctx->device_name,
15000 static void reserve_stdio_fds(void)
15005 fd = open(bb_dev_null, O_RDWR);
15009 fprintf(stderr, _("ERROR: Couldn't open "
15010 "/dev/null (%s)\n"),
15018 static void signal_progress_on(int sig FSCK_ATTR((unused)))
15020 e2fsck_t ctx = e2fsck_global_ctx;
15025 ctx->progress = e2fsck_update_progress;
15026 ctx->progress_fd = 0;
15029 static void signal_progress_off(int sig FSCK_ATTR((unused)))
15031 e2fsck_t ctx = e2fsck_global_ctx;
15036 e2fsck_clear_progbar(ctx);
15040 static void signal_cancel(int sig FSCK_ATTR((unused)))
15042 e2fsck_t ctx = e2fsck_global_ctx;
15045 exit(FSCK_CANCELED);
15047 ctx->flags |= E2F_FLAG_CANCEL;
15050 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15052 char *buf, *token, *next, *p, *arg;
15054 int extended_usage = 0;
15056 buf = string_copy(opts, 0);
15057 for (token = buf; token && *token; token = next) {
15058 p = strchr(token, ',');
15064 arg = strchr(token, '=');
15069 if (strcmp(token, "ea_ver") == 0) {
15074 ea_ver = strtoul(arg, &p, 0);
15076 ((ea_ver != 1) && (ea_ver != 2))) {
15078 _("Invalid EA version.\n"));
15082 ctx->ext_attr_ver = ea_ver;
15086 if (extended_usage) {
15087 bb_error_msg_and_die(
15088 "Extended options are separated by commas, "
15089 "and may take an argument which\n"
15090 "is set off by an equals ('=') sign. "
15091 "Valid raid options are:\n"
15092 "\tea_ver=<ea_version (1 or 2)\n\n");
15097 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15102 extern void *mallwatch;
15106 struct sigaction sa;
15107 char *extended_opts = 0;
15109 retval = e2fsck_allocate_context(&ctx);
15115 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15116 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15117 if (isatty(0) && isatty(1)) {
15118 ctx->interactive = 1;
15120 ctx->start_meta[0] = '\001';
15121 ctx->stop_meta[0] = '\002';
15123 memset(bar, '=', sizeof(bar)-1);
15124 memset(spaces, ' ', sizeof(spaces)-1);
15125 blkid_get_cache(&ctx->blkid, NULL);
15128 ctx->program_name = *argv;
15130 ctx->program_name = "e2fsck";
15131 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15134 ctx->progress = e2fsck_update_progress;
15135 ctx->progress_fd = atoi(optarg);
15136 if (!ctx->progress_fd)
15138 /* Validate the file descriptor to avoid disasters */
15139 fd = dup(ctx->progress_fd);
15142 _("Error validating file descriptor %d: %s\n"),
15144 error_message(errno));
15146 _("Invalid completion information file descriptor"));
15151 ctx->options |= E2F_OPT_COMPRESS_DIRS;
15154 extended_opts = optarg;
15158 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15161 _("Only one the options -p/-a, -n or -y may be specified."));
15163 ctx->options |= E2F_OPT_PREEN;
15166 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15168 ctx->options |= E2F_OPT_NO;
15171 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15173 ctx->options |= E2F_OPT_YES;
15176 #ifdef RESOURCE_TRACK
15177 if (ctx->options & E2F_OPT_TIME)
15178 ctx->options |= E2F_OPT_TIME2;
15180 ctx->options |= E2F_OPT_TIME;
15182 fprintf(stderr, _("The -t option is not "
15183 "supported on this version of e2fsck.\n"));
15188 ctx->options |= E2F_OPT_WRITECHECK;
15189 ctx->options |= E2F_OPT_CHECKBLOCKS;
15192 /* What we do by default, anyway! */
15195 ctx->use_superblock = atoi(optarg);
15196 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15199 ctx->blocksize = atoi(optarg);
15202 ctx->inode_buffer_blocks = atoi(optarg);
15205 ctx->journal_name = string_copy(optarg, 0);
15208 ctx->process_inode_size = atoi(optarg);
15211 replace_bad_blocks++;
15213 bad_blocks_file = string_copy(optarg, 0);
15216 ctx->options |= E2F_OPT_DEBUG;
15219 ctx->options |= E2F_OPT_FORCE;
15228 show_version_only = 1;
15232 mallwatch = (void *) strtol(optarg, NULL, 0);
15236 ctx->device_name = optarg;
15238 #ifdef ENABLE_SWAPFS
15240 normalize_swapfs = 1;
15247 fprintf(stderr, _("Byte-swapping filesystems "
15248 "not compiled in this version "
15258 if (show_version_only)
15260 if (optind != argc - 1)
15262 if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15263 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15264 ctx->options |= E2F_OPT_READONLY;
15265 ctx->io_options = strchr(argv[optind], '?');
15266 if (ctx->io_options)
15267 *ctx->io_options++ = 0;
15268 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15269 if (!ctx->filesystem_name) {
15270 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15272 fatal_error(ctx, 0);
15275 parse_extended_opts(ctx, extended_opts);
15278 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15280 com_err("open", errno,
15281 _("while opening %s for flushing"),
15282 ctx->filesystem_name);
15283 fatal_error(ctx, 0);
15285 if ((retval = ext2fs_sync_device(fd, 1))) {
15286 com_err("ext2fs_sync_device", retval,
15287 _("while trying to flush %s"),
15288 ctx->filesystem_name);
15289 fatal_error(ctx, 0);
15293 #ifdef ENABLE_SWAPFS
15295 if (cflag || bad_blocks_file) {
15296 fprintf(stderr, _("Incompatible options not "
15297 "allowed when byte-swapping.\n"));
15302 if (cflag && bad_blocks_file) {
15303 fprintf(stderr, _("The -c and the -l/-L options may "
15304 "not be both used at the same time.\n"));
15308 * Set up signal action
15310 memset(&sa, 0, sizeof(struct sigaction));
15311 sa.sa_handler = signal_cancel;
15312 sigaction(SIGINT, &sa, 0);
15313 sigaction(SIGTERM, &sa, 0);
15315 sa.sa_flags = SA_RESTART;
15317 e2fsck_global_ctx = ctx;
15318 sa.sa_handler = signal_progress_on;
15319 sigaction(SIGUSR1, &sa, 0);
15320 sa.sa_handler = signal_progress_off;
15321 sigaction(SIGUSR2, &sa, 0);
15323 /* Update our PATH to include /sbin if we need to run badblocks */
15325 e2fs_set_sbin_path();
15326 #ifdef __CONFIG_JBD_DEBUG__E2FS
15327 if (getenv("E2FSCK_JBD_DEBUG"))
15328 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15333 static const char my_ver_string[] = E2FSPROGS_VERSION;
15334 static const char my_ver_date[] = E2FSPROGS_DATE;
15336 int e2fsck_main (int argc, char *argv[])
15339 int exit_value = EXIT_OK;
15340 ext2_filsys fs = 0;
15342 struct ext2_super_block *sb;
15343 const char *lib_ver_date;
15344 int my_ver, lib_ver;
15346 struct problem_context pctx;
15347 int flags, run_result;
15349 clear_problem_context(&pctx);
15357 setlocale(LC_MESSAGES, "");
15358 setlocale(LC_CTYPE, "");
15359 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15360 textdomain(NLS_CAT_NAME);
15362 my_ver = ext2fs_parse_version_string(my_ver_string);
15363 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15364 if (my_ver > lib_ver) {
15365 fprintf( stderr, _("Error: ext2fs library version "
15366 "out of date!\n"));
15367 show_version_only++;
15370 retval = PRS(argc, argv, &ctx);
15372 com_err("e2fsck", retval,
15373 _("while trying to initialize program"));
15376 reserve_stdio_fds();
15378 #ifdef RESOURCE_TRACK
15379 init_resource_track(&ctx->global_rtrack);
15382 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15383 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15386 if (show_version_only) {
15387 fprintf(stderr, _("\tUsing %s, %s\n"),
15388 error_message(EXT2_ET_BASE), lib_ver_date);
15394 if (!(ctx->options & E2F_OPT_PREEN) &&
15395 !(ctx->options & E2F_OPT_NO) &&
15396 !(ctx->options & E2F_OPT_YES)) {
15397 if (!ctx->interactive)
15399 _("need terminal for interactive repairs"));
15401 ctx->superblock = ctx->use_superblock;
15403 #ifdef CONFIG_TESTIO_DEBUG
15404 io_ptr = test_io_manager;
15405 test_io_backing_manager = unix_io_manager;
15407 io_ptr = unix_io_manager;
15410 if ((ctx->options & E2F_OPT_READONLY) == 0)
15411 flags |= EXT2_FLAG_RW;
15413 if (ctx->superblock && ctx->blocksize) {
15414 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15415 flags, ctx->superblock, ctx->blocksize,
15417 } else if (ctx->superblock) {
15419 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15420 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15421 retval = ext2fs_open2(ctx->filesystem_name,
15422 ctx->io_options, flags,
15423 ctx->superblock, blocksize,
15429 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15430 flags, 0, 0, io_ptr, &fs);
15431 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15432 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15433 ((retval == EXT2_ET_BAD_MAGIC) ||
15434 ((retval == 0) && ext2fs_check_desc(fs)))) {
15435 if (!fs || (fs->group_desc_count > 1)) {
15436 printf(_("%s trying backup blocks...\n"),
15437 retval ? _("Couldn't find ext2 superblock,") :
15438 _("Group descriptors look bad..."));
15439 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15446 com_err(ctx->program_name, retval, _("while trying to open %s"),
15447 ctx->filesystem_name);
15448 if (retval == EXT2_ET_REV_TOO_HIGH) {
15449 printf(_("The filesystem revision is apparently "
15450 "too high for this version of e2fsck.\n"
15451 "(Or the filesystem superblock "
15452 "is corrupt)\n\n"));
15453 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15454 } else if (retval == EXT2_ET_SHORT_READ)
15455 printf(_("Could this be a zero-length partition?\n"));
15456 else if ((retval == EPERM) || (retval == EACCES))
15457 printf(_("You must have %s access to the "
15458 "filesystem or be root\n"),
15459 (ctx->options & E2F_OPT_READONLY) ?
15461 else if (retval == ENXIO)
15462 printf(_("Possibly non-existent or swap device?\n"));
15464 else if (retval == EROFS)
15465 printf(_("Disk write-protected; use the -n option "
15466 "to do a read-only\n"
15467 "check of the device.\n"));
15470 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15471 fatal_error(ctx, 0);
15474 fs->priv_data = ctx;
15476 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15477 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15478 _("while trying to open %s"),
15479 ctx->filesystem_name);
15481 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15485 * Set the device name, which is used whenever we print error
15486 * or informational messages to the user.
15488 if (ctx->device_name == 0 &&
15489 (sb->s_volume_name[0] != 0)) {
15490 ctx->device_name = string_copy(sb->s_volume_name,
15491 sizeof(sb->s_volume_name));
15493 if (ctx->device_name == 0)
15494 ctx->device_name = ctx->filesystem_name;
15497 * Make sure the ext3 superblock fields are consistent.
15499 retval = e2fsck_check_ext3_journal(ctx);
15501 com_err(ctx->program_name, retval,
15502 _("while checking ext3 journal for %s"),
15504 fatal_error(ctx, 0);
15508 * Check to see if we need to do ext3-style recovery. If so,
15509 * do it, and then restart the fsck.
15511 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15512 if (ctx->options & E2F_OPT_READONLY) {
15513 printf(_("Warning: skipping journal recovery "
15514 "because doing a read-only filesystem "
15516 io_channel_flush(ctx->fs->io);
15518 if (ctx->flags & E2F_FLAG_RESTARTED) {
15520 * Whoops, we attempted to run the
15521 * journal twice. This should never
15522 * happen, unless the hardware or
15523 * device driver is being bogus.
15525 com_err(ctx->program_name, 0,
15526 _("unable to set superblock flags on %s\n"), ctx->device_name);
15527 fatal_error(ctx, 0);
15529 retval = e2fsck_run_ext3_journal(ctx);
15531 com_err(ctx->program_name, retval,
15532 _("while recovering ext3 journal of %s"),
15534 fatal_error(ctx, 0);
15536 ext2fs_close(ctx->fs);
15538 ctx->flags |= E2F_FLAG_RESTARTED;
15544 * Check for compatibility with the feature sets. We need to
15545 * be more stringent than ext2fs_open().
15547 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15548 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15549 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15550 "(%s)", ctx->device_name);
15553 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15554 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15555 "(%s)", ctx->device_name);
15558 #ifdef ENABLE_COMPRESSION
15559 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15560 com_err(ctx->program_name, 0,
15561 _("Warning: compression support is experimental.\n"));
15563 #ifndef ENABLE_HTREE
15564 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15565 com_err(ctx->program_name, 0,
15566 _("E2fsck not compiled with HTREE support,\n\t"
15567 "but filesystem %s has HTREE directories.\n"),
15574 * If the user specified a specific superblock, presumably the
15575 * master superblock has been trashed. So we mark the
15576 * superblock as dirty, so it can be written out.
15578 if (ctx->superblock &&
15579 !(ctx->options & E2F_OPT_READONLY))
15580 ext2fs_mark_super_dirty(fs);
15583 * We only update the master superblock because (a) paranoia;
15584 * we don't want to corrupt the backup superblocks, and (b) we
15585 * don't need to update the mount count and last checked
15586 * fields in the backup superblock (the kernel doesn't
15587 * update the backup superblocks anyway).
15589 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15591 ehandler_init(fs->io);
15593 if (ctx->superblock)
15594 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15595 ext2fs_mark_valid(fs);
15596 check_super_block(ctx);
15597 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15598 fatal_error(ctx, 0);
15599 check_if_skip(ctx);
15600 if (bad_blocks_file)
15601 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15603 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15604 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15605 fatal_error(ctx, 0);
15606 #ifdef ENABLE_SWAPFS
15608 #ifdef WORDS_BIGENDIAN
15609 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
15611 #define NATIVE_FLAG 0
15615 if (normalize_swapfs) {
15616 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
15617 fprintf(stderr, _("%s: Filesystem byte order "
15618 "already normalized.\n"), ctx->device_name);
15619 fatal_error(ctx, 0);
15624 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15625 fatal_error(ctx, 0);
15630 * Mark the system as valid, 'til proven otherwise
15632 ext2fs_mark_valid(fs);
15634 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15636 com_err(ctx->program_name, retval,
15637 _("while reading bad blocks inode"));
15639 printf(_("This doesn't bode well,"
15640 " but we'll try to go on...\n"));
15643 run_result = e2fsck_run(ctx);
15644 e2fsck_clear_progbar(ctx);
15645 if (run_result == E2F_FLAG_RESTART) {
15646 printf(_("Restarting e2fsck from the beginning...\n"));
15647 retval = e2fsck_reset_context(ctx);
15649 com_err(ctx->program_name, retval,
15650 _("while resetting context"));
15651 fatal_error(ctx, 0);
15656 if (run_result & E2F_FLAG_CANCEL) {
15657 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15658 ctx->device_name : ctx->filesystem_name);
15659 exit_value |= FSCK_CANCELED;
15661 if (run_result & E2F_FLAG_ABORT)
15662 fatal_error(ctx, _("aborted"));
15665 mtrace_print("Cleanup");
15667 if (ext2fs_test_changed(fs)) {
15668 exit_value |= EXIT_NONDESTRUCT;
15669 if (!(ctx->options & E2F_OPT_PREEN))
15670 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15672 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15673 printf(_("%s: ***** REBOOT LINUX *****\n"),
15675 exit_value |= EXIT_DESTRUCT;
15678 if (!ext2fs_test_valid(fs)) {
15679 printf(_("\n%s: ********** WARNING: Filesystem still has "
15680 "errors **********\n\n"), ctx->device_name);
15681 exit_value |= EXIT_UNCORRECTED;
15682 exit_value &= ~EXIT_NONDESTRUCT;
15684 if (exit_value & FSCK_CANCELED)
15685 exit_value &= ~EXIT_NONDESTRUCT;
15688 if (!(ctx->options & E2F_OPT_READONLY)) {
15689 if (ext2fs_test_valid(fs)) {
15690 if (!(sb->s_state & EXT2_VALID_FS))
15691 exit_value |= EXIT_NONDESTRUCT;
15692 sb->s_state = EXT2_VALID_FS;
15694 sb->s_state &= ~EXT2_VALID_FS;
15695 sb->s_mnt_count = 0;
15696 sb->s_lastcheck = time(NULL);
15697 ext2fs_mark_super_dirty(fs);
15701 e2fsck_write_bitmaps(ctx);
15705 free(ctx->filesystem_name);
15706 free(ctx->journal_name);
15707 e2fsck_free_context(ctx);
15709 #ifdef RESOURCE_TRACK
15710 if (ctx->options & E2F_OPT_TIME)
15711 print_resource_track(NULL, &ctx->global_rtrack);