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
3715 * @m multiply-claimed
3729 * This structure defines the abbreviations used by the text strings
3730 * below. The first character in the string is the index letter. An
3731 * abbreviation of the form '@<i>' is expanded by looking up the index
3732 * letter <i> in the table below.
3734 static const char * const abbrevs[] = {
3735 N_("aextended attribute"),
3736 N_("Aerror allocating"),
3740 N_("Cconflicts with some other fs @b"),
3747 N_("E@e '%Dn' in %p (%i)"),
3749 N_("Ffor @i %i (%Q) is"),
3754 N_("mmultiply-claimed"),
3769 * Give more user friendly names to the "special" inodes.
3771 #define num_special_inodes 11
3772 static const char * const special_inode_name[] =
3774 N_("<The NULL inode>"), /* 0 */
3775 N_("<The bad blocks inode>"), /* 1 */
3777 N_("<The ACL index inode>"), /* 3 */
3778 N_("<The ACL data inode>"), /* 4 */
3779 N_("<The boot loader inode>"), /* 5 */
3780 N_("<The undelete directory inode>"), /* 6 */
3781 N_("<The group descriptor inode>"), /* 7 */
3782 N_("<The journal inode>"), /* 8 */
3783 N_("<Reserved inode 9>"), /* 9 */
3784 N_("<Reserved inode 10>"), /* 10 */
3788 * This function does "safe" printing. It will convert non-printable
3789 * ASCII characters using '^' and M- notation.
3791 static void safe_print(const char *cp, int len)
3801 fputs("M-", stdout);
3804 if ((ch < 32) || (ch == 0x7f)) {
3806 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3814 * This function prints a pathname, using the ext2fs_get_pathname
3817 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3822 if (!dir && (ino < num_special_inodes)) {
3823 fputs(_(special_inode_name[ino]), stdout);
3827 retval = ext2fs_get_pathname(fs, dir, ino, &path);
3829 fputs("???", stdout);
3831 safe_print(path, -1);
3832 ext2fs_free_mem(&path);
3836 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3837 struct problem_context *pctx, int first);
3839 * This function handles the '@' expansion. We allow recursive
3840 * expansion; an @ expression can contain further '@' and '%'
3843 static void expand_at_expression(e2fsck_t ctx, char ch,
3844 struct problem_context *pctx,
3847 const char * const *cpp;
3850 /* Search for the abbreviation */
3851 for (cpp = abbrevs; *cpp; cpp++) {
3857 if (*first && islower(*str)) {
3859 fputc(toupper(*str++), stdout);
3861 print_e2fsck_message(ctx, str, pctx, *first);
3867 * This function expands '%IX' expressions
3869 static void expand_inode_expression(char ch,
3870 struct problem_context *ctx)
3872 struct ext2_inode *inode;
3873 struct ext2_inode_large *large_inode;
3878 if (!ctx || !ctx->inode)
3882 large_inode = (struct ext2_inode_large *) inode;
3886 if (LINUX_S_ISDIR(inode->i_mode))
3887 printf("%u", inode->i_size);
3889 #ifdef EXT2_NO_64_TYPE
3890 if (inode->i_size_high)
3891 printf("0x%x%08x", inode->i_size_high,
3894 printf("%u", inode->i_size);
3896 printf("%llu", (inode->i_size |
3897 ((__u64) inode->i_size_high << 32)));
3902 printf("%u", large_inode->i_extra_isize);
3905 printf("%u", inode->i_blocks);
3908 printf("%d", inode->i_links_count);
3911 printf("0%o", inode->i_mode);
3914 /* The diet libc doesn't respect the TZ environemnt variable */
3916 time_str = getenv("TZ");
3919 do_gmt = !strcmp(time_str, "GMT");
3922 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3923 printf("%.24s", time_str);
3926 printf("%u", inode->i_faddr);
3929 printf("%u", inode->i_file_acl);
3932 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3933 inode->i_dir_acl : 0));
3936 printf("%d", (inode->i_uid |
3937 (inode->osd2.linux2.l_i_uid_high << 16)));
3940 printf("%d", (inode->i_gid |
3941 (inode->osd2.linux2.l_i_gid_high << 16)));
3945 printf("%%I%c", ch);
3951 * This function expands '%dX' expressions
3953 static _INLINE_ void expand_dirent_expression(char ch,
3954 struct problem_context *ctx)
3956 struct ext2_dir_entry *dirent;
3959 if (!ctx || !ctx->dirent)
3962 dirent = ctx->dirent;
3966 printf("%u", dirent->inode);
3969 len = dirent->name_len & 0xFF;
3970 if (len > EXT2_NAME_LEN)
3971 len = EXT2_NAME_LEN;
3972 if (len > dirent->rec_len)
3973 len = dirent->rec_len;
3974 safe_print(dirent->name, len);
3977 printf("%u", dirent->rec_len);
3980 printf("%u", dirent->name_len & 0xFF);
3983 printf("%u", dirent->name_len >> 8);
3987 printf("%%D%c", ch);
3992 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
3993 struct problem_context *ctx)
4003 printf("%u", ctx->blk);
4006 #ifdef EXT2_NO_64_TYPE
4007 printf("%d", ctx->blkcount);
4009 printf("%lld", ctx->blkcount);
4013 printf("%u", ctx->blk2);
4016 printf("%u", ctx->dir);
4019 printf("%d", ctx->group);
4022 printf("%u", ctx->ino);
4025 printf("%u", ctx->ino2);
4028 printf("%s", error_message(ctx->errcode));
4031 #ifdef EXT2_NO_64_TYPE
4032 printf("%u", ctx->num);
4034 printf("%llu", ctx->num);
4038 print_pathname(fs, ctx->ino, 0);
4041 print_pathname(fs, ctx->ino2,
4042 ctx->dirent ? ctx->dirent->inode : 0);
4045 print_pathname(fs, ctx->dir, 0);
4048 print_pathname(fs, ctx->dir, ctx->ino);
4051 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4054 printf("%s", ctx->str ? ctx->str : "NULL");
4057 #ifdef EXT2_NO_64_TYPE
4058 printf("0x%x", ctx->num);
4060 printf("0x%llx", ctx->num);
4071 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4072 struct problem_context *pctx, int first)
4074 ext2_filsys fs = ctx->fs;
4078 e2fsck_clear_progbar(ctx);
4079 for (cp = msg; *cp; cp++) {
4082 expand_at_expression(ctx, *cp, pctx, &first);
4083 } else if (cp[0] == '%' && cp[1] == 'I') {
4085 expand_inode_expression(*cp, pctx);
4086 } else if (cp[0] == '%' && cp[1] == 'D') {
4088 expand_dirent_expression(*cp, pctx);
4089 } else if ((cp[0] == '%')) {
4091 expand_percent_expression(fs, *cp, pctx);
4093 for (i=0; cp[i]; i++)
4094 if ((cp[i] == '@') || cp[i] == '%')
4096 printf("%.*s", i, cp);
4105 * region.c --- code which manages allocations within a region.
4109 region_addr_t start;
4111 struct region_el *next;
4114 struct region_struct {
4117 struct region_el *allocated;
4120 static region_t region_create(region_addr_t min, region_addr_t max)
4124 region = malloc(sizeof(struct region_struct));
4127 memset(region, 0, sizeof(struct region_struct));
4133 static void region_free(region_t region)
4135 struct region_el *r, *next;
4137 for (r = region->allocated; r; r = next) {
4141 memset(region, 0, sizeof(struct region_struct));
4145 static int region_allocate(region_t region, region_addr_t start, int n)
4147 struct region_el *r, *new_region, *prev, *next;
4151 if ((start < region->min) || (end > region->max))
4157 * Search through the linked list. If we find that it
4158 * conflicts witih something that's already allocated, return
4159 * 1; if we can find an existing region which we can grow, do
4160 * so. Otherwise, stop when we find the appropriate place
4161 * insert a new region element into the linked list.
4163 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4164 if (((start >= r->start) && (start < r->end)) ||
4165 ((end > r->start) && (end <= r->end)) ||
4166 ((start <= r->start) && (end >= r->end)))
4168 if (end == r->start) {
4172 if (start == r->end) {
4173 if ((next = r->next)) {
4174 if (end > next->start)
4176 if (end == next->start) {
4178 r->next = next->next;
4186 if (start < r->start)
4190 * Insert a new region element structure into the linked list
4192 new_region = malloc(sizeof(struct region_el));
4195 new_region->start = start;
4196 new_region->end = start + n;
4197 new_region->next = r;
4199 prev->next = new_region;
4201 region->allocated = new_region;
4206 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4208 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4209 * and applies the following tests to each inode:
4211 * - The mode field of the inode must be legal.
4212 * - The size and block count fields of the inode are correct.
4213 * - A data block must not be used by another inode
4215 * Pass 1 also gathers the collects the following information:
4217 * - A bitmap of which inodes are in use. (inode_used_map)
4218 * - A bitmap of which inodes are directories. (inode_dir_map)
4219 * - A bitmap of which inodes are regular files. (inode_reg_map)
4220 * - A bitmap of which inodes have bad fields. (inode_bad_map)
4221 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
4222 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
4223 * - A bitmap of which blocks are in use. (block_found_map)
4224 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
4225 * - The data blocks of the directory inodes. (dir_map)
4227 * Pass 1 is designed to stash away enough information so that the
4228 * other passes should not need to read in the inode information
4229 * during the normal course of a filesystem check. (Althogh if an
4230 * inconsistency is detected, other passes may need to read in an
4233 * Note that pass 1B will be invoked if there are any duplicate blocks
4238 static int process_block(ext2_filsys fs, blk_t *blocknr,
4239 e2_blkcnt_t blockcnt, blk_t ref_blk,
4240 int ref_offset, void *priv_data);
4241 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4242 e2_blkcnt_t blockcnt, blk_t ref_blk,
4243 int ref_offset, void *priv_data);
4244 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4246 static void mark_table_blocks(e2fsck_t ctx);
4247 static void alloc_bb_map(e2fsck_t ctx);
4248 static void alloc_imagic_map(e2fsck_t ctx);
4249 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4250 static void handle_fs_bad_blocks(e2fsck_t ctx);
4251 static void process_inodes(e2fsck_t ctx, char *block_buf);
4252 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4253 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4254 dgrp_t group, void * priv_data);
4255 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4256 char *block_buf, int adjust_sign);
4257 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4259 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4260 struct ext2_inode * inode, int bufsize,
4263 struct process_block_struct_1 {
4265 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
4266 fragmented:1, compressed:1, bbcheck:1;
4269 e2_blkcnt_t last_block;
4270 int num_illegal_blocks;
4271 blk_t previous_block;
4272 struct ext2_inode *inode;
4273 struct problem_context *pctx;
4274 ext2fs_block_bitmap fs_meta_blocks;
4278 struct process_inode_block {
4280 struct ext2_inode inode;
4283 struct scan_callback_struct {
4289 * For the inodes to process list.
4291 static struct process_inode_block *inodes_to_process;
4292 static int process_inode_count;
4294 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4295 EXT2_MIN_BLOCK_LOG_SIZE + 1];
4298 * Free all memory allocated by pass1 in preparation for restarting
4301 static void unwind_pass1(void)
4303 ext2fs_free_mem(&inodes_to_process);
4307 * Check to make sure a device inode is real. Returns 1 if the device
4308 * checks out, 0 if not.
4310 * Note: this routine is now also used to check FIFO's and Sockets,
4311 * since they have the same requirement; the i_block fields should be
4315 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4320 * If i_blocks is non-zero, or the index flag is set, then
4321 * this is a bogus device/fifo/socket
4323 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4324 (inode->i_flags & EXT2_INDEX_FL))
4328 * We should be able to do the test below all the time, but
4329 * because the kernel doesn't forcibly clear the device
4330 * inode's additional i_block fields, there are some rare
4331 * occasions when a legitimate device inode will have non-zero
4332 * additional i_block fields. So for now, we only complain
4333 * when the immutable flag is set, which should never happen
4334 * for devices. (And that's when the problem is caused, since
4335 * you can't set or clear immutable flags for devices.) Once
4336 * the kernel has been fixed we can change this...
4338 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4339 for (i=4; i < EXT2_N_BLOCKS; i++)
4340 if (inode->i_block[i])
4347 * Check to make sure a symlink inode is real. Returns 1 if the symlink
4348 * checks out, 0 if not.
4351 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4357 if ((inode->i_size_high || inode->i_size == 0) ||
4358 (inode->i_flags & EXT2_INDEX_FL))
4361 blocks = ext2fs_inode_data_blocks(fs, inode);
4363 if ((inode->i_size >= fs->blocksize) ||
4364 (blocks != fs->blocksize >> 9) ||
4365 (inode->i_block[0] < fs->super->s_first_data_block) ||
4366 (inode->i_block[0] >= fs->super->s_blocks_count))
4369 for (i = 1; i < EXT2_N_BLOCKS; i++)
4370 if (inode->i_block[i])
4373 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4376 len = strnlen(buf, fs->blocksize);
4377 if (len == fs->blocksize)
4380 if (inode->i_size >= sizeof(inode->i_block))
4383 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4384 if (len == sizeof(inode->i_block))
4387 if (len != inode->i_size)
4393 * If the immutable (or append-only) flag is set on the inode, offer
4396 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4397 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4399 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4402 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4405 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4406 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4410 * If device, fifo or socket, check size is zero -- if not offer to
4413 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4415 struct ext2_inode *inode = pctx->inode;
4417 if ((inode->i_size == 0) && (inode->i_size_high == 0))
4420 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4424 inode->i_size_high = 0;
4425 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4428 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4430 struct ext2_super_block *sb = ctx->fs->super;
4431 struct ext2_inode_large *inode;
4432 struct ext2_ext_attr_entry *entry;
4434 int storage_size, remain, offs;
4437 inode = (struct ext2_inode_large *) pctx->inode;
4438 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4439 inode->i_extra_isize;
4440 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4441 inode->i_extra_isize + sizeof(__u32);
4442 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4443 entry = (struct ext2_ext_attr_entry *) start;
4445 /* scan all entry's headers first */
4447 /* take finish entry 0UL into account */
4448 remain = storage_size - sizeof(__u32);
4451 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4453 /* header eats this space */
4454 remain -= sizeof(struct ext2_ext_attr_entry);
4456 /* is attribute name valid? */
4457 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4458 pctx->num = entry->e_name_len;
4459 problem = PR_1_ATTR_NAME_LEN;
4463 /* attribute len eats this space */
4464 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4466 /* check value size */
4467 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4468 pctx->num = entry->e_value_size;
4469 problem = PR_1_ATTR_VALUE_SIZE;
4473 /* check value placement */
4474 if (entry->e_value_offs +
4475 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4476 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4477 pctx->num = entry->e_value_offs;
4478 problem = PR_1_ATTR_VALUE_OFFSET;
4482 /* e_value_block must be 0 in inode's ea */
4483 if (entry->e_value_block != 0) {
4484 pctx->num = entry->e_value_block;
4485 problem = PR_1_ATTR_VALUE_BLOCK;
4489 /* e_hash must be 0 in inode's ea */
4490 if (entry->e_hash != 0) {
4491 pctx->num = entry->e_hash;
4492 problem = PR_1_ATTR_HASH;
4496 remain -= entry->e_value_size;
4497 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4499 entry = EXT2_EXT_ATTR_NEXT(entry);
4503 * it seems like a corruption. it's very unlikely we could repair
4504 * EA(s) in automatic fashion -bzzz
4507 problem = PR_1_ATTR_HASH;
4509 if (problem == 0 || !fix_problem(ctx, problem, pctx))
4512 /* simple remove all possible EA(s) */
4513 *((__u32 *)start) = 0UL;
4514 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4515 EXT2_INODE_SIZE(sb), "pass1");
4518 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4520 struct ext2_super_block *sb = ctx->fs->super;
4521 struct ext2_inode_large *inode;
4525 inode = (struct ext2_inode_large *) pctx->inode;
4526 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4527 /* this isn't large inode. so, nothing to check */
4532 printf("inode #%u, i_extra_size %d\n", pctx->ino,
4533 inode->i_extra_isize);
4535 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4536 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4537 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4539 * For now we will allow i_extra_isize to be 0, but really
4540 * implementations should never allow i_extra_isize to be 0
4542 if (inode->i_extra_isize &&
4543 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4544 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4546 inode->i_extra_isize = min;
4547 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4548 EXT2_INODE_SIZE(sb), "pass1");
4552 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4553 inode->i_extra_isize);
4554 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4555 /* it seems inode has an extended attribute(s) in body */
4556 check_ea_in_inode(ctx, pctx);
4560 static void e2fsck_pass1(e2fsck_t ctx)
4564 ext2_filsys fs = ctx->fs;
4566 struct ext2_inode *inode;
4567 ext2_inode_scan scan;
4569 #ifdef RESOURCE_TRACK
4570 struct resource_track rtrack;
4572 unsigned char frag, fsize;
4573 struct problem_context pctx;
4574 struct scan_callback_struct scan_struct;
4575 struct ext2_super_block *sb = ctx->fs->super;
4577 int busted_fs_time = 0;
4580 #ifdef RESOURCE_TRACK
4581 init_resource_track(&rtrack);
4583 clear_problem_context(&pctx);
4585 if (!(ctx->options & E2F_OPT_PREEN))
4586 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4588 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4589 !(ctx->options & E2F_OPT_NO)) {
4590 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4591 ctx->dirs_to_hash = 0;
4595 mtrace_print("Pass 1");
4598 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4600 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4601 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4602 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4603 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4604 max_sizes = (max_sizes * (1UL << i)) - 1;
4605 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4609 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4612 * Allocate bitmaps structures
4614 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4615 &ctx->inode_used_map);
4618 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4619 ctx->flags |= E2F_FLAG_ABORT;
4622 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4623 _("directory inode map"), &ctx->inode_dir_map);
4626 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4627 ctx->flags |= E2F_FLAG_ABORT;
4630 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4631 _("regular file inode map"), &ctx->inode_reg_map);
4634 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4635 ctx->flags |= E2F_FLAG_ABORT;
4638 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4639 &ctx->block_found_map);
4642 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4643 ctx->flags |= E2F_FLAG_ABORT;
4646 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4647 &ctx->inode_link_info);
4649 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4650 ctx->flags |= E2F_FLAG_ABORT;
4653 inode_size = EXT2_INODE_SIZE(fs->super);
4654 inode = (struct ext2_inode *)
4655 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4657 inodes_to_process = (struct process_inode_block *)
4658 e2fsck_allocate_memory(ctx,
4659 (ctx->process_inode_size *
4660 sizeof(struct process_inode_block)),
4661 "array of inodes to process");
4662 process_inode_count = 0;
4664 pctx.errcode = ext2fs_init_dblist(fs, 0);
4666 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4667 ctx->flags |= E2F_FLAG_ABORT;
4672 * If the last orphan field is set, clear it, since the pass1
4673 * processing will automatically find and clear the orphans.
4674 * In the future, we may want to try using the last_orphan
4675 * linked list ourselves, but for now, we clear it so that the
4676 * ext3 mount code won't get confused.
4678 if (!(ctx->options & E2F_OPT_READONLY)) {
4679 if (fs->super->s_last_orphan) {
4680 fs->super->s_last_orphan = 0;
4681 ext2fs_mark_super_dirty(fs);
4685 mark_table_blocks(ctx);
4686 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4687 "block interate buffer");
4688 e2fsck_use_inode_shortcuts(ctx, 1);
4689 ehandler_operation(_("doing inode scan"));
4690 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4693 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4694 ctx->flags |= E2F_FLAG_ABORT;
4697 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4698 ctx->stashed_inode = inode;
4699 scan_struct.ctx = ctx;
4700 scan_struct.block_buf = block_buf;
4701 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4703 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4705 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
4706 (fs->super->s_mtime < fs->super->s_inodes_count))
4710 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4712 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4714 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4715 if (!ctx->inode_bb_map)
4717 ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4718 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4722 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4723 ctx->flags |= E2F_FLAG_ABORT;
4730 ctx->stashed_ino = ino;
4731 if (inode->i_links_count) {
4732 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4733 ino, inode->i_links_count);
4735 pctx.num = inode->i_links_count;
4736 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4737 ctx->flags |= E2F_FLAG_ABORT;
4741 if (ino == EXT2_BAD_INO) {
4742 struct process_block_struct_1 pb;
4744 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4745 &pb.fs_meta_blocks);
4748 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4749 ctx->flags |= E2F_FLAG_ABORT;
4752 pb.ino = EXT2_BAD_INO;
4753 pb.num_blocks = pb.last_block = 0;
4754 pb.num_illegal_blocks = 0;
4755 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4756 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4760 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4761 block_buf, process_bad_block, &pb);
4762 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4764 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4765 ctx->flags |= E2F_FLAG_ABORT;
4769 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4770 ctx->flags |= E2F_FLAG_ABORT;
4773 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4774 clear_problem_context(&pctx);
4776 } else if (ino == EXT2_ROOT_INO) {
4778 * Make sure the root inode is a directory; if
4779 * not, offer to clear it. It will be
4780 * regnerated in pass #3.
4782 if (!LINUX_S_ISDIR(inode->i_mode)) {
4783 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4784 inode->i_dtime = time(0);
4785 inode->i_links_count = 0;
4786 ext2fs_icount_store(ctx->inode_link_info,
4788 e2fsck_write_inode(ctx, ino, inode,
4794 * If dtime is set, offer to clear it. mke2fs
4795 * version 0.2b created filesystems with the
4796 * dtime field set for the root and lost+found
4797 * directories. We won't worry about
4798 * /lost+found, since that can be regenerated
4799 * easily. But we will fix the root directory
4800 * as a special case.
4802 if (inode->i_dtime && inode->i_links_count) {
4803 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4805 e2fsck_write_inode(ctx, ino, inode,
4809 } else if (ino == EXT2_JOURNAL_INO) {
4810 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4811 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4812 if (!LINUX_S_ISREG(inode->i_mode) &&
4813 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4815 inode->i_mode = LINUX_S_IFREG;
4816 e2fsck_write_inode(ctx, ino, inode,
4819 check_blocks(ctx, &pctx, block_buf);
4822 if ((inode->i_links_count || inode->i_blocks ||
4823 inode->i_blocks || inode->i_block[0]) &&
4824 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4826 memset(inode, 0, inode_size);
4827 ext2fs_icount_store(ctx->inode_link_info,
4829 e2fsck_write_inode_full(ctx, ino, inode,
4830 inode_size, "pass1");
4832 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4835 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4836 if (ino == EXT2_BOOT_LOADER_INO) {
4837 if (LINUX_S_ISDIR(inode->i_mode))
4838 problem = PR_1_RESERVED_BAD_MODE;
4839 } else if (ino == EXT2_RESIZE_INO) {
4840 if (inode->i_mode &&
4841 !LINUX_S_ISREG(inode->i_mode))
4842 problem = PR_1_RESERVED_BAD_MODE;
4844 if (inode->i_mode != 0)
4845 problem = PR_1_RESERVED_BAD_MODE;
4848 if (fix_problem(ctx, problem, &pctx)) {
4850 e2fsck_write_inode(ctx, ino, inode,
4854 check_blocks(ctx, &pctx, block_buf);
4858 * Check for inodes who might have been part of the
4859 * orphaned list linked list. They should have gotten
4860 * dealt with by now, unless the list had somehow been
4863 * FIXME: In the future, inodes which are still in use
4864 * (and which are therefore) pending truncation should
4865 * be handled specially. Right now we just clear the
4866 * dtime field, and the normal e2fsck handling of
4867 * inodes where i_size and the inode blocks are
4868 * inconsistent is to fix i_size, instead of releasing
4869 * the extra blocks. This won't catch the inodes that
4870 * was at the end of the orphan list, but it's better
4871 * than nothing. The right answer is that there
4872 * shouldn't be any bugs in the orphan list handling. :-)
4874 if (inode->i_dtime && !busted_fs_time &&
4875 inode->i_dtime < ctx->fs->super->s_inodes_count) {
4876 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4877 inode->i_dtime = inode->i_links_count ?
4879 e2fsck_write_inode(ctx, ino, inode,
4885 * This code assumes that deleted inodes have
4886 * i_links_count set to 0.
4888 if (!inode->i_links_count) {
4889 if (!inode->i_dtime && inode->i_mode) {
4890 if (fix_problem(ctx,
4891 PR_1_ZERO_DTIME, &pctx)) {
4892 inode->i_dtime = time(0);
4893 e2fsck_write_inode(ctx, ino, inode,
4900 * n.b. 0.3c ext2fs code didn't clear i_links_count for
4901 * deleted files. Oops.
4903 * Since all new ext2 implementations get this right,
4904 * we now assume that the case of non-zero
4905 * i_links_count and non-zero dtime means that we
4906 * should keep the file, not delete it.
4909 if (inode->i_dtime) {
4910 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4912 e2fsck_write_inode(ctx, ino, inode, "pass1");
4916 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4917 switch (fs->super->s_creator_os) {
4919 frag = inode->osd2.linux2.l_i_frag;
4920 fsize = inode->osd2.linux2.l_i_fsize;
4923 frag = inode->osd2.hurd2.h_i_frag;
4924 fsize = inode->osd2.hurd2.h_i_fsize;
4927 frag = inode->osd2.masix2.m_i_frag;
4928 fsize = inode->osd2.masix2.m_i_fsize;
4934 if (inode->i_faddr || frag || fsize ||
4935 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4936 mark_inode_bad(ctx, ino);
4937 if (inode->i_flags & EXT2_IMAGIC_FL) {
4939 if (!ctx->inode_imagic_map)
4940 alloc_imagic_map(ctx);
4941 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4944 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4945 inode->i_flags &= ~EXT2_IMAGIC_FL;
4946 e2fsck_write_inode(ctx, ino,
4952 check_inode_extra_space(ctx, &pctx);
4954 if (LINUX_S_ISDIR(inode->i_mode)) {
4955 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
4956 e2fsck_add_dir_info(ctx, ino, 0);
4957 ctx->fs_directory_count++;
4958 } else if (LINUX_S_ISREG (inode->i_mode)) {
4959 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
4960 ctx->fs_regular_count++;
4961 } else if (LINUX_S_ISCHR (inode->i_mode) &&
4962 e2fsck_pass1_check_device_inode(fs, inode)) {
4963 check_immutable(ctx, &pctx);
4964 check_size(ctx, &pctx);
4965 ctx->fs_chardev_count++;
4966 } else if (LINUX_S_ISBLK (inode->i_mode) &&
4967 e2fsck_pass1_check_device_inode(fs, inode)) {
4968 check_immutable(ctx, &pctx);
4969 check_size(ctx, &pctx);
4970 ctx->fs_blockdev_count++;
4971 } else if (LINUX_S_ISLNK (inode->i_mode) &&
4972 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
4973 check_immutable(ctx, &pctx);
4974 ctx->fs_symlinks_count++;
4975 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
4976 ctx->fs_fast_symlinks_count++;
4977 check_blocks(ctx, &pctx, block_buf);
4981 else if (LINUX_S_ISFIFO (inode->i_mode) &&
4982 e2fsck_pass1_check_device_inode(fs, inode)) {
4983 check_immutable(ctx, &pctx);
4984 check_size(ctx, &pctx);
4985 ctx->fs_fifo_count++;
4986 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
4987 e2fsck_pass1_check_device_inode(fs, inode)) {
4988 check_immutable(ctx, &pctx);
4989 check_size(ctx, &pctx);
4990 ctx->fs_sockets_count++;
4992 mark_inode_bad(ctx, ino);
4993 if (inode->i_block[EXT2_IND_BLOCK])
4994 ctx->fs_ind_count++;
4995 if (inode->i_block[EXT2_DIND_BLOCK])
4996 ctx->fs_dind_count++;
4997 if (inode->i_block[EXT2_TIND_BLOCK])
4998 ctx->fs_tind_count++;
4999 if (inode->i_block[EXT2_IND_BLOCK] ||
5000 inode->i_block[EXT2_DIND_BLOCK] ||
5001 inode->i_block[EXT2_TIND_BLOCK] ||
5002 inode->i_file_acl) {
5003 inodes_to_process[process_inode_count].ino = ino;
5004 inodes_to_process[process_inode_count].inode = *inode;
5005 process_inode_count++;
5007 check_blocks(ctx, &pctx, block_buf);
5009 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5012 if (process_inode_count >= ctx->process_inode_size) {
5013 process_inodes(ctx, block_buf);
5015 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5019 process_inodes(ctx, block_buf);
5020 ext2fs_close_inode_scan(scan);
5021 ehandler_operation(0);
5024 * If any extended attribute blocks' reference counts need to
5025 * be adjusted, either up (ctx->refcount_extra), or down
5026 * (ctx->refcount), then fix them.
5028 if (ctx->refcount) {
5029 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5030 ea_refcount_free(ctx->refcount);
5033 if (ctx->refcount_extra) {
5034 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5036 ea_refcount_free(ctx->refcount_extra);
5037 ctx->refcount_extra = 0;
5040 if (ctx->invalid_bitmaps)
5041 handle_fs_bad_blocks(ctx);
5043 /* We don't need the block_ea_map any more */
5044 ext2fs_free_block_bitmap(ctx->block_ea_map);
5045 ctx->block_ea_map = 0;
5047 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5048 ext2fs_block_bitmap save_bmap;
5050 save_bmap = fs->block_map;
5051 fs->block_map = ctx->block_found_map;
5052 clear_problem_context(&pctx);
5053 pctx.errcode = ext2fs_create_resize_inode(fs);
5055 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5056 /* Should never get here */
5057 ctx->flags |= E2F_FLAG_ABORT;
5060 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
5062 inode->i_mtime = time(0);
5063 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
5065 fs->block_map = save_bmap;
5066 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5069 if (ctx->flags & E2F_FLAG_RESTART) {
5071 * Only the master copy of the superblock and block
5072 * group descriptors are going to be written during a
5073 * restart, so set the superblock to be used to be the
5074 * master superblock.
5076 ctx->use_superblock = 0;
5081 if (ctx->block_dup_map) {
5082 if (ctx->options & E2F_OPT_PREEN) {
5083 clear_problem_context(&pctx);
5084 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5086 e2fsck_pass1_dupblocks(ctx, block_buf);
5088 ext2fs_free_mem(&inodes_to_process);
5090 e2fsck_use_inode_shortcuts(ctx, 0);
5092 ext2fs_free_mem(&block_buf);
5093 ext2fs_free_mem(&inode);
5095 #ifdef RESOURCE_TRACK
5096 if (ctx->options & E2F_OPT_TIME2) {
5097 e2fsck_clear_progbar(ctx);
5098 print_resource_track(_("Pass 1"), &rtrack);
5104 * When the inode_scan routines call this callback at the end of the
5105 * glock group, call process_inodes.
5107 static errcode_t scan_callback(ext2_filsys fs,
5108 ext2_inode_scan scan FSCK_ATTR((unused)),
5109 dgrp_t group, void * priv_data)
5111 struct scan_callback_struct *scan_struct;
5114 scan_struct = (struct scan_callback_struct *) priv_data;
5115 ctx = scan_struct->ctx;
5117 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5120 if ((ctx->progress)(ctx, 1, group+1,
5121 ctx->fs->group_desc_count))
5122 return EXT2_ET_CANCEL_REQUESTED;
5128 * Process the inodes in the "inodes to process" list.
5130 static void process_inodes(e2fsck_t ctx, char *block_buf)
5133 struct ext2_inode *old_stashed_inode;
5134 ext2_ino_t old_stashed_ino;
5135 const char *old_operation;
5137 struct problem_context pctx;
5140 printf("begin process_inodes: ");
5142 if (process_inode_count == 0)
5144 old_operation = ehandler_operation(0);
5145 old_stashed_inode = ctx->stashed_inode;
5146 old_stashed_ino = ctx->stashed_ino;
5147 qsort(inodes_to_process, process_inode_count,
5148 sizeof(struct process_inode_block), process_inode_cmp);
5149 clear_problem_context(&pctx);
5150 for (i=0; i < process_inode_count; i++) {
5151 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5152 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5155 printf("%u ", pctx.ino);
5157 sprintf(buf, _("reading indirect blocks of inode %u"),
5159 ehandler_operation(buf);
5160 check_blocks(ctx, &pctx, block_buf);
5161 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5164 ctx->stashed_inode = old_stashed_inode;
5165 ctx->stashed_ino = old_stashed_ino;
5166 process_inode_count = 0;
5168 printf("end process inodes\n");
5170 ehandler_operation(old_operation);
5173 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5175 const struct process_inode_block *ib_a =
5176 (const struct process_inode_block *) a;
5177 const struct process_inode_block *ib_b =
5178 (const struct process_inode_block *) b;
5181 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5182 ib_b->inode.i_block[EXT2_IND_BLOCK]);
5184 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5189 * Mark an inode as being bad in some what
5191 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5193 struct problem_context pctx;
5195 if (!ctx->inode_bad_map) {
5196 clear_problem_context(&pctx);
5198 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5199 _("bad inode map"), &ctx->inode_bad_map);
5202 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5203 /* Should never get here */
5204 ctx->flags |= E2F_FLAG_ABORT;
5208 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5213 * This procedure will allocate the inode "bb" (badblock) map table
5215 static void alloc_bb_map(e2fsck_t ctx)
5217 struct problem_context pctx;
5219 clear_problem_context(&pctx);
5220 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5221 _("inode in bad block map"),
5222 &ctx->inode_bb_map);
5225 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5226 /* Should never get here */
5227 ctx->flags |= E2F_FLAG_ABORT;
5233 * This procedure will allocate the inode imagic table
5235 static void alloc_imagic_map(e2fsck_t ctx)
5237 struct problem_context pctx;
5239 clear_problem_context(&pctx);
5240 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5241 _("imagic inode map"),
5242 &ctx->inode_imagic_map);
5245 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5246 /* Should never get here */
5247 ctx->flags |= E2F_FLAG_ABORT;
5253 * Marks a block as in use, setting the dup_map if it's been set
5254 * already. Called by process_block and process_bad_block.
5256 * WARNING: Assumes checks have already been done to make sure block
5257 * is valid. This is true in both process_block and process_bad_block.
5259 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5261 struct problem_context pctx;
5263 clear_problem_context(&pctx);
5265 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5266 if (!ctx->block_dup_map) {
5267 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5268 _("multiply claimed block map"),
5269 &ctx->block_dup_map);
5272 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5274 /* Should never get here */
5275 ctx->flags |= E2F_FLAG_ABORT;
5279 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5281 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5286 * Adjust the extended attribute block's reference counts at the end
5287 * of pass 1, either by subtracting out references for EA blocks that
5288 * are still referenced in ctx->refcount, or by adding references for
5289 * EA blocks that had extra references as accounted for in
5290 * ctx->refcount_extra.
5292 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5293 char *block_buf, int adjust_sign)
5295 struct ext2_ext_attr_header *header;
5296 struct problem_context pctx;
5297 ext2_filsys fs = ctx->fs;
5302 clear_problem_context(&pctx);
5304 ea_refcount_intr_begin(refcount);
5306 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5309 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5311 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5314 header = (struct ext2_ext_attr_header *) block_buf;
5315 pctx.blkcount = header->h_refcount;
5316 should_be = header->h_refcount + adjust_sign * count;
5317 pctx.num = should_be;
5318 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5319 header->h_refcount = should_be;
5320 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5323 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5331 * Handle processing the extended attribute blocks
5333 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5336 ext2_filsys fs = ctx->fs;
5337 ext2_ino_t ino = pctx->ino;
5338 struct ext2_inode *inode = pctx->inode;
5341 struct ext2_ext_attr_header *header;
5342 struct ext2_ext_attr_entry *entry;
5346 blk = inode->i_file_acl;
5351 * If the Extended attribute flag isn't set, then a non-zero
5352 * file acl means that the inode is corrupted.
5354 * Or if the extended attribute block is an invalid block,
5355 * then the inode is also corrupted.
5357 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5358 (blk < fs->super->s_first_data_block) ||
5359 (blk >= fs->super->s_blocks_count)) {
5360 mark_inode_bad(ctx, ino);
5364 /* If ea bitmap hasn't been allocated, create it */
5365 if (!ctx->block_ea_map) {
5366 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5367 _("ext attr block map"),
5368 &ctx->block_ea_map);
5369 if (pctx->errcode) {
5371 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5372 ctx->flags |= E2F_FLAG_ABORT;
5377 /* Create the EA refcount structure if necessary */
5378 if (!ctx->refcount) {
5379 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5380 if (pctx->errcode) {
5382 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5383 ctx->flags |= E2F_FLAG_ABORT;
5389 /* Debugging text */
5390 printf("Inode %u has EA block %u\n", ino, blk);
5393 /* Have we seen this EA block before? */
5394 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5395 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5397 /* Ooops, this EA was referenced more than it stated */
5398 if (!ctx->refcount_extra) {
5399 pctx->errcode = ea_refcount_create(0,
5400 &ctx->refcount_extra);
5401 if (pctx->errcode) {
5403 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5404 ctx->flags |= E2F_FLAG_ABORT;
5408 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5413 * OK, we haven't seen this EA block yet. So we need to
5417 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5418 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5420 header = (struct ext2_ext_attr_header *) block_buf;
5421 pctx->blk = inode->i_file_acl;
5422 if (((ctx->ext_attr_ver == 1) &&
5423 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5424 ((ctx->ext_attr_ver == 2) &&
5425 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5426 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5430 if (header->h_blocks != 1) {
5431 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5435 region = region_create(0, fs->blocksize);
5437 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5438 ctx->flags |= E2F_FLAG_ABORT;
5441 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5442 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5446 entry = (struct ext2_ext_attr_entry *)(header+1);
5447 end = block_buf + fs->blocksize;
5448 while ((char *)entry < end && *(__u32 *)entry) {
5449 if (region_allocate(region, (char *)entry - (char *)header,
5450 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5451 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5454 if ((ctx->ext_attr_ver == 1 &&
5455 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5456 (ctx->ext_attr_ver == 2 &&
5457 entry->e_name_index == 0)) {
5458 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5461 if (entry->e_value_block != 0) {
5462 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5465 if (entry->e_value_size &&
5466 region_allocate(region, entry->e_value_offs,
5467 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5468 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5471 entry = EXT2_EXT_ATTR_NEXT(entry);
5473 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5474 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5477 region_free(region);
5479 count = header->h_refcount - 1;
5481 ea_refcount_store(ctx->refcount, blk, count);
5482 mark_block_used(ctx, blk);
5483 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5488 inode->i_file_acl = 0;
5489 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5493 /* Returns 1 if bad htree, 0 if OK */
5494 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5495 ext2_ino_t ino FSCK_ATTR((unused)),
5496 struct ext2_inode *inode,
5499 struct ext2_dx_root_info *root;
5500 ext2_filsys fs = ctx->fs;
5504 if ((!LINUX_S_ISDIR(inode->i_mode) &&
5505 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5506 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5507 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5510 blk = inode->i_block[0];
5512 (blk < fs->super->s_first_data_block) ||
5513 (blk >= fs->super->s_blocks_count)) &&
5514 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5517 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5518 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5521 /* XXX should check that beginning matches a directory */
5522 root = (struct ext2_dx_root_info *) (block_buf + 24);
5524 if ((root->reserved_zero || root->info_length < 8) &&
5525 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5528 pctx->num = root->hash_version;
5529 if ((root->hash_version != EXT2_HASH_LEGACY) &&
5530 (root->hash_version != EXT2_HASH_HALF_MD4) &&
5531 (root->hash_version != EXT2_HASH_TEA) &&
5532 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5535 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5536 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5539 pctx->num = root->indirect_levels;
5540 if ((root->indirect_levels > 1) &&
5541 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5548 * This subroutine is called on each inode to account for all of the
5549 * blocks used by that inode.
5551 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5554 ext2_filsys fs = ctx->fs;
5555 struct process_block_struct_1 pb;
5556 ext2_ino_t ino = pctx->ino;
5557 struct ext2_inode *inode = pctx->inode;
5559 int dirty_inode = 0;
5565 pb.num_illegal_blocks = 0;
5566 pb.suppress = 0; pb.clear = 0;
5569 pb.previous_block = 0;
5570 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5571 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5572 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5579 if (inode->i_flags & EXT2_COMPRBLK_FL) {
5580 if (fs->super->s_feature_incompat &
5581 EXT2_FEATURE_INCOMPAT_COMPRESSION)
5584 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5585 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5591 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5594 if (ext2fs_inode_has_valid_blocks(inode))
5595 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5596 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5597 block_buf, process_block, &pb);
5598 end_problem_latch(ctx, PR_LATCH_BLOCK);
5599 end_problem_latch(ctx, PR_LATCH_TOOBIG);
5600 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5603 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5605 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5606 ctx->fs_fragmented++;
5609 inode->i_links_count = 0;
5610 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5611 inode->i_dtime = time(0);
5613 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5614 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5615 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5617 * The inode was probably partially accounted for
5618 * before processing was aborted, so we need to
5619 * restart the pass 1 scan.
5621 ctx->flags |= E2F_FLAG_RESTART;
5625 if (inode->i_flags & EXT2_INDEX_FL) {
5626 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5627 inode->i_flags &= ~EXT2_INDEX_FL;
5631 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5635 if (ctx->dirs_to_hash && pb.is_dir &&
5636 !(inode->i_flags & EXT2_INDEX_FL) &&
5637 ((inode->i_size / fs->blocksize) >= 3))
5638 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5640 if (!pb.num_blocks && pb.is_dir) {
5641 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5642 inode->i_links_count = 0;
5643 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5644 inode->i_dtime = time(0);
5646 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5647 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5648 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5649 ctx->fs_directory_count--;
5654 pb.num_blocks *= (fs->blocksize / 512);
5656 printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5657 ino, inode->i_size, pb.last_block, inode->i_blocks,
5661 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5662 if (nblock > (pb.last_block + 1))
5664 else if (nblock < (pb.last_block + 1)) {
5665 if (((pb.last_block + 1) - nblock) >
5666 fs->super->s_prealloc_dir_blocks)
5670 size = EXT2_I_SIZE(inode);
5671 if ((pb.last_block >= 0) &&
5672 (size < (__u64) pb.last_block * fs->blocksize))
5674 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5677 /* i_size for symlinks is checked elsewhere */
5678 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5679 pctx->num = (pb.last_block+1) * fs->blocksize;
5680 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5681 inode->i_size = pctx->num;
5682 if (!LINUX_S_ISDIR(inode->i_mode))
5683 inode->i_size_high = pctx->num >> 32;
5688 if (LINUX_S_ISREG(inode->i_mode) &&
5689 (inode->i_size_high || inode->i_size & 0x80000000UL))
5691 if (pb.num_blocks != inode->i_blocks) {
5692 pctx->num = pb.num_blocks;
5693 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5694 inode->i_blocks = pb.num_blocks;
5701 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5706 * Helper function called by process block when an illegal block is
5707 * found. It returns a description about why the block is illegal
5709 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5713 static char problem[80];
5715 super = fs->super->s_first_data_block;
5716 strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5717 if (block < super) {
5718 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5720 } else if (block >= fs->super->s_blocks_count) {
5721 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5724 for (i = 0; i < fs->group_desc_count; i++) {
5725 if (block == super) {
5726 sprintf(problem, "is the superblock in group %d", i);
5729 if (block > super &&
5730 block <= (super + fs->desc_blocks)) {
5731 sprintf(problem, "is in the group descriptors "
5735 if (block == fs->group_desc[i].bg_block_bitmap) {
5736 sprintf(problem, "is the block bitmap of group %d", i);
5739 if (block == fs->group_desc[i].bg_inode_bitmap) {
5740 sprintf(problem, "is the inode bitmap of group %d", i);
5743 if (block >= fs->group_desc[i].bg_inode_table &&
5744 (block < fs->group_desc[i].bg_inode_table
5745 + fs->inode_blocks_per_group)) {
5746 sprintf(problem, "is in the inode table of group %d",
5750 super += fs->super->s_blocks_per_group;
5757 * This is a helper function for check_blocks().
5759 static int process_block(ext2_filsys fs,
5761 e2_blkcnt_t blockcnt,
5762 blk_t ref_block FSCK_ATTR((unused)),
5763 int ref_offset FSCK_ATTR((unused)),
5766 struct process_block_struct_1 *p;
5767 struct problem_context *pctx;
5768 blk_t blk = *block_nr;
5773 p = (struct process_block_struct_1 *) priv_data;
5777 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5778 /* todo: Check that the comprblk_fl is high, that the
5779 blkaddr pattern looks right (all non-holes up to
5780 first EXT2FS_COMPRESSED_BLKADDR, then all
5781 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5782 that the feature_incompat bit is high, and that the
5783 inode is a regular file. If we're doing a "full
5784 check" (a concept introduced to e2fsck by e2compr,
5785 meaning that we look at data blocks as well as
5786 metadata) then call some library routine that
5787 checks the compressed data. I'll have to think
5788 about this, because one particularly important
5789 problem to be able to fix is to recalculate the
5790 cluster size if necessary. I think that perhaps
5791 we'd better do most/all e2compr-specific checks
5792 separately, after the non-e2compr checks. If not
5793 doing a full check, it may be useful to test that
5794 the personality is linux; e.g. if it isn't then
5795 perhaps this really is just an illegal block. */
5800 if (p->is_dir == 0) {
5802 * Should never happen, since only directories
5803 * get called with BLOCK_FLAG_HOLE
5806 printf("process_block() called with blk == 0, "
5807 "blockcnt=%d, inode %lu???\n",
5814 if (blockcnt * fs->blocksize < p->inode->i_size) {
5816 printf("Missing block (#%d) in directory inode %lu!\n",
5825 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5830 * Simplistic fragmentation check. We merely require that the
5831 * file be contiguous. (Which can never be true for really
5832 * big files that are greater than a block group.)
5834 if (!HOLE_BLKADDR(p->previous_block)) {
5835 if (p->previous_block+1 != blk)
5838 p->previous_block = blk;
5840 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5841 problem = PR_1_TOOBIG_DIR;
5842 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5843 problem = PR_1_TOOBIG_REG;
5844 if (!p->is_dir && !p->is_reg && blockcnt > 0)
5845 problem = PR_1_TOOBIG_SYMLINK;
5847 if (blk < fs->super->s_first_data_block ||
5848 blk >= fs->super->s_blocks_count)
5849 problem = PR_1_ILLEGAL_BLOCK_NUM;
5852 p->num_illegal_blocks++;
5853 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5854 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5858 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5860 set_latch_flags(PR_LATCH_BLOCK,
5865 pctx->blkcount = blockcnt;
5866 if (fix_problem(ctx, problem, pctx)) {
5867 blk = *block_nr = 0;
5868 ret_code = BLOCK_CHANGED;
5874 if (p->ino == EXT2_RESIZE_INO) {
5876 * The resize inode has already be sanity checked
5877 * during pass #0 (the superblock checks). All we
5878 * have to do is mark the double indirect block as
5879 * being in use; all of the other blocks are handled
5880 * by mark_table_blocks()).
5882 if (blockcnt == BLOCK_COUNT_DIND)
5883 mark_block_used(ctx, blk);
5885 mark_block_used(ctx, blk);
5888 p->last_block = blockcnt;
5890 if (p->is_dir && (blockcnt >= 0)) {
5891 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5893 if (pctx->errcode) {
5895 pctx->num = blockcnt;
5896 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5897 /* Should never get here */
5898 ctx->flags |= E2F_FLAG_ABORT;
5905 static int process_bad_block(ext2_filsys fs,
5907 e2_blkcnt_t blockcnt,
5908 blk_t ref_block FSCK_ATTR((unused)),
5909 int ref_offset FSCK_ATTR((unused)),
5912 struct process_block_struct_1 *p;
5913 blk_t blk = *block_nr;
5916 struct problem_context *pctx;
5920 * Note: This function processes blocks for the bad blocks
5921 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
5927 p = (struct process_block_struct_1 *) priv_data;
5931 pctx->ino = EXT2_BAD_INO;
5933 pctx->blkcount = blockcnt;
5935 if ((blk < fs->super->s_first_data_block) ||
5936 (blk >= fs->super->s_blocks_count)) {
5937 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5939 return BLOCK_CHANGED;
5945 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5947 if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5949 return BLOCK_CHANGED;
5951 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5954 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5957 return BLOCK_CHANGED;
5959 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5962 mark_block_used(ctx, blk);
5966 printf ("DEBUG: Marking %u as bad.\n", blk);
5968 ctx->fs_badblocks_count++;
5970 * If the block is not used, then mark it as used and return.
5971 * If it is already marked as found, this must mean that
5972 * there's an overlap between the filesystem table blocks
5973 * (bitmaps and inode table) and the bad block list.
5975 if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
5976 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
5980 * Try to find the where the filesystem block was used...
5982 first_block = fs->super->s_first_data_block;
5984 for (i = 0; i < fs->group_desc_count; i++ ) {
5987 if (!ext2fs_bg_has_super(fs, i))
5989 if (blk == first_block) {
5991 if (fix_problem(ctx,
5992 PR_1_BAD_PRIMARY_SUPERBLOCK,
5995 return BLOCK_CHANGED;
5999 fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
6002 if ((blk > first_block) &&
6003 (blk <= first_block + fs->desc_blocks)) {
6005 pctx->blk = *block_nr;
6006 if (fix_problem(ctx,
6007 PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
6009 return BLOCK_CHANGED;
6013 fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6017 if (blk == fs->group_desc[i].bg_block_bitmap) {
6018 if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6019 ctx->invalid_block_bitmap_flag[i]++;
6020 ctx->invalid_bitmaps++;
6024 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6025 if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6026 ctx->invalid_inode_bitmap_flag[i]++;
6027 ctx->invalid_bitmaps++;
6031 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6032 (blk < (fs->group_desc[i].bg_inode_table +
6033 fs->inode_blocks_per_group))) {
6035 * If there are bad blocks in the inode table,
6036 * the inode scan code will try to do
6037 * something reasonable automatically.
6041 first_block += fs->super->s_blocks_per_group;
6044 * If we've gotten to this point, then the only
6045 * possibility is that the bad block inode meta data
6046 * is using a bad block.
6048 if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6049 (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6050 (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6052 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6054 return BLOCK_CHANGED;
6056 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6063 /* Warn user that the block wasn't claimed */
6064 fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6069 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6070 const char *name, int num, blk_t *new_block)
6072 ext2_filsys fs = ctx->fs;
6073 blk_t old_block = *new_block;
6076 struct problem_context pctx;
6078 clear_problem_context(&pctx);
6081 pctx.blk = old_block;
6084 pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6085 first_block + fs->super->s_blocks_per_group,
6086 num, ctx->block_found_map, new_block);
6089 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6090 ext2fs_unmark_valid(fs);
6093 pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6095 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6096 ext2fs_unmark_valid(fs);
6099 ext2fs_mark_super_dirty(fs);
6100 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6101 pctx.blk2 = *new_block;
6102 fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6103 PR_1_RELOC_TO), &pctx);
6105 for (i = 0; i < num; i++) {
6107 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6109 pctx.errcode = io_channel_read_blk(fs->io,
6110 old_block + i, 1, buf);
6112 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6114 memset(buf, 0, fs->blocksize);
6116 pctx.blk = (*new_block) + i;
6117 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6120 fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6122 ext2fs_free_mem(&buf);
6126 * This routine gets called at the end of pass 1 if bad blocks are
6127 * detected in the superblock, group descriptors, inode_bitmaps, or
6128 * block bitmaps. At this point, all of the blocks have been mapped
6129 * out, so we can try to allocate new block(s) to replace the bad
6132 static void handle_fs_bad_blocks(e2fsck_t ctx)
6134 ext2_filsys fs = ctx->fs;
6136 int first_block = fs->super->s_first_data_block;
6138 for (i = 0; i < fs->group_desc_count; i++) {
6139 if (ctx->invalid_block_bitmap_flag[i]) {
6140 new_table_block(ctx, first_block, i, _("block bitmap"),
6141 1, &fs->group_desc[i].bg_block_bitmap);
6143 if (ctx->invalid_inode_bitmap_flag[i]) {
6144 new_table_block(ctx, first_block, i, _("inode bitmap"),
6145 1, &fs->group_desc[i].bg_inode_bitmap);
6147 if (ctx->invalid_inode_table_flag[i]) {
6148 new_table_block(ctx, first_block, i, _("inode table"),
6149 fs->inode_blocks_per_group,
6150 &fs->group_desc[i].bg_inode_table);
6151 ctx->flags |= E2F_FLAG_RESTART;
6153 first_block += fs->super->s_blocks_per_group;
6155 ctx->invalid_bitmaps = 0;
6159 * This routine marks all blocks which are used by the superblock,
6160 * group descriptors, inode bitmaps, and block bitmaps.
6162 static void mark_table_blocks(e2fsck_t ctx)
6164 ext2_filsys fs = ctx->fs;
6168 struct problem_context pctx;
6170 clear_problem_context(&pctx);
6172 block = fs->super->s_first_data_block;
6173 for (i = 0; i < fs->group_desc_count; i++) {
6176 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6179 * Mark the blocks used for the inode table
6181 if (fs->group_desc[i].bg_inode_table) {
6182 for (j = 0, b = fs->group_desc[i].bg_inode_table;
6183 j < fs->inode_blocks_per_group;
6185 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6188 if (fix_problem(ctx,
6189 PR_1_ITABLE_CONFLICT, &pctx)) {
6190 ctx->invalid_inode_table_flag[i]++;
6191 ctx->invalid_bitmaps++;
6194 ext2fs_mark_block_bitmap(ctx->block_found_map,
6201 * Mark block used for the block bitmap
6203 if (fs->group_desc[i].bg_block_bitmap) {
6204 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6205 fs->group_desc[i].bg_block_bitmap)) {
6206 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6207 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6208 ctx->invalid_block_bitmap_flag[i]++;
6209 ctx->invalid_bitmaps++;
6212 ext2fs_mark_block_bitmap(ctx->block_found_map,
6213 fs->group_desc[i].bg_block_bitmap);
6218 * Mark block used for the inode bitmap
6220 if (fs->group_desc[i].bg_inode_bitmap) {
6221 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6222 fs->group_desc[i].bg_inode_bitmap)) {
6223 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6224 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6225 ctx->invalid_inode_bitmap_flag[i]++;
6226 ctx->invalid_bitmaps++;
6229 ext2fs_mark_block_bitmap(ctx->block_found_map,
6230 fs->group_desc[i].bg_inode_bitmap);
6233 block += fs->super->s_blocks_per_group;
6238 * Thes subroutines short circuits ext2fs_get_blocks and
6239 * ext2fs_check_directory; we use them since we already have the inode
6240 * structure, so there's no point in letting the ext2fs library read
6243 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6246 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6249 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6250 return EXT2_ET_CALLBACK_NOTHANDLED;
6252 for (i=0; i < EXT2_N_BLOCKS; i++)
6253 blocks[i] = ctx->stashed_inode->i_block[i];
6257 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6258 struct ext2_inode *inode)
6260 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6262 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6263 return EXT2_ET_CALLBACK_NOTHANDLED;
6264 *inode = *ctx->stashed_inode;
6268 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6269 struct ext2_inode *inode)
6271 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6273 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6274 *ctx->stashed_inode = *inode;
6275 return EXT2_ET_CALLBACK_NOTHANDLED;
6278 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6280 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6282 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6283 return EXT2_ET_CALLBACK_NOTHANDLED;
6285 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6286 return EXT2_ET_NO_DIRECTORY;
6290 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6292 ext2_filsys fs = ctx->fs;
6295 fs->get_blocks = pass1_get_blocks;
6296 fs->check_directory = pass1_check_directory;
6297 fs->read_inode = pass1_read_inode;
6298 fs->write_inode = pass1_write_inode;
6299 ctx->stashed_ino = 0;
6302 fs->check_directory = 0;
6304 fs->write_inode = 0;
6309 * pass1b.c --- Pass #1b of e2fsck
6311 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
6312 * only invoked if pass 1 discovered blocks which are in use by more
6315 * Pass1B scans the data blocks of all the inodes again, generating a
6316 * complete list of duplicate blocks and which inodes have claimed
6319 * Pass1C does a tree-traversal of the filesystem, to determine the
6320 * parent directories of these inodes. This step is necessary so that
6321 * e2fsck can print out the pathnames of affected inodes.
6323 * Pass1D is a reconciliation pass. For each inode with duplicate
6324 * blocks, the user is prompted if s/he would like to clone the file
6325 * (so that the file gets a fresh copy of the duplicated blocks) or
6326 * simply to delete the file.
6331 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6332 #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
6333 #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
6335 /* Define an extension to the ext2 library's block count information */
6336 #define BLOCK_COUNT_EXTATTR (-5)
6340 struct block_el *next;
6345 struct inode_el *next;
6350 struct inode_el *inode_list;
6354 * This structure stores information about a particular inode which
6355 * is sharing blocks with other inodes. This information is collected
6356 * to display to the user, so that the user knows what files he or she
6357 * is dealing with, when trying to decide how to resolve the conflict
6358 * of multiply-claimed blocks.
6363 struct ext2_inode inode;
6364 struct block_el *block_list;
6367 static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
6368 e2_blkcnt_t blockcnt, blk_t ref_blk,
6369 int ref_offset, void *priv_data);
6370 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6371 struct dup_inode *dp, char *block_buf);
6372 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6373 struct dup_inode *dp, char* block_buf);
6374 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6376 static void pass1b(e2fsck_t ctx, char *block_buf);
6377 static void pass1c(e2fsck_t ctx, char *block_buf);
6378 static void pass1d(e2fsck_t ctx, char *block_buf);
6380 static int dup_inode_count = 0;
6382 static dict_t blk_dict, ino_dict;
6384 static ext2fs_inode_bitmap inode_dup_map;
6386 static int dict_int_cmp(const void *a, const void *b)
6397 * Add a duplicate block record
6399 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6400 struct ext2_inode *inode)
6403 struct dup_block *db;
6404 struct dup_inode *di;
6405 struct block_el *blk_el;
6406 struct inode_el *ino_el;
6408 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6410 db = (struct dup_block *) dnode_get(n);
6412 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6413 sizeof(struct dup_block), "duplicate block header");
6416 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6418 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6419 sizeof(struct inode_el), "inode element");
6420 ino_el->inode = ino;
6421 ino_el->next = db->inode_list;
6422 db->inode_list = ino_el;
6425 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6427 di = (struct dup_inode *) dnode_get(n);
6429 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6430 sizeof(struct dup_inode), "duplicate inode header");
6431 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6432 di->num_dupblocks = 0;
6435 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6437 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6438 sizeof(struct block_el), "block element");
6439 blk_el->block = blk;
6440 blk_el->next = di->block_list;
6441 di->block_list = blk_el;
6442 di->num_dupblocks++;
6446 * Free a duplicate inode record
6448 static void inode_dnode_free(dnode_t *node)
6450 struct dup_inode *di;
6451 struct block_el *p, *next;
6453 di = (struct dup_inode *) dnode_get(node);
6454 for (p = di->block_list; p; p = next) {
6462 * Free a duplicate block record
6464 static void block_dnode_free(dnode_t *node)
6466 struct dup_block *db;
6467 struct inode_el *p, *next;
6469 db = (struct dup_block *) dnode_get(node);
6470 for (p = db->inode_list; p; p = next) {
6479 * Main procedure for handling duplicate blocks
6481 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6483 ext2_filsys fs = ctx->fs;
6484 struct problem_context pctx;
6486 clear_problem_context(&pctx);
6488 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6489 _("multiply claimed inode map"), &inode_dup_map);
6491 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6492 ctx->flags |= E2F_FLAG_ABORT;
6496 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6497 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6498 dict_set_allocator(&ino_dict, inode_dnode_free);
6499 dict_set_allocator(&blk_dict, block_dnode_free);
6501 pass1b(ctx, block_buf);
6502 pass1c(ctx, block_buf);
6503 pass1d(ctx, block_buf);
6506 * Time to free all of the accumulated data structures that we
6507 * don't need anymore.
6509 dict_free_nodes(&ino_dict);
6510 dict_free_nodes(&blk_dict);
6514 * Scan the inodes looking for inodes that contain duplicate blocks.
6516 struct process_block_struct_1b {
6520 struct ext2_inode *inode;
6521 struct problem_context *pctx;
6524 static void pass1b(e2fsck_t ctx, char *block_buf)
6526 ext2_filsys fs = ctx->fs;
6528 struct ext2_inode inode;
6529 ext2_inode_scan scan;
6530 struct process_block_struct_1b pb;
6531 struct problem_context pctx;
6533 clear_problem_context(&pctx);
6535 if (!(ctx->options & E2F_OPT_PREEN))
6536 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6537 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6540 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6541 ctx->flags |= E2F_FLAG_ABORT;
6544 ctx->stashed_inode = &inode;
6547 pctx.str = "pass1b";
6549 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6550 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6553 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6554 ctx->flags |= E2F_FLAG_ABORT;
6559 pctx.ino = ctx->stashed_ino = ino;
6560 if ((ino != EXT2_BAD_INO) &&
6561 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6568 if (ext2fs_inode_has_valid_blocks(&inode) ||
6569 (ino == EXT2_BAD_INO))
6570 pctx.errcode = ext2fs_block_iterate2(fs, ino,
6571 0, block_buf, process_pass1b_block, &pb);
6572 if (inode.i_file_acl)
6573 process_pass1b_block(fs, &inode.i_file_acl,
6574 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6575 if (pb.dup_blocks) {
6576 end_problem_latch(ctx, PR_LATCH_DBLOCK);
6577 if (ino >= EXT2_FIRST_INODE(fs->super) ||
6578 ino == EXT2_ROOT_INO)
6582 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6584 ext2fs_close_inode_scan(scan);
6585 e2fsck_use_inode_shortcuts(ctx, 0);
6588 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6590 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6591 blk_t ref_blk FSCK_ATTR((unused)),
6592 int ref_offset FSCK_ATTR((unused)),
6595 struct process_block_struct_1b *p;
6598 if (HOLE_BLKADDR(*block_nr))
6600 p = (struct process_block_struct_1b *) priv_data;
6603 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6606 /* OK, this is a duplicate block */
6607 if (p->ino != EXT2_BAD_INO) {
6608 p->pctx->blk = *block_nr;
6609 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6612 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6614 add_dupe(ctx, p->ino, *block_nr, p->inode);
6620 * Pass 1c: Scan directories for inodes with duplicate blocks. This
6621 * is used so that we can print pathnames when prompting the user for
6624 struct search_dir_struct {
6626 ext2_ino_t first_inode;
6627 ext2_ino_t max_inode;
6630 static int search_dirent_proc(ext2_ino_t dir, int entry,
6631 struct ext2_dir_entry *dirent,
6632 int offset FSCK_ATTR((unused)),
6633 int blocksize FSCK_ATTR((unused)),
6634 char *buf FSCK_ATTR((unused)),
6637 struct search_dir_struct *sd;
6638 struct dup_inode *p;
6641 sd = (struct search_dir_struct *) priv_data;
6643 if (dirent->inode > sd->max_inode)
6644 /* Should abort this inode, but not everything */
6647 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6648 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6651 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6654 p = (struct dup_inode *) dnode_get(n);
6658 return(sd->count ? 0 : DIRENT_ABORT);
6662 static void pass1c(e2fsck_t ctx, char *block_buf)
6664 ext2_filsys fs = ctx->fs;
6665 struct search_dir_struct sd;
6666 struct problem_context pctx;
6668 clear_problem_context(&pctx);
6670 if (!(ctx->options & E2F_OPT_PREEN))
6671 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6674 * Search through all directories to translate inodes to names
6675 * (by searching for the containing directory for that inode.)
6677 sd.count = dup_inode_count;
6678 sd.first_inode = EXT2_FIRST_INODE(fs->super);
6679 sd.max_inode = fs->super->s_inodes_count;
6680 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6681 search_dirent_proc, &sd);
6684 static void pass1d(e2fsck_t ctx, char *block_buf)
6686 ext2_filsys fs = ctx->fs;
6687 struct dup_inode *p, *t;
6688 struct dup_block *q;
6689 ext2_ino_t *shared, ino;
6694 struct problem_context pctx;
6699 clear_problem_context(&pctx);
6701 if (!(ctx->options & E2F_OPT_PREEN))
6702 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6703 e2fsck_read_bitmaps(ctx);
6705 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6706 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6707 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6708 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6709 "Shared inode list");
6710 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6711 p = (struct dup_inode *) dnode_get(n);
6714 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6715 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
6719 * Find all of the inodes which share blocks with this
6720 * one. First we find all of the duplicate blocks
6721 * belonging to this inode, and then search each block
6722 * get the list of inodes, and merge them together.
6724 for (s = p->block_list; s; s = s->next) {
6725 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6727 continue; /* Should never happen... */
6728 q = (struct dup_block *) dnode_get(m);
6731 if (check_if_fs_block(ctx, s->block)) {
6737 * Add all inodes used by this block to the
6738 * shared[] --- which is a unique list, so
6739 * if an inode is already in shared[], don't
6742 for (r = q->inode_list; r; r = r->next) {
6743 if (r->inode == ino)
6745 for (i = 0; i < shared_len; i++)
6746 if (shared[i] == r->inode)
6748 if (i == shared_len) {
6749 shared[shared_len++] = r->inode;
6755 * Report the inode that we are working on
6757 pctx.inode = &p->inode;
6760 pctx.blkcount = p->num_dupblocks;
6761 pctx.num = meta_data ? shared_len+1 : shared_len;
6762 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6767 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6769 for (i = 0; i < shared_len; i++) {
6770 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6772 continue; /* should never happen */
6773 t = (struct dup_inode *) dnode_get(m);
6775 * Report the inode that we are sharing with
6777 pctx.inode = &t->inode;
6778 pctx.ino = shared[i];
6780 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6783 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6786 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6787 pctx.errcode = clone_file(ctx, ino, p, block_buf);
6789 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6793 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6794 delete_file(ctx, ino, p, block_buf);
6796 ext2fs_unmark_valid(fs);
6798 ext2fs_free_mem(&shared);
6802 * Drop the refcount on the dup_block structure, and clear the entry
6803 * in the block_dup_map if appropriate.
6805 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6808 if (p->num_bad <= 0 ||
6809 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6810 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6813 static int delete_file_block(ext2_filsys fs,
6815 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6816 blk_t ref_block FSCK_ATTR((unused)),
6817 int ref_offset FSCK_ATTR((unused)),
6820 struct process_block_struct_1b *pb;
6821 struct dup_block *p;
6825 pb = (struct process_block_struct_1b *) priv_data;
6828 if (HOLE_BLKADDR(*block_nr))
6831 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6832 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6834 p = (struct dup_block *) dnode_get(n);
6835 decrement_badcount(ctx, *block_nr, p);
6837 com_err("delete_file_block", 0,
6838 _("internal error; can't find dup_blk for %d\n"),
6841 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6842 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6848 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6849 struct dup_inode *dp, char* block_buf)
6851 ext2_filsys fs = ctx->fs;
6852 struct process_block_struct_1b pb;
6853 struct ext2_inode inode;
6854 struct problem_context pctx;
6857 clear_problem_context(&pctx);
6858 pctx.ino = pb.ino = ino;
6859 pb.dup_blocks = dp->num_dupblocks;
6861 pctx.str = "delete_file";
6863 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6864 if (ext2fs_inode_has_valid_blocks(&inode))
6865 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6866 delete_file_block, &pb);
6868 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6869 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6870 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6871 if (ctx->inode_bad_map)
6872 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6873 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6875 /* Inode may have changed by block_iterate, so reread it */
6876 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6877 inode.i_links_count = 0;
6878 inode.i_dtime = time(0);
6879 if (inode.i_file_acl &&
6880 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6882 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6883 block_buf, -1, &count);
6884 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6889 pctx.blk = inode.i_file_acl;
6890 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6893 * If the count is zero, then arrange to have the
6894 * block deleted. If the block is in the block_dup_map,
6895 * also call delete_file_block since it will take care
6896 * of keeping the accounting straight.
6899 ext2fs_test_block_bitmap(ctx->block_dup_map,
6901 delete_file_block(fs, &inode.i_file_acl,
6902 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6904 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6907 struct clone_struct {
6914 static int clone_file_block(ext2_filsys fs,
6916 e2_blkcnt_t blockcnt,
6917 blk_t ref_block FSCK_ATTR((unused)),
6918 int ref_offset FSCK_ATTR((unused)),
6921 struct dup_block *p;
6924 struct clone_struct *cs = (struct clone_struct *) priv_data;
6930 if (HOLE_BLKADDR(*block_nr))
6933 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6934 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6936 p = (struct dup_block *) dnode_get(n);
6937 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6940 cs->errcode = retval;
6943 if (cs->dir && (blockcnt >= 0)) {
6944 retval = ext2fs_set_dir_block(fs->dblist,
6945 cs->dir, new_block, blockcnt);
6947 cs->errcode = retval;
6952 printf("Cloning block %u to %u\n", *block_nr,
6955 retval = io_channel_read_blk(fs->io, *block_nr, 1,
6958 cs->errcode = retval;
6961 retval = io_channel_write_blk(fs->io, new_block, 1,
6964 cs->errcode = retval;
6967 decrement_badcount(ctx, *block_nr, p);
6968 *block_nr = new_block;
6969 ext2fs_mark_block_bitmap(ctx->block_found_map,
6971 ext2fs_mark_block_bitmap(fs->block_map, new_block);
6972 return BLOCK_CHANGED;
6974 com_err("clone_file_block", 0,
6975 _("internal error; can't find dup_blk for %d\n"),
6981 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6982 struct dup_inode *dp, char* block_buf)
6984 ext2_filsys fs = ctx->fs;
6986 struct clone_struct cs;
6987 struct problem_context pctx;
6990 struct inode_el *ino_el;
6991 struct dup_block *db;
6992 struct dup_inode *di;
6994 clear_problem_context(&pctx);
6998 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
7002 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
7006 pctx.str = "clone_file";
7007 if (ext2fs_inode_has_valid_blocks(&dp->inode))
7008 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7009 clone_file_block, &cs);
7010 ext2fs_mark_bb_dirty(fs);
7012 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7013 retval = pctx.errcode;
7017 com_err("clone_file", cs.errcode,
7018 _("returned from clone_file_block"));
7019 retval = cs.errcode;
7022 /* The inode may have changed on disk, so we have to re-read it */
7023 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7024 blk = dp->inode.i_file_acl;
7025 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7026 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7028 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7030 * If we cloned the EA block, find all other inodes
7031 * which refered to that EA block, and modify
7032 * them to point to the new EA block.
7034 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7035 db = (struct dup_block *) dnode_get(n);
7036 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7037 if (ino_el->inode == ino)
7039 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7040 di = (struct dup_inode *) dnode_get(n);
7041 if (di->inode.i_file_acl == blk) {
7042 di->inode.i_file_acl = dp->inode.i_file_acl;
7043 e2fsck_write_inode(ctx, ino_el->inode,
7044 &di->inode, "clone file EA");
7045 decrement_badcount(ctx, blk, db);
7051 ext2fs_free_mem(&cs.buf);
7056 * This routine returns 1 if a block overlaps with one of the superblocks,
7057 * group descriptors, inode bitmaps, or block bitmaps.
7059 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7061 ext2_filsys fs = ctx->fs;
7065 block = fs->super->s_first_data_block;
7066 for (i = 0; i < fs->group_desc_count; i++) {
7068 /* Check superblocks/block group descriptros */
7069 if (ext2fs_bg_has_super(fs, i)) {
7070 if (test_block >= block &&
7071 (test_block <= block + fs->desc_blocks))
7075 /* Check the inode table */
7076 if ((fs->group_desc[i].bg_inode_table) &&
7077 (test_block >= fs->group_desc[i].bg_inode_table) &&
7078 (test_block < (fs->group_desc[i].bg_inode_table +
7079 fs->inode_blocks_per_group)))
7082 /* Check the bitmap blocks */
7083 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7084 (test_block == fs->group_desc[i].bg_inode_bitmap))
7087 block += fs->super->s_blocks_per_group;
7092 * pass2.c --- check directory structure
7094 * Pass 2 of e2fsck iterates through all active directory inodes, and
7095 * applies to following tests to each directory entry in the directory
7096 * blocks in the inodes:
7098 * - The length of the directory entry (rec_len) should be at
7099 * least 8 bytes, and no more than the remaining space
7100 * left in the directory block.
7101 * - The length of the name in the directory entry (name_len)
7102 * should be less than (rec_len - 8).
7103 * - The inode number in the directory entry should be within
7105 * - The inode number should refer to a in-use inode.
7106 * - The first entry should be '.', and its inode should be
7107 * the inode of the directory.
7108 * - The second entry should be '..'.
7110 * To minimize disk seek time, the directory blocks are processed in
7111 * sorted order of block numbers.
7113 * Pass 2 also collects the following information:
7114 * - The inode numbers of the subdirectories for each directory.
7116 * Pass 2 relies on the following information from previous passes:
7117 * - The directory information collected in pass 1.
7118 * - The inode_used_map bitmap
7119 * - The inode_bad_map bitmap
7120 * - The inode_dir_map bitmap
7122 * Pass 2 frees the following data structures
7123 * - The inode_bad_map bitmap
7124 * - The inode_reg_map bitmap
7127 /* #define DX_DEBUG */
7130 * Keeps track of how many times an inode is referenced.
7132 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7133 static int check_dir_block(ext2_filsys fs,
7134 struct ext2_db_entry *dir_blocks_info,
7136 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7137 struct problem_context *pctx);
7138 static int update_dir_block(ext2_filsys fs,
7140 e2_blkcnt_t blockcnt,
7144 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7145 static int htree_depth(struct dx_dir_info *dx_dir,
7146 struct dx_dirblock_info *dx_db);
7147 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7149 struct check_dir_struct {
7151 struct problem_context pctx;
7156 static void e2fsck_pass2(e2fsck_t ctx)
7158 struct ext2_super_block *sb = ctx->fs->super;
7159 struct problem_context pctx;
7160 ext2_filsys fs = ctx->fs;
7162 #ifdef RESOURCE_TRACK
7163 struct resource_track rtrack;
7165 struct dir_info *dir;
7166 struct check_dir_struct cd;
7167 struct dx_dir_info *dx_dir;
7168 struct dx_dirblock_info *dx_db, *dx_parent;
7174 #ifdef RESOURCE_TRACK
7175 init_resource_track(&rtrack);
7178 clear_problem_context(&cd.pctx);
7181 mtrace_print("Pass 2");
7184 if (!(ctx->options & E2F_OPT_PREEN))
7185 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7187 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7188 0, ctx->inode_link_info,
7190 if (cd.pctx.errcode) {
7191 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7192 ctx->flags |= E2F_FLAG_ABORT;
7195 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7196 "directory scan buffer");
7199 * Set up the parent pointer for the root directory, if
7200 * present. (If the root directory is not present, we will
7201 * create it in pass 3.)
7203 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7205 dir->parent = EXT2_ROOT_INO;
7210 cd.max = ext2fs_dblist_count(fs->dblist);
7213 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7215 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7216 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7218 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7220 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7222 if (cd.pctx.errcode) {
7223 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7224 ctx->flags |= E2F_FLAG_ABORT;
7229 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7230 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7232 if (dx_dir->numblocks == 0)
7234 clear_problem_context(&pctx);
7236 pctx.dir = dx_dir->ino;
7237 dx_db = dx_dir->dx_block;
7238 if (dx_db->flags & DX_FLAG_REFERENCED)
7239 dx_db->flags |= DX_FLAG_DUP_REF;
7241 dx_db->flags |= DX_FLAG_REFERENCED;
7243 * Find all of the first and last leaf blocks, and
7244 * update their parent's min and max hash values
7246 for (b=0, dx_db = dx_dir->dx_block;
7247 b < dx_dir->numblocks;
7249 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7250 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7252 dx_parent = &dx_dir->dx_block[dx_db->parent];
7254 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7256 if (dx_db->flags & DX_FLAG_FIRST)
7257 dx_parent->min_hash = dx_db->min_hash;
7259 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7261 if (dx_db->flags & DX_FLAG_LAST)
7262 dx_parent->max_hash = dx_db->max_hash;
7265 for (b=0, dx_db = dx_dir->dx_block;
7266 b < dx_dir->numblocks;
7269 pctx.group = dx_db->parent;
7271 if (!(dx_db->flags & DX_FLAG_FIRST) &&
7272 (dx_db->min_hash < dx_db->node_min_hash)) {
7273 pctx.blk = dx_db->min_hash;
7274 pctx.blk2 = dx_db->node_min_hash;
7275 code = PR_2_HTREE_MIN_HASH;
7276 fix_problem(ctx, code, &pctx);
7279 if (dx_db->type == DX_DIRBLOCK_LEAF) {
7280 depth = htree_depth(dx_dir, dx_db);
7281 if (depth != dx_dir->depth) {
7282 code = PR_2_HTREE_BAD_DEPTH;
7283 fix_problem(ctx, code, &pctx);
7288 * This test doesn't apply for the root block
7292 (dx_db->max_hash > dx_db->node_max_hash)) {
7293 pctx.blk = dx_db->max_hash;
7294 pctx.blk2 = dx_db->node_max_hash;
7295 code = PR_2_HTREE_MAX_HASH;
7296 fix_problem(ctx, code, &pctx);
7299 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7300 code = PR_2_HTREE_NOTREF;
7301 fix_problem(ctx, code, &pctx);
7303 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7304 code = PR_2_HTREE_DUPREF;
7305 fix_problem(ctx, code, &pctx);
7311 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7312 clear_htree(ctx, dx_dir->ino);
7313 dx_dir->numblocks = 0;
7317 ext2fs_free_mem(&buf);
7318 ext2fs_free_dblist(fs->dblist);
7320 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7321 ctx->inode_bad_map = 0;
7322 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7323 ctx->inode_reg_map = 0;
7325 clear_problem_context(&pctx);
7326 if (ctx->large_files) {
7327 if (!(sb->s_feature_ro_compat &
7328 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7329 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7330 sb->s_feature_ro_compat |=
7331 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7332 ext2fs_mark_super_dirty(fs);
7334 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7335 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7336 ext2fs_update_dynamic_rev(fs);
7337 ext2fs_mark_super_dirty(fs);
7339 } else if (!ctx->large_files &&
7340 (sb->s_feature_ro_compat &
7341 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7342 if (fs->flags & EXT2_FLAG_RW) {
7343 sb->s_feature_ro_compat &=
7344 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7345 ext2fs_mark_super_dirty(fs);
7349 #ifdef RESOURCE_TRACK
7350 if (ctx->options & E2F_OPT_TIME2) {
7351 e2fsck_clear_progbar(ctx);
7352 print_resource_track(_("Pass 2"), &rtrack);
7357 #define MAX_DEPTH 32000
7358 static int htree_depth(struct dx_dir_info *dx_dir,
7359 struct dx_dirblock_info *dx_db)
7363 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7364 dx_db = &dx_dir->dx_block[dx_db->parent];
7370 static int dict_de_cmp(const void *a, const void *b)
7372 const struct ext2_dir_entry *de_a, *de_b;
7375 de_a = (const struct ext2_dir_entry *) a;
7376 a_len = de_a->name_len & 0xFF;
7377 de_b = (const struct ext2_dir_entry *) b;
7378 b_len = de_b->name_len & 0xFF;
7381 return (a_len - b_len);
7383 return strncmp(de_a->name, de_b->name, a_len);
7387 * This is special sort function that makes sure that directory blocks
7388 * with a dirblock of zero are sorted to the beginning of the list.
7389 * This guarantees that the root node of the htree directories are
7390 * processed first, so we know what hash version to use.
7392 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7394 const struct ext2_db_entry *db_a =
7395 (const struct ext2_db_entry *) a;
7396 const struct ext2_db_entry *db_b =
7397 (const struct ext2_db_entry *) b;
7399 if (db_a->blockcnt && !db_b->blockcnt)
7402 if (!db_a->blockcnt && db_b->blockcnt)
7405 if (db_a->blk != db_b->blk)
7406 return (int) (db_a->blk - db_b->blk);
7408 if (db_a->ino != db_b->ino)
7409 return (int) (db_a->ino - db_b->ino);
7411 return (int) (db_a->blockcnt - db_b->blockcnt);
7416 * Make sure the first entry in the directory is '.', and that the
7417 * directory entry is sane.
7419 static int check_dot(e2fsck_t ctx,
7420 struct ext2_dir_entry *dirent,
7421 ext2_ino_t ino, struct problem_context *pctx)
7423 struct ext2_dir_entry *nextdir;
7430 problem = PR_2_MISSING_DOT;
7431 else if (((dirent->name_len & 0xFF) != 1) ||
7432 (dirent->name[0] != '.'))
7433 problem = PR_2_1ST_NOT_DOT;
7434 else if (dirent->name[1] != '\0')
7435 problem = PR_2_DOT_NULL_TERM;
7438 if (fix_problem(ctx, problem, pctx)) {
7439 if (dirent->rec_len < 12)
7440 dirent->rec_len = 12;
7441 dirent->inode = ino;
7442 dirent->name_len = 1;
7443 dirent->name[0] = '.';
7444 dirent->name[1] = '\0';
7449 if (dirent->inode != ino) {
7450 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7451 dirent->inode = ino;
7455 if (dirent->rec_len > 12) {
7456 new_len = dirent->rec_len - 12;
7459 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7460 nextdir = (struct ext2_dir_entry *)
7461 ((char *) dirent + 12);
7462 dirent->rec_len = 12;
7463 nextdir->rec_len = new_len;
7465 nextdir->name_len = 0;
7474 * Make sure the second entry in the directory is '..', and that the
7475 * directory entry is sane. We do not check the inode number of '..'
7476 * here; this gets done in pass 3.
7478 static int check_dotdot(e2fsck_t ctx,
7479 struct ext2_dir_entry *dirent,
7480 struct dir_info *dir, struct problem_context *pctx)
7485 problem = PR_2_MISSING_DOT_DOT;
7486 else if (((dirent->name_len & 0xFF) != 2) ||
7487 (dirent->name[0] != '.') ||
7488 (dirent->name[1] != '.'))
7489 problem = PR_2_2ND_NOT_DOT_DOT;
7490 else if (dirent->name[2] != '\0')
7491 problem = PR_2_DOT_DOT_NULL_TERM;
7494 if (fix_problem(ctx, problem, pctx)) {
7495 if (dirent->rec_len < 12)
7496 dirent->rec_len = 12;
7498 * Note: we don't have the parent inode just
7499 * yet, so we will fill it in with the root
7500 * inode. This will get fixed in pass 3.
7502 dirent->inode = EXT2_ROOT_INO;
7503 dirent->name_len = 2;
7504 dirent->name[0] = '.';
7505 dirent->name[1] = '.';
7506 dirent->name[2] = '\0';
7511 dir->dotdot = dirent->inode;
7516 * Check to make sure a directory entry doesn't contain any illegal
7519 static int check_name(e2fsck_t ctx,
7520 struct ext2_dir_entry *dirent,
7521 struct problem_context *pctx)
7527 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7528 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7530 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7533 dirent->name[i] = '.';
7542 * Check the directory filetype (if present)
7546 * Given a mode, return the ext2 file type
7548 static int ext2_file_type(unsigned int mode)
7550 if (LINUX_S_ISREG(mode))
7551 return EXT2_FT_REG_FILE;
7553 if (LINUX_S_ISDIR(mode))
7556 if (LINUX_S_ISCHR(mode))
7557 return EXT2_FT_CHRDEV;
7559 if (LINUX_S_ISBLK(mode))
7560 return EXT2_FT_BLKDEV;
7562 if (LINUX_S_ISLNK(mode))
7563 return EXT2_FT_SYMLINK;
7565 if (LINUX_S_ISFIFO(mode))
7566 return EXT2_FT_FIFO;
7568 if (LINUX_S_ISSOCK(mode))
7569 return EXT2_FT_SOCK;
7574 static _INLINE_ int check_filetype(e2fsck_t ctx,
7575 struct ext2_dir_entry *dirent,
7576 struct problem_context *pctx)
7578 int filetype = dirent->name_len >> 8;
7579 int should_be = EXT2_FT_UNKNOWN;
7580 struct ext2_inode inode;
7582 if (!(ctx->fs->super->s_feature_incompat &
7583 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7584 if (filetype == 0 ||
7585 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7587 dirent->name_len = dirent->name_len & 0xFF;
7591 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7592 should_be = EXT2_FT_DIR;
7593 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7595 should_be = EXT2_FT_REG_FILE;
7596 } else if (ctx->inode_bad_map &&
7597 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7601 e2fsck_read_inode(ctx, dirent->inode, &inode,
7603 should_be = ext2_file_type(inode.i_mode);
7605 if (filetype == should_be)
7607 pctx->num = should_be;
7609 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7613 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7618 static void parse_int_node(ext2_filsys fs,
7619 struct ext2_db_entry *db,
7620 struct check_dir_struct *cd,
7621 struct dx_dir_info *dx_dir,
7624 struct ext2_dx_root_info *root;
7625 struct ext2_dx_entry *ent;
7626 struct ext2_dx_countlimit *limit;
7627 struct dx_dirblock_info *dx_db;
7628 int i, expect_limit, count;
7630 ext2_dirhash_t min_hash = 0xffffffff;
7631 ext2_dirhash_t max_hash = 0;
7632 ext2_dirhash_t hash = 0, prev_hash;
7634 if (db->blockcnt == 0) {
7635 root = (struct ext2_dx_root_info *) (block_buf + 24);
7638 printf("Root node dump:\n");
7639 printf("\t Reserved zero: %d\n", root->reserved_zero);
7640 printf("\t Hash Version: %d\n", root->hash_version);
7641 printf("\t Info length: %d\n", root->info_length);
7642 printf("\t Indirect levels: %d\n", root->indirect_levels);
7643 printf("\t Flags: %d\n", root->unused_flags);
7646 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7648 ent = (struct ext2_dx_entry *) (block_buf+8);
7650 limit = (struct ext2_dx_countlimit *) ent;
7653 printf("Number of entries (count): %d\n",
7654 ext2fs_le16_to_cpu(limit->count));
7655 printf("Number of entries (limit): %d\n",
7656 ext2fs_le16_to_cpu(limit->limit));
7659 count = ext2fs_le16_to_cpu(limit->count);
7660 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7661 sizeof(struct ext2_dx_entry);
7662 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7663 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7664 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7665 goto clear_and_exit;
7667 if (count > expect_limit) {
7668 cd->pctx.num = count;
7669 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7670 goto clear_and_exit;
7671 count = expect_limit;
7674 for (i=0; i < count; i++) {
7676 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7678 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7679 hash, ext2fs_le32_to_cpu(ent[i].block));
7681 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7682 /* Check to make sure the block is valid */
7683 if (blk > (blk_t) dx_dir->numblocks) {
7685 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7687 goto clear_and_exit;
7689 if (hash < prev_hash &&
7690 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7691 goto clear_and_exit;
7692 dx_db = &dx_dir->dx_block[blk];
7693 if (dx_db->flags & DX_FLAG_REFERENCED) {
7694 dx_db->flags |= DX_FLAG_DUP_REF;
7696 dx_db->flags |= DX_FLAG_REFERENCED;
7697 dx_db->parent = db->blockcnt;
7699 if (hash < min_hash)
7701 if (hash > max_hash)
7703 dx_db->node_min_hash = hash;
7705 dx_db->node_max_hash =
7706 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7708 dx_db->node_max_hash = 0xfffffffe;
7709 dx_db->flags |= DX_FLAG_LAST;
7712 dx_db->flags |= DX_FLAG_FIRST;
7715 printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7716 db->blockcnt, min_hash, max_hash);
7718 dx_db = &dx_dir->dx_block[db->blockcnt];
7719 dx_db->min_hash = min_hash;
7720 dx_db->max_hash = max_hash;
7724 clear_htree(cd->ctx, cd->pctx.ino);
7725 dx_dir->numblocks = 0;
7727 #endif /* ENABLE_HTREE */
7730 * Given a busted directory, try to salvage it somehow.
7733 static void salvage_directory(ext2_filsys fs,
7734 struct ext2_dir_entry *dirent,
7735 struct ext2_dir_entry *prev,
7736 unsigned int *offset)
7738 char *cp = (char *) dirent;
7739 int left = fs->blocksize - *offset - dirent->rec_len;
7740 int name_len = dirent->name_len & 0xFF;
7743 * Special case of directory entry of size 8: copy what's left
7744 * of the directory block up to cover up the invalid hole.
7746 if ((left >= 12) && (dirent->rec_len == 8)) {
7747 memmove(cp, cp+8, left);
7748 memset(cp + left, 0, 8);
7752 * If the directory entry overruns the end of the directory
7753 * block, and the name is small enough to fit, then adjust the
7757 (name_len + 8 <= dirent->rec_len + left) &&
7758 dirent->inode <= fs->super->s_inodes_count &&
7759 strnlen(dirent->name, name_len) == name_len) {
7760 dirent->rec_len += left;
7764 * If the directory entry is a multiple of four, so it is
7765 * valid, let the previous directory entry absorb the invalid
7768 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7769 prev->rec_len += dirent->rec_len;
7770 *offset += dirent->rec_len;
7774 * Default salvage method --- kill all of the directory
7775 * entries for the rest of the block. We will either try to
7776 * absorb it into the previous directory entry, or create a
7777 * new empty directory entry the rest of the directory block.
7780 prev->rec_len += fs->blocksize - *offset;
7781 *offset = fs->blocksize;
7783 dirent->rec_len = fs->blocksize - *offset;
7784 dirent->name_len = 0;
7789 static int check_dir_block(ext2_filsys fs,
7790 struct ext2_db_entry *db,
7793 struct dir_info *subdir, *dir;
7794 struct dx_dir_info *dx_dir;
7796 struct dx_dirblock_info *dx_db = 0;
7797 #endif /* ENABLE_HTREE */
7798 struct ext2_dir_entry *dirent, *prev;
7799 ext2_dirhash_t hash;
7800 unsigned int offset = 0;
7801 int dir_modified = 0;
7803 blk_t block_nr = db->blk;
7804 ext2_ino_t ino = db->ino;
7806 struct check_dir_struct *cd;
7810 struct ext2_dx_root_info *root;
7811 struct ext2_dx_countlimit *limit;
7812 static dict_t de_dict;
7813 struct problem_context pctx;
7816 cd = (struct check_dir_struct *) priv_data;
7820 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7821 return DIRENT_ABORT;
7823 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7824 return DIRENT_ABORT;
7827 * Make sure the inode is still in use (could have been
7828 * deleted in the duplicate/bad blocks pass.
7830 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7834 cd->pctx.blk = block_nr;
7835 cd->pctx.blkcount = db->blockcnt;
7837 cd->pctx.dirent = 0;
7841 if (allocate_dir_block(ctx, db, &cd->pctx))
7851 if (ctx->dirs_to_hash &&
7852 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7856 printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7860 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7861 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7862 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7863 if (cd->pctx.errcode) {
7864 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7865 ctx->flags |= E2F_FLAG_ABORT;
7866 return DIRENT_ABORT;
7868 memset(buf, 0, fs->blocksize);
7871 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7872 if (dx_dir && dx_dir->numblocks) {
7873 if (db->blockcnt >= dx_dir->numblocks) {
7874 printf("XXX should never happen!!!\n");
7877 dx_db = &dx_dir->dx_block[db->blockcnt];
7878 dx_db->type = DX_DIRBLOCK_LEAF;
7879 dx_db->phys = block_nr;
7880 dx_db->min_hash = ~0;
7881 dx_db->max_hash = 0;
7883 dirent = (struct ext2_dir_entry *) buf;
7884 limit = (struct ext2_dx_countlimit *) (buf+8);
7885 if (db->blockcnt == 0) {
7886 root = (struct ext2_dx_root_info *) (buf + 24);
7887 dx_db->type = DX_DIRBLOCK_ROOT;
7888 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7889 if ((root->reserved_zero ||
7890 root->info_length < 8 ||
7891 root->indirect_levels > 1) &&
7892 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7893 clear_htree(ctx, ino);
7894 dx_dir->numblocks = 0;
7897 dx_dir->hashversion = root->hash_version;
7898 dx_dir->depth = root->indirect_levels + 1;
7899 } else if ((dirent->inode == 0) &&
7900 (dirent->rec_len == fs->blocksize) &&
7901 (dirent->name_len == 0) &&
7902 (ext2fs_le16_to_cpu(limit->limit) ==
7903 ((fs->blocksize-8) /
7904 sizeof(struct ext2_dx_entry))))
7905 dx_db->type = DX_DIRBLOCK_NODE;
7907 #endif /* ENABLE_HTREE */
7909 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7913 dirent = (struct ext2_dir_entry *) (buf + offset);
7914 cd->pctx.dirent = dirent;
7915 cd->pctx.num = offset;
7916 if (((offset + dirent->rec_len) > fs->blocksize) ||
7917 (dirent->rec_len < 12) ||
7918 ((dirent->rec_len % 4) != 0) ||
7919 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7920 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7921 salvage_directory(fs, dirent, prev, &offset);
7925 goto abort_free_dict;
7927 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7928 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7929 dirent->name_len = EXT2_NAME_LEN;
7934 if (dot_state == 0) {
7935 if (check_dot(ctx, dirent, ino, &cd->pctx))
7937 } else if (dot_state == 1) {
7938 dir = e2fsck_get_dir_info(ctx, ino);
7940 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7941 goto abort_free_dict;
7943 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7945 } else if (dirent->inode == ino) {
7946 problem = PR_2_LINK_DOT;
7947 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7957 * Make sure the inode listed is a legal one.
7959 if (((dirent->inode != EXT2_ROOT_INO) &&
7960 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
7961 (dirent->inode > fs->super->s_inodes_count)) {
7962 problem = PR_2_BAD_INO;
7963 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
7966 * If the inode is unused, offer to clear it.
7968 problem = PR_2_UNUSED_INODE;
7969 } else if (ctx->inode_bb_map &&
7970 (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
7973 * If the inode is in a bad block, offer to
7976 problem = PR_2_BB_INODE;
7977 } else if ((dot_state > 1) &&
7978 ((dirent->name_len & 0xFF) == 1) &&
7979 (dirent->name[0] == '.')) {
7981 * If there's a '.' entry in anything other
7982 * than the first directory entry, it's a
7983 * duplicate entry that should be removed.
7985 problem = PR_2_DUP_DOT;
7986 } else if ((dot_state > 1) &&
7987 ((dirent->name_len & 0xFF) == 2) &&
7988 (dirent->name[0] == '.') &&
7989 (dirent->name[1] == '.')) {
7991 * If there's a '..' entry in anything other
7992 * than the second directory entry, it's a
7993 * duplicate entry that should be removed.
7995 problem = PR_2_DUP_DOT_DOT;
7996 } else if ((dot_state > 1) &&
7997 (dirent->inode == EXT2_ROOT_INO)) {
7999 * Don't allow links to the root directory.
8000 * We check this specially to make sure we
8001 * catch this error case even if the root
8002 * directory hasn't been created yet.
8004 problem = PR_2_LINK_ROOT;
8005 } else if ((dot_state > 1) &&
8006 (dirent->name_len & 0xFF) == 0) {
8008 * Don't allow zero-length directory names.
8010 problem = PR_2_NULL_NAME;
8014 if (fix_problem(ctx, problem, &cd->pctx)) {
8019 ext2fs_unmark_valid(fs);
8020 if (problem == PR_2_BAD_INO)
8026 * If the inode was marked as having bad fields in
8027 * pass1, process it and offer to fix/clear it.
8028 * (We wait until now so that we can display the
8029 * pathname to the user.)
8031 if (ctx->inode_bad_map &&
8032 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8034 if (e2fsck_process_bad_inode(ctx, ino,
8036 buf + fs->blocksize)) {
8041 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8042 return DIRENT_ABORT;
8045 if (check_name(ctx, dirent, &cd->pctx))
8048 if (check_filetype(ctx, dirent, &cd->pctx))
8053 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8054 (dirent->name_len & 0xFF),
8055 fs->super->s_hash_seed, &hash, 0);
8056 if (hash < dx_db->min_hash)
8057 dx_db->min_hash = hash;
8058 if (hash > dx_db->max_hash)
8059 dx_db->max_hash = hash;
8064 * If this is a directory, then mark its parent in its
8065 * dir_info structure. If the parent field is already
8066 * filled in, then this directory has more than one
8067 * hard link. We assume the first link is correct,
8068 * and ask the user if he/she wants to clear this one.
8070 if ((dot_state > 1) &&
8071 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8073 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8075 cd->pctx.ino = dirent->inode;
8076 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8077 goto abort_free_dict;
8079 if (subdir->parent) {
8080 cd->pctx.ino2 = subdir->parent;
8081 if (fix_problem(ctx, PR_2_LINK_DIR,
8089 subdir->parent = ino;
8094 } else if (dict_lookup(&de_dict, dirent)) {
8095 clear_problem_context(&pctx);
8097 pctx.dirent = dirent;
8098 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8099 if (!ctx->dirs_to_hash)
8100 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8101 if (ctx->dirs_to_hash)
8102 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8105 dict_alloc_insert(&de_dict, dirent, dirent);
8107 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8110 ctx->fs_links_count++;
8111 ctx->fs_total_count++;
8114 offset += dirent->rec_len;
8116 } while (offset < fs->blocksize);
8123 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8124 db->blockcnt, dx_db->type,
8125 dx_db->min_hash, dx_db->max_hash);
8127 cd->pctx.dir = cd->pctx.ino;
8128 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8129 (dx_db->type == DX_DIRBLOCK_NODE))
8130 parse_int_node(fs, db, cd, dx_dir, buf);
8132 #endif /* ENABLE_HTREE */
8133 if (offset != fs->blocksize) {
8134 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8135 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8136 dirent->rec_len = cd->pctx.num;
8141 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8142 if (cd->pctx.errcode) {
8143 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8145 goto abort_free_dict;
8147 ext2fs_mark_changed(fs);
8149 dict_free_nodes(&de_dict);
8152 dict_free_nodes(&de_dict);
8153 ctx->flags |= E2F_FLAG_ABORT;
8154 return DIRENT_ABORT;
8158 * This function is called to deallocate a block, and is an interator
8159 * functioned called by deallocate inode via ext2fs_iterate_block().
8161 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8162 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
8163 blk_t ref_block FSCK_ATTR((unused)),
8164 int ref_offset FSCK_ATTR((unused)),
8167 e2fsck_t ctx = (e2fsck_t) priv_data;
8169 if (HOLE_BLKADDR(*block_nr))
8171 if ((*block_nr < fs->super->s_first_data_block) ||
8172 (*block_nr >= fs->super->s_blocks_count))
8174 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8175 ext2fs_block_alloc_stats(fs, *block_nr, -1);
8180 * This fuction deallocates an inode
8182 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8184 ext2_filsys fs = ctx->fs;
8185 struct ext2_inode inode;
8186 struct problem_context pctx;
8189 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8190 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8191 inode.i_links_count = 0;
8192 inode.i_dtime = time(0);
8193 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8194 clear_problem_context(&pctx);
8198 * Fix up the bitmaps...
8200 e2fsck_read_bitmaps(ctx);
8201 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8202 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8203 if (ctx->inode_bad_map)
8204 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8205 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8207 if (inode.i_file_acl &&
8208 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8209 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8210 block_buf, -1, &count);
8211 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8216 pctx.blk = inode.i_file_acl;
8217 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8218 ctx->flags |= E2F_FLAG_ABORT;
8222 ext2fs_unmark_block_bitmap(ctx->block_found_map,
8224 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8226 inode.i_file_acl = 0;
8229 if (!ext2fs_inode_has_valid_blocks(&inode))
8232 if (LINUX_S_ISREG(inode.i_mode) &&
8233 (inode.i_size_high || inode.i_size & 0x80000000UL))
8236 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8237 deallocate_inode_block, ctx);
8239 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8240 ctx->flags |= E2F_FLAG_ABORT;
8246 * This fuction clears the htree flag on an inode
8248 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8250 struct ext2_inode inode;
8252 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8253 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8254 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8255 if (ctx->dirs_to_hash)
8256 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8260 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8261 ext2_ino_t ino, char *buf)
8263 ext2_filsys fs = ctx->fs;
8264 struct ext2_inode inode;
8265 int inode_modified = 0;
8267 unsigned char *frag, *fsize;
8268 struct problem_context pctx;
8271 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8273 clear_problem_context(&pctx);
8276 pctx.inode = &inode;
8278 if (inode.i_file_acl &&
8279 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8280 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8281 inode.i_file_acl = 0;
8282 #ifdef EXT2FS_ENABLE_SWAPFS
8284 * This is a special kludge to deal with long symlinks
8285 * on big endian systems. i_blocks had already been
8286 * decremented earlier in pass 1, but since i_file_acl
8287 * hadn't yet been cleared, ext2fs_read_inode()
8288 * assumed that the file was short symlink and would
8289 * not have byte swapped i_block[0]. Hence, we have
8290 * to byte-swap it here.
8292 if (LINUX_S_ISLNK(inode.i_mode) &&
8293 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8294 (inode.i_blocks == fs->blocksize >> 9))
8295 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8301 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8302 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8303 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8304 !(LINUX_S_ISSOCK(inode.i_mode)))
8305 problem = PR_2_BAD_MODE;
8306 else if (LINUX_S_ISCHR(inode.i_mode)
8307 && !e2fsck_pass1_check_device_inode(fs, &inode))
8308 problem = PR_2_BAD_CHAR_DEV;
8309 else if (LINUX_S_ISBLK(inode.i_mode)
8310 && !e2fsck_pass1_check_device_inode(fs, &inode))
8311 problem = PR_2_BAD_BLOCK_DEV;
8312 else if (LINUX_S_ISFIFO(inode.i_mode)
8313 && !e2fsck_pass1_check_device_inode(fs, &inode))
8314 problem = PR_2_BAD_FIFO;
8315 else if (LINUX_S_ISSOCK(inode.i_mode)
8316 && !e2fsck_pass1_check_device_inode(fs, &inode))
8317 problem = PR_2_BAD_SOCKET;
8318 else if (LINUX_S_ISLNK(inode.i_mode)
8319 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8320 problem = PR_2_INVALID_SYMLINK;
8324 if (fix_problem(ctx, problem, &pctx)) {
8325 deallocate_inode(ctx, ino, 0);
8326 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8334 if (inode.i_faddr) {
8335 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8342 switch (fs->super->s_creator_os) {
8344 frag = &inode.osd2.linux2.l_i_frag;
8345 fsize = &inode.osd2.linux2.l_i_fsize;
8348 frag = &inode.osd2.hurd2.h_i_frag;
8349 fsize = &inode.osd2.hurd2.h_i_fsize;
8352 frag = &inode.osd2.masix2.m_i_frag;
8353 fsize = &inode.osd2.masix2.m_i_fsize;
8358 if (frag && *frag) {
8360 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8367 if (fsize && *fsize) {
8369 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8377 if (inode.i_file_acl &&
8378 ((inode.i_file_acl < fs->super->s_first_data_block) ||
8379 (inode.i_file_acl >= fs->super->s_blocks_count))) {
8380 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8381 inode.i_file_acl = 0;
8386 if (inode.i_dir_acl &&
8387 LINUX_S_ISDIR(inode.i_mode)) {
8388 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8389 inode.i_dir_acl = 0;
8396 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8398 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8404 * allocate_dir_block --- this function allocates a new directory
8405 * block for a particular inode; this is done if a directory has
8406 * a "hole" in it, or if a directory has a illegal block number
8407 * that was zeroed out and now needs to be replaced.
8409 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8410 struct problem_context *pctx)
8412 ext2_filsys fs = ctx->fs;
8415 struct ext2_inode inode;
8417 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8421 * Read the inode and block bitmaps in; we'll be messing with
8424 e2fsck_read_bitmaps(ctx);
8427 * First, find a free block
8429 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8430 if (pctx->errcode) {
8431 pctx->str = "ext2fs_new_block";
8432 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8435 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8436 ext2fs_mark_block_bitmap(fs->block_map, blk);
8437 ext2fs_mark_bb_dirty(fs);
8440 * Now let's create the actual data block for the inode
8443 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8445 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8446 EXT2_ROOT_INO, &block);
8448 if (pctx->errcode) {
8449 pctx->str = "ext2fs_new_dir_block";
8450 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8454 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8455 ext2fs_free_mem(&block);
8456 if (pctx->errcode) {
8457 pctx->str = "ext2fs_write_dir_block";
8458 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8463 * Update the inode block count
8465 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8466 inode.i_blocks += fs->blocksize / 512;
8467 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8468 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8469 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8472 * Finally, update the block pointers for the inode
8475 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8476 0, update_dir_block, db);
8477 if (pctx->errcode) {
8478 pctx->str = "ext2fs_block_iterate";
8479 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8487 * This is a helper function for allocate_dir_block().
8489 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8491 e2_blkcnt_t blockcnt,
8492 blk_t ref_block FSCK_ATTR((unused)),
8493 int ref_offset FSCK_ATTR((unused)),
8496 struct ext2_db_entry *db;
8498 db = (struct ext2_db_entry *) priv_data;
8499 if (db->blockcnt == (int) blockcnt) {
8500 *block_nr = db->blk;
8501 return BLOCK_CHANGED;
8507 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8509 * Pass #3 assures that all directories are connected to the
8510 * filesystem tree, using the following algorithm:
8512 * First, the root directory is checked to make sure it exists; if
8513 * not, e2fsck will offer to create a new one. It is then marked as
8516 * Then, pass3 interates over all directory inodes; for each directory
8517 * it attempts to trace up the filesystem tree, using dirinfo.parent
8518 * until it reaches a directory which has been marked "done". If it
8519 * can not do so, then the directory must be disconnected, and e2fsck
8520 * will offer to reconnect it to /lost+found. While it is chasing
8521 * parent pointers up the filesystem tree, if pass3 sees a directory
8522 * twice, then it has detected a filesystem loop, and it will again
8523 * offer to reconnect the directory to /lost+found in to break the
8526 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8527 * reconnect inodes to /lost+found; this subroutine is also used by
8528 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
8529 * is responsible for creating /lost+found if it does not exist.
8531 * Pass 3 frees the following data structures:
8532 * - The dirinfo directory information cache.
8535 static void check_root(e2fsck_t ctx);
8536 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8537 struct problem_context *pctx);
8538 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8540 static ext2fs_inode_bitmap inode_loop_detect;
8541 static ext2fs_inode_bitmap inode_done_map;
8543 static void e2fsck_pass3(e2fsck_t ctx)
8545 ext2_filsys fs = ctx->fs;
8547 #ifdef RESOURCE_TRACK
8548 struct resource_track rtrack;
8550 struct problem_context pctx;
8551 struct dir_info *dir;
8552 unsigned long maxdirs, count;
8554 #ifdef RESOURCE_TRACK
8555 init_resource_track(&rtrack);
8558 clear_problem_context(&pctx);
8561 mtrace_print("Pass 3");
8564 if (!(ctx->options & E2F_OPT_PREEN))
8565 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8568 * Allocate some bitmaps to do loop detection.
8570 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8574 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8575 ctx->flags |= E2F_FLAG_ABORT;
8578 #ifdef RESOURCE_TRACK
8579 if (ctx->options & E2F_OPT_TIME) {
8580 e2fsck_clear_progbar(ctx);
8581 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8586 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8589 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8591 maxdirs = e2fsck_get_num_dirinfo(ctx);
8595 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8598 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8599 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8601 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8603 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8604 if (check_directory(ctx, dir, &pctx))
8609 * Force the creation of /lost+found if not present
8611 if ((ctx->flags & E2F_OPT_READONLY) == 0)
8612 e2fsck_get_lost_and_found(ctx, 1);
8615 * If there are any directories that need to be indexed or
8616 * optimized, do it here.
8618 e2fsck_rehash_directories(ctx);
8621 e2fsck_free_dir_info(ctx);
8622 ext2fs_free_inode_bitmap(inode_loop_detect);
8623 inode_loop_detect = 0;
8624 ext2fs_free_inode_bitmap(inode_done_map);
8627 #ifdef RESOURCE_TRACK
8628 if (ctx->options & E2F_OPT_TIME2) {
8629 e2fsck_clear_progbar(ctx);
8630 print_resource_track(_("Pass 3"), &rtrack);
8636 * This makes sure the root inode is present; if not, we ask if the
8637 * user wants us to create it. Not creating it is a fatal error.
8639 static void check_root(e2fsck_t ctx)
8641 ext2_filsys fs = ctx->fs;
8643 struct ext2_inode inode;
8645 struct problem_context pctx;
8647 clear_problem_context(&pctx);
8649 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8651 * If the root inode is not a directory, die here. The
8652 * user must have answered 'no' in pass1 when we
8653 * offered to clear it.
8655 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8657 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8658 ctx->flags |= E2F_FLAG_ABORT;
8663 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8664 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8665 ctx->flags |= E2F_FLAG_ABORT;
8669 e2fsck_read_bitmaps(ctx);
8672 * First, find a free block
8674 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8676 pctx.str = "ext2fs_new_block";
8677 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8678 ctx->flags |= E2F_FLAG_ABORT;
8681 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8682 ext2fs_mark_block_bitmap(fs->block_map, blk);
8683 ext2fs_mark_bb_dirty(fs);
8686 * Now let's create the actual data block for the inode
8688 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8691 pctx.str = "ext2fs_new_dir_block";
8692 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8693 ctx->flags |= E2F_FLAG_ABORT;
8697 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8699 pctx.str = "ext2fs_write_dir_block";
8700 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8701 ctx->flags |= E2F_FLAG_ABORT;
8704 ext2fs_free_mem(&block);
8707 * Set up the inode structure
8709 memset(&inode, 0, sizeof(inode));
8710 inode.i_mode = 040755;
8711 inode.i_size = fs->blocksize;
8712 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8713 inode.i_links_count = 2;
8714 inode.i_blocks = fs->blocksize / 512;
8715 inode.i_block[0] = blk;
8718 * Write out the inode.
8720 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8722 pctx.str = "ext2fs_write_inode";
8723 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8724 ctx->flags |= E2F_FLAG_ABORT;
8729 * Miscellaneous bookkeeping...
8731 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8732 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8733 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8735 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8736 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8737 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8738 ext2fs_mark_ib_dirty(fs);
8742 * This subroutine is responsible for making sure that a particular
8743 * directory is connected to the root; if it isn't we trace it up as
8744 * far as we can go, and then offer to connect the resulting parent to
8745 * the lost+found. We have to do loop detection; if we ever discover
8746 * a loop, we treat that as a disconnected directory and offer to
8747 * reparent it to lost+found.
8749 * However, loop detection is expensive, because for very large
8750 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8751 * is non-trivial. Loops in filesystems are also a rare error case,
8752 * and we shouldn't optimize for error cases. So we try two passes of
8753 * the algorithm. The first time, we ignore loop detection and merely
8754 * increment a counter; if the counter exceeds some extreme threshold,
8755 * then we try again with the loop detection bitmap enabled.
8757 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8758 struct problem_context *pctx)
8760 ext2_filsys fs = ctx->fs;
8761 struct dir_info *p = dir;
8762 int loop_pass = 0, parent_count = 0;
8769 * Mark this inode as being "done"; by the time we
8770 * return from this function, the inode we either be
8771 * verified as being connected to the directory tree,
8772 * or we will have offered to reconnect this to
8775 * If it was marked done already, then we've reached a
8776 * parent we've already checked.
8778 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8782 * If this directory doesn't have a parent, or we've
8783 * seen the parent once already, then offer to
8784 * reparent it to lost+found
8788 (ext2fs_test_inode_bitmap(inode_loop_detect,
8791 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8792 if (e2fsck_reconnect_file(ctx, pctx->ino))
8793 ext2fs_unmark_valid(fs);
8795 p = e2fsck_get_dir_info(ctx, pctx->ino);
8796 p->parent = ctx->lost_and_found;
8797 fix_dotdot(ctx, p, ctx->lost_and_found);
8802 p = e2fsck_get_dir_info(ctx, p->parent);
8804 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8808 ext2fs_mark_inode_bitmap(inode_loop_detect,
8810 } else if (parent_count++ > 2048) {
8812 * If we've run into a path depth that's
8813 * greater than 2048, try again with the inode
8814 * loop bitmap turned on and start from the
8818 if (inode_loop_detect)
8819 ext2fs_clear_inode_bitmap(inode_loop_detect);
8821 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8822 if (pctx->errcode) {
8825 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8826 ctx->flags |= E2F_FLAG_ABORT;
8835 * Make sure that .. and the parent directory are the same;
8836 * offer to fix it if not.
8838 if (dir->parent != dir->dotdot) {
8839 pctx->ino = dir->ino;
8840 pctx->ino2 = dir->dotdot;
8841 pctx->dir = dir->parent;
8842 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8843 fix_dotdot(ctx, dir, dir->parent);
8849 * This routine gets the lost_and_found inode, making it a directory
8852 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8854 ext2_filsys fs = ctx->fs;
8858 struct ext2_inode inode;
8860 static const char name[] = "lost+found";
8861 struct problem_context pctx;
8862 struct dir_info *dirinfo;
8864 if (ctx->lost_and_found)
8865 return ctx->lost_and_found;
8867 clear_problem_context(&pctx);
8869 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8870 sizeof(name)-1, 0, &ino);
8874 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8875 ctx->lost_and_found = ino;
8879 /* Lost+found isn't a directory! */
8883 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8886 /* OK, unlink the old /lost+found file. */
8887 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8889 pctx.str = "ext2fs_unlink";
8890 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8893 dirinfo = e2fsck_get_dir_info(ctx, ino);
8895 dirinfo->parent = 0;
8896 e2fsck_adjust_inode_count(ctx, ino, -1);
8897 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8898 pctx.errcode = retval;
8899 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8901 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8905 * Read the inode and block bitmaps in; we'll be messing with
8908 e2fsck_read_bitmaps(ctx);
8911 * First, find a free block
8913 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8915 pctx.errcode = retval;
8916 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8919 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8920 ext2fs_block_alloc_stats(fs, blk, +1);
8923 * Next find a free inode.
8925 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8926 ctx->inode_used_map, &ino);
8928 pctx.errcode = retval;
8929 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8932 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8933 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8934 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8937 * Now let's create the actual data block for the inode
8939 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8941 pctx.errcode = retval;
8942 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8946 retval = ext2fs_write_dir_block(fs, blk, block);
8947 ext2fs_free_mem(&block);
8949 pctx.errcode = retval;
8950 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
8955 * Set up the inode structure
8957 memset(&inode, 0, sizeof(inode));
8958 inode.i_mode = 040700;
8959 inode.i_size = fs->blocksize;
8960 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8961 inode.i_links_count = 2;
8962 inode.i_blocks = fs->blocksize / 512;
8963 inode.i_block[0] = blk;
8966 * Next, write out the inode.
8968 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
8970 pctx.str = "ext2fs_write_inode";
8971 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8975 * Finally, create the directory link
8977 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
8979 pctx.str = "ext2fs_link";
8980 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8985 * Miscellaneous bookkeeping that needs to be kept straight.
8987 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
8988 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
8989 ext2fs_icount_store(ctx->inode_count, ino, 2);
8990 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
8991 ctx->lost_and_found = ino;
8993 printf("/lost+found created; inode #%lu\n", ino);
8999 * This routine will connect a file to lost+found
9001 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
9003 ext2_filsys fs = ctx->fs;
9006 struct problem_context pctx;
9007 struct ext2_inode inode;
9010 clear_problem_context(&pctx);
9013 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9014 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9015 ctx->bad_lost_and_found++;
9017 if (ctx->bad_lost_and_found) {
9018 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9022 sprintf(name, "#%u", ino);
9023 if (ext2fs_read_inode(fs, ino, &inode) == 0)
9024 file_type = ext2_file_type(inode.i_mode);
9025 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9026 if (retval == EXT2_ET_DIR_NO_SPACE) {
9027 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9029 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9032 pctx.errcode = retval;
9033 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9036 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9040 pctx.errcode = retval;
9041 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9044 e2fsck_adjust_inode_count(ctx, ino, 1);
9050 * Utility routine to adjust the inode counts on an inode.
9052 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9054 ext2_filsys fs = ctx->fs;
9056 struct ext2_inode inode;
9061 retval = ext2fs_read_inode(fs, ino, &inode);
9066 printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9067 inode.i_links_count);
9071 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9072 if (inode.i_links_count == (__u16) ~0)
9074 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9075 inode.i_links_count++;
9076 } else if (adj == -1) {
9077 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9078 if (inode.i_links_count == 0)
9080 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9081 inode.i_links_count--;
9084 retval = ext2fs_write_inode(fs, ino, &inode);
9092 * Fix parent --- this routine fixes up the parent of a directory.
9094 struct fix_dotdot_struct {
9101 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9102 int offset FSCK_ATTR((unused)),
9103 int blocksize FSCK_ATTR((unused)),
9104 char *buf FSCK_ATTR((unused)),
9107 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9109 struct problem_context pctx;
9111 if ((dirent->name_len & 0xFF) != 2)
9113 if (strncmp(dirent->name, "..", 2))
9116 clear_problem_context(&pctx);
9118 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9120 pctx.errcode = retval;
9121 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9123 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9125 pctx.errcode = retval;
9126 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9128 dirent->inode = fp->parent;
9131 return DIRENT_ABORT | DIRENT_CHANGED;
9134 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9136 ext2_filsys fs = ctx->fs;
9138 struct fix_dotdot_struct fp;
9139 struct problem_context pctx;
9147 printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9150 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9151 0, fix_dotdot_proc, &fp);
9152 if (retval || !fp.done) {
9153 clear_problem_context(&pctx);
9154 pctx.ino = dir->ino;
9155 pctx.errcode = retval;
9156 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9157 PR_3_FIX_PARENT_NOFIND, &pctx);
9158 ext2fs_unmark_valid(fs);
9160 dir->dotdot = parent;
9166 * These routines are responsible for expanding a /lost+found if it is
9170 struct expand_dir_struct {
9172 int guaranteed_size;
9179 static int expand_dir_proc(ext2_filsys fs,
9181 e2_blkcnt_t blockcnt,
9182 blk_t ref_block FSCK_ATTR((unused)),
9183 int ref_offset FSCK_ATTR((unused)),
9186 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9188 static blk_t last_blk = 0;
9195 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9199 es->last_block = blockcnt;
9201 last_blk = *blocknr;
9204 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9211 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9217 retval = ext2fs_write_dir_block(fs, new_blk, block);
9219 retval = ext2fs_get_mem(fs->blocksize, &block);
9224 memset(block, 0, fs->blocksize);
9225 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9231 ext2fs_free_mem(&block);
9233 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9234 ext2fs_block_alloc_stats(fs, new_blk, +1);
9238 return (BLOCK_CHANGED | BLOCK_ABORT);
9240 return BLOCK_CHANGED;
9243 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9244 int num, int guaranteed_size)
9246 ext2_filsys fs = ctx->fs;
9248 struct expand_dir_struct es;
9249 struct ext2_inode inode;
9251 if (!(fs->flags & EXT2_FLAG_RW))
9252 return EXT2_ET_RO_FILSYS;
9255 * Read the inode and block bitmaps in; we'll be messing with
9258 e2fsck_read_bitmaps(ctx);
9260 retval = ext2fs_check_directory(fs, dir);
9265 es.guaranteed_size = guaranteed_size;
9271 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9272 0, expand_dir_proc, &es);
9278 * Update the size and block count fields in the inode.
9280 retval = ext2fs_read_inode(fs, dir, &inode);
9284 inode.i_size = (es.last_block + 1) * fs->blocksize;
9285 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9287 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9293 * pass4.c -- pass #4 of e2fsck: Check reference counts
9295 * Pass 4 frees the following data structures:
9296 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
9297 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
9301 * This routine is called when an inode is not connected to the
9304 * This subroutine returns 1 then the caller shouldn't bother with the
9305 * rest of the pass 4 tests.
9307 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9309 ext2_filsys fs = ctx->fs;
9310 struct ext2_inode inode;
9311 struct problem_context pctx;
9313 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9314 clear_problem_context(&pctx);
9316 pctx.inode = &inode;
9319 * Offer to delete any zero-length files that does not have
9320 * blocks. If there is an EA block, it might have useful
9321 * information, so we won't prompt to delete it, but let it be
9322 * reconnected to lost+found.
9324 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9325 LINUX_S_ISDIR(inode.i_mode))) {
9326 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9327 ext2fs_icount_store(ctx->inode_link_info, i, 0);
9328 inode.i_links_count = 0;
9329 inode.i_dtime = time(0);
9330 e2fsck_write_inode(ctx, i, &inode,
9331 "disconnect_inode");
9333 * Fix up the bitmaps...
9335 e2fsck_read_bitmaps(ctx);
9336 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9337 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9338 ext2fs_inode_alloc_stats2(fs, i, -1,
9339 LINUX_S_ISDIR(inode.i_mode));
9345 * Prompt to reconnect.
9347 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9348 if (e2fsck_reconnect_file(ctx, i))
9349 ext2fs_unmark_valid(fs);
9352 * If we don't attach the inode, then skip the
9353 * i_links_test since there's no point in trying to
9354 * force i_links_count to zero.
9356 ext2fs_unmark_valid(fs);
9363 static void e2fsck_pass4(e2fsck_t ctx)
9365 ext2_filsys fs = ctx->fs;
9367 struct ext2_inode inode;
9368 #ifdef RESOURCE_TRACK
9369 struct resource_track rtrack;
9371 struct problem_context pctx;
9372 __u16 link_count, link_counted;
9374 int group, maxgroup;
9376 #ifdef RESOURCE_TRACK
9377 init_resource_track(&rtrack);
9381 mtrace_print("Pass 4");
9384 clear_problem_context(&pctx);
9386 if (!(ctx->options & E2F_OPT_PREEN))
9387 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9390 maxgroup = fs->group_desc_count;
9392 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9395 for (i=1; i <= fs->super->s_inodes_count; i++) {
9396 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9398 if ((i % fs->super->s_inodes_per_group) == 0) {
9401 if ((ctx->progress)(ctx, 4, group, maxgroup))
9404 if (i == EXT2_BAD_INO ||
9405 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9407 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9408 (ctx->inode_imagic_map &&
9409 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9410 (ctx->inode_bb_map &&
9411 ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9413 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9414 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9415 if (link_counted == 0) {
9417 buf = e2fsck_allocate_memory(ctx,
9418 fs->blocksize, "bad_inode buffer");
9419 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9421 if (disconnect_inode(ctx, i))
9423 ext2fs_icount_fetch(ctx->inode_link_info, i,
9425 ext2fs_icount_fetch(ctx->inode_count, i,
9428 if (link_counted != link_count) {
9429 e2fsck_read_inode(ctx, i, &inode, "pass4");
9431 pctx.inode = &inode;
9432 if (link_count != inode.i_links_count) {
9433 pctx.num = link_count;
9435 PR_4_INCONSISTENT_COUNT, &pctx);
9437 pctx.num = link_counted;
9438 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9439 inode.i_links_count = link_counted;
9440 e2fsck_write_inode(ctx, i, &inode, "pass4");
9444 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9445 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9446 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9447 ctx->inode_bb_map = 0;
9448 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9449 ctx->inode_imagic_map = 0;
9450 ext2fs_free_mem(&buf);
9451 #ifdef RESOURCE_TRACK
9452 if (ctx->options & E2F_OPT_TIME2) {
9453 e2fsck_clear_progbar(ctx);
9454 print_resource_track(_("Pass 4"), &rtrack);
9460 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9463 #define NO_BLK ((blk_t) -1)
9465 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9466 struct problem_context *pctx)
9469 case PR_5_BLOCK_UNUSED:
9470 if (pctx->blk == pctx->blk2)
9473 problem = PR_5_BLOCK_RANGE_UNUSED;
9475 case PR_5_BLOCK_USED:
9476 if (pctx->blk == pctx->blk2)
9479 problem = PR_5_BLOCK_RANGE_USED;
9481 case PR_5_INODE_UNUSED:
9482 if (pctx->ino == pctx->ino2)
9485 problem = PR_5_INODE_RANGE_UNUSED;
9487 case PR_5_INODE_USED:
9488 if (pctx->ino == pctx->ino2)
9491 problem = PR_5_INODE_RANGE_USED;
9494 fix_problem(ctx, problem, pctx);
9495 pctx->blk = pctx->blk2 = NO_BLK;
9496 pctx->ino = pctx->ino2 = 0;
9499 static void check_block_bitmaps(e2fsck_t ctx)
9501 ext2_filsys fs = ctx->fs;
9505 unsigned int blocks = 0;
9506 unsigned int free_blocks = 0;
9509 struct problem_context pctx;
9510 int problem, save_problem, fixit, had_problem;
9513 clear_problem_context(&pctx);
9514 free_array = (int *) e2fsck_allocate_memory(ctx,
9515 fs->group_desc_count * sizeof(int), "free block count array");
9517 if ((fs->super->s_first_data_block <
9518 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9519 (fs->super->s_blocks_count-1 >
9520 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9522 pctx.blk = fs->super->s_first_data_block;
9523 pctx.blk2 = fs->super->s_blocks_count -1;
9524 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9525 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9526 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9528 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9532 if ((fs->super->s_first_data_block <
9533 ext2fs_get_block_bitmap_start(fs->block_map)) ||
9534 (fs->super->s_blocks_count-1 >
9535 ext2fs_get_block_bitmap_end(fs->block_map))) {
9537 pctx.blk = fs->super->s_first_data_block;
9538 pctx.blk2 = fs->super->s_blocks_count -1;
9539 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9540 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9541 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9543 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9550 pctx.blk = pctx.blk2 = NO_BLK;
9551 for (i = fs->super->s_first_data_block;
9552 i < fs->super->s_blocks_count;
9554 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9555 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9557 if (actual == bitmap)
9560 if (!actual && bitmap) {
9562 * Block not used, but marked in use in the bitmap.
9564 problem = PR_5_BLOCK_UNUSED;
9567 * Block used, but not marked in use in the bitmap.
9569 problem = PR_5_BLOCK_USED;
9571 if (pctx.blk == NO_BLK) {
9572 pctx.blk = pctx.blk2 = i;
9573 save_problem = problem;
9575 if ((problem == save_problem) &&
9579 print_bitmap_problem(ctx, save_problem, &pctx);
9580 pctx.blk = pctx.blk2 = i;
9581 save_problem = problem;
9584 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9593 if ((blocks == fs->super->s_blocks_per_group) ||
9594 (i == fs->super->s_blocks_count-1)) {
9595 free_array[group] = group_free;
9600 if ((ctx->progress)(ctx, 5, group,
9601 fs->group_desc_count*2))
9605 if (pctx.blk != NO_BLK)
9606 print_bitmap_problem(ctx, save_problem, &pctx);
9608 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9611 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9614 ext2fs_free_block_bitmap(fs->block_map);
9615 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9618 clear_problem_context(&pctx);
9619 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9620 ctx->flags |= E2F_FLAG_ABORT;
9623 ext2fs_set_bitmap_padding(fs->block_map);
9624 ext2fs_mark_bb_dirty(fs);
9626 /* Redo the counts */
9627 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9628 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9630 } else if (fixit == 0)
9631 ext2fs_unmark_valid(fs);
9633 for (i = 0; i < fs->group_desc_count; i++) {
9634 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9636 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9637 pctx.blk2 = free_array[i];
9639 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9641 fs->group_desc[i].bg_free_blocks_count =
9643 ext2fs_mark_super_dirty(fs);
9645 ext2fs_unmark_valid(fs);
9648 if (free_blocks != fs->super->s_free_blocks_count) {
9650 pctx.blk = fs->super->s_free_blocks_count;
9651 pctx.blk2 = free_blocks;
9653 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9654 fs->super->s_free_blocks_count = free_blocks;
9655 ext2fs_mark_super_dirty(fs);
9657 ext2fs_unmark_valid(fs);
9659 ext2fs_free_mem(&free_array);
9662 static void check_inode_bitmaps(e2fsck_t ctx)
9664 ext2_filsys fs = ctx->fs;
9666 unsigned int free_inodes = 0;
9670 unsigned int inodes = 0;
9675 struct problem_context pctx;
9676 int problem, save_problem, fixit, had_problem;
9678 clear_problem_context(&pctx);
9679 free_array = (int *) e2fsck_allocate_memory(ctx,
9680 fs->group_desc_count * sizeof(int), "free inode count array");
9682 dir_array = (int *) e2fsck_allocate_memory(ctx,
9683 fs->group_desc_count * sizeof(int), "directory count array");
9685 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9686 (fs->super->s_inodes_count >
9687 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9690 pctx.blk2 = fs->super->s_inodes_count;
9691 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9692 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9693 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9695 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9698 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9699 (fs->super->s_inodes_count >
9700 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9703 pctx.blk2 = fs->super->s_inodes_count;
9704 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9705 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9706 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9708 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9715 pctx.ino = pctx.ino2 = 0;
9716 for (i = 1; i <= fs->super->s_inodes_count; i++) {
9717 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9718 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9720 if (actual == bitmap)
9723 if (!actual && bitmap) {
9725 * Inode wasn't used, but marked in bitmap
9727 problem = PR_5_INODE_UNUSED;
9728 } else /* if (actual && !bitmap) */ {
9730 * Inode used, but not in bitmap
9732 problem = PR_5_INODE_USED;
9734 if (pctx.ino == 0) {
9735 pctx.ino = pctx.ino2 = i;
9736 save_problem = problem;
9738 if ((problem == save_problem) &&
9742 print_bitmap_problem(ctx, save_problem, &pctx);
9743 pctx.ino = pctx.ino2 = i;
9744 save_problem = problem;
9747 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9755 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9759 if ((inodes == fs->super->s_inodes_per_group) ||
9760 (i == fs->super->s_inodes_count)) {
9761 free_array[group] = group_free;
9762 dir_array[group] = dirs_count;
9768 if ((ctx->progress)(ctx, 5,
9769 group + fs->group_desc_count,
9770 fs->group_desc_count*2))
9775 print_bitmap_problem(ctx, save_problem, &pctx);
9778 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9781 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9784 ext2fs_free_inode_bitmap(fs->inode_map);
9785 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9788 clear_problem_context(&pctx);
9789 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9790 ctx->flags |= E2F_FLAG_ABORT;
9793 ext2fs_set_bitmap_padding(fs->inode_map);
9794 ext2fs_mark_ib_dirty(fs);
9797 inodes = 0; free_inodes = 0; group_free = 0;
9798 dirs_count = 0; group = 0;
9799 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9800 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9802 } else if (fixit == 0)
9803 ext2fs_unmark_valid(fs);
9805 for (i = 0; i < fs->group_desc_count; i++) {
9806 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9808 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9809 pctx.ino2 = free_array[i];
9810 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9812 fs->group_desc[i].bg_free_inodes_count =
9814 ext2fs_mark_super_dirty(fs);
9816 ext2fs_unmark_valid(fs);
9818 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9820 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9821 pctx.ino2 = dir_array[i];
9823 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9825 fs->group_desc[i].bg_used_dirs_count =
9827 ext2fs_mark_super_dirty(fs);
9829 ext2fs_unmark_valid(fs);
9832 if (free_inodes != fs->super->s_free_inodes_count) {
9834 pctx.ino = fs->super->s_free_inodes_count;
9835 pctx.ino2 = free_inodes;
9837 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9838 fs->super->s_free_inodes_count = free_inodes;
9839 ext2fs_mark_super_dirty(fs);
9841 ext2fs_unmark_valid(fs);
9843 ext2fs_free_mem(&free_array);
9844 ext2fs_free_mem(&dir_array);
9847 static void check_inode_end(e2fsck_t ctx)
9849 ext2_filsys fs = ctx->fs;
9850 ext2_ino_t end, save_inodes_count, i;
9851 struct problem_context pctx;
9853 clear_problem_context(&pctx);
9855 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9856 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9857 &save_inodes_count);
9860 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9861 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9864 if (save_inodes_count == end)
9867 for (i = save_inodes_count + 1; i <= end; i++) {
9868 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9869 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9870 for (i = save_inodes_count + 1; i <= end; i++)
9871 ext2fs_mark_inode_bitmap(fs->inode_map,
9873 ext2fs_mark_ib_dirty(fs);
9875 ext2fs_unmark_valid(fs);
9880 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9881 save_inodes_count, 0);
9884 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9885 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9890 static void check_block_end(e2fsck_t ctx)
9892 ext2_filsys fs = ctx->fs;
9893 blk_t end, save_blocks_count, i;
9894 struct problem_context pctx;
9896 clear_problem_context(&pctx);
9898 end = fs->block_map->start +
9899 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9900 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9901 &save_blocks_count);
9904 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9905 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9908 if (save_blocks_count == end)
9911 for (i = save_blocks_count + 1; i <= end; i++) {
9912 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9913 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9914 for (i = save_blocks_count + 1; i <= end; i++)
9915 ext2fs_mark_block_bitmap(fs->block_map,
9917 ext2fs_mark_bb_dirty(fs);
9919 ext2fs_unmark_valid(fs);
9924 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9925 save_blocks_count, 0);
9928 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9929 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9934 static void e2fsck_pass5(e2fsck_t ctx)
9936 #ifdef RESOURCE_TRACK
9937 struct resource_track rtrack;
9939 struct problem_context pctx;
9942 mtrace_print("Pass 5");
9945 #ifdef RESOURCE_TRACK
9946 init_resource_track(&rtrack);
9949 clear_problem_context(&pctx);
9951 if (!(ctx->options & E2F_OPT_PREEN))
9952 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9955 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9958 e2fsck_read_bitmaps(ctx);
9960 check_block_bitmaps(ctx);
9961 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9963 check_inode_bitmaps(ctx);
9964 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9966 check_inode_end(ctx);
9967 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9969 check_block_end(ctx);
9970 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9973 ext2fs_free_inode_bitmap(ctx->inode_used_map);
9974 ctx->inode_used_map = 0;
9975 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9976 ctx->inode_dir_map = 0;
9977 ext2fs_free_block_bitmap(ctx->block_found_map);
9978 ctx->block_found_map = 0;
9980 #ifdef RESOURCE_TRACK
9981 if (ctx->options & E2F_OPT_TIME2) {
9982 e2fsck_clear_progbar(ctx);
9983 print_resource_track(_("Pass 5"), &rtrack);
9989 * problem.c --- report filesystem problems to the user
9992 #define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
9993 #define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
9994 #define PR_NO_DEFAULT 0x000004 /* Default to no */
9995 #define PR_MSG_ONLY 0x000008 /* Print message only */
9997 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
9999 #define PR_FATAL 0x001000 /* Fatal error */
10000 #define PR_AFTER_CODE 0x002000 /* After asking the first question, */
10002 #define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
10003 #define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
10004 #define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
10005 #define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
10006 #define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
10009 #define PROMPT_NONE 0
10010 #define PROMPT_FIX 1
10011 #define PROMPT_CLEAR 2
10012 #define PROMPT_RELOCATE 3
10013 #define PROMPT_ALLOCATE 4
10014 #define PROMPT_EXPAND 5
10015 #define PROMPT_CONNECT 6
10016 #define PROMPT_CREATE 7
10017 #define PROMPT_SALVAGE 8
10018 #define PROMPT_TRUNCATE 9
10019 #define PROMPT_CLEAR_INODE 10
10020 #define PROMPT_ABORT 11
10021 #define PROMPT_SPLIT 12
10022 #define PROMPT_CONTINUE 13
10023 #define PROMPT_CLONE 14
10024 #define PROMPT_DELETE 15
10025 #define PROMPT_SUPPRESS 16
10026 #define PROMPT_UNLINK 17
10027 #define PROMPT_CLEAR_HTREE 18
10028 #define PROMPT_RECREATE 19
10029 #define PROMPT_NULL 20
10031 struct e2fsck_problem {
10032 problem_t e2p_code;
10033 const char * e2p_description;
10036 problem_t second_code;
10039 struct latch_descr {
10041 problem_t question;
10042 problem_t end_message;
10047 * These are the prompts which are used to ask the user if they want
10048 * to fix a problem.
10050 static const char * const prompt[] = {
10051 N_("(no prompt)"), /* 0 */
10053 N_("Clear"), /* 2 */
10054 N_("Relocate"), /* 3 */
10055 N_("Allocate"), /* 4 */
10056 N_("Expand"), /* 5 */
10057 N_("Connect to /lost+found"), /* 6 */
10058 N_("Create"), /* 7 */
10059 N_("Salvage"), /* 8 */
10060 N_("Truncate"), /* 9 */
10061 N_("Clear inode"), /* 10 */
10062 N_("Abort"), /* 11 */
10063 N_("Split"), /* 12 */
10064 N_("Continue"), /* 13 */
10065 N_("Clone multiply-claimed blocks"), /* 14 */
10066 N_("Delete file"), /* 15 */
10067 N_("Suppress messages"),/* 16 */
10068 N_("Unlink"), /* 17 */
10069 N_("Clear HTree index"),/* 18 */
10070 N_("Recreate"), /* 19 */
10075 * These messages are printed when we are preen mode and we will be
10076 * automatically fixing the problem.
10078 static const char * const preen_msg[] = {
10079 N_("(NONE)"), /* 0 */
10080 N_("FIXED"), /* 1 */
10081 N_("CLEARED"), /* 2 */
10082 N_("RELOCATED"), /* 3 */
10083 N_("ALLOCATED"), /* 4 */
10084 N_("EXPANDED"), /* 5 */
10085 N_("RECONNECTED"), /* 6 */
10086 N_("CREATED"), /* 7 */
10087 N_("SALVAGED"), /* 8 */
10088 N_("TRUNCATED"), /* 9 */
10089 N_("INODE CLEARED"), /* 10 */
10090 N_("ABORTED"), /* 11 */
10091 N_("SPLIT"), /* 12 */
10092 N_("CONTINUING"), /* 13 */
10093 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
10094 N_("FILE DELETED"), /* 15 */
10095 N_("SUPPRESSED"), /* 16 */
10096 N_("UNLINKED"), /* 17 */
10097 N_("HTREE INDEX CLEARED"),/* 18 */
10098 N_("WILL RECREATE"), /* 19 */
10102 static const struct e2fsck_problem problem_table[] = {
10104 /* Pre-Pass 1 errors */
10106 /* Block bitmap not in group */
10107 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
10108 PROMPT_RELOCATE, PR_LATCH_RELOC },
10110 /* Inode bitmap not in group */
10111 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
10112 PROMPT_RELOCATE, PR_LATCH_RELOC },
10114 /* Inode table not in group */
10115 { PR_0_ITABLE_NOT_GROUP,
10116 N_("@i table for @g %g is not in @g. (@b %b)\n"
10117 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10118 PROMPT_RELOCATE, PR_LATCH_RELOC },
10120 /* Superblock corrupt */
10122 N_("\nThe @S could not be read or does not describe a correct ext2\n"
10123 "@f. If the @v is valid and it really contains an ext2\n"
10124 "@f (and not swap or ufs or something else), then the @S\n"
10125 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10126 " e2fsck -b %S <@v>\n\n"),
10127 PROMPT_NONE, PR_FATAL },
10129 /* Filesystem size is wrong */
10130 { PR_0_FS_SIZE_WRONG,
10131 N_("The @f size (according to the @S) is %b @bs\n"
10132 "The physical size of the @v is %c @bs\n"
10133 "Either the @S or the partition table is likely to be corrupt!\n"),
10136 /* Fragments not supported */
10137 { PR_0_NO_FRAGMENTS,
10138 N_("@S @b_size = %b, fragsize = %c.\n"
10139 "This version of e2fsck does not support fragment sizes different\n"
10140 "from the @b size.\n"),
10141 PROMPT_NONE, PR_FATAL },
10143 /* Bad blocks_per_group */
10144 { PR_0_BLOCKS_PER_GROUP,
10145 N_("@S @bs_per_group = %b, should have been %c\n"),
10146 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10148 /* Bad first_data_block */
10149 { PR_0_FIRST_DATA_BLOCK,
10150 N_("@S first_data_@b = %b, should have been %c\n"),
10151 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10153 /* Adding UUID to filesystem */
10155 N_("@f did not have a UUID; generating one.\n\n"),
10158 /* Relocate hint */
10159 { PR_0_RELOCATE_HINT,
10160 N_("Note: if several inode or block bitmap blocks or part\n"
10161 "of the inode table require relocation, you may wish to try\n"
10162 "running e2fsck with the '-b %S' option first. The problem\n"
10163 "may lie only with the primary block group descriptors, and\n"
10164 "the backup block group descriptors may be OK.\n\n"),
10165 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10167 /* Miscellaneous superblock corruption */
10168 { PR_0_MISC_CORRUPT_SUPER,
10169 N_("Corruption found in @S. (%s = %N).\n"),
10170 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10172 /* Error determing physical device size of filesystem */
10173 { PR_0_GETSIZE_ERROR,
10174 N_("Error determining size of the physical @v: %m\n"),
10175 PROMPT_NONE, PR_FATAL },
10177 /* Inode count in superblock is incorrect */
10178 { PR_0_INODE_COUNT_WRONG,
10179 N_("@i count in @S is %i, @s %j.\n"),
10182 { PR_0_HURD_CLEAR_FILETYPE,
10183 N_("The Hurd does not support the filetype feature.\n"),
10186 /* Journal inode is invalid */
10187 { PR_0_JOURNAL_BAD_INODE,
10188 N_("@S has an @n ext3 @j (@i %i).\n"),
10189 PROMPT_CLEAR, PR_PREEN_OK },
10191 /* The external journal has (unsupported) multiple filesystems */
10192 { PR_0_JOURNAL_UNSUPP_MULTIFS,
10193 N_("External @j has multiple @f users (unsupported).\n"),
10194 PROMPT_NONE, PR_FATAL },
10196 /* Can't find external journal */
10197 { PR_0_CANT_FIND_JOURNAL,
10198 N_("Can't find external @j\n"),
10199 PROMPT_NONE, PR_FATAL },
10201 /* External journal has bad superblock */
10202 { PR_0_EXT_JOURNAL_BAD_SUPER,
10203 N_("External @j has bad @S\n"),
10204 PROMPT_NONE, PR_FATAL },
10206 /* Superblock has a bad journal UUID */
10207 { PR_0_JOURNAL_BAD_UUID,
10208 N_("External @j does not support this @f\n"),
10209 PROMPT_NONE, PR_FATAL },
10211 /* Journal has an unknown superblock type */
10212 { PR_0_JOURNAL_UNSUPP_SUPER,
10213 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10214 "It is likely that your copy of e2fsck is old and/or doesn't "
10215 "support this @j format.\n"
10216 "It is also possible the @j @S is corrupt.\n"),
10217 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10219 /* Journal superblock is corrupt */
10220 { PR_0_JOURNAL_BAD_SUPER,
10221 N_("Ext3 @j @S is corrupt.\n"),
10222 PROMPT_FIX, PR_PREEN_OK },
10224 /* Superblock flag should be cleared */
10225 { PR_0_JOURNAL_HAS_JOURNAL,
10226 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10227 PROMPT_CLEAR, PR_PREEN_OK },
10229 /* Superblock flag is incorrect */
10230 { PR_0_JOURNAL_RECOVER_SET,
10231 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10232 PROMPT_CLEAR, PR_PREEN_OK },
10234 /* Journal has data, but recovery flag is clear */
10235 { PR_0_JOURNAL_RECOVERY_CLEAR,
10236 N_("ext3 recovery flag is clear, but @j has data.\n"),
10239 /* Ask if we should clear the journal */
10240 { PR_0_JOURNAL_RESET_JOURNAL,
10242 PROMPT_NULL, PR_PREEN_NOMSG },
10244 /* Ask if we should run the journal anyway */
10245 { PR_0_JOURNAL_RUN,
10246 N_("Run @j anyway"),
10249 /* Run the journal by default */
10250 { PR_0_JOURNAL_RUN_DEFAULT,
10251 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10254 /* Clearing orphan inode */
10255 { PR_0_ORPHAN_CLEAR_INODE,
10256 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10259 /* Illegal block found in orphaned inode */
10260 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10261 N_("@I @b #%B (%b) found in @o @i %i.\n"),
10264 /* Already cleared block found in orphaned inode */
10265 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10266 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10269 /* Illegal orphan inode in superblock */
10270 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10271 N_("@I @o @i %i in @S.\n"),
10274 /* Illegal inode in orphaned inode list */
10275 { PR_0_ORPHAN_ILLEGAL_INODE,
10276 N_("@I @i %i in @o @i list.\n"),
10279 /* Filesystem revision is 0, but feature flags are set */
10280 { PR_0_FS_REV_LEVEL,
10281 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
10282 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10284 /* Journal superblock has an unknown read-only feature flag set */
10285 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10286 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10289 /* Journal superblock has an unknown incompatible feature flag set */
10290 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10291 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10294 /* Journal has unsupported version number */
10295 { PR_0_JOURNAL_UNSUPP_VERSION,
10296 N_("@j version not supported by this e2fsck.\n"),
10299 /* Moving journal to hidden file */
10300 { PR_0_MOVE_JOURNAL,
10301 N_("Moving @j from /%s to hidden @i.\n\n"),
10304 /* Error moving journal to hidden file */
10305 { PR_0_ERR_MOVE_JOURNAL,
10306 N_("Error moving @j: %m\n\n"),
10309 /* Clearing V2 journal superblock */
10310 { PR_0_CLEAR_V2_JOURNAL,
10311 N_("Found @n V2 @j @S fields (from V1 @j).\n"
10312 "Clearing fields beyond the V1 @j @S...\n\n"),
10315 /* Backup journal inode blocks */
10317 N_("Backing up @j @i @b information.\n\n"),
10320 /* Reserved blocks w/o resize_inode */
10321 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10322 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10323 "is %N; @s zero. "),
10326 /* Resize_inode not enabled, but resize inode is non-zero */
10327 { PR_0_CLEAR_RESIZE_INODE,
10328 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
10331 /* Resize inode invalid */
10332 { PR_0_RESIZE_INODE_INVALID,
10333 N_("Resize @i not valid. "),
10334 PROMPT_RECREATE, 0 },
10336 /* Pass 1 errors */
10338 /* Pass 1: Checking inodes, blocks, and sizes */
10339 { PR_1_PASS_HEADER,
10340 N_("Pass 1: Checking @is, @bs, and sizes\n"),
10343 /* Root directory is not an inode */
10344 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
10347 /* Root directory has dtime set */
10349 N_("@r has dtime set (probably due to old mke2fs). "),
10350 PROMPT_FIX, PR_PREEN_OK },
10352 /* Reserved inode has bad mode */
10353 { PR_1_RESERVED_BAD_MODE,
10354 N_("Reserved @i %i (%Q) has @n mode. "),
10355 PROMPT_CLEAR, PR_PREEN_OK },
10357 /* Deleted inode has zero dtime */
10359 N_("@D @i %i has zero dtime. "),
10360 PROMPT_FIX, PR_PREEN_OK },
10362 /* Inode in use, but dtime set */
10364 N_("@i %i is in use, but has dtime set. "),
10365 PROMPT_FIX, PR_PREEN_OK },
10367 /* Zero-length directory */
10368 { PR_1_ZERO_LENGTH_DIR,
10369 N_("@i %i is a @z @d. "),
10370 PROMPT_CLEAR, PR_PREEN_OK },
10372 /* Block bitmap conflicts with some other fs block */
10373 { PR_1_BB_CONFLICT,
10374 N_("@g %g's @b @B at %b @C.\n"),
10375 PROMPT_RELOCATE, 0 },
10377 /* Inode bitmap conflicts with some other fs block */
10378 { PR_1_IB_CONFLICT,
10379 N_("@g %g's @i @B at %b @C.\n"),
10380 PROMPT_RELOCATE, 0 },
10382 /* Inode table conflicts with some other fs block */
10383 { PR_1_ITABLE_CONFLICT,
10384 N_("@g %g's @i table at %b @C.\n"),
10385 PROMPT_RELOCATE, 0 },
10387 /* Block bitmap is on a bad block */
10388 { PR_1_BB_BAD_BLOCK,
10389 N_("@g %g's @b @B (%b) is bad. "),
10390 PROMPT_RELOCATE, 0 },
10392 /* Inode bitmap is on a bad block */
10393 { PR_1_IB_BAD_BLOCK,
10394 N_("@g %g's @i @B (%b) is bad. "),
10395 PROMPT_RELOCATE, 0 },
10397 /* Inode has incorrect i_size */
10399 N_("@i %i, i_size is %Is, @s %N. "),
10400 PROMPT_FIX, PR_PREEN_OK },
10402 /* Inode has incorrect i_blocks */
10403 { PR_1_BAD_I_BLOCKS,
10404 N_("@i %i, i_@bs is %Ib, @s %N. "),
10405 PROMPT_FIX, PR_PREEN_OK },
10407 /* Illegal blocknumber in inode */
10408 { PR_1_ILLEGAL_BLOCK_NUM,
10409 N_("@I @b #%B (%b) in @i %i. "),
10410 PROMPT_CLEAR, PR_LATCH_BLOCK },
10412 /* Block number overlaps fs metadata */
10413 { PR_1_BLOCK_OVERLAPS_METADATA,
10414 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
10415 PROMPT_CLEAR, PR_LATCH_BLOCK },
10417 /* Inode has illegal blocks (latch question) */
10418 { PR_1_INODE_BLOCK_LATCH,
10419 N_("@i %i has illegal @b(s). "),
10422 /* Too many bad blocks in inode */
10423 { PR_1_TOO_MANY_BAD_BLOCKS,
10424 N_("Too many illegal @bs in @i %i.\n"),
10425 PROMPT_CLEAR_INODE, PR_NO_OK },
10427 /* Illegal block number in bad block inode */
10428 { PR_1_BB_ILLEGAL_BLOCK_NUM,
10429 N_("@I @b #%B (%b) in bad @b @i. "),
10430 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10432 /* Bad block inode has illegal blocks (latch question) */
10433 { PR_1_INODE_BBLOCK_LATCH,
10434 N_("Bad @b @i has illegal @b(s). "),
10437 /* Duplicate or bad blocks in use! */
10438 { PR_1_DUP_BLOCKS_PREENSTOP,
10439 N_("Duplicate or bad @b in use!\n"),
10442 /* Bad block used as bad block indirect block */
10443 { PR_1_BBINODE_BAD_METABLOCK,
10444 N_("Bad @b %b used as bad @b @i indirect @b. "),
10445 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10447 /* Inconsistency can't be fixed prompt */
10448 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10449 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
10450 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10452 PROMPT_CONTINUE, PR_PREEN_NOMSG },
10454 /* Bad primary block */
10455 { PR_1_BAD_PRIMARY_BLOCK,
10456 N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10457 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10459 /* Bad primary block prompt */
10460 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10461 N_("You can remove this @b from the bad @b list and hope\n"
10462 "that the @b is really OK. But there are no guarantees.\n\n"),
10463 PROMPT_CLEAR, PR_PREEN_NOMSG },
10465 /* Bad primary superblock */
10466 { PR_1_BAD_PRIMARY_SUPERBLOCK,
10467 N_("The primary @S (%b) is on the bad @b list.\n"),
10468 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10470 /* Bad primary block group descriptors */
10471 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10472 N_("Block %b in the primary @g descriptors "
10473 "is on the bad @b list\n"),
10474 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10476 /* Bad superblock in group */
10477 { PR_1_BAD_SUPERBLOCK,
10478 N_("Warning: Group %g's @S (%b) is bad.\n"),
10479 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10481 /* Bad block group descriptors in group */
10482 { PR_1_BAD_GROUP_DESCRIPTORS,
10483 N_("Warning: Group %g's copy of the @g descriptors has a bad "
10485 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10487 /* Block claimed for no reason */
10488 { PR_1_PROGERR_CLAIMED_BLOCK,
10489 N_("Programming error? @b #%b claimed for no reason in "
10490 "process_bad_@b.\n"),
10491 PROMPT_NONE, PR_PREEN_OK },
10493 /* Error allocating blocks for relocating metadata */
10494 { PR_1_RELOC_BLOCK_ALLOCATE,
10495 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10496 PROMPT_NONE, PR_PREEN_OK },
10498 /* Error allocating block buffer during relocation process */
10499 { PR_1_RELOC_MEMORY_ALLOCATE,
10500 N_("@A @b buffer for relocating %s\n"),
10501 PROMPT_NONE, PR_PREEN_OK },
10503 /* Relocating metadata group information from X to Y */
10504 { PR_1_RELOC_FROM_TO,
10505 N_("Relocating @g %g's %s from %b to %c...\n"),
10506 PROMPT_NONE, PR_PREEN_OK },
10508 /* Relocating metatdata group information to X */
10510 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10511 PROMPT_NONE, PR_PREEN_OK },
10513 /* Block read error during relocation process */
10514 { PR_1_RELOC_READ_ERR,
10515 N_("Warning: could not read @b %b of %s: %m\n"),
10516 PROMPT_NONE, PR_PREEN_OK },
10518 /* Block write error during relocation process */
10519 { PR_1_RELOC_WRITE_ERR,
10520 N_("Warning: could not write @b %b for %s: %m\n"),
10521 PROMPT_NONE, PR_PREEN_OK },
10523 /* Error allocating inode bitmap */
10524 { PR_1_ALLOCATE_IBITMAP_ERROR,
10525 N_("@A @i @B (%N): %m\n"),
10526 PROMPT_NONE, PR_FATAL },
10528 /* Error allocating block bitmap */
10529 { PR_1_ALLOCATE_BBITMAP_ERROR,
10530 N_("@A @b @B (%N): %m\n"),
10531 PROMPT_NONE, PR_FATAL },
10533 /* Error allocating icount structure */
10534 { PR_1_ALLOCATE_ICOUNT,
10535 N_("@A icount link information: %m\n"),
10536 PROMPT_NONE, PR_FATAL },
10538 /* Error allocating dbcount */
10539 { PR_1_ALLOCATE_DBCOUNT,
10540 N_("@A @d @b array: %m\n"),
10541 PROMPT_NONE, PR_FATAL },
10543 /* Error while scanning inodes */
10544 { PR_1_ISCAN_ERROR,
10545 N_("Error while scanning @is (%i): %m\n"),
10546 PROMPT_NONE, PR_FATAL },
10548 /* Error while iterating over blocks */
10549 { PR_1_BLOCK_ITERATE,
10550 N_("Error while iterating over @bs in @i %i: %m\n"),
10551 PROMPT_NONE, PR_FATAL },
10553 /* Error while storing inode count information */
10554 { PR_1_ICOUNT_STORE,
10555 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10556 PROMPT_NONE, PR_FATAL },
10558 /* Error while storing directory block information */
10560 N_("Error storing @d @b information "
10561 "(@i=%i, @b=%b, num=%N): %m\n"),
10562 PROMPT_NONE, PR_FATAL },
10564 /* Error while reading inode (for clearing) */
10566 N_("Error reading @i %i: %m\n"),
10567 PROMPT_NONE, PR_FATAL },
10569 /* Suppress messages prompt */
10570 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10572 /* Imagic flag set on an inode when filesystem doesn't support it */
10574 N_("@i %i has imagic flag set. "),
10577 /* Immutable flag set on a device or socket inode */
10578 { PR_1_SET_IMMUTABLE,
10579 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10580 "or append-only flag set. "),
10581 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10583 /* Compression flag set on an inode when filesystem doesn't support it */
10585 N_("@i %i has @cion flag set on @f without @cion support. "),
10588 /* Non-zero size for device, fifo or socket inode */
10589 { PR_1_SET_NONZSIZE,
10590 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
10591 PROMPT_FIX, PR_PREEN_OK },
10593 /* Filesystem revision is 0, but feature flags are set */
10594 { PR_1_FS_REV_LEVEL,
10595 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
10596 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10598 /* Journal inode is not in use, but contains data */
10599 { PR_1_JOURNAL_INODE_NOT_CLEAR,
10600 N_("@j @i is not in use, but contains data. "),
10601 PROMPT_CLEAR, PR_PREEN_OK },
10603 /* Journal has bad mode */
10604 { PR_1_JOURNAL_BAD_MODE,
10605 N_("@j is not regular file. "),
10606 PROMPT_FIX, PR_PREEN_OK },
10608 /* Deal with inodes that were part of orphan linked list */
10610 N_("@i %i was part of the @o @i list. "),
10611 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10613 /* Deal with inodes that were part of corrupted orphan linked
10614 list (latch question) */
10615 { PR_1_ORPHAN_LIST_REFUGEES,
10616 N_("@is that were part of a corrupted orphan linked list found. "),
10619 /* Error allocating refcount structure */
10620 { PR_1_ALLOCATE_REFCOUNT,
10621 N_("@A refcount structure (%N): %m\n"),
10622 PROMPT_NONE, PR_FATAL },
10624 /* Error reading extended attribute block */
10625 { PR_1_READ_EA_BLOCK,
10626 N_("Error reading @a @b %b for @i %i. "),
10629 /* Invalid extended attribute block */
10630 { PR_1_BAD_EA_BLOCK,
10631 N_("@i %i has a bad @a @b %b. "),
10634 /* Error reading Extended Attribute block while fixing refcount */
10635 { PR_1_EXTATTR_READ_ABORT,
10636 N_("Error reading @a @b %b (%m). "),
10639 /* Extended attribute reference count incorrect */
10640 { PR_1_EXTATTR_REFCOUNT,
10641 N_("@a @b %b has reference count %B, @s %N. "),
10644 /* Error writing Extended Attribute block while fixing refcount */
10645 { PR_1_EXTATTR_WRITE,
10646 N_("Error writing @a @b %b (%m). "),
10649 /* Multiple EA blocks not supported */
10650 { PR_1_EA_MULTI_BLOCK,
10651 N_("@a @b %b has h_@bs > 1. "),
10654 /* Error allocating EA region allocation structure */
10655 { PR_1_EA_ALLOC_REGION,
10656 N_("@A @a @b %b. "),
10659 /* Error EA allocation collision */
10660 { PR_1_EA_ALLOC_COLLISION,
10661 N_("@a @b %b is corrupt (allocation collision). "),
10664 /* Bad extended attribute name */
10665 { PR_1_EA_BAD_NAME,
10666 N_("@a @b %b is corrupt (@n name). "),
10669 /* Bad extended attribute value */
10670 { PR_1_EA_BAD_VALUE,
10671 N_("@a @b %b is corrupt (@n value). "),
10674 /* Inode too big (latch question) */
10675 { PR_1_INODE_TOOBIG,
10676 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
10678 /* Directory too big */
10680 N_("@b #%B (%b) causes @d to be too big. "),
10681 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10683 /* Regular file too big */
10685 N_("@b #%B (%b) causes file to be too big. "),
10686 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10688 /* Symlink too big */
10689 { PR_1_TOOBIG_SYMLINK,
10690 N_("@b #%B (%b) causes symlink to be too big. "),
10691 PROMPT_CLEAR, PR_LATCH_TOOBIG },
10693 /* INDEX_FL flag set on a non-HTREE filesystem */
10695 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10696 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10698 /* INDEX_FL flag set on a non-directory */
10699 { PR_1_HTREE_NODIR,
10700 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10701 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10703 /* Invalid root node in HTREE directory */
10704 { PR_1_HTREE_BADROOT,
10705 N_("@h %i has an @n root node.\n"),
10706 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10708 /* Unsupported hash version in HTREE directory */
10709 { PR_1_HTREE_HASHV,
10710 N_("@h %i has an unsupported hash version (%N)\n"),
10711 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10713 /* Incompatible flag in HTREE root node */
10714 { PR_1_HTREE_INCOMPAT,
10715 N_("@h %i uses an incompatible htree root node flag.\n"),
10716 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10718 /* HTREE too deep */
10719 { PR_1_HTREE_DEPTH,
10720 N_("@h %i has a tree depth (%N) which is too big\n"),
10721 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10723 /* Bad block has indirect block that conflicts with filesystem block */
10724 { PR_1_BB_FS_BLOCK,
10725 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10727 PROMPT_CLEAR, PR_LATCH_BBLOCK },
10729 /* Resize inode failed */
10730 { PR_1_RESIZE_INODE_CREATE,
10731 N_("Resize @i (re)creation failed: %m."),
10734 /* invalid inode->i_extra_isize */
10735 { PR_1_EXTRA_ISIZE,
10736 N_("@i %i has a extra size (%IS) which is @n\n"),
10737 PROMPT_FIX, PR_PREEN_OK },
10739 /* invalid ea entry->e_name_len */
10740 { PR_1_ATTR_NAME_LEN,
10741 N_("@a in @i %i has a namelen (%N) which is @n\n"),
10742 PROMPT_CLEAR, PR_PREEN_OK },
10744 /* invalid ea entry->e_value_size */
10745 { PR_1_ATTR_VALUE_SIZE,
10746 N_("@a in @i %i has a value size (%N) which is @n\n"),
10747 PROMPT_CLEAR, PR_PREEN_OK },
10749 /* invalid ea entry->e_value_offs */
10750 { PR_1_ATTR_VALUE_OFFSET,
10751 N_("@a in @i %i has a value offset (%N) which is @n\n"),
10752 PROMPT_CLEAR, PR_PREEN_OK },
10754 /* invalid ea entry->e_value_block */
10755 { PR_1_ATTR_VALUE_BLOCK,
10756 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
10757 PROMPT_CLEAR, PR_PREEN_OK },
10759 /* invalid ea entry->e_hash */
10761 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
10762 PROMPT_CLEAR, PR_PREEN_OK },
10764 /* Pass 1b errors */
10766 /* Pass 1B: Rescan for duplicate/bad blocks */
10767 { PR_1B_PASS_HEADER,
10768 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
10769 "Pass 1B: Rescanning for @m @bs\n"),
10772 /* Duplicate/bad block(s) header */
10773 { PR_1B_DUP_BLOCK_HEADER,
10774 N_("@m @b(s) in @i %i:"),
10777 /* Duplicate/bad block(s) in inode */
10780 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10782 /* Duplicate/bad block(s) end */
10783 { PR_1B_DUP_BLOCK_END,
10785 PROMPT_NONE, PR_PREEN_NOHDR },
10787 /* Error while scanning inodes */
10788 { PR_1B_ISCAN_ERROR,
10789 N_("Error while scanning inodes (%i): %m\n"),
10790 PROMPT_NONE, PR_FATAL },
10792 /* Error allocating inode bitmap */
10793 { PR_1B_ALLOCATE_IBITMAP_ERROR,
10794 N_("@A @i @B (@i_dup_map): %m\n"),
10795 PROMPT_NONE, PR_FATAL },
10797 /* Error while iterating over blocks */
10798 { PR_1B_BLOCK_ITERATE,
10799 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10802 /* Error adjusting EA refcount */
10803 { PR_1B_ADJ_EA_REFCOUNT,
10804 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
10808 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
10809 { PR_1C_PASS_HEADER,
10810 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
10814 /* Pass 1D: Reconciling multiply-claimed blocks */
10815 { PR_1D_PASS_HEADER,
10816 N_("Pass 1D: Reconciling @m @bs\n"),
10819 /* File has duplicate blocks */
10821 N_("File %Q (@i #%i, mod time %IM) \n"
10822 " has %B @m @b(s), shared with %N file(s):\n"),
10825 /* List of files sharing duplicate blocks */
10826 { PR_1D_DUP_FILE_LIST,
10827 N_("\t%Q (@i #%i, mod time %IM)\n"),
10830 /* File sharing blocks with filesystem metadata */
10831 { PR_1D_SHARE_METADATA,
10832 N_("\t<@f metadata>\n"),
10835 /* Report of how many duplicate/bad inodes */
10836 { PR_1D_NUM_DUP_INODES,
10837 N_("(There are %N @is containing @m @bs.)\n\n"),
10840 /* Duplicated blocks already reassigned or cloned. */
10841 { PR_1D_DUP_BLOCKS_DEALT,
10842 N_("@m @bs already reassigned or cloned.\n\n"),
10845 /* Clone duplicate/bad blocks? */
10846 { PR_1D_CLONE_QUESTION,
10847 "", PROMPT_CLONE, PR_NO_OK },
10850 { PR_1D_DELETE_QUESTION,
10851 "", PROMPT_DELETE, 0 },
10853 /* Couldn't clone file (error) */
10854 { PR_1D_CLONE_ERROR,
10855 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10857 /* Pass 2 errors */
10859 /* Pass 2: Checking directory structure */
10860 { PR_2_PASS_HEADER,
10861 N_("Pass 2: Checking @d structure\n"),
10864 /* Bad inode number for '.' */
10865 { PR_2_BAD_INODE_DOT,
10866 N_("@n @i number for '.' in @d @i %i.\n"),
10869 /* Directory entry has bad inode number */
10871 N_("@E has @n @i #: %Di.\n"),
10874 /* Directory entry has deleted or unused inode */
10875 { PR_2_UNUSED_INODE,
10876 N_("@E has @D/unused @i %Di. "),
10877 PROMPT_CLEAR, PR_PREEN_OK },
10879 /* Directry entry is link to '.' */
10881 N_("@E @L to '.' "),
10884 /* Directory entry points to inode now located in a bad block */
10886 N_("@E points to @i (%Di) located in a bad @b.\n"),
10889 /* Directory entry contains a link to a directory */
10891 N_("@E @L to @d %P (%Di).\n"),
10894 /* Directory entry contains a link to the root directry */
10896 N_("@E @L to the @r.\n"),
10899 /* Directory entry has illegal characters in its name */
10901 N_("@E has illegal characters in its name.\n"),
10904 /* Missing '.' in directory inode */
10905 { PR_2_MISSING_DOT,
10906 N_("Missing '.' in @d @i %i.\n"),
10909 /* Missing '..' in directory inode */
10910 { PR_2_MISSING_DOT_DOT,
10911 N_("Missing '..' in @d @i %i.\n"),
10914 /* First entry in directory inode doesn't contain '.' */
10915 { PR_2_1ST_NOT_DOT,
10916 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
10919 /* Second entry in directory inode doesn't contain '..' */
10920 { PR_2_2ND_NOT_DOT_DOT,
10921 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
10924 /* i_faddr should be zero */
10926 N_("i_faddr @F %IF, @s zero.\n"),
10929 /* i_file_acl should be zero */
10930 { PR_2_FILE_ACL_ZERO,
10931 N_("i_file_acl @F %If, @s zero.\n"),
10934 /* i_dir_acl should be zero */
10935 { PR_2_DIR_ACL_ZERO,
10936 N_("i_dir_acl @F %Id, @s zero.\n"),
10939 /* i_frag should be zero */
10941 N_("i_frag @F %N, @s zero.\n"),
10944 /* i_fsize should be zero */
10946 N_("i_fsize @F %N, @s zero.\n"),
10949 /* inode has bad mode */
10951 N_("@i %i (%Q) has @n mode (%Im).\n"),
10954 /* directory corrupted */
10955 { PR_2_DIR_CORRUPTED,
10956 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
10957 PROMPT_SALVAGE, 0 },
10959 /* filename too long */
10960 { PR_2_FILENAME_LONG,
10961 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
10962 PROMPT_TRUNCATE, 0 },
10964 /* Directory inode has a missing block (hole) */
10965 { PR_2_DIRECTORY_HOLE,
10966 N_("@d @i %i has an unallocated @b #%B. "),
10967 PROMPT_ALLOCATE, 0 },
10969 /* '.' is not NULL terminated */
10970 { PR_2_DOT_NULL_TERM,
10971 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
10974 /* '..' is not NULL terminated */
10975 { PR_2_DOT_DOT_NULL_TERM,
10976 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
10979 /* Illegal character device inode */
10980 { PR_2_BAD_CHAR_DEV,
10981 N_("@i %i (%Q) is an @I character @v.\n"),
10984 /* Illegal block device inode */
10985 { PR_2_BAD_BLOCK_DEV,
10986 N_("@i %i (%Q) is an @I @b @v.\n"),
10989 /* Duplicate '.' entry */
10991 N_("@E is duplicate '.' @e.\n"),
10994 /* Duplicate '..' entry */
10995 { PR_2_DUP_DOT_DOT,
10996 N_("@E is duplicate '..' @e.\n"),
10999 /* Internal error: couldn't find dir_info */
11001 N_("Internal error: couldn't find dir_info for %i.\n"),
11002 PROMPT_NONE, PR_FATAL },
11004 /* Final rec_len is wrong */
11005 { PR_2_FINAL_RECLEN,
11006 N_("@E has rec_len of %Dr, @s %N.\n"),
11009 /* Error allocating icount structure */
11010 { PR_2_ALLOCATE_ICOUNT,
11011 N_("@A icount structure: %m\n"),
11012 PROMPT_NONE, PR_FATAL },
11014 /* Error iterating over directory blocks */
11015 { PR_2_DBLIST_ITERATE,
11016 N_("Error iterating over @d @bs: %m\n"),
11017 PROMPT_NONE, PR_FATAL },
11019 /* Error reading directory block */
11020 { PR_2_READ_DIRBLOCK,
11021 N_("Error reading @d @b %b (@i %i): %m\n"),
11022 PROMPT_CONTINUE, 0 },
11024 /* Error writing directory block */
11025 { PR_2_WRITE_DIRBLOCK,
11026 N_("Error writing @d @b %b (@i %i): %m\n"),
11027 PROMPT_CONTINUE, 0 },
11029 /* Error allocating new directory block */
11030 { PR_2_ALLOC_DIRBOCK,
11031 N_("@A new @d @b for @i %i (%s): %m\n"),
11034 /* Error deallocating inode */
11035 { PR_2_DEALLOC_INODE,
11036 N_("Error deallocating @i %i: %m\n"),
11037 PROMPT_NONE, PR_FATAL },
11039 /* Directory entry for '.' is big. Split? */
11041 N_("@d @e for '.' is big. "),
11042 PROMPT_SPLIT, PR_NO_OK },
11044 /* Illegal FIFO inode */
11046 N_("@i %i (%Q) is an @I FIFO.\n"),
11049 /* Illegal socket inode */
11051 N_("@i %i (%Q) is an @I socket.\n"),
11054 /* Directory filetype not set */
11055 { PR_2_SET_FILETYPE,
11056 N_("Setting filetype for @E to %N.\n"),
11057 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11059 /* Directory filetype incorrect */
11060 { PR_2_BAD_FILETYPE,
11061 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
11064 /* Directory filetype set on filesystem */
11065 { PR_2_CLEAR_FILETYPE,
11066 N_("@E has filetype set.\n"),
11067 PROMPT_CLEAR, PR_PREEN_OK },
11069 /* Directory filename is null */
11071 N_("@E has a @z name.\n"),
11074 /* Invalid symlink */
11075 { PR_2_INVALID_SYMLINK,
11076 N_("Symlink %Q (@i #%i) is @n.\n"),
11079 /* i_file_acl (extended attribute block) is bad */
11080 { PR_2_FILE_ACL_BAD,
11081 N_("@a @b @F @n (%If).\n"),
11084 /* Filesystem contains large files, but has no such flag in sb */
11085 { PR_2_FEATURE_LARGE_FILES,
11086 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11089 /* Node in HTREE directory not referenced */
11090 { PR_2_HTREE_NOTREF,
11091 N_("@p @h %d: node (%B) not referenced\n"),
11094 /* Node in HTREE directory referenced twice */
11095 { PR_2_HTREE_DUPREF,
11096 N_("@p @h %d: node (%B) referenced twice\n"),
11099 /* Node in HTREE directory has bad min hash */
11100 { PR_2_HTREE_MIN_HASH,
11101 N_("@p @h %d: node (%B) has bad min hash\n"),
11104 /* Node in HTREE directory has bad max hash */
11105 { PR_2_HTREE_MAX_HASH,
11106 N_("@p @h %d: node (%B) has bad max hash\n"),
11109 /* Clear invalid HTREE directory */
11110 { PR_2_HTREE_CLEAR,
11111 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
11113 /* Bad block in htree interior node */
11114 { PR_2_HTREE_BADBLK,
11115 N_("@p @h %d (%q): bad @b number %b.\n"),
11116 PROMPT_CLEAR_HTREE, 0 },
11118 /* Error adjusting EA refcount */
11119 { PR_2_ADJ_EA_REFCOUNT,
11120 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
11121 PROMPT_NONE, PR_FATAL },
11123 /* Invalid HTREE root node */
11124 { PR_2_HTREE_BAD_ROOT,
11125 N_("@p @h %d: root node is @n\n"),
11126 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11128 /* Invalid HTREE limit */
11129 { PR_2_HTREE_BAD_LIMIT,
11130 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
11131 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11133 /* Invalid HTREE count */
11134 { PR_2_HTREE_BAD_COUNT,
11135 N_("@p @h %d: node (%B) has @n count (%N)\n"),
11136 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11138 /* HTREE interior node has out-of-order hashes in table */
11139 { PR_2_HTREE_HASH_ORDER,
11140 N_("@p @h %d: node (%B) has an unordered hash table\n"),
11141 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11143 /* Node in HTREE directory has invalid depth */
11144 { PR_2_HTREE_BAD_DEPTH,
11145 N_("@p @h %d: node (%B) has @n depth\n"),
11148 /* Duplicate directory entry found */
11149 { PR_2_DUPLICATE_DIRENT,
11150 N_("Duplicate @E found. "),
11153 /* Non-unique filename found */
11154 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11155 N_("@E has a non-unique filename.\nRename to %s"),
11158 /* Duplicate directory entry found */
11159 { PR_2_REPORT_DUP_DIRENT,
11160 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11163 /* Pass 3 errors */
11165 /* Pass 3: Checking directory connectivity */
11166 { PR_3_PASS_HEADER,
11167 N_("Pass 3: Checking @d connectivity\n"),
11170 /* Root inode not allocated */
11171 { PR_3_NO_ROOT_INODE,
11172 N_("@r not allocated. "),
11173 PROMPT_ALLOCATE, 0 },
11175 /* No room in lost+found */
11176 { PR_3_EXPAND_LF_DIR,
11177 N_("No room in @l @d. "),
11178 PROMPT_EXPAND, 0 },
11180 /* Unconnected directory inode */
11181 { PR_3_UNCONNECTED_DIR,
11182 N_("Unconnected @d @i %i (%p)\n"),
11183 PROMPT_CONNECT, 0 },
11185 /* /lost+found not found */
11187 N_("/@l not found. "),
11188 PROMPT_CREATE, PR_PREEN_OK },
11190 /* .. entry is incorrect */
11191 { PR_3_BAD_DOT_DOT,
11192 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11195 /* Bad or non-existent /lost+found. Cannot reconnect */
11197 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
11200 /* Could not expand /lost+found */
11201 { PR_3_CANT_EXPAND_LPF,
11202 N_("Could not expand /@l: %m\n"),
11205 /* Could not reconnect inode */
11206 { PR_3_CANT_RECONNECT,
11207 N_("Could not reconnect %i: %m\n"),
11210 /* Error while trying to find /lost+found */
11211 { PR_3_ERR_FIND_LPF,
11212 N_("Error while trying to find /@l: %m\n"),
11215 /* Error in ext2fs_new_block while creating /lost+found */
11216 { PR_3_ERR_LPF_NEW_BLOCK,
11217 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11220 /* Error in ext2fs_new_inode while creating /lost+found */
11221 { PR_3_ERR_LPF_NEW_INODE,
11222 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11225 /* Error in ext2fs_new_dir_block while creating /lost+found */
11226 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11227 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11230 /* Error while writing directory block for /lost+found */
11231 { PR_3_ERR_LPF_WRITE_BLOCK,
11232 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11235 /* Error while adjusting inode count */
11236 { PR_3_ADJUST_INODE,
11237 N_("Error while adjusting @i count on @i %i\n"),
11240 /* Couldn't fix parent directory -- error */
11241 { PR_3_FIX_PARENT_ERR,
11242 N_("Couldn't fix parent of @i %i: %m\n\n"),
11245 /* Couldn't fix parent directory -- couldn't find it */
11246 { PR_3_FIX_PARENT_NOFIND,
11247 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
11250 /* Error allocating inode bitmap */
11251 { PR_3_ALLOCATE_IBITMAP_ERROR,
11252 N_("@A @i @B (%N): %m\n"),
11253 PROMPT_NONE, PR_FATAL },
11255 /* Error creating root directory */
11256 { PR_3_CREATE_ROOT_ERROR,
11257 N_("Error creating root @d (%s): %m\n"),
11258 PROMPT_NONE, PR_FATAL },
11260 /* Error creating lost and found directory */
11261 { PR_3_CREATE_LPF_ERROR,
11262 N_("Error creating /@l @d (%s): %m\n"),
11263 PROMPT_NONE, PR_FATAL },
11265 /* Root inode is not directory; aborting */
11266 { PR_3_ROOT_NOT_DIR_ABORT,
11267 N_("@r is not a @d; aborting.\n"),
11268 PROMPT_NONE, PR_FATAL },
11270 /* Cannot proceed without a root inode. */
11271 { PR_3_NO_ROOT_INODE_ABORT,
11272 N_("Cannot proceed without a @r.\n"),
11273 PROMPT_NONE, PR_FATAL },
11275 /* Internal error: couldn't find dir_info */
11277 N_("Internal error: couldn't find dir_info for %i.\n"),
11278 PROMPT_NONE, PR_FATAL },
11280 /* Lost+found not a directory */
11282 N_("/@l is not a @d (ino=%i)\n"),
11283 PROMPT_UNLINK, 0 },
11285 /* Pass 3A Directory Optimization */
11287 /* Pass 3A: Optimizing directories */
11288 { PR_3A_PASS_HEADER,
11289 N_("Pass 3A: Optimizing directories\n"),
11290 PROMPT_NONE, PR_PREEN_NOMSG },
11292 /* Error iterating over directories */
11293 { PR_3A_OPTIMIZE_ITER,
11294 N_("Failed to create dirs_to_hash iterator: %m"),
11297 /* Error rehash directory */
11298 { PR_3A_OPTIMIZE_DIR_ERR,
11299 N_("Failed to optimize directory %q (%d): %m"),
11302 /* Rehashing dir header */
11303 { PR_3A_OPTIMIZE_DIR_HEADER,
11304 N_("Optimizing directories: "),
11305 PROMPT_NONE, PR_MSG_ONLY },
11307 /* Rehashing directory %d */
11308 { PR_3A_OPTIMIZE_DIR,
11310 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11312 /* Rehashing dir end */
11313 { PR_3A_OPTIMIZE_DIR_END,
11315 PROMPT_NONE, PR_PREEN_NOHDR },
11317 /* Pass 4 errors */
11319 /* Pass 4: Checking reference counts */
11320 { PR_4_PASS_HEADER,
11321 N_("Pass 4: Checking reference counts\n"),
11324 /* Unattached zero-length inode */
11325 { PR_4_ZERO_LEN_INODE,
11326 N_("@u @z @i %i. "),
11327 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11329 /* Unattached inode */
11330 { PR_4_UNATTACHED_INODE,
11332 PROMPT_CONNECT, 0 },
11334 /* Inode ref count wrong */
11335 { PR_4_BAD_REF_COUNT,
11336 N_("@i %i ref count is %Il, @s %N. "),
11337 PROMPT_FIX, PR_PREEN_OK },
11339 { PR_4_INCONSISTENT_COUNT,
11340 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11341 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11342 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
11343 "They @s the same!\n"),
11346 /* Pass 5 errors */
11348 /* Pass 5: Checking group summary information */
11349 { PR_5_PASS_HEADER,
11350 N_("Pass 5: Checking @g summary information\n"),
11353 /* Padding at end of inode bitmap is not set. */
11354 { PR_5_INODE_BMAP_PADDING,
11355 N_("Padding at end of @i @B is not set. "),
11356 PROMPT_FIX, PR_PREEN_OK },
11358 /* Padding at end of block bitmap is not set. */
11359 { PR_5_BLOCK_BMAP_PADDING,
11360 N_("Padding at end of @b @B is not set. "),
11361 PROMPT_FIX, PR_PREEN_OK },
11363 /* Block bitmap differences header */
11364 { PR_5_BLOCK_BITMAP_HEADER,
11365 N_("@b @B differences: "),
11366 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11368 /* Block not used, but marked in bitmap */
11369 { PR_5_BLOCK_UNUSED,
11371 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11373 /* Block used, but not marked used in bitmap */
11376 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11378 /* Block bitmap differences end */
11379 { PR_5_BLOCK_BITMAP_END,
11381 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11383 /* Inode bitmap differences header */
11384 { PR_5_INODE_BITMAP_HEADER,
11385 N_("@i @B differences: "),
11386 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11388 /* Inode not used, but marked in bitmap */
11389 { PR_5_INODE_UNUSED,
11391 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11393 /* Inode used, but not marked used in bitmap */
11396 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11398 /* Inode bitmap differences end */
11399 { PR_5_INODE_BITMAP_END,
11401 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11403 /* Free inodes count for group wrong */
11404 { PR_5_FREE_INODE_COUNT_GROUP,
11405 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11406 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11408 /* Directories count for group wrong */
11409 { PR_5_FREE_DIR_COUNT_GROUP,
11410 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11411 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11413 /* Free inodes count wrong */
11414 { PR_5_FREE_INODE_COUNT,
11415 N_("Free @is count wrong (%i, counted=%j).\n"),
11416 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11418 /* Free blocks count for group wrong */
11419 { PR_5_FREE_BLOCK_COUNT_GROUP,
11420 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11421 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11423 /* Free blocks count wrong */
11424 { PR_5_FREE_BLOCK_COUNT,
11425 N_("Free @bs count wrong (%b, counted=%c).\n"),
11426 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11428 /* Programming error: bitmap endpoints don't match */
11429 { PR_5_BMAP_ENDPOINTS,
11430 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11431 "match calculated @B endpoints (%i, %j)\n"),
11432 PROMPT_NONE, PR_FATAL },
11434 /* Internal error: fudging end of bitmap */
11435 { PR_5_FUDGE_BITMAP_ERROR,
11436 N_("Internal error: fudging end of bitmap (%N)\n"),
11437 PROMPT_NONE, PR_FATAL },
11439 /* Error copying in replacement inode bitmap */
11440 { PR_5_COPY_IBITMAP_ERROR,
11441 N_("Error copying in replacement @i @B: %m\n"),
11442 PROMPT_NONE, PR_FATAL },
11444 /* Error copying in replacement block bitmap */
11445 { PR_5_COPY_BBITMAP_ERROR,
11446 N_("Error copying in replacement @b @B: %m\n"),
11447 PROMPT_NONE, PR_FATAL },
11449 /* Block range not used, but marked in bitmap */
11450 { PR_5_BLOCK_RANGE_UNUSED,
11452 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11454 /* Block range used, but not marked used in bitmap */
11455 { PR_5_BLOCK_RANGE_USED,
11457 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11459 /* Inode range not used, but marked in bitmap */
11460 { PR_5_INODE_RANGE_UNUSED,
11462 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11464 /* Inode range used, but not marked used in bitmap */
11465 { PR_5_INODE_RANGE_USED,
11467 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11473 * This is the latch flags register. It allows several problems to be
11474 * "latched" together. This means that the user has to answer but one
11475 * question for the set of problems, and all of the associated
11476 * problems will be either fixed or not fixed.
11478 static struct latch_descr pr_latch_info[] = {
11479 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11480 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11481 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11482 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11483 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11484 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11485 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11486 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11487 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11491 static const struct e2fsck_problem *find_problem(problem_t code)
11495 for (i=0; problem_table[i].e2p_code; i++) {
11496 if (problem_table[i].e2p_code == code)
11497 return &problem_table[i];
11502 static struct latch_descr *find_latch(int code)
11506 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11507 if (pr_latch_info[i].latch_code == code)
11508 return &pr_latch_info[i];
11513 int end_problem_latch(e2fsck_t ctx, int mask)
11515 struct latch_descr *ldesc;
11516 struct problem_context pctx;
11519 ldesc = find_latch(mask);
11520 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11521 clear_problem_context(&pctx);
11522 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11524 ldesc->flags &= ~(PRL_VARIABLE);
11528 int set_latch_flags(int mask, int setflags, int clearflags)
11530 struct latch_descr *ldesc;
11532 ldesc = find_latch(mask);
11535 ldesc->flags |= setflags;
11536 ldesc->flags &= ~clearflags;
11540 void clear_problem_context(struct problem_context *ctx)
11542 memset(ctx, 0, sizeof(struct problem_context));
11543 ctx->blkcount = -1;
11547 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11549 ext2_filsys fs = ctx->fs;
11550 const struct e2fsck_problem *ptr;
11551 struct latch_descr *ldesc = 0;
11552 const char *message;
11553 int def_yn, answer, ans;
11554 int print_answer = 0;
11557 ptr = find_problem(code);
11559 printf(_("Unhandled error code (0x%x)!\n"), code);
11563 if ((ptr->flags & PR_NO_DEFAULT) ||
11564 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11565 (ctx->options & E2F_OPT_NO))
11569 * Do special latch processing. This is where we ask the
11570 * latch question, if it exists
11572 if (ptr->flags & PR_LATCH_MASK) {
11573 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11574 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11575 ans = fix_problem(ctx, ldesc->question, pctx);
11577 ldesc->flags |= PRL_YES;
11579 ldesc->flags |= PRL_NO;
11580 ldesc->flags |= PRL_LATCHED;
11582 if (ldesc->flags & PRL_SUPPRESS)
11585 if ((ptr->flags & PR_PREEN_NOMSG) &&
11586 (ctx->options & E2F_OPT_PREEN))
11588 if ((ptr->flags & PR_NO_NOMSG) &&
11589 (ctx->options & E2F_OPT_NO))
11592 message = ptr->e2p_description;
11593 if ((ctx->options & E2F_OPT_PREEN) &&
11594 !(ptr->flags & PR_PREEN_NOHDR)) {
11595 printf("%s: ", ctx->device_name ?
11596 ctx->device_name : ctx->filesystem_name);
11599 print_e2fsck_message(ctx, _(message), pctx, 1);
11601 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11604 if (ptr->flags & PR_FATAL)
11605 fatal_error(ctx, 0);
11607 if (ptr->prompt == PROMPT_NONE) {
11608 if (ptr->flags & PR_NOCOLLATE)
11613 if (ctx->options & E2F_OPT_PREEN) {
11615 if (!(ptr->flags & PR_PREEN_NOMSG))
11617 } else if ((ptr->flags & PR_LATCH_MASK) &&
11618 (ldesc->flags & (PRL_YES | PRL_NO))) {
11621 if (ldesc->flags & PRL_YES)
11626 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11627 if (!answer && !(ptr->flags & PR_NO_OK))
11628 ext2fs_unmark_valid(fs);
11631 printf("%s.\n", answer ?
11632 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11636 if ((ptr->prompt == PROMPT_ABORT) && answer)
11637 fatal_error(ctx, 0);
11639 if (ptr->flags & PR_AFTER_CODE)
11640 answer = fix_problem(ctx, ptr->second_code, pctx);
11646 * linux/fs/recovery.c
11648 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11652 * Maintain information about the progress of the recovery job, so that
11653 * the different passes can carry information between them.
11655 struct recovery_info
11657 tid_t start_transaction;
11658 tid_t end_transaction;
11662 int nr_revoke_hits;
11665 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11666 static int do_one_pass(journal_t *journal,
11667 struct recovery_info *info, enum passtype pass);
11668 static int scan_revoke_records(journal_t *, struct buffer_head *,
11669 tid_t, struct recovery_info *);
11672 * Read a block from the journal
11675 static int jread(struct buffer_head **bhp, journal_t *journal,
11676 unsigned int offset)
11679 unsigned long blocknr;
11680 struct buffer_head *bh;
11684 J_ASSERT (offset < journal->j_maxlen);
11686 err = journal_bmap(journal, offset, &blocknr);
11689 printk (KERN_ERR "JBD: bad block at offset %u\n",
11694 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11698 if (!buffer_uptodate(bh)) {
11699 /* If this is a brand new buffer, start readahead.
11700 Otherwise, we assume we are already reading it. */
11701 if (!buffer_req(bh))
11702 do_readahead(journal, offset);
11703 wait_on_buffer(bh);
11706 if (!buffer_uptodate(bh)) {
11707 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11719 * Count the number of in-use tags in a journal descriptor block.
11722 static int count_tags(struct buffer_head *bh, int size)
11725 journal_block_tag_t * tag;
11728 tagp = &bh->b_data[sizeof(journal_header_t)];
11730 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11731 tag = (journal_block_tag_t *) tagp;
11734 tagp += sizeof(journal_block_tag_t);
11735 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11738 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11746 /* Make sure we wrap around the log correctly! */
11747 #define wrap(journal, var) \
11749 if (var >= (journal)->j_last) \
11750 var -= ((journal)->j_last - (journal)->j_first); \
11754 * int journal_recover(journal_t *journal) - recovers a on-disk journal
11755 * @journal: the journal to recover
11757 * The primary function for recovering the log contents when mounting a
11758 * journaled device.
11760 * Recovery is done in three passes. In the first pass, we look for the
11761 * end of the log. In the second, we assemble the list of revoke
11762 * blocks. In the third and final pass, we replay any un-revoked blocks
11765 int journal_recover(journal_t *journal)
11768 journal_superblock_t * sb;
11770 struct recovery_info info;
11772 memset(&info, 0, sizeof(info));
11773 sb = journal->j_superblock;
11776 * The journal superblock's s_start field (the current log head)
11777 * is always zero if, and only if, the journal was cleanly
11781 if (!sb->s_start) {
11782 jbd_debug(1, "No recovery required, last transaction %d\n",
11783 ntohl(sb->s_sequence));
11784 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11788 err = do_one_pass(journal, &info, PASS_SCAN);
11790 err = do_one_pass(journal, &info, PASS_REVOKE);
11792 err = do_one_pass(journal, &info, PASS_REPLAY);
11794 jbd_debug(0, "JBD: recovery, exit status %d, "
11795 "recovered transactions %u to %u\n",
11796 err, info.start_transaction, info.end_transaction);
11797 jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11798 info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11800 /* Restart the log at the next transaction ID, thus invalidating
11801 * any existing commit records in the log. */
11802 journal->j_transaction_sequence = ++info.end_transaction;
11804 journal_clear_revoke(journal);
11805 sync_blockdev(journal->j_fs_dev);
11809 static int do_one_pass(journal_t *journal,
11810 struct recovery_info *info, enum passtype pass)
11812 unsigned int first_commit_ID, next_commit_ID;
11813 unsigned long next_log_block;
11814 int err, success = 0;
11815 journal_superblock_t * sb;
11816 journal_header_t * tmp;
11817 struct buffer_head * bh;
11818 unsigned int sequence;
11821 /* Precompute the maximum metadata descriptors in a descriptor block */
11822 int MAX_BLOCKS_PER_DESC;
11823 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11824 / sizeof(journal_block_tag_t));
11827 * First thing is to establish what we expect to find in the log
11828 * (in terms of transaction IDs), and where (in terms of log
11829 * block offsets): query the superblock.
11832 sb = journal->j_superblock;
11833 next_commit_ID = ntohl(sb->s_sequence);
11834 next_log_block = ntohl(sb->s_start);
11836 first_commit_ID = next_commit_ID;
11837 if (pass == PASS_SCAN)
11838 info->start_transaction = first_commit_ID;
11840 jbd_debug(1, "Starting recovery pass %d\n", pass);
11843 * Now we walk through the log, transaction by transaction,
11844 * making sure that each transaction has a commit block in the
11845 * expected place. Each complete transaction gets replayed back
11846 * into the main filesystem.
11852 journal_block_tag_t * tag;
11853 struct buffer_head * obh;
11854 struct buffer_head * nbh;
11856 /* If we already know where to stop the log traversal,
11857 * check right now that we haven't gone past the end of
11860 if (pass != PASS_SCAN)
11861 if (tid_geq(next_commit_ID, info->end_transaction))
11864 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11865 next_commit_ID, next_log_block, journal->j_last);
11867 /* Skip over each chunk of the transaction looking
11868 * either the next descriptor block or the final commit
11871 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11872 err = jread(&bh, journal, next_log_block);
11877 wrap(journal, next_log_block);
11879 /* What kind of buffer is it?
11881 * If it is a descriptor block, check that it has the
11882 * expected sequence number. Otherwise, we're all done
11885 tmp = (journal_header_t *)bh->b_data;
11887 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11892 blocktype = ntohl(tmp->h_blocktype);
11893 sequence = ntohl(tmp->h_sequence);
11894 jbd_debug(3, "Found magic %d, sequence %d\n",
11895 blocktype, sequence);
11897 if (sequence != next_commit_ID) {
11902 /* OK, we have a valid descriptor block which matches
11903 * all of the sequence number checks. What are we going
11904 * to do with it? That depends on the pass... */
11906 switch(blocktype) {
11907 case JFS_DESCRIPTOR_BLOCK:
11908 /* If it is a valid descriptor block, replay it
11909 * in pass REPLAY; otherwise, just skip over the
11910 * blocks it describes. */
11911 if (pass != PASS_REPLAY) {
11913 count_tags(bh, journal->j_blocksize);
11914 wrap(journal, next_log_block);
11919 /* A descriptor block: we can now write all of
11920 * the data blocks. Yay, useful work is finally
11921 * getting done here! */
11923 tagp = &bh->b_data[sizeof(journal_header_t)];
11924 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11925 <= journal->j_blocksize) {
11926 unsigned long io_block;
11928 tag = (journal_block_tag_t *) tagp;
11929 flags = ntohl(tag->t_flags);
11931 io_block = next_log_block++;
11932 wrap(journal, next_log_block);
11933 err = jread(&obh, journal, io_block);
11935 /* Recover what we can, but
11936 * report failure at the end. */
11939 "JBD: IO error %d recovering "
11940 "block %ld in log\n",
11943 unsigned long blocknr;
11945 J_ASSERT(obh != NULL);
11946 blocknr = ntohl(tag->t_blocknr);
11948 /* If the block has been
11949 * revoked, then we're all done
11951 if (journal_test_revoke
11955 ++info->nr_revoke_hits;
11959 /* Find a buffer for the new
11960 * data being restored */
11961 nbh = getblk(journal->j_fs_dev,
11963 journal->j_blocksize);
11966 "JBD: Out of memory "
11967 "during recovery.\n");
11975 memcpy(nbh->b_data, obh->b_data,
11976 journal->j_blocksize);
11977 if (flags & JFS_FLAG_ESCAPE) {
11978 *((unsigned int *)bh->b_data) =
11979 htonl(JFS_MAGIC_NUMBER);
11982 BUFFER_TRACE(nbh, "marking dirty");
11983 mark_buffer_uptodate(nbh, 1);
11984 mark_buffer_dirty(nbh);
11985 BUFFER_TRACE(nbh, "marking uptodate");
11986 ++info->nr_replays;
11987 /* ll_rw_block(WRITE, 1, &nbh); */
11988 unlock_buffer(nbh);
11994 tagp += sizeof(journal_block_tag_t);
11995 if (!(flags & JFS_FLAG_SAME_UUID))
11998 if (flags & JFS_FLAG_LAST_TAG)
12005 case JFS_COMMIT_BLOCK:
12006 /* Found an expected commit block: not much to
12007 * do other than move on to the next sequence
12013 case JFS_REVOKE_BLOCK:
12014 /* If we aren't in the REVOKE pass, then we can
12015 * just skip over this block. */
12016 if (pass != PASS_REVOKE) {
12021 err = scan_revoke_records(journal, bh,
12022 next_commit_ID, info);
12029 jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12037 * We broke out of the log scan loop: either we came to the
12038 * known end of the log or we found an unexpected block in the
12039 * log. If the latter happened, then we know that the "current"
12040 * transaction marks the end of the valid log.
12043 if (pass == PASS_SCAN)
12044 info->end_transaction = next_commit_ID;
12046 /* It's really bad news if different passes end up at
12047 * different places (but possible due to IO errors). */
12048 if (info->end_transaction != next_commit_ID) {
12049 printk (KERN_ERR "JBD: recovery pass %d ended at "
12050 "transaction %u, expected %u\n",
12051 pass, next_commit_ID, info->end_transaction);
12064 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12066 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12067 tid_t sequence, struct recovery_info *info)
12069 journal_revoke_header_t *header;
12072 header = (journal_revoke_header_t *) bh->b_data;
12073 offset = sizeof(journal_revoke_header_t);
12074 max = ntohl(header->r_count);
12076 while (offset < max) {
12077 unsigned long blocknr;
12080 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12082 err = journal_set_revoke(journal, blocknr, sequence);
12085 ++info->nr_revokes;
12092 * rehash.c --- rebuild hash tree directories
12094 * This algorithm is designed for simplicity of implementation and to
12095 * pack the directory as much as possible. It however requires twice
12096 * as much memory as the size of the directory. The maximum size
12097 * directory supported using a 4k blocksize is roughly a gigabyte, and
12098 * so there may very well be problems with machines that don't have
12099 * virtual memory, and obscenely large directories.
12101 * An alternate algorithm which is much more disk intensive could be
12102 * written, and probably will need to be written in the future. The
12103 * design goals of such an algorithm are: (a) use (roughly) constant
12104 * amounts of memory, no matter how large the directory, (b) the
12105 * directory must be safe at all times, even if e2fsck is interrupted
12106 * in the middle, (c) we must use minimal amounts of extra disk
12107 * blocks. This pretty much requires an incremental approach, where
12108 * we are reading from one part of the directory, and inserting into
12109 * the front half. So the algorithm will have to keep track of a
12110 * moving block boundary between the new tree and the old tree, and
12111 * files will need to be moved from the old directory and inserted
12112 * into the new tree. If the new directory requires space which isn't
12113 * yet available, blocks from the beginning part of the old directory
12114 * may need to be moved to the end of the directory to make room for
12117 * --------------------------------------------------------
12118 * | new tree | | old tree |
12119 * --------------------------------------------------------
12121 * tail new head old
12123 * This is going to be a pain in the tuckus to implement, and will
12124 * require a lot more disk accesses. So I'm going to skip it for now;
12125 * it's only really going to be an issue for really, really big
12126 * filesystems (when we reach the level of tens of millions of files
12127 * in a single directory). It will probably be easier to simply
12128 * require that e2fsck use VM first.
12131 struct fill_dir_struct {
12133 struct ext2_inode *inode;
12136 struct hash_entry *harray;
12137 int max_array, num_array;
12143 struct hash_entry {
12144 ext2_dirhash_t hash;
12145 ext2_dirhash_t minor_hash;
12146 struct ext2_dir_entry *dir;
12153 ext2_dirhash_t *hashes;
12156 static int fill_dir_block(ext2_filsys fs,
12158 e2_blkcnt_t blockcnt,
12159 blk_t ref_block FSCK_ATTR((unused)),
12160 int ref_offset FSCK_ATTR((unused)),
12163 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
12164 struct hash_entry *new_array, *ent;
12165 struct ext2_dir_entry *dirent;
12167 unsigned int offset, dir_offset;
12172 offset = blockcnt * fs->blocksize;
12173 if (offset + fs->blocksize > fd->inode->i_size) {
12174 fd->err = EXT2_ET_DIR_CORRUPTED;
12175 return BLOCK_ABORT;
12177 dir = (fd->buf+offset);
12178 if (HOLE_BLKADDR(*block_nr)) {
12179 memset(dir, 0, fs->blocksize);
12180 dirent = (struct ext2_dir_entry *) dir;
12181 dirent->rec_len = fs->blocksize;
12183 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12185 return BLOCK_ABORT;
12187 /* While the directory block is "hot", index it. */
12189 while (dir_offset < fs->blocksize) {
12190 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12191 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12192 (dirent->rec_len < 8) ||
12193 ((dirent->rec_len % 4) != 0) ||
12194 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12195 fd->err = EXT2_ET_DIR_CORRUPTED;
12196 return BLOCK_ABORT;
12198 dir_offset += dirent->rec_len;
12199 if (dirent->inode == 0)
12201 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12202 (dirent->name[0] == '.'))
12204 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12205 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12206 fd->parent = dirent->inode;
12209 if (fd->num_array >= fd->max_array) {
12210 new_array = realloc(fd->harray,
12211 sizeof(struct hash_entry) * (fd->max_array+500));
12214 return BLOCK_ABORT;
12216 fd->harray = new_array;
12217 fd->max_array += 500;
12219 ent = fd->harray + fd->num_array++;
12221 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12223 ent->hash = ent->minor_hash = 0;
12225 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12227 dirent->name_len & 0xFF,
12228 fs->super->s_hash_seed,
12229 &ent->hash, &ent->minor_hash);
12231 return BLOCK_ABORT;
12238 /* Used for sorting the hash entry */
12239 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12241 const struct hash_entry *he_a = (const struct hash_entry *) a;
12242 const struct hash_entry *he_b = (const struct hash_entry *) b;
12246 min_len = he_a->dir->name_len;
12247 if (min_len > he_b->dir->name_len)
12248 min_len = he_b->dir->name_len;
12250 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12252 if (he_a->dir->name_len > he_b->dir->name_len)
12254 else if (he_a->dir->name_len < he_b->dir->name_len)
12257 ret = he_b->dir->inode - he_a->dir->inode;
12262 /* Used for sorting the hash entry */
12263 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12265 const struct hash_entry *he_a = (const struct hash_entry *) a;
12266 const struct hash_entry *he_b = (const struct hash_entry *) b;
12269 if (he_a->hash > he_b->hash)
12271 else if (he_a->hash < he_b->hash)
12274 if (he_a->minor_hash > he_b->minor_hash)
12276 else if (he_a->minor_hash < he_b->minor_hash)
12279 ret = name_cmp(a, b);
12284 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12290 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12293 outdir->buf = new_mem;
12294 new_mem = realloc(outdir->hashes,
12295 blocks * sizeof(ext2_dirhash_t));
12298 outdir->hashes = new_mem;
12300 outdir->buf = malloc(blocks * fs->blocksize);
12301 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12304 outdir->max = blocks;
12308 static void free_out_dir(struct out_dir *outdir)
12311 free(outdir->hashes);
12316 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12321 if (outdir->num >= outdir->max) {
12322 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12326 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12327 memset(*ret, 0, fs->blocksize);
12332 * This function is used to make a unique filename. We do this by
12333 * appending ~0, and then incrementing the number. However, we cannot
12334 * expand the length of the filename beyond the padding available in
12335 * the directory entry.
12337 static void mutate_name(char *str, __u16 *len)
12340 __u16 l = *len & 0xFF, h = *len & 0xff00;
12343 * First check to see if it looks the name has been mutated
12346 for (i = l-1; i > 0; i--) {
12347 if (!isdigit(str[i]))
12350 if ((i == l-1) || (str[i] != '~')) {
12351 if (((l-1) & 3) < 2)
12360 for (i = l-1; i >= 0; i--) {
12361 if (isdigit(str[i])) {
12373 else if (str[0] == 'Z') {
12378 } else if (i > 0) {
12391 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12393 struct fill_dir_struct *fd)
12395 struct problem_context pctx;
12396 struct hash_entry *ent, *prev;
12399 char new_name[256];
12402 clear_problem_context(&pctx);
12405 for (i=1; i < fd->num_array; i++) {
12406 ent = fd->harray + i;
12408 if (!ent->dir->inode ||
12409 ((ent->dir->name_len & 0xFF) !=
12410 (prev->dir->name_len & 0xFF)) ||
12411 (strncmp(ent->dir->name, prev->dir->name,
12412 ent->dir->name_len & 0xFF)))
12414 pctx.dirent = ent->dir;
12415 if ((ent->dir->inode == prev->dir->inode) &&
12416 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12417 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12418 ent->dir->inode = 0;
12422 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12423 new_len = ent->dir->name_len;
12424 mutate_name(new_name, &new_len);
12425 for (j=0; j < fd->num_array; j++) {
12427 ((ent->dir->name_len & 0xFF) !=
12428 (fd->harray[j].dir->name_len & 0xFF)) ||
12429 (strncmp(new_name, fd->harray[j].dir->name,
12432 mutate_name(new_name, &new_len);
12436 new_name[new_len & 0xFF] = 0;
12437 pctx.str = new_name;
12438 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12439 memcpy(ent->dir->name, new_name, new_len & 0xFF);
12440 ent->dir->name_len = new_len;
12441 ext2fs_dirhash(fs->super->s_def_hash_version,
12443 ent->dir->name_len & 0xFF,
12444 fs->super->s_hash_seed,
12445 &ent->hash, &ent->minor_hash);
12453 static errcode_t copy_dir_entries(ext2_filsys fs,
12454 struct fill_dir_struct *fd,
12455 struct out_dir *outdir)
12459 struct hash_entry *ent;
12460 struct ext2_dir_entry *dirent;
12461 int i, rec_len, left;
12462 ext2_dirhash_t prev_hash;
12466 retval = alloc_size_dir(fs, outdir,
12467 (fd->dir_size / fs->blocksize) + 2);
12470 outdir->num = fd->compress ? 0 : 1;
12472 outdir->hashes[0] = 0;
12474 if ((retval = get_next_block(fs, outdir, &block_start)))
12476 dirent = (struct ext2_dir_entry *) block_start;
12477 left = fs->blocksize;
12478 for (i=0; i < fd->num_array; i++) {
12479 ent = fd->harray + i;
12480 if (ent->dir->inode == 0)
12482 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12483 if (rec_len > left) {
12485 dirent->rec_len += left;
12486 if ((retval = get_next_block(fs, outdir,
12491 left = fs->blocksize - offset;
12492 dirent = (struct ext2_dir_entry *) (block_start + offset);
12494 if (ent->hash == prev_hash)
12495 outdir->hashes[outdir->num-1] = ent->hash | 1;
12497 outdir->hashes[outdir->num-1] = ent->hash;
12499 dirent->inode = ent->dir->inode;
12500 dirent->name_len = ent->dir->name_len;
12501 dirent->rec_len = rec_len;
12502 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12506 dirent->rec_len += left;
12510 prev_hash = ent->hash;
12513 dirent->rec_len += left;
12519 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12520 ext2_ino_t ino, ext2_ino_t parent)
12522 struct ext2_dir_entry *dir;
12523 struct ext2_dx_root_info *root;
12524 struct ext2_dx_countlimit *limits;
12527 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12528 filetype = EXT2_FT_DIR << 8;
12530 memset(buf, 0, fs->blocksize);
12531 dir = (struct ext2_dir_entry *) buf;
12533 dir->name[0] = '.';
12534 dir->name_len = 1 | filetype;
12536 dir = (struct ext2_dir_entry *) (buf + 12);
12537 dir->inode = parent;
12538 dir->name[0] = '.';
12539 dir->name[1] = '.';
12540 dir->name_len = 2 | filetype;
12541 dir->rec_len = fs->blocksize - 12;
12543 root = (struct ext2_dx_root_info *) (buf+24);
12544 root->reserved_zero = 0;
12545 root->hash_version = fs->super->s_def_hash_version;
12546 root->info_length = 8;
12547 root->indirect_levels = 0;
12548 root->unused_flags = 0;
12550 limits = (struct ext2_dx_countlimit *) (buf+32);
12551 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12558 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12560 struct ext2_dir_entry *dir;
12561 struct ext2_dx_countlimit *limits;
12563 memset(buf, 0, fs->blocksize);
12564 dir = (struct ext2_dir_entry *) buf;
12566 dir->rec_len = fs->blocksize;
12568 limits = (struct ext2_dx_countlimit *) (buf+8);
12569 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12572 return (struct ext2_dx_entry *) limits;
12576 * This function takes the leaf nodes which have been written in
12577 * outdir, and populates the root node and any necessary interior nodes.
12579 static errcode_t calculate_tree(ext2_filsys fs,
12580 struct out_dir *outdir,
12584 struct ext2_dx_root_info *root_info;
12585 struct ext2_dx_entry *root, *dx_ent = 0;
12586 struct ext2_dx_countlimit *root_limit, *limit;
12588 char * block_start;
12589 int i, c1, c2, nblks;
12590 int limit_offset, root_offset;
12592 root_info = set_root_node(fs, outdir->buf, ino, parent);
12593 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12594 root_info->info_length;
12595 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12596 c1 = root_limit->limit;
12597 nblks = outdir->num;
12599 /* Write out the pointer blocks */
12600 if (nblks-1 <= c1) {
12601 /* Just write out the root block, and we're done */
12602 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12603 for (i=1; i < nblks; i++) {
12604 root->block = ext2fs_cpu_to_le32(i);
12607 ext2fs_cpu_to_le32(outdir->hashes[i]);
12614 root_info->indirect_levels = 1;
12615 for (i=1; i < nblks; i++) {
12620 limit->limit = limit->count =
12621 ext2fs_cpu_to_le16(limit->limit);
12622 root = (struct ext2_dx_entry *)
12623 (outdir->buf + root_offset);
12624 root->block = ext2fs_cpu_to_le32(outdir->num);
12627 ext2fs_cpu_to_le32(outdir->hashes[i]);
12628 if ((retval = get_next_block(fs, outdir,
12631 dx_ent = set_int_node(fs, block_start);
12632 limit = (struct ext2_dx_countlimit *) dx_ent;
12634 root_offset += sizeof(struct ext2_dx_entry);
12637 dx_ent->block = ext2fs_cpu_to_le32(i);
12638 if (c2 != limit->limit)
12640 ext2fs_cpu_to_le32(outdir->hashes[i]);
12644 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12645 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12647 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12648 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12649 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12654 struct write_dir_struct {
12655 struct out_dir *outdir;
12662 * Helper function which writes out a directory block.
12664 static int write_dir_block(ext2_filsys fs,
12666 e2_blkcnt_t blockcnt,
12667 blk_t ref_block FSCK_ATTR((unused)),
12668 int ref_offset FSCK_ATTR((unused)),
12671 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12675 if (*block_nr == 0)
12677 if (blockcnt >= wd->outdir->num) {
12678 e2fsck_read_bitmaps(wd->ctx);
12680 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12681 ext2fs_block_alloc_stats(fs, blk, -1);
12684 return BLOCK_CHANGED;
12689 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12690 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12692 return BLOCK_ABORT;
12696 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12697 struct out_dir *outdir,
12698 ext2_ino_t ino, int compress)
12700 struct write_dir_struct wd;
12702 struct ext2_inode inode;
12704 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12708 wd.outdir = outdir;
12713 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12714 write_dir_block, &wd);
12720 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12722 inode.i_flags &= ~EXT2_INDEX_FL;
12724 inode.i_flags |= EXT2_INDEX_FL;
12725 inode.i_size = outdir->num * fs->blocksize;
12726 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12727 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12732 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12734 ext2_filsys fs = ctx->fs;
12736 struct ext2_inode inode;
12738 struct fill_dir_struct fd;
12739 struct out_dir outdir;
12741 outdir.max = outdir.num = 0;
12744 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12748 dir_buf = malloc(inode.i_size);
12752 fd.max_array = inode.i_size / 32;
12754 fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12764 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12765 (inode.i_size / fs->blocksize) < 2)
12769 /* Read in the entire directory into memory */
12770 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12771 fill_dir_block, &fd);
12778 printf("%d entries (%d bytes) found in inode %d\n",
12779 fd.num_array, fd.dir_size, ino);
12782 /* Sort the list */
12785 qsort(fd.harray+2, fd.num_array-2,
12786 sizeof(struct hash_entry), name_cmp);
12788 qsort(fd.harray, fd.num_array,
12789 sizeof(struct hash_entry), hash_cmp);
12792 * Look for duplicates
12794 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12797 if (ctx->options & E2F_OPT_NO) {
12803 * Copy the directory entries. In a htree directory these
12804 * will become the leaf nodes.
12806 retval = copy_dir_entries(fs, &fd, &outdir);
12810 free(dir_buf); dir_buf = 0;
12812 if (!fd.compress) {
12813 /* Calculate the interior nodes */
12814 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12819 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12825 free_out_dir(&outdir);
12829 void e2fsck_rehash_directories(e2fsck_t ctx)
12831 struct problem_context pctx;
12832 #ifdef RESOURCE_TRACK
12833 struct resource_track rtrack;
12835 struct dir_info *dir;
12836 ext2_u32_iterate iter;
12839 int i, cur, max, all_dirs, dir_index, first = 1;
12841 #ifdef RESOURCE_TRACK
12842 init_resource_track(&rtrack);
12845 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12847 if (!ctx->dirs_to_hash && !all_dirs)
12850 e2fsck_get_lost_and_found(ctx, 0);
12852 clear_problem_context(&pctx);
12854 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12858 max = e2fsck_get_num_dirinfo(ctx);
12860 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12863 pctx.errcode = retval;
12864 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12867 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12871 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12875 if (!ext2fs_u32_list_iterate(iter, &ino))
12878 if (ino == ctx->lost_and_found)
12882 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12886 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12888 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12889 if (pctx.errcode) {
12890 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12891 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12893 if (ctx->progress && !ctx->progress_fd)
12894 e2fsck_simple_progress(ctx, "Rebuilding directory",
12895 100.0 * (float) (++cur) / (float) max, ino);
12897 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12899 ext2fs_u32_list_iterate_end(iter);
12901 ext2fs_u32_list_free(ctx->dirs_to_hash);
12902 ctx->dirs_to_hash = 0;
12904 #ifdef RESOURCE_TRACK
12905 if (ctx->options & E2F_OPT_TIME2) {
12906 e2fsck_clear_progbar(ctx);
12907 print_resource_track("Pass 3A", &rtrack);
12913 * linux/fs/revoke.c
12915 * Journal revoke routines for the generic filesystem journaling code;
12916 * part of the ext2fs journaling system.
12918 * Revoke is the mechanism used to prevent old log records for deleted
12919 * metadata from being replayed on top of newer data using the same
12920 * blocks. The revoke mechanism is used in two separate places:
12922 * + Commit: during commit we write the entire list of the current
12923 * transaction's revoked blocks to the journal
12925 * + Recovery: during recovery we record the transaction ID of all
12926 * revoked blocks. If there are multiple revoke records in the log
12927 * for a single block, only the last one counts, and if there is a log
12928 * entry for a block beyond the last revoke, then that log entry still
12931 * We can get interactions between revokes and new log data within a
12932 * single transaction:
12934 * Block is revoked and then journaled:
12935 * The desired end result is the journaling of the new block, so we
12936 * cancel the revoke before the transaction commits.
12938 * Block is journaled and then revoked:
12939 * The revoke must take precedence over the write of the block, so we
12940 * need either to cancel the journal entry or to write the revoke
12941 * later in the log than the log block. In this case, we choose the
12942 * latter: journaling a block cancels any revoke record for that block
12943 * in the current transaction, so any revoke for that block in the
12944 * transaction must have happened after the block was journaled and so
12945 * the revoke must take precedence.
12947 * Block is revoked and then written as data:
12948 * The data write is allowed to succeed, but the revoke is _not_
12949 * cancelled. We still need to prevent old log records from
12950 * overwriting the new data. We don't even need to clear the revoke
12953 * Revoke information on buffers is a tri-state value:
12955 * RevokeValid clear: no cached revoke status, need to look it up
12956 * RevokeValid set, Revoked clear:
12957 * buffer has not been revoked, and cancel_revoke
12959 * RevokeValid set, Revoked set:
12960 * buffer has been revoked.
12963 static kmem_cache_t *revoke_record_cache;
12964 static kmem_cache_t *revoke_table_cache;
12966 /* Each revoke record represents one single revoked block. During
12967 journal replay, this involves recording the transaction ID of the
12968 last transaction to revoke this block. */
12970 struct jbd_revoke_record_s
12972 struct list_head hash;
12973 tid_t sequence; /* Used for recovery only */
12974 unsigned long blocknr;
12978 /* The revoke table is just a simple hash table of revoke records. */
12979 struct jbd_revoke_table_s
12981 /* It is conceivable that we might want a larger hash table
12982 * for recovery. Must be a power of two. */
12985 struct list_head *hash_table;
12989 /* Utility functions to maintain the revoke table */
12991 /* Borrowed from buffer.c: this is a tried and tested block hash function */
12992 static inline int hash(journal_t *journal, unsigned long block)
12994 struct jbd_revoke_table_s *table = journal->j_revoke;
12995 int hash_shift = table->hash_shift;
12997 return ((block << (hash_shift - 6)) ^
12999 (block << (hash_shift - 12))) & (table->hash_size - 1);
13002 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
13005 struct list_head *hash_list;
13006 struct jbd_revoke_record_s *record;
13008 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13012 record->sequence = seq;
13013 record->blocknr = blocknr;
13014 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13015 list_add(&record->hash, hash_list);
13022 /* Find a revoke record in the journal's hash table. */
13024 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13025 unsigned long blocknr)
13027 struct list_head *hash_list;
13028 struct jbd_revoke_record_s *record;
13030 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13032 record = (struct jbd_revoke_record_s *) hash_list->next;
13033 while (&(record->hash) != hash_list) {
13034 if (record->blocknr == blocknr)
13036 record = (struct jbd_revoke_record_s *) record->hash.next;
13041 int journal_init_revoke_caches(void)
13043 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13044 if (revoke_record_cache == 0)
13047 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13048 if (revoke_table_cache == 0) {
13049 do_cache_destroy(revoke_record_cache);
13050 revoke_record_cache = NULL;
13056 void journal_destroy_revoke_caches(void)
13058 do_cache_destroy(revoke_record_cache);
13059 revoke_record_cache = 0;
13060 do_cache_destroy(revoke_table_cache);
13061 revoke_table_cache = 0;
13064 /* Initialise the revoke table for a given journal to a given size. */
13066 int journal_init_revoke(journal_t *journal, int hash_size)
13070 J_ASSERT (journal->j_revoke == NULL);
13072 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13073 if (!journal->j_revoke)
13076 /* Check that the hash_size is a power of two */
13077 J_ASSERT ((hash_size & (hash_size-1)) == 0);
13079 journal->j_revoke->hash_size = hash_size;
13083 while((tmp >>= 1UL) != 0UL)
13085 journal->j_revoke->hash_shift = shift;
13087 journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13088 if (!journal->j_revoke->hash_table) {
13089 free(journal->j_revoke);
13090 journal->j_revoke = NULL;
13094 for (tmp = 0; tmp < hash_size; tmp++)
13095 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13100 /* Destoy a journal's revoke table. The table must already be empty! */
13102 void journal_destroy_revoke(journal_t *journal)
13104 struct jbd_revoke_table_s *table;
13105 struct list_head *hash_list;
13108 table = journal->j_revoke;
13112 for (i=0; i<table->hash_size; i++) {
13113 hash_list = &table->hash_table[i];
13114 J_ASSERT (list_empty(hash_list));
13117 free(table->hash_table);
13119 journal->j_revoke = NULL;
13123 * Revoke support for recovery.
13125 * Recovery needs to be able to:
13127 * record all revoke records, including the tid of the latest instance
13128 * of each revoke in the journal
13130 * check whether a given block in a given transaction should be replayed
13131 * (ie. has not been revoked by a revoke record in that or a subsequent
13134 * empty the revoke table after recovery.
13138 * First, setting revoke records. We create a new revoke record for
13139 * every block ever revoked in the log as we scan it for recovery, and
13140 * we update the existing records if we find multiple revokes for a
13144 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13147 struct jbd_revoke_record_s *record;
13149 record = find_revoke_record(journal, blocknr);
13151 /* If we have multiple occurences, only record the
13152 * latest sequence number in the hashed record */
13153 if (tid_gt(sequence, record->sequence))
13154 record->sequence = sequence;
13157 return insert_revoke_hash(journal, blocknr, sequence);
13161 * Test revoke records. For a given block referenced in the log, has
13162 * that block been revoked? A revoke record with a given transaction
13163 * sequence number revokes all blocks in that transaction and earlier
13164 * ones, but later transactions still need replayed.
13167 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13170 struct jbd_revoke_record_s *record;
13172 record = find_revoke_record(journal, blocknr);
13175 if (tid_gt(sequence, record->sequence))
13181 * Finally, once recovery is over, we need to clear the revoke table so
13182 * that it can be reused by the running filesystem.
13185 void journal_clear_revoke(journal_t *journal)
13188 struct list_head *hash_list;
13189 struct jbd_revoke_record_s *record;
13190 struct jbd_revoke_table_s *revoke_var;
13192 revoke_var = journal->j_revoke;
13194 for (i = 0; i < revoke_var->hash_size; i++) {
13195 hash_list = &revoke_var->hash_table[i];
13196 while (!list_empty(hash_list)) {
13197 record = (struct jbd_revoke_record_s*) hash_list->next;
13198 list_del(&record->hash);
13205 * e2fsck.c - superblock checks
13208 #define MIN_CHECK 1
13209 #define MAX_CHECK 2
13211 static void check_super_value(e2fsck_t ctx, const char *descr,
13212 unsigned long value, int flags,
13213 unsigned long min_val, unsigned long max_val)
13215 struct problem_context pctx;
13217 if (((flags & MIN_CHECK) && (value < min_val)) ||
13218 ((flags & MAX_CHECK) && (value > max_val))) {
13219 clear_problem_context(&pctx);
13222 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13223 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13228 * This routine may get stubbed out in special compilations of the
13231 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13232 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13234 return (ext2fs_get_device_size(ctx->filesystem_name,
13235 EXT2_BLOCK_SIZE(ctx->fs->super),
13236 &ctx->num_blocks));
13241 * helper function to release an inode
13243 struct process_block_struct {
13246 struct problem_context *pctx;
13248 int truncate_offset;
13249 e2_blkcnt_t truncate_block;
13250 int truncated_blocks;
13255 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13256 e2_blkcnt_t blockcnt,
13257 blk_t ref_blk FSCK_ATTR((unused)),
13258 int ref_offset FSCK_ATTR((unused)),
13261 struct process_block_struct *pb;
13263 struct problem_context *pctx;
13264 blk_t blk = *block_nr;
13267 pb = (struct process_block_struct *) priv_data;
13272 pctx->blkcount = blockcnt;
13274 if (HOLE_BLKADDR(blk))
13277 if ((blk < fs->super->s_first_data_block) ||
13278 (blk >= fs->super->s_blocks_count)) {
13279 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13282 return BLOCK_ABORT;
13285 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13286 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13291 * If we are deleting an orphan, then we leave the fields alone.
13292 * If we are truncating an orphan, then update the inode fields
13293 * and clean up any partial block data.
13295 if (pb->truncating) {
13297 * We only remove indirect blocks if they are
13298 * completely empty.
13300 if (blockcnt < 0) {
13304 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13309 limit = fs->blocksize >> 2;
13310 for (i = 0, bp = (blk_t *) pb->buf;
13311 i < limit; i++, bp++)
13316 * We don't remove direct blocks until we've reached
13317 * the truncation block.
13319 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13322 * If part of the last block needs truncating, we do
13325 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13326 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13330 memset(pb->buf + pb->truncate_offset, 0,
13331 fs->blocksize - pb->truncate_offset);
13332 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13337 pb->truncated_blocks++;
13339 retval |= BLOCK_CHANGED;
13342 ext2fs_block_alloc_stats(fs, blk, -1);
13347 * This function releases an inode. Returns 1 if an inconsistency was
13348 * found. If the inode has a link count, then it is being truncated and
13351 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13352 struct ext2_inode *inode, char *block_buf,
13353 struct problem_context *pctx)
13355 struct process_block_struct pb;
13356 ext2_filsys fs = ctx->fs;
13360 if (!ext2fs_inode_has_valid_blocks(inode))
13363 pb.buf = block_buf + 3 * ctx->fs->blocksize;
13368 if (inode->i_links_count) {
13370 pb.truncate_block = (e2_blkcnt_t)
13371 ((((long long)inode->i_size_high << 32) +
13372 inode->i_size + fs->blocksize - 1) /
13374 pb.truncate_offset = inode->i_size % fs->blocksize;
13377 pb.truncate_block = 0;
13378 pb.truncate_offset = 0;
13380 pb.truncated_blocks = 0;
13381 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13382 block_buf, release_inode_block, &pb);
13384 com_err("release_inode_blocks", retval,
13385 _("while calling ext2fs_block_iterate for inode %d"),
13392 /* Refresh the inode since ext2fs_block_iterate may have changed it */
13393 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13395 if (pb.truncated_blocks)
13396 inode->i_blocks -= pb.truncated_blocks *
13397 (fs->blocksize / 512);
13399 if (inode->i_file_acl) {
13400 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13401 block_buf, -1, &count);
13402 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13407 com_err("release_inode_blocks", retval,
13408 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13413 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13414 inode->i_file_acl = 0;
13420 * This function releases all of the orphan inodes. It returns 1 if
13421 * it hit some error, and 0 on success.
13423 static int release_orphan_inodes(e2fsck_t ctx)
13425 ext2_filsys fs = ctx->fs;
13426 ext2_ino_t ino, next_ino;
13427 struct ext2_inode inode;
13428 struct problem_context pctx;
13431 if ((ino = fs->super->s_last_orphan) == 0)
13435 * Win or lose, we won't be using the head of the orphan inode
13438 fs->super->s_last_orphan = 0;
13439 ext2fs_mark_super_dirty(fs);
13442 * If the filesystem contains errors, don't run the orphan
13443 * list, since the orphan list can't be trusted; and we're
13444 * going to be running a full e2fsck run anyway...
13446 if (fs->super->s_state & EXT2_ERROR_FS)
13449 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13450 (ino > fs->super->s_inodes_count)) {
13451 clear_problem_context(&pctx);
13453 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13457 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13458 "block iterate buffer");
13459 e2fsck_read_bitmaps(ctx);
13462 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13463 clear_problem_context(&pctx);
13465 pctx.inode = &inode;
13466 pctx.str = inode.i_links_count ? _("Truncating") :
13469 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13471 next_ino = inode.i_dtime;
13473 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13474 (next_ino > fs->super->s_inodes_count))) {
13475 pctx.ino = next_ino;
13476 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13480 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13483 if (!inode.i_links_count) {
13484 ext2fs_inode_alloc_stats2(fs, ino, -1,
13485 LINUX_S_ISDIR(inode.i_mode));
13486 inode.i_dtime = time(0);
13490 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13493 ext2fs_free_mem(&block_buf);
13496 ext2fs_free_mem(&block_buf);
13501 * Check the resize inode to make sure it is sane. We check both for
13502 * the case where on-line resizing is not enabled (in which case the
13503 * resize inode should be cleared) as well as the case where on-line
13504 * resizing is enabled.
13506 static void check_resize_inode(e2fsck_t ctx)
13508 ext2_filsys fs = ctx->fs;
13509 struct ext2_inode inode;
13510 struct problem_context pctx;
13511 int i, j, gdt_off, ind_off;
13512 blk_t blk, pblk, expect;
13513 __u32 *dind_buf = 0, *ind_buf;
13516 clear_problem_context(&pctx);
13519 * If the resize inode feature isn't set, then
13520 * s_reserved_gdt_blocks must be zero.
13522 if (!(fs->super->s_feature_compat &
13523 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13524 if (fs->super->s_reserved_gdt_blocks) {
13525 pctx.num = fs->super->s_reserved_gdt_blocks;
13526 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13528 fs->super->s_reserved_gdt_blocks = 0;
13529 ext2fs_mark_super_dirty(fs);
13534 /* Read the resize inode */
13535 pctx.ino = EXT2_RESIZE_INO;
13536 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13538 if (fs->super->s_feature_compat &
13539 EXT2_FEATURE_COMPAT_RESIZE_INODE)
13540 ctx->flags |= E2F_FLAG_RESIZE_INODE;
13545 * If the resize inode feature isn't set, check to make sure
13546 * the resize inode is cleared; then we're done.
13548 if (!(fs->super->s_feature_compat &
13549 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13550 for (i=0; i < EXT2_N_BLOCKS; i++) {
13551 if (inode.i_block[i])
13554 if ((i < EXT2_N_BLOCKS) &&
13555 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13556 memset(&inode, 0, sizeof(inode));
13557 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13564 * The resize inode feature is enabled; check to make sure the
13565 * only block in use is the double indirect block
13567 blk = inode.i_block[EXT2_DIND_BLOCK];
13568 for (i=0; i < EXT2_N_BLOCKS; i++) {
13569 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13572 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13573 !(inode.i_mode & LINUX_S_IFREG) ||
13574 (blk < fs->super->s_first_data_block ||
13575 blk >= fs->super->s_blocks_count)) {
13576 resize_inode_invalid:
13577 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13578 memset(&inode, 0, sizeof(inode));
13579 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13581 ctx->flags |= E2F_FLAG_RESIZE_INODE;
13583 if (!(ctx->options & E2F_OPT_READONLY)) {
13584 fs->super->s_state &= ~EXT2_VALID_FS;
13585 ext2fs_mark_super_dirty(fs);
13589 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13590 "resize dind buffer");
13591 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13593 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13595 goto resize_inode_invalid;
13597 gdt_off = fs->desc_blocks;
13598 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13599 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13600 i++, gdt_off++, pblk++) {
13601 gdt_off %= fs->blocksize/4;
13602 if (dind_buf[gdt_off] != pblk)
13603 goto resize_inode_invalid;
13604 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13606 goto resize_inode_invalid;
13608 for (j = 1; j < fs->group_desc_count; j++) {
13609 if (!ext2fs_bg_has_super(fs, j))
13611 expect = pblk + (j * fs->super->s_blocks_per_group);
13612 if (ind_buf[ind_off] != expect)
13613 goto resize_inode_invalid;
13619 ext2fs_free_mem(&dind_buf);
13623 static void check_super_block(e2fsck_t ctx)
13625 ext2_filsys fs = ctx->fs;
13626 blk_t first_block, last_block;
13627 struct ext2_super_block *sb = fs->super;
13628 struct ext2_group_desc *gd;
13629 blk_t blocks_per_group = fs->super->s_blocks_per_group;
13631 int inodes_per_block;
13636 struct problem_context pctx;
13637 __u32 free_blocks = 0, free_inodes = 0;
13639 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13640 ipg_max = inodes_per_block * (blocks_per_group - 4);
13641 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13642 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13643 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13644 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13645 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13647 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13648 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13649 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13650 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13651 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13652 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13654 clear_problem_context(&pctx);
13657 * Verify the super block constants...
13659 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13661 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13663 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13664 MAX_CHECK, 0, sb->s_blocks_count);
13665 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13666 MIN_CHECK | MAX_CHECK, 0,
13667 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13668 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13669 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13670 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13671 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13673 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13674 MIN_CHECK | MAX_CHECK, 8, bpg_max);
13675 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13676 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13677 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13678 MAX_CHECK, 0, sb->s_blocks_count / 2);
13679 check_super_value(ctx, "reserved_gdt_blocks",
13680 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13682 inode_size = EXT2_INODE_SIZE(sb);
13683 check_super_value(ctx, "inode_size",
13684 inode_size, MIN_CHECK | MAX_CHECK,
13685 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13686 if (inode_size & (inode_size - 1)) {
13687 pctx.num = inode_size;
13688 pctx.str = "inode_size";
13689 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13690 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13694 if (!ctx->num_blocks) {
13695 pctx.errcode = e2fsck_get_device_size(ctx);
13696 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13697 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13698 ctx->flags |= E2F_FLAG_ABORT;
13701 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13702 (ctx->num_blocks < sb->s_blocks_count)) {
13703 pctx.blk = sb->s_blocks_count;
13704 pctx.blk2 = ctx->num_blocks;
13705 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13706 ctx->flags |= E2F_FLAG_ABORT;
13712 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13713 pctx.blk = EXT2_BLOCK_SIZE(sb);
13714 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13715 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13716 ctx->flags |= E2F_FLAG_ABORT;
13720 should_be = sb->s_frags_per_group >>
13721 (sb->s_log_block_size - sb->s_log_frag_size);
13722 if (sb->s_blocks_per_group != should_be) {
13723 pctx.blk = sb->s_blocks_per_group;
13724 pctx.blk2 = should_be;
13725 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13726 ctx->flags |= E2F_FLAG_ABORT;
13730 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13731 if (sb->s_first_data_block != should_be) {
13732 pctx.blk = sb->s_first_data_block;
13733 pctx.blk2 = should_be;
13734 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13735 ctx->flags |= E2F_FLAG_ABORT;
13739 should_be = sb->s_inodes_per_group * fs->group_desc_count;
13740 if (sb->s_inodes_count != should_be) {
13741 pctx.ino = sb->s_inodes_count;
13742 pctx.ino2 = should_be;
13743 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13744 sb->s_inodes_count = should_be;
13745 ext2fs_mark_super_dirty(fs);
13750 * Verify the group descriptors....
13752 first_block = sb->s_first_data_block;
13753 last_block = first_block + blocks_per_group;
13755 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13758 if (i == fs->group_desc_count - 1)
13759 last_block = sb->s_blocks_count;
13760 if ((gd->bg_block_bitmap < first_block) ||
13761 (gd->bg_block_bitmap >= last_block)) {
13762 pctx.blk = gd->bg_block_bitmap;
13763 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13764 gd->bg_block_bitmap = 0;
13766 if (gd->bg_block_bitmap == 0) {
13767 ctx->invalid_block_bitmap_flag[i]++;
13768 ctx->invalid_bitmaps++;
13770 if ((gd->bg_inode_bitmap < first_block) ||
13771 (gd->bg_inode_bitmap >= last_block)) {
13772 pctx.blk = gd->bg_inode_bitmap;
13773 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13774 gd->bg_inode_bitmap = 0;
13776 if (gd->bg_inode_bitmap == 0) {
13777 ctx->invalid_inode_bitmap_flag[i]++;
13778 ctx->invalid_bitmaps++;
13780 if ((gd->bg_inode_table < first_block) ||
13781 ((gd->bg_inode_table +
13782 fs->inode_blocks_per_group - 1) >= last_block)) {
13783 pctx.blk = gd->bg_inode_table;
13784 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13785 gd->bg_inode_table = 0;
13787 if (gd->bg_inode_table == 0) {
13788 ctx->invalid_inode_table_flag[i]++;
13789 ctx->invalid_bitmaps++;
13791 free_blocks += gd->bg_free_blocks_count;
13792 free_inodes += gd->bg_free_inodes_count;
13793 first_block += sb->s_blocks_per_group;
13794 last_block += sb->s_blocks_per_group;
13796 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13797 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13798 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13799 ext2fs_unmark_valid(fs);
13804 * Update the global counts from the block group counts. This
13805 * is needed for an experimental patch which eliminates
13806 * locking the entire filesystem when allocating blocks or
13807 * inodes; if the filesystem is not unmounted cleanly, the
13808 * global counts may not be accurate.
13810 if ((free_blocks != sb->s_free_blocks_count) ||
13811 (free_inodes != sb->s_free_inodes_count)) {
13812 if (ctx->options & E2F_OPT_READONLY)
13813 ext2fs_unmark_valid(fs);
13815 sb->s_free_blocks_count = free_blocks;
13816 sb->s_free_inodes_count = free_inodes;
13817 ext2fs_mark_super_dirty(fs);
13821 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13822 (sb->s_free_inodes_count > sb->s_inodes_count))
13823 ext2fs_unmark_valid(fs);
13827 * If we have invalid bitmaps, set the error state of the
13830 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13831 sb->s_state &= ~EXT2_VALID_FS;
13832 ext2fs_mark_super_dirty(fs);
13835 clear_problem_context(&pctx);
13837 #ifndef EXT2_SKIP_UUID
13839 * If the UUID field isn't assigned, assign it.
13841 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13842 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13843 uuid_generate(sb->s_uuid);
13844 ext2fs_mark_super_dirty(fs);
13845 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13851 * For the Hurd, check to see if the filetype option is set,
13852 * since it doesn't support it.
13854 if (!(ctx->options & E2F_OPT_READONLY) &&
13855 fs->super->s_creator_os == EXT2_OS_HURD &&
13856 (fs->super->s_feature_incompat &
13857 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13858 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13859 fs->super->s_feature_incompat &=
13860 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13861 ext2fs_mark_super_dirty(fs);
13867 * If we have any of the compatibility flags set, we need to have a
13868 * revision 1 filesystem. Most kernels will not check the flags on
13869 * a rev 0 filesystem and we may have corruption issues because of
13870 * the incompatible changes to the filesystem.
13872 if (!(ctx->options & E2F_OPT_READONLY) &&
13873 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13874 (fs->super->s_feature_compat ||
13875 fs->super->s_feature_ro_compat ||
13876 fs->super->s_feature_incompat) &&
13877 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13878 ext2fs_update_dynamic_rev(fs);
13879 ext2fs_mark_super_dirty(fs);
13882 check_resize_inode(ctx);
13885 * Clean up any orphan inodes, if present.
13887 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13888 fs->super->s_state &= ~EXT2_VALID_FS;
13889 ext2fs_mark_super_dirty(fs);
13893 * Move the ext3 journal file, if necessary.
13895 e2fsck_move_ext3_journal(ctx);
13900 * swapfs.c --- byte-swap an ext2 filesystem
13903 #ifdef ENABLE_SWAPFS
13905 struct swap_block_struct {
13910 struct ext2_inode *inode;
13914 * This is a helper function for block_iterate. We mark all of the
13915 * indirect and direct blocks as changed, so that block_iterate will
13918 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13923 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13925 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13926 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13928 sb->errcode = retval;
13929 return BLOCK_ABORT;
13931 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13933 sb->errcode = retval;
13934 return BLOCK_ABORT;
13937 if (blockcnt >= 0) {
13938 if (blockcnt < EXT2_NDIR_BLOCKS)
13940 return BLOCK_CHANGED;
13942 if (blockcnt == BLOCK_COUNT_IND) {
13943 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
13945 return BLOCK_CHANGED;
13947 if (blockcnt == BLOCK_COUNT_DIND) {
13948 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
13950 return BLOCK_CHANGED;
13952 if (blockcnt == BLOCK_COUNT_TIND) {
13953 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
13955 return BLOCK_CHANGED;
13957 return BLOCK_CHANGED;
13961 * This function is responsible for byte-swapping all of the indirect,
13962 * block pointers. It is also responsible for byte-swapping directories.
13964 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
13965 struct ext2_inode *inode)
13968 struct swap_block_struct sb;
13972 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
13975 if (LINUX_S_ISDIR(inode->i_mode))
13978 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
13981 com_err("swap_inode_blocks", retval,
13982 _("while calling ext2fs_block_iterate"));
13983 ctx->flags |= E2F_FLAG_ABORT;
13987 com_err("swap_inode_blocks", sb.errcode,
13988 _("while calling iterator function"));
13989 ctx->flags |= E2F_FLAG_ABORT;
13994 static void swap_inodes(e2fsck_t ctx)
13996 ext2_filsys fs = ctx->fs;
13999 ext2_ino_t ino = 1;
14000 char *buf, *block_buf;
14002 struct ext2_inode * inode;
14004 e2fsck_use_inode_shortcuts(ctx, 1);
14006 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
14009 com_err("swap_inodes", retval,
14010 _("while allocating inode buffer"));
14011 ctx->flags |= E2F_FLAG_ABORT;
14014 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14015 "block interate buffer");
14016 for (group = 0; group < fs->group_desc_count; group++) {
14017 retval = io_channel_read_blk(fs->io,
14018 fs->group_desc[group].bg_inode_table,
14019 fs->inode_blocks_per_group, buf);
14021 com_err("swap_inodes", retval,
14022 _("while reading inode table (group %d)"),
14024 ctx->flags |= E2F_FLAG_ABORT;
14027 inode = (struct ext2_inode *) buf;
14028 for (i=0; i < fs->super->s_inodes_per_group;
14029 i++, ino++, inode++) {
14030 ctx->stashed_ino = ino;
14031 ctx->stashed_inode = inode;
14033 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14034 ext2fs_swap_inode(fs, inode, inode, 0);
14037 * Skip deleted files.
14039 if (inode->i_links_count == 0)
14042 if (LINUX_S_ISDIR(inode->i_mode) ||
14043 ((inode->i_block[EXT2_IND_BLOCK] ||
14044 inode->i_block[EXT2_DIND_BLOCK] ||
14045 inode->i_block[EXT2_TIND_BLOCK]) &&
14046 ext2fs_inode_has_valid_blocks(inode)))
14047 swap_inode_blocks(ctx, ino, block_buf, inode);
14049 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14052 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14053 ext2fs_swap_inode(fs, inode, inode, 1);
14055 retval = io_channel_write_blk(fs->io,
14056 fs->group_desc[group].bg_inode_table,
14057 fs->inode_blocks_per_group, buf);
14059 com_err("swap_inodes", retval,
14060 _("while writing inode table (group %d)"),
14062 ctx->flags |= E2F_FLAG_ABORT;
14066 ext2fs_free_mem(&buf);
14067 ext2fs_free_mem(&block_buf);
14068 e2fsck_use_inode_shortcuts(ctx, 0);
14069 ext2fs_flush_icache(fs);
14072 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14074 * On the PowerPC, the big-endian variant of the ext2 filesystem
14075 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14076 * of each word. Thus a bitmap with only bit 0 set would be, as
14077 * a string of bytes, 00 00 00 01 00 ...
14078 * To cope with this, we byte-reverse each word of a bitmap if
14079 * we have a big-endian filesystem, that is, if we are *not*
14080 * byte-swapping other word-sized numbers.
14082 #define EXT2_BIG_ENDIAN_BITMAPS
14085 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14086 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14088 __u32 *p = (__u32 *) bmap->bitmap;
14089 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14091 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14092 *p = ext2fs_swab32(*p);
14097 #ifdef ENABLE_SWAPFS
14098 static void swap_filesys(e2fsck_t ctx)
14100 ext2_filsys fs = ctx->fs;
14101 #ifdef RESOURCE_TRACK
14102 struct resource_track rtrack;
14104 init_resource_track(&rtrack);
14107 if (!(ctx->options & E2F_OPT_PREEN))
14108 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14111 mtrace_print("Byte swap");
14114 if (fs->super->s_mnt_count) {
14115 fprintf(stderr, _("%s: the filesystem must be freshly "
14116 "checked using fsck\n"
14117 "and not mounted before trying to "
14118 "byte-swap it.\n"), ctx->device_name);
14119 ctx->flags |= E2F_FLAG_ABORT;
14122 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14123 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14124 EXT2_FLAG_SWAP_BYTES_WRITE);
14125 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14127 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14128 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14131 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14133 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14134 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14135 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14136 EXT2_FLAG_SWAP_BYTES_WRITE);
14138 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14139 e2fsck_read_bitmaps(ctx);
14140 ext2fs_swap_bitmap(fs->inode_map);
14141 ext2fs_swap_bitmap(fs->block_map);
14142 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14144 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14146 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14148 #ifdef RESOURCE_TRACK
14149 if (ctx->options & E2F_OPT_TIME2)
14150 print_resource_track(_("Byte swap"), &rtrack);
14153 #endif /* ENABLE_SWAPFS */
14158 * util.c --- miscellaneous utilities
14161 #ifdef HAVE_CONIO_H
14162 #undef HAVE_TERMIOS_H
14164 #define read_a_char() getch()
14166 #ifdef HAVE_TERMIOS_H
14167 #include <termios.h>
14172 void fatal_error(e2fsck_t ctx, const char *msg)
14175 fprintf (stderr, "e2fsck: %s\n", msg);
14176 if (ctx->fs && ctx->fs->io) {
14177 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14178 io_channel_flush(ctx->fs->io);
14180 fprintf(stderr, "e2fsck: io manager magic bad!\n");
14182 ctx->flags |= E2F_FLAG_ABORT;
14183 if (ctx->flags & E2F_FLAG_SETJMP_OK)
14184 longjmp(ctx->abort_loc, 1);
14189 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14190 const char *description)
14195 #ifdef DEBUG_ALLOCATE_MEMORY
14196 printf("Allocating %d bytes for %s...\n", size, description);
14198 ret = malloc(size);
14200 sprintf(buf, "Can't allocate %s\n", description);
14201 fatal_error(ctx, buf);
14203 memset(ret, 0, size);
14207 static char *string_copy(const char *str, int len)
14215 ret = malloc(len+1);
14217 strncpy(ret, str, len);
14223 #ifndef HAVE_CONIO_H
14224 static int read_a_char(void)
14231 if (e2fsck_global_ctx &&
14232 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14235 r = read(0, &c, 1);
14245 static int ask_yn(const char * string, int def)
14248 const char *defstr;
14249 static const char short_yes[] = "yY";
14250 static const char short_no[] = "nN";
14252 #ifdef HAVE_TERMIOS_H
14253 struct termios termios, tmp;
14255 tcgetattr (0, &termios);
14257 tmp.c_lflag &= ~(ICANON | ECHO);
14258 tmp.c_cc[VMIN] = 1;
14259 tmp.c_cc[VTIME] = 0;
14260 tcsetattr (0, TCSANOW, &tmp);
14269 printf("%s%s? ", string, defstr);
14272 if ((c = read_a_char()) == EOF)
14275 #ifdef HAVE_TERMIOS_H
14276 tcsetattr (0, TCSANOW, &termios);
14278 if (e2fsck_global_ctx &&
14279 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14281 longjmp(e2fsck_global_ctx->abort_loc, 1);
14283 puts(_("cancelled!\n"));
14286 if (strchr(short_yes, (char) c)) {
14290 else if (strchr(short_no, (char) c)) {
14294 else if ((c == ' ' || c == '\n') && (def != -1))
14301 #ifdef HAVE_TERMIOS_H
14302 tcsetattr (0, TCSANOW, &termios);
14307 int ask (e2fsck_t ctx, const char * string, int def)
14309 if (ctx->options & E2F_OPT_NO) {
14310 printf (_("%s? no\n\n"), string);
14313 if (ctx->options & E2F_OPT_YES) {
14314 printf (_("%s? yes\n\n"), string);
14317 if (ctx->options & E2F_OPT_PREEN) {
14318 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14321 return ask_yn(string, def);
14324 void e2fsck_read_bitmaps(e2fsck_t ctx)
14326 ext2_filsys fs = ctx->fs;
14329 if (ctx->invalid_bitmaps) {
14330 com_err(ctx->program_name, 0,
14331 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14333 fatal_error(ctx, 0);
14336 ehandler_operation(_("reading inode and block bitmaps"));
14337 retval = ext2fs_read_bitmaps(fs);
14338 ehandler_operation(0);
14340 com_err(ctx->program_name, retval,
14341 _("while retrying to read bitmaps for %s"),
14343 fatal_error(ctx, 0);
14347 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14349 ext2_filsys fs = ctx->fs;
14352 if (ext2fs_test_bb_dirty(fs)) {
14353 ehandler_operation(_("writing block bitmaps"));
14354 retval = ext2fs_write_block_bitmap(fs);
14355 ehandler_operation(0);
14357 com_err(ctx->program_name, retval,
14358 _("while retrying to write block bitmaps for %s"),
14360 fatal_error(ctx, 0);
14364 if (ext2fs_test_ib_dirty(fs)) {
14365 ehandler_operation(_("writing inode bitmaps"));
14366 retval = ext2fs_write_inode_bitmap(fs);
14367 ehandler_operation(0);
14369 com_err(ctx->program_name, retval,
14370 _("while retrying to write inode bitmaps for %s"),
14372 fatal_error(ctx, 0);
14377 void preenhalt(e2fsck_t ctx)
14379 ext2_filsys fs = ctx->fs;
14381 if (!(ctx->options & E2F_OPT_PREEN))
14383 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14384 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14387 fs->super->s_state |= EXT2_ERROR_FS;
14388 ext2fs_mark_super_dirty(fs);
14391 exit(EXIT_UNCORRECTED);
14394 #ifdef RESOURCE_TRACK
14395 void init_resource_track(struct resource_track *track)
14397 #ifdef HAVE_GETRUSAGE
14401 track->brk_start = sbrk(0);
14402 gettimeofday(&track->time_start, 0);
14403 #ifdef HAVE_GETRUSAGE
14405 memset(&r, 0, sizeof(struct rusage));
14407 getrusage(RUSAGE_SELF, &r);
14408 track->user_start = r.ru_utime;
14409 track->system_start = r.ru_stime;
14411 track->user_start.tv_sec = track->user_start.tv_usec = 0;
14412 track->system_start.tv_sec = track->system_start.tv_usec = 0;
14416 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14417 struct timeval *tv2)
14419 return ((tv1->tv_sec - tv2->tv_sec) +
14420 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14423 void print_resource_track(const char *desc, struct resource_track *track)
14425 #ifdef HAVE_GETRUSAGE
14428 #ifdef HAVE_MALLINFO
14429 struct mallinfo malloc_info;
14431 struct timeval time_end;
14433 gettimeofday(&time_end, 0);
14436 printf("%s: ", desc);
14438 #ifdef HAVE_MALLINFO
14439 #define kbytes(x) (((x) + 1023) / 1024)
14441 malloc_info = mallinfo();
14442 printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14443 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14444 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14446 printf(_("Memory used: %d, "),
14447 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14449 #ifdef HAVE_GETRUSAGE
14450 getrusage(RUSAGE_SELF, &r);
14452 printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14453 timeval_subtract(&time_end, &track->time_start),
14454 timeval_subtract(&r.ru_utime, &track->user_start),
14455 timeval_subtract(&r.ru_stime, &track->system_start));
14457 printf(_("elapsed time: %6.3f\n"),
14458 timeval_subtract(&time_end, &track->time_start));
14461 #endif /* RESOURCE_TRACK */
14463 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14464 struct ext2_inode * inode, const char *proc)
14468 retval = ext2fs_read_inode(ctx->fs, ino, inode);
14470 com_err("ext2fs_read_inode", retval,
14471 _("while reading inode %ld in %s"), ino, proc);
14472 fatal_error(ctx, 0);
14476 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14477 struct ext2_inode * inode, int bufsize,
14482 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14484 com_err("ext2fs_write_inode", retval,
14485 _("while writing inode %ld in %s"), ino, proc);
14486 fatal_error(ctx, 0);
14490 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14491 struct ext2_inode * inode, const char *proc)
14495 retval = ext2fs_write_inode(ctx->fs, ino, inode);
14497 com_err("ext2fs_write_inode", retval,
14498 _("while writing inode %ld in %s"), ino, proc);
14499 fatal_error(ctx, 0);
14504 void mtrace_print(char *mesg)
14506 FILE *malloc_get_mallstream();
14507 FILE *f = malloc_get_mallstream();
14510 fprintf(f, "============= %s\n", mesg);
14514 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14515 io_manager manager)
14517 struct ext2_super_block *sb;
14518 io_channel io = NULL;
14521 blk_t superblock, ret_sb = 8193;
14523 if (fs && fs->super) {
14524 ret_sb = (fs->super->s_blocks_per_group +
14525 fs->super->s_first_data_block);
14527 ctx->superblock = ret_sb;
14528 ctx->blocksize = fs->blocksize;
14534 if (ctx->blocksize) {
14535 ret_sb = ctx->blocksize * 8;
14536 if (ctx->blocksize == 1024)
14538 ctx->superblock = ret_sb;
14541 ctx->superblock = ret_sb;
14542 ctx->blocksize = 1024;
14545 if (!name || !manager)
14548 if (manager->open(name, 0, &io) != 0)
14551 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14553 sb = (struct ext2_super_block *) buf;
14555 for (blocksize = EXT2_MIN_BLOCK_SIZE;
14556 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14557 superblock = blocksize*8;
14558 if (blocksize == 1024)
14560 io_channel_set_blksize(io, blocksize);
14561 if (io_channel_read_blk(io, superblock,
14562 -SUPERBLOCK_SIZE, buf))
14564 #ifdef EXT2FS_ENABLE_SWAPFS
14565 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14566 ext2fs_swap_super(sb);
14568 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14569 ret_sb = superblock;
14571 ctx->superblock = superblock;
14572 ctx->blocksize = blocksize;
14580 io_channel_close(io);
14581 ext2fs_free_mem(&buf);
14587 * This function runs through the e2fsck passes and calls them all,
14588 * returning restart, abort, or cancel as necessary...
14590 typedef void (*pass_t)(e2fsck_t ctx);
14592 static const pass_t e2fsck_passes[] = {
14593 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14596 #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14598 static int e2fsck_run(e2fsck_t ctx)
14601 pass_t e2fsck_pass;
14603 if (setjmp(ctx->abort_loc)) {
14604 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14605 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14607 ctx->flags |= E2F_FLAG_SETJMP_OK;
14609 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14610 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14614 (void) (ctx->progress)(ctx, 0, 0, 0);
14616 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14618 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14619 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14625 * unix.c - The unix-specific code for e2fsck
14629 /* Command line options */
14631 #ifdef ENABLE_SWAPFS
14632 static int normalize_swapfs;
14634 static int cflag; /* check disk */
14635 static int show_version_only;
14636 static int verbose;
14638 static int replace_bad_blocks;
14639 static int keep_bad_blocks;
14640 static char *bad_blocks_file;
14642 #ifdef __CONFIG_JBD_DEBUG__E2FS /* Enabled by configure --enable-jfs-debug */
14643 int journal_enable_debug = -1;
14647 static void usage(e2fsck_t ctx)
14650 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14651 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14652 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
14653 "\t\t[-E extended-options] device\n"),
14654 ctx->program_name);
14656 fprintf(stderr, _("\nEmergency help:\n"
14657 " -p Automatic repair (no questions)\n"
14658 " -n Make no changes to the filesystem\n"
14659 " -y Assume \"yes\" to all questions\n"
14660 " -c Check for bad blocks and add them to the badblock list\n"
14661 " -f Force checking even if filesystem is marked clean\n"));
14662 fprintf(stderr, _(""
14664 " -b superblock Use alternative superblock\n"
14665 " -B blocksize Force blocksize when looking for superblock\n"
14666 " -j external_journal Set location of the external journal\n"
14667 " -l bad_blocks_file Add to badblocks list\n"
14668 " -L bad_blocks_file Set badblocks list\n"
14675 #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
14677 static void show_stats(e2fsck_t ctx)
14679 ext2_filsys fs = ctx->fs;
14680 int inodes, inodes_used, blocks, blocks_used;
14682 int num_files, num_links;
14685 dir_links = 2 * ctx->fs_directory_count - 1;
14686 num_files = ctx->fs_total_count - dir_links;
14687 num_links = ctx->fs_links_count - dir_links;
14688 inodes = fs->super->s_inodes_count;
14689 inodes_used = (fs->super->s_inodes_count -
14690 fs->super->s_free_inodes_count);
14691 blocks = fs->super->s_blocks_count;
14692 blocks_used = (fs->super->s_blocks_count -
14693 fs->super->s_free_blocks_count);
14695 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14696 frag_percent = (frag_percent + 5) / 10;
14699 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14700 ctx->device_name, inodes_used, inodes,
14701 frag_percent / 10, frag_percent % 10,
14702 blocks_used, blocks);
14705 printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14706 100 * inodes_used / inodes);
14707 printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14708 P_E2("", "s", ctx->fs_fragmented),
14709 frag_percent / 10, frag_percent % 10);
14710 printf (_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14711 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14712 printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14713 (int) ((long long) 100 * blocks_used / blocks));
14714 printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14715 printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14716 printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14717 printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14718 printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14719 printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14720 printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14721 printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14722 printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14723 printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14724 printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14725 printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14728 static void check_mount(e2fsck_t ctx)
14733 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14734 &ctx->mount_flags);
14736 com_err("ext2fs_check_if_mount", retval,
14737 _("while determining whether %s is mounted."),
14738 ctx->filesystem_name);
14743 * If the filesystem isn't mounted, or it's the root filesystem
14744 * and it's mounted read-only, then everything's fine.
14746 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14747 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14748 (ctx->mount_flags & EXT2_MF_READONLY)))
14751 if (ctx->options & E2F_OPT_READONLY) {
14752 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
14756 printf(_("%s is mounted. "), ctx->filesystem_name);
14757 if (!ctx->interactive)
14758 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14759 printf(_("\n\n\007\007\007\007WARNING!!! "
14760 "Running e2fsck on a mounted filesystem may cause\n"
14761 "SEVERE filesystem damage.\007\007\007\n\n"));
14762 cont = ask_yn(_("Do you really want to continue"), -1);
14764 printf (_("check aborted.\n"));
14770 static int is_on_batt(void)
14774 char tmp[80], tmp2[80], fname[80];
14775 unsigned int acflag;
14778 f = fopen("/proc/apm", "r");
14780 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14783 return (acflag != 1);
14785 d = opendir("/proc/acpi/ac_adapter");
14787 while ((de=readdir(d)) != NULL) {
14788 if (!strncmp(".", de->d_name, 1))
14790 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14792 f = fopen(fname, "r");
14795 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14798 if (strncmp(tmp, "off-line", 8) == 0) {
14809 * This routine checks to see if a filesystem can be skipped; if so,
14810 * it will exit with EXIT_OK. Under some conditions it will print a
14811 * message explaining why a check is being forced.
14813 static void check_if_skip(e2fsck_t ctx)
14815 ext2_filsys fs = ctx->fs;
14816 const char *reason = NULL;
14817 unsigned int reason_arg = 0;
14819 int batt = is_on_batt();
14820 time_t now = time(0);
14822 if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14826 if ((fs->super->s_state & EXT2_ERROR_FS) ||
14827 !ext2fs_test_valid(fs))
14828 reason = _(" contains a file system with errors");
14829 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14830 reason = _(" was not cleanly unmounted");
14831 else if ((fs->super->s_max_mnt_count > 0) &&
14832 (fs->super->s_mnt_count >=
14833 (unsigned) fs->super->s_max_mnt_count)) {
14834 reason = _(" has been mounted %u times without being checked");
14835 reason_arg = fs->super->s_mnt_count;
14836 if (batt && (fs->super->s_mnt_count <
14837 (unsigned) fs->super->s_max_mnt_count*2))
14839 } else if (fs->super->s_checkinterval &&
14840 ((now - fs->super->s_lastcheck) >=
14841 fs->super->s_checkinterval)) {
14842 reason = _(" has gone %u days without being checked");
14843 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14844 if (batt && ((now - fs->super->s_lastcheck) <
14845 fs->super->s_checkinterval*2))
14849 fputs(ctx->device_name, stdout);
14850 printf(reason, reason_arg);
14851 fputs(_(", check forced.\n"), stdout);
14854 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14855 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14856 fs->super->s_inodes_count,
14857 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14858 fs->super->s_blocks_count);
14859 next_check = 100000;
14860 if (fs->super->s_max_mnt_count > 0) {
14861 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14862 if (next_check <= 0)
14865 if (fs->super->s_checkinterval &&
14866 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14868 if (next_check <= 5) {
14869 if (next_check == 1)
14870 fputs(_(" (check after next mount)"), stdout);
14872 printf(_(" (check in %ld mounts)"), next_check);
14874 fputc('\n', stdout);
14877 e2fsck_free_context(ctx);
14882 * For completion notice
14884 struct percent_tbl {
14888 static const struct percent_tbl e2fsck_tbl = {
14889 5, { 0, 70, 90, 92, 95, 100 }
14892 static char bar[128], spaces[128];
14894 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14901 if (pass > tbl->max_pass || max == 0)
14903 percent = ((float) curr) / ((float) max);
14904 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14905 + tbl->table[pass-1]);
14908 void e2fsck_clear_progbar(e2fsck_t ctx)
14910 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14913 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14916 ctx->flags &= ~E2F_FLAG_PROG_BAR;
14919 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14920 unsigned int dpynum)
14922 static const char spinner[] = "\\|/-";
14929 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14933 * Calculate the new progress position. If the
14934 * percentage hasn't changed, then we skip out right
14937 fixed_percent = (int) ((10 * percent) + 0.5);
14938 if (ctx->progress_last_percent == fixed_percent)
14940 ctx->progress_last_percent = fixed_percent;
14943 * If we've already updated the spinner once within
14944 * the last 1/8th of a second, no point doing it
14947 gettimeofday(&tv, NULL);
14948 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
14949 if ((tick == ctx->progress_last_time) &&
14950 (fixed_percent != 0) && (fixed_percent != 1000))
14952 ctx->progress_last_time = tick;
14955 * Advance the spinner, and note that the progress bar
14956 * will be on the screen
14958 ctx->progress_pos = (ctx->progress_pos+1) & 3;
14959 ctx->flags |= E2F_FLAG_PROG_BAR;
14961 dpywidth = 66 - strlen(label);
14962 dpywidth = 8 * (dpywidth / 8);
14966 i = ((percent * dpywidth) + 50) / 100;
14967 printf("%s%s: |%s%s", ctx->start_meta, label,
14968 bar + (sizeof(bar) - (i+1)),
14969 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
14970 if (fixed_percent == 1000)
14971 fputc('|', stdout);
14973 fputc(spinner[ctx->progress_pos & 3], stdout);
14974 printf(" %4.1f%% ", percent);
14976 printf("%u\r", dpynum);
14978 fputs(" \r", stdout);
14979 fputs(ctx->stop_meta, stdout);
14981 if (fixed_percent == 1000)
14982 e2fsck_clear_progbar(ctx);
14988 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
14989 unsigned long cur, unsigned long max)
14997 if (ctx->progress_fd) {
14998 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
14999 write(ctx->progress_fd, buf, strlen(buf));
15001 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
15002 e2fsck_simple_progress(ctx, ctx->device_name,
15008 static void reserve_stdio_fds(void)
15013 fd = open(bb_dev_null, O_RDWR);
15017 fprintf(stderr, _("ERROR: Couldn't open "
15018 "/dev/null (%s)\n"),
15026 static void signal_progress_on(int sig FSCK_ATTR((unused)))
15028 e2fsck_t ctx = e2fsck_global_ctx;
15033 ctx->progress = e2fsck_update_progress;
15034 ctx->progress_fd = 0;
15037 static void signal_progress_off(int sig FSCK_ATTR((unused)))
15039 e2fsck_t ctx = e2fsck_global_ctx;
15044 e2fsck_clear_progbar(ctx);
15048 static void signal_cancel(int sig FSCK_ATTR((unused)))
15050 e2fsck_t ctx = e2fsck_global_ctx;
15053 exit(FSCK_CANCELED);
15055 ctx->flags |= E2F_FLAG_CANCEL;
15058 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15060 char *buf, *token, *next, *p, *arg;
15062 int extended_usage = 0;
15064 buf = string_copy(opts, 0);
15065 for (token = buf; token && *token; token = next) {
15066 p = strchr(token, ',');
15072 arg = strchr(token, '=');
15077 if (strcmp(token, "ea_ver") == 0) {
15082 ea_ver = strtoul(arg, &p, 0);
15084 ((ea_ver != 1) && (ea_ver != 2))) {
15086 _("Invalid EA version.\n"));
15090 ctx->ext_attr_ver = ea_ver;
15092 fprintf(stderr, _("Unknown extended option: %s\n"),
15097 if (extended_usage) {
15098 bb_error_msg_and_die(
15099 "Extended options are separated by commas, "
15100 "and may take an argument which\n"
15101 "is set off by an equals ('=') sign. "
15102 "Valid extended options are:\n"
15103 "\tea_ver=<ea_version (1 or 2)>\n\n");
15108 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15113 extern void *mallwatch;
15117 struct sigaction sa;
15118 char *extended_opts = 0;
15120 retval = e2fsck_allocate_context(&ctx);
15126 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15127 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15128 if (isatty(0) && isatty(1)) {
15129 ctx->interactive = 1;
15131 ctx->start_meta[0] = '\001';
15132 ctx->stop_meta[0] = '\002';
15134 memset(bar, '=', sizeof(bar)-1);
15135 memset(spaces, ' ', sizeof(spaces)-1);
15136 blkid_get_cache(&ctx->blkid, NULL);
15139 ctx->program_name = *argv;
15141 ctx->program_name = "e2fsck";
15142 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15145 ctx->progress = e2fsck_update_progress;
15146 ctx->progress_fd = atoi(optarg);
15147 if (!ctx->progress_fd)
15149 /* Validate the file descriptor to avoid disasters */
15150 fd = dup(ctx->progress_fd);
15153 _("Error validating file descriptor %d: %s\n"),
15155 error_message(errno));
15157 _("Invalid completion information file descriptor"));
15162 ctx->options |= E2F_OPT_COMPRESS_DIRS;
15165 extended_opts = optarg;
15169 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15172 _("Only one the options -p/-a, -n or -y may be specified."));
15174 ctx->options |= E2F_OPT_PREEN;
15177 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15179 ctx->options |= E2F_OPT_NO;
15182 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15184 ctx->options |= E2F_OPT_YES;
15187 #ifdef RESOURCE_TRACK
15188 if (ctx->options & E2F_OPT_TIME)
15189 ctx->options |= E2F_OPT_TIME2;
15191 ctx->options |= E2F_OPT_TIME;
15193 fprintf(stderr, _("The -t option is not "
15194 "supported on this version of e2fsck.\n"));
15199 ctx->options |= E2F_OPT_WRITECHECK;
15200 ctx->options |= E2F_OPT_CHECKBLOCKS;
15203 /* What we do by default, anyway! */
15206 ctx->use_superblock = atoi(optarg);
15207 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15210 ctx->blocksize = atoi(optarg);
15213 ctx->inode_buffer_blocks = atoi(optarg);
15216 ctx->journal_name = string_copy(optarg, 0);
15219 ctx->process_inode_size = atoi(optarg);
15222 replace_bad_blocks++;
15224 bad_blocks_file = string_copy(optarg, 0);
15227 ctx->options |= E2F_OPT_DEBUG;
15230 ctx->options |= E2F_OPT_FORCE;
15239 show_version_only = 1;
15243 mallwatch = (void *) strtol(optarg, NULL, 0);
15247 ctx->device_name = optarg;
15249 #ifdef ENABLE_SWAPFS
15251 normalize_swapfs = 1;
15258 fprintf(stderr, _("Byte-swapping filesystems "
15259 "not compiled in this version "
15269 if (show_version_only)
15271 if (optind != argc - 1)
15273 if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15274 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15275 ctx->options |= E2F_OPT_READONLY;
15276 ctx->io_options = strchr(argv[optind], '?');
15277 if (ctx->io_options)
15278 *ctx->io_options++ = 0;
15279 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15280 if (!ctx->filesystem_name) {
15281 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15283 fatal_error(ctx, 0);
15286 parse_extended_opts(ctx, extended_opts);
15289 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15291 com_err("open", errno,
15292 _("while opening %s for flushing"),
15293 ctx->filesystem_name);
15294 fatal_error(ctx, 0);
15296 if ((retval = ext2fs_sync_device(fd, 1))) {
15297 com_err("ext2fs_sync_device", retval,
15298 _("while trying to flush %s"),
15299 ctx->filesystem_name);
15300 fatal_error(ctx, 0);
15304 #ifdef ENABLE_SWAPFS
15306 if (cflag || bad_blocks_file) {
15307 fprintf(stderr, _("Incompatible options not "
15308 "allowed when byte-swapping.\n"));
15313 if (cflag && bad_blocks_file) {
15314 fprintf(stderr, _("The -c and the -l/-L options may "
15315 "not be both used at the same time.\n"));
15319 * Set up signal action
15321 memset(&sa, 0, sizeof(struct sigaction));
15322 sa.sa_handler = signal_cancel;
15323 sigaction(SIGINT, &sa, 0);
15324 sigaction(SIGTERM, &sa, 0);
15326 sa.sa_flags = SA_RESTART;
15328 e2fsck_global_ctx = ctx;
15329 sa.sa_handler = signal_progress_on;
15330 sigaction(SIGUSR1, &sa, 0);
15331 sa.sa_handler = signal_progress_off;
15332 sigaction(SIGUSR2, &sa, 0);
15334 /* Update our PATH to include /sbin if we need to run badblocks */
15336 e2fs_set_sbin_path();
15337 #ifdef __CONFIG_JBD_DEBUG__E2FS
15338 if (getenv("E2FSCK_JBD_DEBUG"))
15339 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15344 static const char my_ver_string[] = E2FSPROGS_VERSION;
15345 static const char my_ver_date[] = E2FSPROGS_DATE;
15347 int e2fsck_main (int argc, char *argv[])
15350 int exit_value = EXIT_OK;
15351 ext2_filsys fs = 0;
15353 struct ext2_super_block *sb;
15354 const char *lib_ver_date;
15355 int my_ver, lib_ver;
15357 struct problem_context pctx;
15358 int flags, run_result;
15360 clear_problem_context(&pctx);
15368 setlocale(LC_MESSAGES, "");
15369 setlocale(LC_CTYPE, "");
15370 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15371 textdomain(NLS_CAT_NAME);
15373 my_ver = ext2fs_parse_version_string(my_ver_string);
15374 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15375 if (my_ver > lib_ver) {
15376 fprintf( stderr, _("Error: ext2fs library version "
15377 "out of date!\n"));
15378 show_version_only++;
15381 retval = PRS(argc, argv, &ctx);
15383 com_err("e2fsck", retval,
15384 _("while trying to initialize program"));
15387 reserve_stdio_fds();
15389 #ifdef RESOURCE_TRACK
15390 init_resource_track(&ctx->global_rtrack);
15393 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15394 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15397 if (show_version_only) {
15398 fprintf(stderr, _("\tUsing %s, %s\n"),
15399 error_message(EXT2_ET_BASE), lib_ver_date);
15405 if (!(ctx->options & E2F_OPT_PREEN) &&
15406 !(ctx->options & E2F_OPT_NO) &&
15407 !(ctx->options & E2F_OPT_YES)) {
15408 if (!ctx->interactive)
15410 _("need terminal for interactive repairs"));
15412 ctx->superblock = ctx->use_superblock;
15414 #ifdef CONFIG_TESTIO_DEBUG
15415 io_ptr = test_io_manager;
15416 test_io_backing_manager = unix_io_manager;
15418 io_ptr = unix_io_manager;
15421 if ((ctx->options & E2F_OPT_READONLY) == 0)
15422 flags |= EXT2_FLAG_RW;
15424 if (ctx->superblock && ctx->blocksize) {
15425 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15426 flags, ctx->superblock, ctx->blocksize,
15428 } else if (ctx->superblock) {
15430 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15431 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15432 retval = ext2fs_open2(ctx->filesystem_name,
15433 ctx->io_options, flags,
15434 ctx->superblock, blocksize,
15440 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15441 flags, 0, 0, io_ptr, &fs);
15442 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15443 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15444 ((retval == EXT2_ET_BAD_MAGIC) ||
15445 ((retval == 0) && ext2fs_check_desc(fs)))) {
15446 if (!fs || (fs->group_desc_count > 1)) {
15447 printf(_("%s trying backup blocks...\n"),
15448 retval ? _("Couldn't find ext2 superblock,") :
15449 _("Group descriptors look bad..."));
15450 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15457 com_err(ctx->program_name, retval, _("while trying to open %s"),
15458 ctx->filesystem_name);
15459 if (retval == EXT2_ET_REV_TOO_HIGH) {
15460 printf(_("The filesystem revision is apparently "
15461 "too high for this version of e2fsck.\n"
15462 "(Or the filesystem superblock "
15463 "is corrupt)\n\n"));
15464 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15465 } else if (retval == EXT2_ET_SHORT_READ)
15466 printf(_("Could this be a zero-length partition?\n"));
15467 else if ((retval == EPERM) || (retval == EACCES))
15468 printf(_("You must have %s access to the "
15469 "filesystem or be root\n"),
15470 (ctx->options & E2F_OPT_READONLY) ?
15472 else if (retval == ENXIO)
15473 printf(_("Possibly non-existent or swap device?\n"));
15475 else if (retval == EROFS)
15476 printf(_("Disk write-protected; use the -n option "
15477 "to do a read-only\n"
15478 "check of the device.\n"));
15481 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15482 fatal_error(ctx, 0);
15485 fs->priv_data = ctx;
15487 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15488 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15489 _("while trying to open %s"),
15490 ctx->filesystem_name);
15492 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15496 * Set the device name, which is used whenever we print error
15497 * or informational messages to the user.
15499 if (ctx->device_name == 0 &&
15500 (sb->s_volume_name[0] != 0)) {
15501 ctx->device_name = string_copy(sb->s_volume_name,
15502 sizeof(sb->s_volume_name));
15504 if (ctx->device_name == 0)
15505 ctx->device_name = ctx->filesystem_name;
15508 * Make sure the ext3 superblock fields are consistent.
15510 retval = e2fsck_check_ext3_journal(ctx);
15512 com_err(ctx->program_name, retval,
15513 _("while checking ext3 journal for %s"),
15515 fatal_error(ctx, 0);
15519 * Check to see if we need to do ext3-style recovery. If so,
15520 * do it, and then restart the fsck.
15522 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15523 if (ctx->options & E2F_OPT_READONLY) {
15524 printf(_("Warning: skipping journal recovery "
15525 "because doing a read-only filesystem "
15527 io_channel_flush(ctx->fs->io);
15529 if (ctx->flags & E2F_FLAG_RESTARTED) {
15531 * Whoops, we attempted to run the
15532 * journal twice. This should never
15533 * happen, unless the hardware or
15534 * device driver is being bogus.
15536 com_err(ctx->program_name, 0,
15537 _("unable to set superblock flags on %s\n"), ctx->device_name);
15538 fatal_error(ctx, 0);
15540 retval = e2fsck_run_ext3_journal(ctx);
15542 com_err(ctx->program_name, retval,
15543 _("while recovering ext3 journal of %s"),
15545 fatal_error(ctx, 0);
15547 ext2fs_close(ctx->fs);
15549 ctx->flags |= E2F_FLAG_RESTARTED;
15555 * Check for compatibility with the feature sets. We need to
15556 * be more stringent than ext2fs_open().
15558 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15559 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15560 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15561 "(%s)", ctx->device_name);
15564 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15565 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15566 "(%s)", ctx->device_name);
15569 #ifdef ENABLE_COMPRESSION
15570 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15571 com_err(ctx->program_name, 0,
15572 _("Warning: compression support is experimental.\n"));
15574 #ifndef ENABLE_HTREE
15575 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15576 com_err(ctx->program_name, 0,
15577 _("E2fsck not compiled with HTREE support,\n\t"
15578 "but filesystem %s has HTREE directories.\n"),
15585 * If the user specified a specific superblock, presumably the
15586 * master superblock has been trashed. So we mark the
15587 * superblock as dirty, so it can be written out.
15589 if (ctx->superblock &&
15590 !(ctx->options & E2F_OPT_READONLY))
15591 ext2fs_mark_super_dirty(fs);
15594 * We only update the master superblock because (a) paranoia;
15595 * we don't want to corrupt the backup superblocks, and (b) we
15596 * don't need to update the mount count and last checked
15597 * fields in the backup superblock (the kernel doesn't
15598 * update the backup superblocks anyway).
15600 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15602 ehandler_init(fs->io);
15604 if (ctx->superblock)
15605 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15606 ext2fs_mark_valid(fs);
15607 check_super_block(ctx);
15608 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15609 fatal_error(ctx, 0);
15610 check_if_skip(ctx);
15611 if (bad_blocks_file)
15612 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15614 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15615 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15616 fatal_error(ctx, 0);
15617 #ifdef ENABLE_SWAPFS
15619 #ifdef WORDS_BIGENDIAN
15620 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
15622 #define NATIVE_FLAG 0
15626 if (normalize_swapfs) {
15627 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
15628 fprintf(stderr, _("%s: Filesystem byte order "
15629 "already normalized.\n"), ctx->device_name);
15630 fatal_error(ctx, 0);
15635 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15636 fatal_error(ctx, 0);
15641 * Mark the system as valid, 'til proven otherwise
15643 ext2fs_mark_valid(fs);
15645 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15647 com_err(ctx->program_name, retval,
15648 _("while reading bad blocks inode"));
15650 printf(_("This doesn't bode well,"
15651 " but we'll try to go on...\n"));
15654 run_result = e2fsck_run(ctx);
15655 e2fsck_clear_progbar(ctx);
15656 if (run_result == E2F_FLAG_RESTART) {
15657 printf(_("Restarting e2fsck from the beginning...\n"));
15658 retval = e2fsck_reset_context(ctx);
15660 com_err(ctx->program_name, retval,
15661 _("while resetting context"));
15662 fatal_error(ctx, 0);
15667 if (run_result & E2F_FLAG_CANCEL) {
15668 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15669 ctx->device_name : ctx->filesystem_name);
15670 exit_value |= FSCK_CANCELED;
15672 if (run_result & E2F_FLAG_ABORT)
15673 fatal_error(ctx, _("aborted"));
15676 mtrace_print("Cleanup");
15678 if (ext2fs_test_changed(fs)) {
15679 exit_value |= EXIT_NONDESTRUCT;
15680 if (!(ctx->options & E2F_OPT_PREEN))
15681 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15683 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15684 printf(_("%s: ***** REBOOT LINUX *****\n"),
15686 exit_value |= EXIT_DESTRUCT;
15689 if (!ext2fs_test_valid(fs)) {
15690 printf(_("\n%s: ********** WARNING: Filesystem still has "
15691 "errors **********\n\n"), ctx->device_name);
15692 exit_value |= EXIT_UNCORRECTED;
15693 exit_value &= ~EXIT_NONDESTRUCT;
15695 if (exit_value & FSCK_CANCELED)
15696 exit_value &= ~EXIT_NONDESTRUCT;
15699 if (!(ctx->options & E2F_OPT_READONLY)) {
15700 if (ext2fs_test_valid(fs)) {
15701 if (!(sb->s_state & EXT2_VALID_FS))
15702 exit_value |= EXIT_NONDESTRUCT;
15703 sb->s_state = EXT2_VALID_FS;
15705 sb->s_state &= ~EXT2_VALID_FS;
15706 sb->s_mnt_count = 0;
15707 sb->s_lastcheck = time(NULL);
15708 ext2fs_mark_super_dirty(fs);
15712 e2fsck_write_bitmaps(ctx);
15716 free(ctx->filesystem_name);
15717 free(ctx->journal_name);
15718 e2fsck_free_context(ctx);
15720 #ifdef RESOURCE_TRACK
15721 if (ctx->options & E2F_OPT_TIME)
15722 print_resource_track(NULL, &ctx->global_rtrack);