1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* pass2.c --- check directory structure
|
2008-08-28 07:07:54 +04:00
|
|
|
*
|
1997-04-29 20:15:03 +04:00
|
|
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
|
|
|
|
*
|
|
|
|
* %Begin-Header%
|
|
|
|
* This file may be redistributed under the terms of the GNU Public
|
|
|
|
* License.
|
|
|
|
* %End-Header%
|
2008-08-28 07:07:54 +04:00
|
|
|
*
|
1997-04-26 17:21:57 +04:00
|
|
|
* Pass 2 of e2fsck iterates through all active directory inodes, and
|
|
|
|
* applies to following tests to each directory entry in the directory
|
|
|
|
* blocks in the inodes:
|
|
|
|
*
|
|
|
|
* - The length of the directory entry (rec_len) should be at
|
|
|
|
* least 8 bytes, and no more than the remaining space
|
|
|
|
* left in the directory block.
|
|
|
|
* - The length of the name in the directory entry (name_len)
|
2008-08-28 07:07:54 +04:00
|
|
|
* should be less than (rec_len - 8).
|
1997-04-26 17:21:57 +04:00
|
|
|
* - The inode number in the directory entry should be within
|
|
|
|
* legal bounds.
|
|
|
|
* - The inode number should refer to a in-use inode.
|
|
|
|
* - The first entry should be '.', and its inode should be
|
|
|
|
* the inode of the directory.
|
|
|
|
* - The second entry should be '..'.
|
|
|
|
*
|
|
|
|
* To minimize disk seek time, the directory blocks are processed in
|
|
|
|
* sorted order of block numbers.
|
|
|
|
*
|
|
|
|
* Pass 2 also collects the following information:
|
|
|
|
* - The inode numbers of the subdirectories for each directory.
|
|
|
|
*
|
|
|
|
* Pass 2 relies on the following information from previous passes:
|
|
|
|
* - The directory information collected in pass 1.
|
|
|
|
* - The inode_used_map bitmap
|
|
|
|
* - The inode_bad_map bitmap
|
|
|
|
* - The inode_dir_map bitmap
|
|
|
|
*
|
|
|
|
* Pass 2 frees the following data structures
|
|
|
|
* - The inode_bad_map bitmap
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
* - The inode_reg_map bitmap
|
1997-04-26 17:21:57 +04:00
|
|
|
*/
|
|
|
|
|
2003-12-28 15:04:35 +03:00
|
|
|
#define _GNU_SOURCE 1 /* get strnlen() */
|
2011-09-19 01:34:37 +04:00
|
|
|
#include "config.h"
|
2003-07-06 08:36:48 +04:00
|
|
|
#include <string.h>
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
#include "e2fsck.h"
|
1997-04-29 20:15:03 +04:00
|
|
|
#include "problem.h"
|
2015-07-13 05:43:31 +03:00
|
|
|
#include "support/dict.h"
|
1997-04-26 17:21:57 +04:00
|
|
|
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
#ifdef NO_INLINE_FUNCS
|
|
|
|
#define _INLINE_
|
|
|
|
#else
|
|
|
|
#define _INLINE_ inline
|
|
|
|
#endif
|
|
|
|
|
2002-09-30 19:19:19 +04:00
|
|
|
/* #define DX_DEBUG */
|
2002-06-26 07:26:34 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Keeps track of how many times an inode is referenced.
|
|
|
|
*/
|
2001-01-12 23:25:50 +03:00
|
|
|
static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
|
2015-04-21 05:27:19 +03:00
|
|
|
static int check_dir_block2(ext2_filsys fs,
|
|
|
|
struct ext2_db_entry2 *dir_blocks_info,
|
|
|
|
void *priv_data);
|
1997-04-26 17:21:57 +04:00
|
|
|
static int check_dir_block(ext2_filsys fs,
|
2010-06-14 01:00:00 +04:00
|
|
|
struct ext2_db_entry2 *dir_blocks_info,
|
Many files:
e2fsck.h: If EXT2_FLAT_INCLUDES is defined, then assume all of
the ext2-specific header files are in a flat directory.
dirinfo.c, ehandler.c, pass1.c, pass1b.c, pass2.c, pass5.c,
super.c, swapfs.c, unix.c: Explicitly cast all assignments
from void * to be compatible with C++.
unix.c (sync_disk): Remove sync_disk and calls to that function,
since ext2fs_close() now takes care of this.
pass1.c, pass1b.c, pass2.c, pass3.c, swapfs, badblocks.c,
ehandler.c, unix.c: Change use of private to be priv_data, to
avoid C++ reserved name clash.
1998-01-19 17:50:49 +03:00
|
|
|
void *priv_data);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
static int allocate_dir_block(e2fsck_t ctx,
|
2010-06-14 01:00:00 +04:00
|
|
|
struct ext2_db_entry2 *dir_blocks_info,
|
1997-04-29 20:15:03 +04:00
|
|
|
char *buf, struct problem_context *pctx);
|
2002-06-26 07:26:34 +04:00
|
|
|
static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
|
2002-09-30 19:19:19 +04:00
|
|
|
static int htree_depth(struct dx_dir_info *dx_dir,
|
|
|
|
struct dx_dirblock_info *dx_db);
|
2002-08-31 10:32:41 +04:00
|
|
|
static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
|
1997-04-26 17:21:57 +04:00
|
|
|
|
1997-04-29 20:15:03 +04:00
|
|
|
struct check_dir_struct {
|
|
|
|
char *buf;
|
|
|
|
struct problem_context pctx;
|
Many files:
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c: Add calls to the progress
indicator function.
pass1.c (scan_callback): Add call to the progress feedback function
(if it exists).
super.c (check_super_block): Skip the device size check if the
get_device_size returns EXT2_EXT_UNIMPLEMENTED.
iscan.c (main): Don't use fatal_error() anymore.
pass1b.c, swapfs.c, badblocks.c: Set E2F_FLAG_ABORT instead of calling
fatal_error(0).
problem.c, pass3.c (PR_3_ROOT_NOT_DIR_ABORT,
PR_3_NO_ROOT_INODE_ABORT): New problem codes.
problem.c, pass2.c (PR_2_SPLIT_DOT): New problem code.
problem.c, pass1.c (PR_1_SUPPRESS_MESSAGES): New problem code.
problemP.h: New file which separates out the private fix_problem data
structures.
util.c, dirinfo.c, pass1.c, pass1b.c, pass2.c, pass5.c, super.c,
swapfs.c util.c: allocate_memory() now takes a e2fsck context as its
first argument, and rename it to be e2fsck_allocate_memory().
problemP.h:
New file which contains the private problem abstraction definitions.
Makefile.pq:
Remove include of MAKEFILE.STD, which doesn't exist at this point.
1997-11-14 08:23:04 +03:00
|
|
|
int count, max;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
e2fsck_t ctx;
|
2015-04-21 05:27:19 +03:00
|
|
|
unsigned long long list_offset;
|
|
|
|
unsigned long long ra_entries;
|
|
|
|
unsigned long long next_ra_off;
|
2008-08-28 07:07:54 +04:00
|
|
|
};
|
1997-04-29 20:15:03 +04:00
|
|
|
|
1997-11-03 22:42:40 +03:00
|
|
|
void e2fsck_pass2(e2fsck_t ctx)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2001-08-09 12:14:04 +04:00
|
|
|
struct ext2_super_block *sb = ctx->fs->super;
|
|
|
|
struct problem_context pctx;
|
|
|
|
ext2_filsys fs = ctx->fs;
|
|
|
|
char *buf;
|
1997-10-20 05:38:32 +04:00
|
|
|
#ifdef RESOURCE_TRACK
|
1997-04-26 17:21:57 +04:00
|
|
|
struct resource_track rtrack;
|
1997-10-20 05:38:32 +04:00
|
|
|
#endif
|
1997-04-29 20:15:03 +04:00
|
|
|
struct check_dir_struct cd;
|
2002-06-26 07:26:34 +04:00
|
|
|
struct dx_dir_info *dx_dir;
|
|
|
|
struct dx_dirblock_info *dx_db, *dx_parent;
|
2003-12-07 09:28:50 +03:00
|
|
|
int b;
|
2002-09-30 19:19:19 +04:00
|
|
|
int i, depth;
|
2002-06-26 07:26:34 +04:00
|
|
|
problem_t code;
|
|
|
|
int bad_dir;
|
2015-04-21 05:27:19 +03:00
|
|
|
int (*check_dir_func)(ext2_filsys fs,
|
|
|
|
struct ext2_db_entry2 *dir_blocks_info,
|
|
|
|
void *priv_data);
|
2002-06-26 07:26:34 +04:00
|
|
|
|
2007-08-04 04:07:09 +04:00
|
|
|
init_resource_track(&rtrack, ctx->fs->io);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
clear_problem_context(&cd.pctx);
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
#ifdef MTRACE
|
|
|
|
mtrace_print("Pass 2");
|
|
|
|
#endif
|
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (!(ctx->options & E2F_OPT_PREEN))
|
|
|
|
fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
|
|
|
|
|
2016-05-30 03:48:54 +03:00
|
|
|
cd.pctx.errcode = e2fsck_setup_icount(ctx, "inode_count",
|
|
|
|
EXT2_ICOUNT_OPT_INCREMENT,
|
|
|
|
ctx->inode_link_info, &ctx->inode_count);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (cd.pctx.errcode) {
|
|
|
|
fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
|
1997-11-03 22:42:40 +03:00
|
|
|
ctx->flags |= E2F_FLAG_ABORT;
|
|
|
|
return;
|
1997-04-29 20:15:03 +04:00
|
|
|
}
|
2002-05-21 17:14:17 +04:00
|
|
|
buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
|
Many files:
e2fsck.h: If EXT2_FLAT_INCLUDES is defined, then assume all of
the ext2-specific header files are in a flat directory.
dirinfo.c, ehandler.c, pass1.c, pass1b.c, pass2.c, pass5.c,
super.c, swapfs.c, unix.c: Explicitly cast all assignments
from void * to be compatible with C++.
unix.c (sync_disk): Remove sync_disk and calls to that function,
since ext2fs_close() now takes care of this.
pass1.c, pass1b.c, pass2.c, pass3.c, swapfs, badblocks.c,
ehandler.c, unix.c: Change use of private to be priv_data, to
avoid C++ reserved name clash.
1998-01-19 17:50:49 +03:00
|
|
|
"directory scan buffer");
|
1997-04-26 17:21:57 +04:00
|
|
|
|
1997-04-29 20:15:03 +04:00
|
|
|
/*
|
|
|
|
* Set up the parent pointer for the root directory, if
|
|
|
|
* present. (If the root directory is not present, we will
|
|
|
|
* create it in pass 3.)
|
|
|
|
*/
|
2007-04-05 06:33:31 +04:00
|
|
|
(void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
|
1997-04-29 20:15:03 +04:00
|
|
|
|
|
|
|
cd.buf = buf;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
cd.ctx = ctx;
|
1998-08-01 08:18:06 +04:00
|
|
|
cd.count = 1;
|
2010-06-14 01:00:00 +04:00
|
|
|
cd.max = ext2fs_dblist_count2(fs->dblist);
|
2015-04-21 05:27:19 +03:00
|
|
|
cd.list_offset = 0;
|
|
|
|
cd.ra_entries = ctx->readahead_kb * 1024 / ctx->fs->blocksize;
|
|
|
|
cd.next_ra_off = 0;
|
1998-08-01 08:18:06 +04:00
|
|
|
|
|
|
|
if (ctx->progress)
|
|
|
|
(void) (ctx->progress)(ctx, 2, 0, cd.max);
|
2002-08-31 10:32:41 +04:00
|
|
|
|
2015-10-24 07:43:19 +03:00
|
|
|
if (ext2fs_has_feature_dir_index(fs->super))
|
2010-06-14 01:00:00 +04:00
|
|
|
ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2015-04-21 05:27:19 +03:00
|
|
|
check_dir_func = cd.ra_entries ? check_dir_block2 : check_dir_block;
|
|
|
|
cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_func,
|
2010-06-14 01:00:00 +04:00
|
|
|
&cd);
|
2009-05-28 10:39:49 +04:00
|
|
|
if (ctx->flags & E2F_FLAG_RESTART_LATER) {
|
|
|
|
ctx->flags |= E2F_FLAG_RESTART;
|
e2fsck: skip quota update when interrupted
There is a bug in how e2fsck handles being interrupted by CTRL-C.
If CTRL-C is pressed to kill e2fsck rather than e.g. kill -9, then
the interrupt handler sets E2F_FLAG_CANCEL in the context but doesn't
actually kill the process. Instead, e2fsck_pass1() checks this flag
before processing the next inode.
If a filesystem is running in fix mode (e2fsck -fy) is interrupted,
and the quota feature is enabled, then the quota file will still be
written to disk even though the inode scan was not complete and the
quota information is totally inaccurate. Even worse, if the Pass 1
inode and block scan was not finished, then the in-memory block
bitmaps (which are used for block allocation during e2fsck) are also
invalid, so any blocks allocated to the quota files may corrupt other
files if those blocks were actually used.
e2fsck 1.42.13.wc3 (28-Aug-2015)
Pass 1: Checking inodes, blocks, and sizes
^C[QUOTA WARNING] Usage inconsistent for ID 0:
actual (6455296, 168) != expected (8568832, 231)
[QUOTA WARNING] Usage inconsistent for ID 695:
actual (614932320256, 63981) != expected (2102405386240, 176432)
Update quota info for quota type 0? yes
[QUOTA WARNING] Usage inconsistent for ID 0:
actual (6455296, 168) != expected (8568832, 231)
[QUOTA WARNING] Usage inconsistent for ID 538:
actual (614932320256, 63981) != expected (2102405386240, 176432)
Update quota info for quota type 1? yes
myth-OST0001: e2fsck canceled.
myth-OST0001: ***** FILE SYSTEM WAS MODIFIED *****
There may be a desire to flush out modified inodes and such that have
been repaired, so that restarting an interrupted e2fsck will make
progress, but the quota file update is plain wrong unless at least
pass1 has finished, and the journal recreation is also dangerous if
the block bitmaps have not been fully updated.
Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-11-14 04:10:27 +03:00
|
|
|
ctx->flags &= ~E2F_FLAG_RESTART_LATER;
|
2009-05-28 10:39:49 +04:00
|
|
|
}
|
|
|
|
|
e2fsck: skip quota update when interrupted
There is a bug in how e2fsck handles being interrupted by CTRL-C.
If CTRL-C is pressed to kill e2fsck rather than e.g. kill -9, then
the interrupt handler sets E2F_FLAG_CANCEL in the context but doesn't
actually kill the process. Instead, e2fsck_pass1() checks this flag
before processing the next inode.
If a filesystem is running in fix mode (e2fsck -fy) is interrupted,
and the quota feature is enabled, then the quota file will still be
written to disk even though the inode scan was not complete and the
quota information is totally inaccurate. Even worse, if the Pass 1
inode and block scan was not finished, then the in-memory block
bitmaps (which are used for block allocation during e2fsck) are also
invalid, so any blocks allocated to the quota files may corrupt other
files if those blocks were actually used.
e2fsck 1.42.13.wc3 (28-Aug-2015)
Pass 1: Checking inodes, blocks, and sizes
^C[QUOTA WARNING] Usage inconsistent for ID 0:
actual (6455296, 168) != expected (8568832, 231)
[QUOTA WARNING] Usage inconsistent for ID 695:
actual (614932320256, 63981) != expected (2102405386240, 176432)
Update quota info for quota type 0? yes
[QUOTA WARNING] Usage inconsistent for ID 0:
actual (6455296, 168) != expected (8568832, 231)
[QUOTA WARNING] Usage inconsistent for ID 538:
actual (614932320256, 63981) != expected (2102405386240, 176432)
Update quota info for quota type 1? yes
myth-OST0001: e2fsck canceled.
myth-OST0001: ***** FILE SYSTEM WAS MODIFIED *****
There may be a desire to flush out modified inodes and such that have
been repaired, so that restarting an interrupted e2fsck will make
progress, but the quota file update is plain wrong unless at least
pass1 has finished, and the journal recreation is also dangerous if
the block bitmaps have not been fully updated.
Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-11-14 04:10:27 +03:00
|
|
|
if (ctx->flags & E2F_FLAG_RUN_RETURN)
|
|
|
|
return;
|
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (cd.pctx.errcode) {
|
|
|
|
fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
|
1997-11-03 22:42:40 +03:00
|
|
|
ctx->flags |= E2F_FLAG_ABORT;
|
|
|
|
return;
|
1997-06-11 22:32:35 +04:00
|
|
|
}
|
2002-06-26 07:26:34 +04:00
|
|
|
|
|
|
|
for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
|
2002-07-21 22:14:03 +04:00
|
|
|
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
|
|
|
|
return;
|
2014-12-14 05:55:12 +03:00
|
|
|
if (e2fsck_dir_will_be_rehashed(ctx, dx_dir->ino) ||
|
|
|
|
dx_dir->numblocks == 0)
|
2002-06-26 07:26:34 +04:00
|
|
|
continue;
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
bad_dir = 0;
|
|
|
|
pctx.dir = dx_dir->ino;
|
|
|
|
dx_db = dx_dir->dx_block;
|
|
|
|
if (dx_db->flags & DX_FLAG_REFERENCED)
|
|
|
|
dx_db->flags |= DX_FLAG_DUP_REF;
|
|
|
|
else
|
|
|
|
dx_db->flags |= DX_FLAG_REFERENCED;
|
|
|
|
/*
|
|
|
|
* Find all of the first and last leaf blocks, and
|
|
|
|
* update their parent's min and max hash values
|
|
|
|
*/
|
|
|
|
for (b=0, dx_db = dx_dir->dx_block;
|
|
|
|
b < dx_dir->numblocks;
|
|
|
|
b++, dx_db++) {
|
|
|
|
if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
|
|
|
|
!(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
|
|
|
|
continue;
|
|
|
|
dx_parent = &dx_dir->dx_block[dx_db->parent];
|
|
|
|
/*
|
|
|
|
* XXX Make sure dx_parent->min_hash > dx_db->min_hash
|
|
|
|
*/
|
|
|
|
if (dx_db->flags & DX_FLAG_FIRST)
|
|
|
|
dx_parent->min_hash = dx_db->min_hash;
|
|
|
|
/*
|
|
|
|
* XXX Make sure dx_parent->max_hash < dx_db->max_hash
|
|
|
|
*/
|
|
|
|
if (dx_db->flags & DX_FLAG_LAST)
|
|
|
|
dx_parent->max_hash = dx_db->max_hash;
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
for (b=0, dx_db = dx_dir->dx_block;
|
|
|
|
b < dx_dir->numblocks;
|
|
|
|
b++, dx_db++) {
|
|
|
|
pctx.blkcount = b;
|
|
|
|
pctx.group = dx_db->parent;
|
|
|
|
code = 0;
|
|
|
|
if (!(dx_db->flags & DX_FLAG_FIRST) &&
|
|
|
|
(dx_db->min_hash < dx_db->node_min_hash)) {
|
|
|
|
pctx.blk = dx_db->min_hash;
|
|
|
|
pctx.blk2 = dx_db->node_min_hash;
|
|
|
|
code = PR_2_HTREE_MIN_HASH;
|
|
|
|
fix_problem(ctx, code, &pctx);
|
|
|
|
bad_dir++;
|
|
|
|
}
|
2002-09-30 19:19:19 +04:00
|
|
|
if (dx_db->type == DX_DIRBLOCK_LEAF) {
|
|
|
|
depth = htree_depth(dx_dir, dx_db);
|
|
|
|
if (depth != dx_dir->depth) {
|
2008-08-24 07:45:11 +04:00
|
|
|
pctx.num = dx_dir->depth;
|
2002-09-30 19:19:19 +04:00
|
|
|
code = PR_2_HTREE_BAD_DEPTH;
|
|
|
|
fix_problem(ctx, code, &pctx);
|
|
|
|
bad_dir++;
|
|
|
|
}
|
|
|
|
}
|
2002-06-26 07:26:34 +04:00
|
|
|
/*
|
2008-08-28 07:07:54 +04:00
|
|
|
* This test doesn't apply for the root block
|
2002-06-26 07:26:34 +04:00
|
|
|
* at block #0
|
|
|
|
*/
|
|
|
|
if (b &&
|
|
|
|
(dx_db->max_hash > dx_db->node_max_hash)) {
|
|
|
|
pctx.blk = dx_db->max_hash;
|
|
|
|
pctx.blk2 = dx_db->node_max_hash;
|
|
|
|
code = PR_2_HTREE_MAX_HASH;
|
|
|
|
fix_problem(ctx, code, &pctx);
|
2002-06-27 00:52:10 +04:00
|
|
|
bad_dir++;
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
|
|
|
if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
|
|
|
|
code = PR_2_HTREE_NOTREF;
|
|
|
|
fix_problem(ctx, code, &pctx);
|
|
|
|
bad_dir++;
|
|
|
|
} else if (dx_db->flags & DX_FLAG_DUP_REF) {
|
|
|
|
code = PR_2_HTREE_DUPREF;
|
|
|
|
fix_problem(ctx, code, &pctx);
|
|
|
|
bad_dir++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
|
|
|
|
clear_htree(ctx, dx_dir->ino);
|
2002-07-16 00:54:42 +04:00
|
|
|
dx_dir->numblocks = 0;
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
|
|
|
}
|
2009-06-15 11:50:07 +04:00
|
|
|
e2fsck_free_dx_dir_info(ctx);
|
2015-07-03 23:29:35 +03:00
|
|
|
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&buf);
|
1997-04-29 20:15:03 +04:00
|
|
|
ext2fs_free_dblist(fs->dblist);
|
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (ctx->inode_bad_map) {
|
|
|
|
ext2fs_free_inode_bitmap(ctx->inode_bad_map);
|
|
|
|
ctx->inode_bad_map = 0;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
if (ctx->inode_reg_map) {
|
|
|
|
ext2fs_free_inode_bitmap(ctx->inode_reg_map);
|
|
|
|
ctx->inode_reg_map = 0;
|
|
|
|
}
|
2015-02-24 01:44:23 +03:00
|
|
|
if (ctx->encrypted_dirs) {
|
|
|
|
ext2fs_u32_list_free(ctx->encrypted_dirs);
|
|
|
|
ctx->encrypted_dirs = 0;
|
|
|
|
}
|
2001-08-09 12:14:04 +04:00
|
|
|
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
if (ctx->large_files) {
|
2015-10-24 07:43:19 +03:00
|
|
|
if (!ext2fs_has_feature_large_file(sb) &&
|
2001-08-09 12:14:04 +04:00
|
|
|
fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
|
2015-10-24 07:43:19 +03:00
|
|
|
ext2fs_set_feature_large_file(sb);
|
2007-10-06 20:37:08 +04:00
|
|
|
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
|
2001-08-09 12:14:04 +04:00
|
|
|
ext2fs_mark_super_dirty(fs);
|
|
|
|
}
|
|
|
|
if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
|
|
|
|
fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
|
|
|
|
ext2fs_update_dynamic_rev(fs);
|
|
|
|
ext2fs_mark_super_dirty(fs);
|
|
|
|
}
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2009-05-28 17:55:10 +04:00
|
|
|
print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io);
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 19:19:19 +04:00
|
|
|
#define MAX_DEPTH 32000
|
|
|
|
static int htree_depth(struct dx_dir_info *dx_dir,
|
|
|
|
struct dx_dirblock_info *dx_db)
|
|
|
|
{
|
|
|
|
int depth = 0;
|
|
|
|
|
|
|
|
while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
|
|
|
|
dx_db = &dx_dir->dx_block[dx_db->parent];
|
|
|
|
depth++;
|
|
|
|
}
|
|
|
|
return depth;
|
|
|
|
}
|
|
|
|
|
2003-03-15 06:19:10 +03:00
|
|
|
static int dict_de_cmp(const void *a, const void *b)
|
|
|
|
{
|
2003-04-19 21:48:27 +04:00
|
|
|
const struct ext2_dir_entry *de_a, *de_b;
|
2003-03-15 06:19:10 +03:00
|
|
|
int a_len, b_len;
|
|
|
|
|
2003-04-19 21:48:27 +04:00
|
|
|
de_a = (const struct ext2_dir_entry *) a;
|
2013-06-08 19:26:14 +04:00
|
|
|
a_len = ext2fs_dirent_name_len(de_a);
|
2003-04-19 21:48:27 +04:00
|
|
|
de_b = (const struct ext2_dir_entry *) b;
|
2013-06-08 19:26:14 +04:00
|
|
|
b_len = ext2fs_dirent_name_len(de_b);
|
2003-03-15 06:19:10 +03:00
|
|
|
|
|
|
|
if (a_len != b_len)
|
|
|
|
return (a_len - b_len);
|
|
|
|
|
2015-03-02 19:40:18 +03:00
|
|
|
return memcmp(de_a->name, de_b->name, a_len);
|
2003-03-15 06:19:10 +03:00
|
|
|
}
|
2002-09-30 19:19:19 +04:00
|
|
|
|
2002-08-31 10:32:41 +04:00
|
|
|
/*
|
|
|
|
* This is special sort function that makes sure that directory blocks
|
|
|
|
* with a dirblock of zero are sorted to the beginning of the list.
|
|
|
|
* This guarantees that the root node of the htree directories are
|
|
|
|
* processed first, so we know what hash version to use.
|
|
|
|
*/
|
|
|
|
static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
|
|
|
|
{
|
2010-06-14 01:00:00 +04:00
|
|
|
const struct ext2_db_entry2 *db_a =
|
|
|
|
(const struct ext2_db_entry2 *) a;
|
|
|
|
const struct ext2_db_entry2 *db_b =
|
|
|
|
(const struct ext2_db_entry2 *) b;
|
2002-08-31 10:32:41 +04:00
|
|
|
|
|
|
|
if (db_a->blockcnt && !db_b->blockcnt)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (!db_a->blockcnt && db_b->blockcnt)
|
|
|
|
return -1;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-08-31 10:32:41 +04:00
|
|
|
if (db_a->blk != db_b->blk)
|
|
|
|
return (int) (db_a->blk - db_b->blk);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-08-31 10:32:41 +04:00
|
|
|
if (db_a->ino != db_b->ino)
|
|
|
|
return (int) (db_a->ino - db_b->ino);
|
|
|
|
|
|
|
|
return (int) (db_a->blockcnt - db_b->blockcnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Make sure the first entry in the directory is '.', and that the
|
|
|
|
* directory entry is sane.
|
|
|
|
*/
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
static int check_dot(e2fsck_t ctx,
|
1997-04-26 17:21:57 +04:00
|
|
|
struct ext2_dir_entry *dirent,
|
Many files:
dirinfo.c, e2fsck.h, emptydir.c, iscan.c, jfs_user.h, journal.c,
message.c, pass1.c, pass1b.c, pass2.c, pass3.c, pass4.c, pass5.c,
problem.h, scantest.c, super.c, swapfs.c: Change ino_t to ext2_ino_t.
2001-01-11 18:12:14 +03:00
|
|
|
ext2_ino_t ino, struct problem_context *pctx)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
struct ext2_dir_entry *nextdir;
|
2009-06-22 05:07:38 +04:00
|
|
|
unsigned int rec_len, new_len;
|
2013-12-03 05:52:43 +04:00
|
|
|
int status = 0;
|
|
|
|
int created = 0;
|
|
|
|
problem_t problem = 0;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-29 20:15:03 +04:00
|
|
|
if (!dirent->inode)
|
|
|
|
problem = PR_2_MISSING_DOT;
|
2013-06-08 19:26:14 +04:00
|
|
|
else if ((ext2fs_dirent_name_len(dirent) != 1) ||
|
1997-04-29 20:15:03 +04:00
|
|
|
(dirent->name[0] != '.'))
|
|
|
|
problem = PR_2_1ST_NOT_DOT;
|
|
|
|
else if (dirent->name[1] != '\0')
|
|
|
|
problem = PR_2_DOT_NULL_TERM;
|
2008-08-26 05:08:19 +04:00
|
|
|
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
|
1997-04-29 20:15:03 +04:00
|
|
|
if (problem) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, problem, pctx)) {
|
2008-08-26 05:08:19 +04:00
|
|
|
if (rec_len < 12)
|
|
|
|
rec_len = dirent->rec_len = 12;
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode = ino;
|
2013-06-08 19:26:14 +04:00
|
|
|
ext2fs_dirent_set_name_len(dirent, 1);
|
|
|
|
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->name[0] = '.';
|
1997-04-29 20:15:03 +04:00
|
|
|
dirent->name[1] = '\0';
|
1997-04-26 17:21:57 +04:00
|
|
|
status = 1;
|
|
|
|
created = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dirent->inode != ino) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode = ino;
|
|
|
|
status = 1;
|
1997-04-29 20:15:03 +04:00
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2008-08-26 05:08:19 +04:00
|
|
|
if (rec_len > 12) {
|
|
|
|
new_len = rec_len - 12;
|
1997-04-26 17:21:57 +04:00
|
|
|
if (new_len > 12) {
|
|
|
|
if (created ||
|
Many files:
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c: Add calls to the progress
indicator function.
pass1.c (scan_callback): Add call to the progress feedback function
(if it exists).
super.c (check_super_block): Skip the device size check if the
get_device_size returns EXT2_EXT_UNIMPLEMENTED.
iscan.c (main): Don't use fatal_error() anymore.
pass1b.c, swapfs.c, badblocks.c: Set E2F_FLAG_ABORT instead of calling
fatal_error(0).
problem.c, pass3.c (PR_3_ROOT_NOT_DIR_ABORT,
PR_3_NO_ROOT_INODE_ABORT): New problem codes.
problem.c, pass2.c (PR_2_SPLIT_DOT): New problem code.
problem.c, pass1.c (PR_1_SUPPRESS_MESSAGES): New problem code.
problemP.h: New file which separates out the private fix_problem data
structures.
util.c, dirinfo.c, pass1.c, pass1b.c, pass2.c, pass5.c, super.c,
swapfs.c util.c: allocate_memory() now takes a e2fsck context as its
first argument, and rename it to be e2fsck_allocate_memory().
problemP.h:
New file which contains the private problem abstraction definitions.
Makefile.pq:
Remove include of MAKEFILE.STD, which doesn't exist at this point.
1997-11-14 08:23:04 +03:00
|
|
|
fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
|
1997-04-26 17:21:57 +04:00
|
|
|
nextdir = (struct ext2_dir_entry *)
|
|
|
|
((char *) dirent + 12);
|
|
|
|
dirent->rec_len = 12;
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_set_rec_len(ctx->fs, new_len,
|
|
|
|
nextdir);
|
1997-04-26 17:21:57 +04:00
|
|
|
nextdir->inode = 0;
|
2013-06-08 19:26:14 +04:00
|
|
|
ext2fs_dirent_set_name_len(nextdir, 0);
|
|
|
|
ext2fs_dirent_set_file_type(nextdir,
|
|
|
|
EXT2_FT_UNKNOWN);
|
1997-04-26 17:21:57 +04:00
|
|
|
status = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure the second entry in the directory is '..', and that the
|
|
|
|
* directory entry is sane. We do not check the inode number of '..'
|
|
|
|
* here; this gets done in pass 3.
|
|
|
|
*/
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
static int check_dotdot(e2fsck_t ctx,
|
1997-04-26 17:21:57 +04:00
|
|
|
struct ext2_dir_entry *dirent,
|
2007-04-05 06:33:31 +04:00
|
|
|
ext2_ino_t ino, struct problem_context *pctx)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2013-12-03 05:52:43 +04:00
|
|
|
problem_t problem = 0;
|
2011-06-11 18:58:25 +04:00
|
|
|
unsigned int rec_len;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-29 20:15:03 +04:00
|
|
|
if (!dirent->inode)
|
|
|
|
problem = PR_2_MISSING_DOT_DOT;
|
2013-06-08 19:26:14 +04:00
|
|
|
else if ((ext2fs_dirent_name_len(dirent) != 2) ||
|
1997-04-29 20:15:03 +04:00
|
|
|
(dirent->name[0] != '.') ||
|
|
|
|
(dirent->name[1] != '.'))
|
|
|
|
problem = PR_2_2ND_NOT_DOT_DOT;
|
|
|
|
else if (dirent->name[2] != '\0')
|
|
|
|
problem = PR_2_DOT_DOT_NULL_TERM;
|
|
|
|
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
|
1997-04-29 20:15:03 +04:00
|
|
|
if (problem) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, problem, pctx)) {
|
2008-08-26 05:08:19 +04:00
|
|
|
if (rec_len < 12)
|
1997-04-29 20:15:03 +04:00
|
|
|
dirent->rec_len = 12;
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Note: we don't have the parent inode just
|
|
|
|
* yet, so we will fill it in with the root
|
|
|
|
* inode. This will get fixed in pass 3.
|
|
|
|
*/
|
|
|
|
dirent->inode = EXT2_ROOT_INO;
|
2013-06-08 19:26:14 +04:00
|
|
|
ext2fs_dirent_set_name_len(dirent, 2);
|
|
|
|
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->name[0] = '.';
|
|
|
|
dirent->name[1] = '.';
|
1997-04-29 20:15:03 +04:00
|
|
|
dirent->name[2] = '\0';
|
1997-04-26 17:21:57 +04:00
|
|
|
return 1;
|
2008-08-28 07:07:54 +04:00
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2007-04-05 06:33:31 +04:00
|
|
|
if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) {
|
|
|
|
fix_problem(ctx, PR_2_NO_DIRINFO, pctx);
|
|
|
|
return -1;
|
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check to make sure a directory entry doesn't contain any illegal
|
|
|
|
* characters.
|
|
|
|
*/
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
static int check_name(e2fsck_t ctx,
|
1997-04-26 17:21:57 +04:00
|
|
|
struct ext2_dir_entry *dirent,
|
2003-12-07 09:28:50 +03:00
|
|
|
struct problem_context *pctx)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int fixup = -1;
|
|
|
|
int ret = 0;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2013-06-08 19:26:14 +04:00
|
|
|
for ( i = 0; i < ext2fs_dirent_name_len(dirent); i++) {
|
2015-02-24 01:44:23 +03:00
|
|
|
if (dirent->name[i] != '/' && dirent->name[i] != '\0')
|
|
|
|
continue;
|
|
|
|
if (fixup < 0)
|
|
|
|
fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
|
|
|
|
if (fixup == 0)
|
|
|
|
return 0;
|
|
|
|
dirent->name[i] = '.';
|
|
|
|
ret = 1;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-17 00:19:38 +03:00
|
|
|
static int encrypted_check_name(e2fsck_t ctx,
|
|
|
|
struct ext2_dir_entry *dirent,
|
|
|
|
struct problem_context *pctx)
|
|
|
|
{
|
|
|
|
if (ext2fs_dirent_name_len(dirent) < EXT4_CRYPTO_BLOCK_SIZE) {
|
|
|
|
if (fix_problem(ctx, PR_2_BAD_ENCRYPTED_NAME, pctx)) {
|
|
|
|
dirent->inode = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
ext2fs_unmark_valid(ctx->fs);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
/*
|
|
|
|
* Check the directory filetype (if present)
|
|
|
|
*/
|
|
|
|
static _INLINE_ int check_filetype(e2fsck_t ctx,
|
2003-12-07 09:28:50 +03:00
|
|
|
struct ext2_dir_entry *dirent,
|
|
|
|
ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
|
|
|
|
struct problem_context *pctx)
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
{
|
2013-06-08 19:26:14 +04:00
|
|
|
int filetype = ext2fs_dirent_file_type(dirent);
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
int should_be = EXT2_FT_UNKNOWN;
|
|
|
|
struct ext2_inode inode;
|
|
|
|
|
2015-10-24 07:43:19 +03:00
|
|
|
if (!ext2fs_has_feature_filetype(ctx->fs->super)) {
|
1999-10-22 19:11:42 +04:00
|
|
|
if (filetype == 0 ||
|
|
|
|
!fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
|
|
|
|
return 0;
|
2013-06-08 19:26:14 +04:00
|
|
|
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
|
1999-10-22 19:11:42 +04:00
|
|
|
return 1;
|
|
|
|
}
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
|
2009-08-23 06:29:02 +04:00
|
|
|
if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
should_be = EXT2_FT_DIR;
|
2009-08-23 06:29:02 +04:00
|
|
|
} else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
dirent->inode)) {
|
|
|
|
should_be = EXT2_FT_REG_FILE;
|
|
|
|
} else if (ctx->inode_bad_map &&
|
2009-08-23 06:29:02 +04:00
|
|
|
ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
dirent->inode))
|
|
|
|
should_be = 0;
|
|
|
|
else {
|
|
|
|
e2fsck_read_inode(ctx, dirent->inode, &inode,
|
|
|
|
"check_filetype");
|
ChangeLog, e2fsck.h, pass1.c, pass2.c, pass3.c, problem.c, problem.h, util.c:
pass1.c (e2fsck_pass1): If the filesystem does not support imagic
inodes, if an inode has the imagic flag set, offer to clear the imagic
flag. If a valid device/fifo/socket has the immutable flag set, call
the new helper function check_immutable() to offerto clear the
immutable flag.
pass2.c (check_filetype): Use the new ext2_file_type() helper function
instead of calculating the file_type information manually.
pass3.c (e2fsck_reconnect_file): When adding a link to lost+found,
calculate the filetype information so that ext2fs_link() can use the
information if applicable. (get_lost_and_found): Create the
/lost+found directory with the correct filetype information if
applicable.
util.c (ext2_file_type), e2fsck.h: New function which returns the
directory entry file type information given the inode's mode bits.
problem.c, problem.h: Added new problem codes PR_1_SET_IMAGIC and
PR_1_SET_IMMUTABLE.
ChangeLog, mke2fs.8.in:
mke2fs.8.in: Update manual page so that the sparse_option filesystem
option is properly named.
1999-11-10 16:34:40 +03:00
|
|
|
should_be = ext2_file_type(inode.i_mode);
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
}
|
|
|
|
if (filetype == should_be)
|
|
|
|
return 0;
|
|
|
|
pctx->num = should_be;
|
|
|
|
|
|
|
|
if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
|
|
|
|
pctx) == 0)
|
|
|
|
return 0;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2013-06-08 19:26:14 +04:00
|
|
|
ext2fs_dirent_set_file_type(dirent, should_be);
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
static void parse_int_node(ext2_filsys fs,
|
2010-06-14 01:00:00 +04:00
|
|
|
struct ext2_db_entry2 *db,
|
2002-06-26 07:26:34 +04:00
|
|
|
struct check_dir_struct *cd,
|
|
|
|
struct dx_dir_info *dx_dir,
|
2012-08-03 01:27:30 +04:00
|
|
|
char *block_buf, int failed_csum)
|
2002-06-26 07:26:34 +04:00
|
|
|
{
|
|
|
|
struct ext2_dx_root_info *root;
|
|
|
|
struct ext2_dx_entry *ent;
|
|
|
|
struct ext2_dx_countlimit *limit;
|
|
|
|
struct dx_dirblock_info *dx_db;
|
2002-09-30 19:19:19 +04:00
|
|
|
int i, expect_limit, count;
|
2002-06-26 07:26:34 +04:00
|
|
|
blk_t blk;
|
|
|
|
ext2_dirhash_t min_hash = 0xffffffff;
|
|
|
|
ext2_dirhash_t max_hash = 0;
|
2002-09-30 19:19:19 +04:00
|
|
|
ext2_dirhash_t hash = 0, prev_hash;
|
2012-08-03 01:27:30 +04:00
|
|
|
int csum_size = 0;
|
2002-06-26 07:26:34 +04:00
|
|
|
|
|
|
|
if (db->blockcnt == 0) {
|
|
|
|
root = (struct ext2_dx_root_info *) (block_buf + 24);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
#ifdef DX_DEBUG
|
|
|
|
printf("Root node dump:\n");
|
2006-03-19 05:43:46 +03:00
|
|
|
printf("\t Reserved zero: %u\n", root->reserved_zero);
|
2002-06-26 07:26:34 +04:00
|
|
|
printf("\t Hash Version: %d\n", root->hash_version);
|
|
|
|
printf("\t Info length: %d\n", root->info_length);
|
|
|
|
printf("\t Indirect levels: %d\n", root->indirect_levels);
|
|
|
|
printf("\t Flags: %d\n", root->unused_flags);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
|
2012-08-03 01:27:30 +04:00
|
|
|
|
|
|
|
if (failed_csum &&
|
|
|
|
(e2fsck_dir_will_be_rehashed(cd->ctx, cd->pctx.ino) ||
|
|
|
|
fix_problem(cd->ctx, PR_2_HTREE_ROOT_CSUM_INVALID,
|
|
|
|
&cd->pctx)))
|
|
|
|
goto clear_and_exit;
|
2002-06-26 07:26:34 +04:00
|
|
|
} else {
|
|
|
|
ent = (struct ext2_dx_entry *) (block_buf+8);
|
2012-08-03 01:27:30 +04:00
|
|
|
|
|
|
|
if (failed_csum &&
|
|
|
|
(e2fsck_dir_will_be_rehashed(cd->ctx, cd->pctx.ino) ||
|
|
|
|
fix_problem(cd->ctx, PR_2_HTREE_NODE_CSUM_INVALID,
|
|
|
|
&cd->pctx)))
|
|
|
|
goto clear_and_exit;
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
2012-08-03 01:27:30 +04:00
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
limit = (struct ext2_dx_countlimit *) ent;
|
|
|
|
|
|
|
|
#ifdef DX_DEBUG
|
2008-08-28 07:07:54 +04:00
|
|
|
printf("Number of entries (count): %d\n",
|
2002-10-03 06:07:17 +04:00
|
|
|
ext2fs_le16_to_cpu(limit->count));
|
2008-08-28 07:07:54 +04:00
|
|
|
printf("Number of entries (limit): %d\n",
|
2002-10-03 06:07:17 +04:00
|
|
|
ext2fs_le16_to_cpu(limit->limit));
|
2002-06-26 07:26:34 +04:00
|
|
|
#endif
|
|
|
|
|
2002-10-03 06:07:17 +04:00
|
|
|
count = ext2fs_le16_to_cpu(limit->count);
|
2015-10-24 07:43:19 +03:00
|
|
|
if (ext2fs_has_feature_metadata_csum(fs->super))
|
2012-08-03 01:27:30 +04:00
|
|
|
csum_size = sizeof(struct ext2_dx_tail);
|
|
|
|
expect_limit = (fs->blocksize -
|
|
|
|
(csum_size + ((char *) ent - block_buf))) /
|
|
|
|
sizeof(struct ext2_dx_entry);
|
2002-10-03 06:07:17 +04:00
|
|
|
if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
|
|
|
|
cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
|
2002-09-30 19:19:19 +04:00
|
|
|
if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
|
|
|
|
goto clear_and_exit;
|
|
|
|
}
|
2002-10-03 06:07:17 +04:00
|
|
|
if (count > expect_limit) {
|
|
|
|
cd->pctx.num = count;
|
2002-09-30 19:19:19 +04:00
|
|
|
if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
|
|
|
|
goto clear_and_exit;
|
|
|
|
count = expect_limit;
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-09-30 19:19:19 +04:00
|
|
|
for (i=0; i < count; i++) {
|
|
|
|
prev_hash = hash;
|
2002-10-03 06:07:17 +04:00
|
|
|
hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
|
2002-06-26 07:26:34 +04:00
|
|
|
#ifdef DX_DEBUG
|
2006-03-19 05:43:46 +03:00
|
|
|
printf("Entry #%d: Hash 0x%08x, block %u\n", i,
|
2002-10-03 06:07:17 +04:00
|
|
|
hash, ext2fs_le32_to_cpu(ent[i].block));
|
2002-06-26 07:26:34 +04:00
|
|
|
#endif
|
2002-10-03 06:07:17 +04:00
|
|
|
blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
|
2002-06-26 07:26:34 +04:00
|
|
|
/* Check to make sure the block is valid */
|
2006-10-22 07:27:03 +04:00
|
|
|
if (blk >= (blk_t) dx_dir->numblocks) {
|
2002-07-20 08:28:07 +04:00
|
|
|
cd->pctx.blk = blk;
|
2002-06-26 07:26:34 +04:00
|
|
|
if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
|
2002-09-30 19:19:19 +04:00
|
|
|
&cd->pctx))
|
|
|
|
goto clear_and_exit;
|
2006-10-22 07:27:03 +04:00
|
|
|
continue;
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
2002-09-30 19:19:19 +04:00
|
|
|
if (hash < prev_hash &&
|
|
|
|
fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
|
|
|
|
goto clear_and_exit;
|
2002-06-26 07:26:34 +04:00
|
|
|
dx_db = &dx_dir->dx_block[blk];
|
|
|
|
if (dx_db->flags & DX_FLAG_REFERENCED) {
|
|
|
|
dx_db->flags |= DX_FLAG_DUP_REF;
|
|
|
|
} else {
|
|
|
|
dx_db->flags |= DX_FLAG_REFERENCED;
|
|
|
|
dx_db->parent = db->blockcnt;
|
|
|
|
}
|
|
|
|
if (hash < min_hash)
|
|
|
|
min_hash = hash;
|
|
|
|
if (hash > max_hash)
|
|
|
|
max_hash = hash;
|
|
|
|
dx_db->node_min_hash = hash;
|
2002-10-03 06:07:17 +04:00
|
|
|
if ((i+1) < count)
|
2008-08-28 07:07:54 +04:00
|
|
|
dx_db->node_max_hash =
|
2002-10-03 06:07:17 +04:00
|
|
|
ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
|
2002-06-26 07:26:34 +04:00
|
|
|
else {
|
|
|
|
dx_db->node_max_hash = 0xfffffffe;
|
|
|
|
dx_db->flags |= DX_FLAG_LAST;
|
|
|
|
}
|
|
|
|
if (i == 0)
|
|
|
|
dx_db->flags |= DX_FLAG_FIRST;
|
|
|
|
}
|
|
|
|
#ifdef DX_DEBUG
|
|
|
|
printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
|
|
|
|
db->blockcnt, min_hash, max_hash);
|
|
|
|
#endif
|
|
|
|
dx_db = &dx_dir->dx_block[db->blockcnt];
|
|
|
|
dx_db->min_hash = min_hash;
|
|
|
|
dx_db->max_hash = max_hash;
|
2002-09-30 19:19:19 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
clear_and_exit:
|
|
|
|
clear_htree(cd->ctx, cd->pctx.ino);
|
|
|
|
dx_dir->numblocks = 0;
|
2012-08-03 01:27:30 +04:00
|
|
|
e2fsck_rehash_dir_later(cd->ctx, cd->pctx.ino);
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
|
2002-09-28 17:16:28 +04:00
|
|
|
/*
|
|
|
|
* Given a busted directory, try to salvage it somehow.
|
2008-08-28 07:07:54 +04:00
|
|
|
*
|
2002-09-28 17:16:28 +04:00
|
|
|
*/
|
2002-09-30 19:19:19 +04:00
|
|
|
static void salvage_directory(ext2_filsys fs,
|
2002-09-28 17:16:28 +04:00
|
|
|
struct ext2_dir_entry *dirent,
|
|
|
|
struct ext2_dir_entry *prev,
|
2014-07-28 03:45:04 +04:00
|
|
|
unsigned int *offset,
|
|
|
|
unsigned int block_len)
|
2002-09-28 17:16:28 +04:00
|
|
|
{
|
|
|
|
char *cp = (char *) dirent;
|
2009-06-22 05:07:38 +04:00
|
|
|
int left;
|
|
|
|
unsigned int rec_len, prev_rec_len;
|
2015-01-29 19:09:07 +03:00
|
|
|
unsigned int name_len;
|
2002-09-28 17:16:28 +04:00
|
|
|
|
2015-01-29 19:09:07 +03:00
|
|
|
/*
|
|
|
|
* If the space left for the entry is too small to be an entry,
|
|
|
|
* we can't access dirent's fields, so plumb in the values needed
|
|
|
|
* so that the previous entry absorbs this one.
|
|
|
|
*/
|
|
|
|
if (block_len - *offset < EXT2_DIR_ENTRY_HEADER_LEN) {
|
|
|
|
name_len = 0;
|
|
|
|
rec_len = block_len - *offset;
|
|
|
|
} else {
|
|
|
|
name_len = ext2fs_dirent_name_len(dirent);
|
|
|
|
(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
|
|
|
|
}
|
2014-07-28 03:45:04 +04:00
|
|
|
left = block_len - *offset - rec_len;
|
2008-08-26 05:08:19 +04:00
|
|
|
|
2002-09-28 17:16:28 +04:00
|
|
|
/*
|
|
|
|
* Special case of directory entry of size 8: copy what's left
|
|
|
|
* of the directory block up to cover up the invalid hole.
|
|
|
|
*/
|
2015-01-29 19:09:07 +03:00
|
|
|
if ((left >= 12) && (rec_len == EXT2_DIR_ENTRY_HEADER_LEN)) {
|
|
|
|
memmove(cp, cp+EXT2_DIR_ENTRY_HEADER_LEN, left);
|
|
|
|
memset(cp + left, 0, EXT2_DIR_ENTRY_HEADER_LEN);
|
2002-09-30 19:19:19 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If the directory entry overruns the end of the directory
|
|
|
|
* block, and the name is small enough to fit, then adjust the
|
|
|
|
* record length.
|
|
|
|
*/
|
|
|
|
if ((left < 0) &&
|
2015-01-29 19:09:07 +03:00
|
|
|
((int) rec_len + left > EXT2_DIR_ENTRY_HEADER_LEN) &&
|
|
|
|
((int) name_len + EXT2_DIR_ENTRY_HEADER_LEN <= (int) rec_len + left) &&
|
2002-09-30 19:19:19 +04:00
|
|
|
dirent->inode <= fs->super->s_inodes_count &&
|
|
|
|
strnlen(dirent->name, name_len) == name_len) {
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent);
|
2002-09-30 19:19:19 +04:00
|
|
|
return;
|
2002-09-28 17:16:28 +04:00
|
|
|
}
|
|
|
|
/*
|
2007-07-09 21:05:45 +04:00
|
|
|
* If the record length of the directory entry is a multiple
|
|
|
|
* of four, and not too big, such that it is valid, let the
|
|
|
|
* previous directory entry absorb the invalid one.
|
2002-09-28 17:16:28 +04:00
|
|
|
*/
|
2008-08-26 05:08:19 +04:00
|
|
|
if (prev && rec_len && (rec_len % 4) == 0 &&
|
2014-07-28 03:45:04 +04:00
|
|
|
(*offset + rec_len <= block_len)) {
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
|
|
|
|
prev_rec_len += rec_len;
|
|
|
|
(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
|
2008-08-26 05:08:19 +04:00
|
|
|
*offset += rec_len;
|
2002-09-30 19:19:19 +04:00
|
|
|
return;
|
2002-09-28 17:16:28 +04:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Default salvage method --- kill all of the directory
|
|
|
|
* entries for the rest of the block. We will either try to
|
|
|
|
* absorb it into the previous directory entry, or create a
|
|
|
|
* new empty directory entry the rest of the directory block.
|
|
|
|
*/
|
|
|
|
if (prev) {
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
|
2014-07-28 03:45:04 +04:00
|
|
|
prev_rec_len += block_len - *offset;
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
|
2002-09-30 19:19:19 +04:00
|
|
|
*offset = fs->blocksize;
|
2002-09-28 17:16:28 +04:00
|
|
|
} else {
|
2014-07-28 03:45:04 +04:00
|
|
|
rec_len = block_len - *offset;
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_set_rec_len(fs, rec_len, dirent);
|
2013-06-08 19:26:14 +04:00
|
|
|
ext2fs_dirent_set_name_len(dirent, 0);
|
|
|
|
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
|
2002-09-28 17:16:28 +04:00
|
|
|
dirent->inode = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-28 03:46:15 +04:00
|
|
|
#define NEXT_DIRENT(d) ((void *)((char *)(d) + (d)->rec_len))
|
2014-07-27 01:13:31 +04:00
|
|
|
static errcode_t insert_dirent_tail(ext2_filsys fs, void *dirbuf)
|
|
|
|
{
|
|
|
|
struct ext2_dir_entry *d;
|
|
|
|
void *top;
|
|
|
|
struct ext2_dir_entry_tail *t;
|
|
|
|
|
|
|
|
d = dirbuf;
|
|
|
|
top = EXT2_DIRENT_TAIL(dirbuf, fs->blocksize);
|
|
|
|
|
2014-07-28 03:46:15 +04:00
|
|
|
while (d->rec_len && !(d->rec_len & 0x3) && NEXT_DIRENT(d) <= top)
|
|
|
|
d = NEXT_DIRENT(d);
|
2014-07-27 01:13:31 +04:00
|
|
|
|
|
|
|
if (d != top) {
|
2016-05-29 20:36:20 +03:00
|
|
|
unsigned int min_size = EXT2_DIR_REC_LEN(
|
2014-07-27 01:13:31 +04:00
|
|
|
ext2fs_dirent_name_len(dirbuf));
|
2016-05-29 20:36:20 +03:00
|
|
|
if (min_size > (char *)top - (char *)d)
|
2014-07-27 01:13:31 +04:00
|
|
|
return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
|
2016-05-29 20:36:20 +03:00
|
|
|
d->rec_len = (char *)top - (char *)d;
|
2014-07-27 01:13:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
t = (struct ext2_dir_entry_tail *)top;
|
|
|
|
if (t->det_reserved_zero1 ||
|
|
|
|
t->det_rec_len != sizeof(struct ext2_dir_entry_tail) ||
|
|
|
|
t->det_reserved_name_len != EXT2_DIR_NAME_LEN_CSUM)
|
|
|
|
ext2fs_initialize_dirent_tail(fs, t);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-07-28 03:46:15 +04:00
|
|
|
#undef NEXT_DIRENT
|
2014-07-27 01:13:31 +04:00
|
|
|
|
2014-08-11 02:46:53 +04:00
|
|
|
static errcode_t fix_inline_dir_size(e2fsck_t ctx, ext2_ino_t ino,
|
|
|
|
size_t *inline_data_size,
|
|
|
|
struct problem_context *pctx,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
ext2_filsys fs = ctx->fs;
|
|
|
|
struct ext2_inode inode;
|
|
|
|
size_t new_size, old_size;
|
|
|
|
errcode_t retval;
|
|
|
|
|
|
|
|
old_size = *inline_data_size;
|
2015-01-28 17:00:13 +03:00
|
|
|
/*
|
|
|
|
* If there's not enough bytes to start the "second" dir block
|
|
|
|
* (in the EA space) then truncate everything to the first block.
|
|
|
|
*/
|
|
|
|
if (old_size > EXT4_MIN_INLINE_DATA_SIZE &&
|
|
|
|
old_size < EXT4_MIN_INLINE_DATA_SIZE +
|
|
|
|
EXT2_DIR_REC_LEN(1)) {
|
|
|
|
old_size = EXT4_MIN_INLINE_DATA_SIZE;
|
|
|
|
new_size = old_size;
|
|
|
|
} else
|
|
|
|
/* Increase to the next four-byte boundary for salvaging */
|
|
|
|
new_size = old_size + (4 - (old_size & 3));
|
2014-08-11 02:46:53 +04:00
|
|
|
memset(buf + old_size, 0, new_size - old_size);
|
|
|
|
retval = ext2fs_inline_data_set(fs, ino, 0, buf, new_size);
|
|
|
|
if (retval == EXT2_ET_INLINE_DATA_NO_SPACE) {
|
2015-01-28 17:00:13 +03:00
|
|
|
/* Or we can't, so truncate. */
|
2014-08-11 02:46:53 +04:00
|
|
|
new_size -= 4;
|
|
|
|
retval = ext2fs_inline_data_set(fs, ino, 0, buf, new_size);
|
|
|
|
if (retval) {
|
|
|
|
if (fix_problem(ctx, PR_2_FIX_INLINE_DIR_FAILED,
|
|
|
|
pctx)) {
|
|
|
|
new_size = 0;
|
|
|
|
goto write_inode;
|
|
|
|
}
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else if (retval) {
|
|
|
|
if (fix_problem(ctx, PR_2_FIX_INLINE_DIR_FAILED,
|
|
|
|
pctx)) {
|
|
|
|
new_size = 0;
|
|
|
|
goto write_inode;
|
|
|
|
}
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_inode:
|
|
|
|
retval = ext2fs_read_inode(fs, ino, &inode);
|
|
|
|
if (retval)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
retval = ext2fs_inode_size_set(fs, &inode, new_size);
|
|
|
|
if (retval)
|
|
|
|
goto err;
|
|
|
|
if (new_size == 0)
|
|
|
|
inode.i_flags &= ~EXT4_INLINE_DATA_FL;
|
|
|
|
retval = ext2fs_write_inode(fs, ino, &inode);
|
|
|
|
if (retval)
|
|
|
|
goto err;
|
|
|
|
*inline_data_size = new_size;
|
|
|
|
|
|
|
|
err:
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2015-04-21 05:27:19 +03:00
|
|
|
static int check_dir_block2(ext2_filsys fs,
|
|
|
|
struct ext2_db_entry2 *db,
|
|
|
|
void *priv_data)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
struct check_dir_struct *cd = priv_data;
|
|
|
|
|
|
|
|
if (cd->ra_entries && cd->list_offset >= cd->next_ra_off) {
|
|
|
|
err = e2fsck_readahead_dblist(fs,
|
|
|
|
E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT,
|
|
|
|
fs->dblist,
|
|
|
|
cd->list_offset + cd->ra_entries / 8,
|
|
|
|
cd->ra_entries);
|
|
|
|
if (err)
|
|
|
|
cd->ra_entries = 0;
|
|
|
|
cd->next_ra_off = cd->list_offset + (cd->ra_entries * 7 / 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
err = check_dir_block(fs, db, priv_data);
|
|
|
|
cd->list_offset++;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
static int check_dir_block(ext2_filsys fs,
|
2010-06-14 01:00:00 +04:00
|
|
|
struct ext2_db_entry2 *db,
|
Many files:
e2fsck.h: If EXT2_FLAT_INCLUDES is defined, then assume all of
the ext2-specific header files are in a flat directory.
dirinfo.c, ehandler.c, pass1.c, pass1b.c, pass2.c, pass5.c,
super.c, swapfs.c, unix.c: Explicitly cast all assignments
from void * to be compatible with C++.
unix.c (sync_disk): Remove sync_disk and calls to that function,
since ext2fs_close() now takes care of this.
pass1.c, pass1b.c, pass2.c, pass3.c, swapfs, badblocks.c,
ehandler.c, unix.c: Change use of private to be priv_data, to
avoid C++ reserved name clash.
1998-01-19 17:50:49 +03:00
|
|
|
void *priv_data)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2002-06-26 07:26:34 +04:00
|
|
|
struct dx_dir_info *dx_dir;
|
|
|
|
struct dx_dirblock_info *dx_db = 0;
|
2014-03-03 10:02:44 +04:00
|
|
|
struct ext2_dir_entry *dirent, *prev, dot, dotdot;
|
2002-06-26 07:26:34 +04:00
|
|
|
ext2_dirhash_t hash;
|
2003-12-07 09:28:50 +03:00
|
|
|
unsigned int offset = 0;
|
1997-04-26 17:21:57 +04:00
|
|
|
int dir_modified = 0;
|
1997-04-29 20:15:03 +04:00
|
|
|
int dot_state;
|
2008-11-16 18:03:00 +03:00
|
|
|
unsigned int rec_len;
|
2010-06-14 01:00:00 +04:00
|
|
|
blk64_t block_nr = db->blk;
|
Many files:
dirinfo.c, e2fsck.h, emptydir.c, iscan.c, jfs_user.h, journal.c,
message.c, pass1.c, pass1b.c, pass2.c, pass3.c, pass4.c, pass5.c,
problem.h, scantest.c, super.c, swapfs.c: Change ino_t to ext2_ino_t.
2001-01-11 18:12:14 +03:00
|
|
|
ext2_ino_t ino = db->ino;
|
2007-04-05 06:33:31 +04:00
|
|
|
ext2_ino_t subdir_parent;
|
1997-04-29 20:15:03 +04:00
|
|
|
__u16 links;
|
Many files:
e2fsck.h: If EXT2_FLAT_INCLUDES is defined, then assume all of
the ext2-specific header files are in a flat directory.
dirinfo.c, ehandler.c, pass1.c, pass1b.c, pass2.c, pass5.c,
super.c, swapfs.c, unix.c: Explicitly cast all assignments
from void * to be compatible with C++.
unix.c (sync_disk): Remove sync_disk and calls to that function,
since ext2fs_close() now takes care of this.
pass1.c, pass1b.c, pass2.c, pass3.c, swapfs, badblocks.c,
ehandler.c, unix.c: Change use of private to be priv_data, to
avoid C++ reserved name clash.
1998-01-19 17:50:49 +03:00
|
|
|
struct check_dir_struct *cd;
|
2015-01-28 17:00:13 +03:00
|
|
|
char *buf, *ibuf;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
e2fsck_t ctx;
|
2013-12-03 05:52:43 +04:00
|
|
|
problem_t problem;
|
2002-08-31 10:32:41 +04:00
|
|
|
struct ext2_dx_root_info *root;
|
2002-09-30 03:30:28 +04:00
|
|
|
struct ext2_dx_countlimit *limit;
|
2003-03-15 06:19:10 +03:00
|
|
|
static dict_t de_dict;
|
|
|
|
struct problem_context pctx;
|
|
|
|
int dups_found = 0;
|
2007-04-05 06:33:31 +04:00
|
|
|
int ret;
|
2012-08-03 01:27:43 +04:00
|
|
|
int dx_csum_size = 0, de_csum_size = 0;
|
2012-08-03 01:27:43 +04:00
|
|
|
int failed_csum = 0;
|
2012-08-03 01:27:43 +04:00
|
|
|
int is_leaf = 1;
|
2014-03-14 17:34:10 +04:00
|
|
|
size_t inline_data_size = 0;
|
2014-03-03 10:02:44 +04:00
|
|
|
int filetype = 0;
|
2015-03-09 02:09:52 +03:00
|
|
|
int encrypted = 0;
|
2015-01-28 17:00:13 +03:00
|
|
|
size_t max_block_size;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
|
Many files:
e2fsck.h: If EXT2_FLAT_INCLUDES is defined, then assume all of
the ext2-specific header files are in a flat directory.
dirinfo.c, ehandler.c, pass1.c, pass1b.c, pass2.c, pass5.c,
super.c, swapfs.c, unix.c: Explicitly cast all assignments
from void * to be compatible with C++.
unix.c (sync_disk): Remove sync_disk and calls to that function,
since ext2fs_close() now takes care of this.
pass1.c, pass1b.c, pass2.c, pass3.c, swapfs, badblocks.c,
ehandler.c, unix.c: Change use of private to be priv_data, to
avoid C++ reserved name clash.
1998-01-19 17:50:49 +03:00
|
|
|
cd = (struct check_dir_struct *) priv_data;
|
2015-01-28 17:00:13 +03:00
|
|
|
ibuf = buf = cd->buf;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
ctx = cd->ctx;
|
Many files:
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c: Add calls to the progress
indicator function.
pass1.c (scan_callback): Add call to the progress feedback function
(if it exists).
super.c (check_super_block): Skip the device size check if the
get_device_size returns EXT2_EXT_UNIMPLEMENTED.
iscan.c (main): Don't use fatal_error() anymore.
pass1b.c, swapfs.c, badblocks.c: Set E2F_FLAG_ABORT instead of calling
fatal_error(0).
problem.c, pass3.c (PR_3_ROOT_NOT_DIR_ABORT,
PR_3_NO_ROOT_INODE_ABORT): New problem codes.
problem.c, pass2.c (PR_2_SPLIT_DOT): New problem code.
problem.c, pass1.c (PR_1_SUPPRESS_MESSAGES): New problem code.
problemP.h: New file which separates out the private fix_problem data
structures.
util.c, dirinfo.c, pass1.c, pass1b.c, pass2.c, pass5.c, super.c,
swapfs.c util.c: allocate_memory() now takes a e2fsck context as its
first argument, and rename it to be e2fsck_allocate_memory().
problemP.h:
New file which contains the private problem abstraction definitions.
Makefile.pq:
Remove include of MAKEFILE.STD, which doesn't exist at this point.
1997-11-14 08:23:04 +03:00
|
|
|
|
e2fsck: skip quota update when interrupted
There is a bug in how e2fsck handles being interrupted by CTRL-C.
If CTRL-C is pressed to kill e2fsck rather than e.g. kill -9, then
the interrupt handler sets E2F_FLAG_CANCEL in the context but doesn't
actually kill the process. Instead, e2fsck_pass1() checks this flag
before processing the next inode.
If a filesystem is running in fix mode (e2fsck -fy) is interrupted,
and the quota feature is enabled, then the quota file will still be
written to disk even though the inode scan was not complete and the
quota information is totally inaccurate. Even worse, if the Pass 1
inode and block scan was not finished, then the in-memory block
bitmaps (which are used for block allocation during e2fsck) are also
invalid, so any blocks allocated to the quota files may corrupt other
files if those blocks were actually used.
e2fsck 1.42.13.wc3 (28-Aug-2015)
Pass 1: Checking inodes, blocks, and sizes
^C[QUOTA WARNING] Usage inconsistent for ID 0:
actual (6455296, 168) != expected (8568832, 231)
[QUOTA WARNING] Usage inconsistent for ID 695:
actual (614932320256, 63981) != expected (2102405386240, 176432)
Update quota info for quota type 0? yes
[QUOTA WARNING] Usage inconsistent for ID 0:
actual (6455296, 168) != expected (8568832, 231)
[QUOTA WARNING] Usage inconsistent for ID 538:
actual (614932320256, 63981) != expected (2102405386240, 176432)
Update quota info for quota type 1? yes
myth-OST0001: e2fsck canceled.
myth-OST0001: ***** FILE SYSTEM WAS MODIFIED *****
There may be a desire to flush out modified inodes and such that have
been repaired, so that restarting an interrupted e2fsck will make
progress, but the quota file update is plain wrong unless at least
pass1 has finished, and the journal recreation is also dangerous if
the block bitmaps have not been fully updated.
Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2015-11-14 04:10:27 +03:00
|
|
|
if (ctx->flags & E2F_FLAG_RUN_RETURN)
|
2002-07-21 22:14:03 +04:00
|
|
|
return DIRENT_ABORT;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-07-21 22:14:03 +04:00
|
|
|
if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
|
|
|
|
return DIRENT_ABORT;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2015-10-24 07:43:19 +03:00
|
|
|
if (ext2fs_has_feature_metadata_csum(fs->super)) {
|
2012-08-03 01:27:30 +04:00
|
|
|
dx_csum_size = sizeof(struct ext2_dx_tail);
|
2012-08-03 01:27:43 +04:00
|
|
|
de_csum_size = sizeof(struct ext2_dir_entry_tail);
|
|
|
|
}
|
2012-08-03 01:27:30 +04:00
|
|
|
|
2015-10-24 07:43:19 +03:00
|
|
|
if (ext2fs_has_feature_filetype(fs->super))
|
2014-03-03 10:02:44 +04:00
|
|
|
filetype = EXT2_FT_DIR << 8;
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
2008-08-28 07:07:54 +04:00
|
|
|
* Make sure the inode is still in use (could have been
|
1997-04-26 17:21:57 +04:00
|
|
|
* deleted in the duplicate/bad blocks pass.
|
|
|
|
*/
|
2009-08-23 06:29:02 +04:00
|
|
|
if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino)))
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
1997-04-26 17:58:21 +04:00
|
|
|
|
1997-04-29 20:15:03 +04:00
|
|
|
cd->pctx.ino = ino;
|
|
|
|
cd->pctx.blk = block_nr;
|
|
|
|
cd->pctx.blkcount = db->blockcnt;
|
|
|
|
cd->pctx.ino2 = 0;
|
|
|
|
cd->pctx.dirent = 0;
|
|
|
|
cd->pctx.num = 0;
|
|
|
|
|
2015-10-24 07:43:19 +03:00
|
|
|
if (ext2fs_has_feature_inline_data(fs->super)) {
|
2014-03-03 10:02:44 +04:00
|
|
|
errcode_t ec;
|
|
|
|
|
|
|
|
ec = ext2fs_inline_data_size(fs, ino, &inline_data_size);
|
|
|
|
if (ec && ec != EXT2_ET_NO_INLINE_DATA)
|
|
|
|
return DIRENT_ABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (db->blk == 0 && !inline_data_size) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (allocate_dir_block(ctx, db, buf, &cd->pctx))
|
1997-04-26 17:58:21 +04:00
|
|
|
return 0;
|
|
|
|
block_nr = db->blk;
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
if (db->blockcnt)
|
|
|
|
dot_state = 2;
|
|
|
|
else
|
|
|
|
dot_state = 0;
|
|
|
|
|
2003-03-15 06:19:10 +03:00
|
|
|
if (ctx->dirs_to_hash &&
|
|
|
|
ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
|
|
|
|
dups_found++;
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
#if 0
|
1997-04-26 17:34:30 +04:00
|
|
|
printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
|
1997-04-26 17:21:57 +04:00
|
|
|
db->blockcnt, ino);
|
|
|
|
#endif
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2011-09-17 00:49:27 +04:00
|
|
|
ehandler_operation(_("reading directory block"));
|
2014-08-11 02:22:54 +04:00
|
|
|
if (inline_data_size) {
|
2015-01-29 19:09:07 +03:00
|
|
|
memset(buf, 0, fs->blocksize - inline_data_size);
|
2014-03-03 10:02:44 +04:00
|
|
|
cd->pctx.errcode = ext2fs_inline_data_get(fs, ino, 0, buf, 0);
|
2014-08-11 02:22:54 +04:00
|
|
|
if (cd->pctx.errcode)
|
|
|
|
goto inline_read_fail;
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
2015-01-28 17:00:13 +03:00
|
|
|
if (db->blockcnt)
|
|
|
|
goto skip_first_read_swab;
|
2014-08-11 02:22:54 +04:00
|
|
|
*((__u32 *)buf) = ext2fs_le32_to_cpu(*((__u32 *)buf));
|
|
|
|
cd->pctx.errcode = ext2fs_dirent_swab_in2(fs,
|
|
|
|
buf + EXT4_INLINE_DATA_DOTDOT_SIZE,
|
2015-01-28 17:00:13 +03:00
|
|
|
EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE,
|
|
|
|
0);
|
|
|
|
if (cd->pctx.errcode)
|
|
|
|
goto inline_read_fail;
|
|
|
|
skip_first_read_swab:
|
|
|
|
if (inline_data_size <= EXT4_MIN_INLINE_DATA_SIZE ||
|
|
|
|
!db->blockcnt)
|
|
|
|
goto inline_read_fail;
|
|
|
|
cd->pctx.errcode = ext2fs_dirent_swab_in2(fs,
|
|
|
|
buf + EXT4_MIN_INLINE_DATA_SIZE,
|
|
|
|
inline_data_size - EXT4_MIN_INLINE_DATA_SIZE,
|
2014-08-11 02:22:54 +04:00
|
|
|
0);
|
|
|
|
#endif
|
|
|
|
} else
|
2014-03-03 10:02:44 +04:00
|
|
|
cd->pctx.errcode = ext2fs_read_dir_block4(fs, block_nr,
|
|
|
|
buf, 0, ino);
|
2014-08-11 02:22:54 +04:00
|
|
|
inline_read_fail:
|
2014-08-11 02:46:53 +04:00
|
|
|
pctx.ino = ino;
|
|
|
|
pctx.num = inline_data_size;
|
2015-01-28 17:00:13 +03:00
|
|
|
if (((inline_data_size & 3) ||
|
|
|
|
(inline_data_size > EXT4_MIN_INLINE_DATA_SIZE &&
|
|
|
|
inline_data_size < EXT4_MIN_INLINE_DATA_SIZE +
|
|
|
|
EXT2_DIR_REC_LEN(1))) &&
|
2014-08-11 02:46:53 +04:00
|
|
|
fix_problem(ctx, PR_2_BAD_INLINE_DIR_SIZE, &pctx)) {
|
|
|
|
errcode_t err = fix_inline_dir_size(ctx, ino,
|
|
|
|
&inline_data_size, &pctx,
|
|
|
|
buf);
|
|
|
|
if (err)
|
|
|
|
return DIRENT_ABORT;
|
|
|
|
|
|
|
|
}
|
2007-04-14 17:29:02 +04:00
|
|
|
ehandler_operation(0);
|
2001-05-05 09:14:59 +04:00
|
|
|
if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
|
|
|
|
cd->pctx.errcode = 0; /* We'll handle this ourselves */
|
2012-08-03 01:27:43 +04:00
|
|
|
else if (cd->pctx.errcode == EXT2_ET_DIR_CSUM_INVALID) {
|
|
|
|
cd->pctx.errcode = 0; /* We'll handle this ourselves */
|
|
|
|
failed_csum = 1;
|
|
|
|
}
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (cd->pctx.errcode) {
|
2012-08-03 01:27:43 +04:00
|
|
|
char *buf2;
|
1997-11-03 22:42:40 +03:00
|
|
|
if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
|
|
|
|
ctx->flags |= E2F_FLAG_ABORT;
|
|
|
|
return DIRENT_ABORT;
|
|
|
|
}
|
2012-08-03 01:27:43 +04:00
|
|
|
ext2fs_new_dir_block(fs, db->blockcnt == 0 ? ino : 0,
|
|
|
|
EXT2_ROOT_INO, &buf2);
|
|
|
|
memcpy(buf, buf2, fs->blocksize);
|
|
|
|
ext2fs_free_mem(&buf2);
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2002-06-26 07:26:34 +04:00
|
|
|
dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
|
2002-07-16 00:54:42 +04:00
|
|
|
if (dx_dir && dx_dir->numblocks) {
|
2002-06-26 07:26:34 +04:00
|
|
|
if (db->blockcnt >= dx_dir->numblocks) {
|
2014-11-05 19:10:31 +03:00
|
|
|
pctx.dir = ino;
|
2008-08-28 07:07:54 +04:00
|
|
|
if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK,
|
2008-03-12 23:10:48 +03:00
|
|
|
&pctx)) {
|
|
|
|
clear_htree(ctx, ino);
|
|
|
|
dx_dir->numblocks = 0;
|
|
|
|
dx_db = 0;
|
|
|
|
goto out_htree;
|
|
|
|
}
|
|
|
|
fatal_error(ctx, _("Can not continue."));
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
|
|
|
dx_db = &dx_dir->dx_block[db->blockcnt];
|
|
|
|
dx_db->type = DX_DIRBLOCK_LEAF;
|
|
|
|
dx_db->phys = block_nr;
|
|
|
|
dx_db->min_hash = ~0;
|
|
|
|
dx_db->max_hash = 0;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
dirent = (struct ext2_dir_entry *) buf;
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
|
2002-09-30 03:30:28 +04:00
|
|
|
limit = (struct ext2_dx_countlimit *) (buf+8);
|
2002-06-26 07:26:34 +04:00
|
|
|
if (db->blockcnt == 0) {
|
2002-08-31 10:32:41 +04:00
|
|
|
root = (struct ext2_dx_root_info *) (buf + 24);
|
2002-06-26 07:26:34 +04:00
|
|
|
dx_db->type = DX_DIRBLOCK_ROOT;
|
|
|
|
dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
|
2002-08-31 10:32:41 +04:00
|
|
|
if ((root->reserved_zero ||
|
|
|
|
root->info_length < 8 ||
|
|
|
|
root->indirect_levels > 1) &&
|
|
|
|
fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
|
|
|
|
clear_htree(ctx, ino);
|
|
|
|
dx_dir->numblocks = 0;
|
|
|
|
dx_db = 0;
|
2006-11-12 06:32:35 +03:00
|
|
|
}
|
2002-08-31 10:32:41 +04:00
|
|
|
dx_dir->hashversion = root->hash_version;
|
2006-11-12 06:32:35 +03:00
|
|
|
if ((dx_dir->hashversion <= EXT2_HASH_TEA) &&
|
|
|
|
(fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
|
|
|
|
dx_dir->hashversion += 3;
|
2002-09-30 19:19:19 +04:00
|
|
|
dx_dir->depth = root->indirect_levels + 1;
|
2002-06-26 07:26:34 +04:00
|
|
|
} else if ((dirent->inode == 0) &&
|
2008-08-26 05:08:19 +04:00
|
|
|
(rec_len == fs->blocksize) &&
|
2013-06-08 19:26:14 +04:00
|
|
|
(ext2fs_dirent_name_len(dirent) == 0) &&
|
2008-08-28 07:07:54 +04:00
|
|
|
(ext2fs_le16_to_cpu(limit->limit) ==
|
2012-08-03 01:27:30 +04:00
|
|
|
((fs->blocksize - (8 + dx_csum_size)) /
|
2002-10-03 06:07:17 +04:00
|
|
|
sizeof(struct ext2_dx_entry))))
|
2002-06-26 07:26:34 +04:00
|
|
|
dx_db->type = DX_DIRBLOCK_NODE;
|
2015-07-22 07:06:43 +03:00
|
|
|
is_leaf = (dx_db->type == DX_DIRBLOCK_LEAF);
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
2008-03-12 23:10:48 +03:00
|
|
|
out_htree:
|
1997-04-26 17:21:57 +04:00
|
|
|
|
2014-08-03 06:32:12 +04:00
|
|
|
/* Leaf node with no space for csum? Rebuild dirs in pass 3A. */
|
|
|
|
if (is_leaf && !inline_data_size && failed_csum &&
|
|
|
|
!ext2fs_dirent_has_tail(fs, (struct ext2_dir_entry *)buf)) {
|
|
|
|
de_csum_size = 0;
|
2014-12-14 05:55:12 +03:00
|
|
|
if (e2fsck_dir_will_be_rehashed(ctx, ino)) {
|
|
|
|
failed_csum = 0;
|
|
|
|
goto skip_checksum;
|
|
|
|
}
|
|
|
|
if (!fix_problem(cd->ctx, PR_2_LEAF_NODE_MISSING_CSUM,
|
2014-08-03 06:32:12 +04:00
|
|
|
&cd->pctx))
|
2012-08-03 01:27:43 +04:00
|
|
|
goto skip_checksum;
|
2014-08-03 06:32:12 +04:00
|
|
|
e2fsck_rehash_dir_later(ctx, ino);
|
2014-12-14 05:55:12 +03:00
|
|
|
failed_csum = 0;
|
2014-08-03 06:32:12 +04:00
|
|
|
goto skip_checksum;
|
2012-08-03 01:27:43 +04:00
|
|
|
}
|
|
|
|
/* htree nodes don't use fake dirents to store checksums */
|
|
|
|
if (!is_leaf)
|
|
|
|
de_csum_size = 0;
|
|
|
|
|
|
|
|
skip_checksum:
|
2015-01-28 17:00:13 +03:00
|
|
|
if (inline_data_size) {
|
|
|
|
if (db->blockcnt) {
|
|
|
|
buf += EXT4_MIN_INLINE_DATA_SIZE;
|
|
|
|
max_block_size = inline_data_size - EXT4_MIN_INLINE_DATA_SIZE;
|
|
|
|
/* Zero-length second block, just exit */
|
|
|
|
if (max_block_size == 0)
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
max_block_size = EXT4_MIN_INLINE_DATA_SIZE;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
max_block_size = fs->blocksize - de_csum_size;
|
|
|
|
|
2015-03-09 02:09:52 +03:00
|
|
|
if (ctx->encrypted_dirs)
|
|
|
|
encrypted = ext2fs_u32_list_test(ctx->encrypted_dirs, ino);
|
|
|
|
|
2003-03-15 06:19:10 +03:00
|
|
|
dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
|
2002-09-28 17:16:28 +04:00
|
|
|
prev = 0;
|
1997-04-26 17:21:57 +04:00
|
|
|
do {
|
2013-12-03 08:21:31 +04:00
|
|
|
dgrp_t group;
|
2007-10-22 06:04:03 +04:00
|
|
|
ext2_ino_t first_unused_inode;
|
2013-06-08 19:26:14 +04:00
|
|
|
unsigned int name_len;
|
2007-10-22 06:04:03 +04:00
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
problem = 0;
|
2014-03-03 10:02:44 +04:00
|
|
|
if (!inline_data_size || dot_state > 1) {
|
|
|
|
dirent = (struct ext2_dir_entry *) (buf + offset);
|
2015-01-29 19:09:07 +03:00
|
|
|
/*
|
|
|
|
* If there's not even space for the entry header,
|
|
|
|
* force salvaging this dir.
|
|
|
|
*/
|
|
|
|
if (max_block_size - offset < EXT2_DIR_ENTRY_HEADER_LEN)
|
|
|
|
rec_len = EXT2_DIR_REC_LEN(1);
|
|
|
|
else
|
|
|
|
(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
|
2014-03-03 10:02:44 +04:00
|
|
|
cd->pctx.dirent = dirent;
|
|
|
|
cd->pctx.num = offset;
|
2015-01-29 19:09:07 +03:00
|
|
|
if ((offset + rec_len > max_block_size) ||
|
2014-03-03 10:02:44 +04:00
|
|
|
(rec_len < 12) ||
|
|
|
|
((rec_len % 4) != 0) ||
|
2016-05-29 20:36:20 +03:00
|
|
|
(((unsigned) ext2fs_dirent_name_len(dirent) + EXT2_DIR_ENTRY_HEADER_LEN) > rec_len)) {
|
2014-07-28 03:45:04 +04:00
|
|
|
if (fix_problem(ctx, PR_2_DIR_CORRUPTED,
|
|
|
|
&cd->pctx)) {
|
2014-08-25 06:02:49 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
/*
|
|
|
|
* On big-endian systems, if the dirent
|
|
|
|
* swap routine finds a rec_len that it
|
|
|
|
* doesn't like, it continues
|
|
|
|
* processing the block as if rec_len
|
2015-01-29 19:09:07 +03:00
|
|
|
* == EXT2_DIR_ENTRY_HEADER_LEN. This means that the name
|
2014-08-25 06:02:49 +04:00
|
|
|
* field gets byte swapped, which means
|
|
|
|
* that salvage will not detect the
|
|
|
|
* correct name length (unless the name
|
|
|
|
* has a length that's an exact
|
|
|
|
* multiple of four bytes), and it'll
|
|
|
|
* discard the entry (unnecessarily)
|
|
|
|
* and the rest of the dirent block.
|
|
|
|
* Therefore, swap the rest of the
|
|
|
|
* block back to disk order, run
|
|
|
|
* salvage, and re-swap anything after
|
|
|
|
* the salvaged dirent.
|
|
|
|
*/
|
|
|
|
int need_reswab = 0;
|
2015-01-29 19:09:07 +03:00
|
|
|
if (rec_len < EXT2_DIR_ENTRY_HEADER_LEN || rec_len % 4) {
|
2014-08-25 06:02:49 +04:00
|
|
|
need_reswab = 1;
|
|
|
|
ext2fs_dirent_swab_in2(fs,
|
2015-01-29 19:09:07 +03:00
|
|
|
((char *)dirent) + EXT2_DIR_ENTRY_HEADER_LEN,
|
|
|
|
max_block_size - offset - EXT2_DIR_ENTRY_HEADER_LEN,
|
2014-08-25 06:02:49 +04:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
#endif
|
2014-07-28 03:45:04 +04:00
|
|
|
salvage_directory(fs, dirent, prev,
|
|
|
|
&offset,
|
2014-08-11 02:44:42 +04:00
|
|
|
max_block_size);
|
2014-08-25 06:02:49 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
if (need_reswab) {
|
|
|
|
(void) ext2fs_get_rec_len(fs,
|
|
|
|
dirent, &rec_len);
|
|
|
|
ext2fs_dirent_swab_in2(fs,
|
|
|
|
((char *)dirent) + offset + rec_len,
|
|
|
|
max_block_size - offset - rec_len,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
#endif
|
2014-03-03 10:02:44 +04:00
|
|
|
dir_modified++;
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
goto abort_free_dict;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (dot_state == 0) {
|
|
|
|
memset(&dot, 0, sizeof(dot));
|
|
|
|
dirent = ˙
|
|
|
|
dirent->inode = ino;
|
|
|
|
dirent->rec_len = EXT2_DIR_REC_LEN(1);
|
|
|
|
dirent->name_len = 1 | filetype;
|
|
|
|
dirent->name[0] = '.';
|
|
|
|
} else if (dot_state == 1) {
|
|
|
|
memset(&dotdot, 0, sizeof(dotdot));
|
|
|
|
dirent = &dotdot;
|
|
|
|
dirent->inode =
|
|
|
|
((struct ext2_dir_entry *)buf)->inode;
|
|
|
|
dirent->rec_len = EXT2_DIR_REC_LEN(2);
|
|
|
|
dirent->name_len = 2 | filetype;
|
|
|
|
dirent->name[0] = '.';
|
|
|
|
dirent->name[1] = '.';
|
|
|
|
} else {
|
|
|
|
fatal_error(ctx, _("Can not continue."));
|
|
|
|
}
|
|
|
|
cd->pctx.dirent = dirent;
|
|
|
|
cd->pctx.num = offset;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
1997-04-26 17:58:21 +04:00
|
|
|
|
2002-09-28 17:16:28 +04:00
|
|
|
if (dot_state == 0) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (check_dot(ctx, dirent, ino, &cd->pctx))
|
1997-04-26 17:21:57 +04:00
|
|
|
dir_modified++;
|
2002-09-28 17:16:28 +04:00
|
|
|
} else if (dot_state == 1) {
|
2007-04-05 06:33:31 +04:00
|
|
|
ret = check_dotdot(ctx, dirent, ino, &cd->pctx);
|
|
|
|
if (ret < 0)
|
2003-03-15 06:19:10 +03:00
|
|
|
goto abort_free_dict;
|
2007-04-05 06:33:31 +04:00
|
|
|
if (ret)
|
1997-04-26 17:21:57 +04:00
|
|
|
dir_modified++;
|
|
|
|
} else if (dirent->inode == ino) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
problem = PR_2_LINK_DOT;
|
|
|
|
if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode = 0;
|
|
|
|
dir_modified++;
|
1997-04-29 20:15:03 +04:00
|
|
|
goto next;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
if (!dirent->inode)
|
1997-04-26 17:21:57 +04:00
|
|
|
goto next;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Make sure the inode listed is a legal one.
|
2008-08-28 07:07:54 +04:00
|
|
|
*/
|
2013-06-08 19:26:14 +04:00
|
|
|
name_len = ext2fs_dirent_name_len(dirent);
|
1997-04-26 17:21:57 +04:00
|
|
|
if (((dirent->inode != EXT2_ROOT_INO) &&
|
1997-04-26 18:48:50 +04:00
|
|
|
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
|
1997-04-26 17:21:57 +04:00
|
|
|
(dirent->inode > fs->super->s_inodes_count)) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
problem = PR_2_BAD_INO;
|
|
|
|
} else if (ctx->inode_bb_map &&
|
2009-08-23 06:29:02 +04:00
|
|
|
(ext2fs_test_inode_bitmap2(ctx->inode_bb_map,
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
dirent->inode))) {
|
|
|
|
/*
|
|
|
|
* If the inode is in a bad block, offer to
|
|
|
|
* clear it.
|
|
|
|
*/
|
|
|
|
problem = PR_2_BB_INODE;
|
2013-06-08 19:26:14 +04:00
|
|
|
} else if ((dot_state > 1) && (name_len == 1) &&
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
(dirent->name[0] == '.')) {
|
|
|
|
/*
|
|
|
|
* If there's a '.' entry in anything other
|
|
|
|
* than the first directory entry, it's a
|
|
|
|
* duplicate entry that should be removed.
|
|
|
|
*/
|
|
|
|
problem = PR_2_DUP_DOT;
|
2013-06-08 19:26:14 +04:00
|
|
|
} else if ((dot_state > 1) && (name_len == 2) &&
|
2008-08-28 07:07:54 +04:00
|
|
|
(dirent->name[0] == '.') &&
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
(dirent->name[1] == '.')) {
|
|
|
|
/*
|
|
|
|
* If there's a '..' entry in anything other
|
|
|
|
* than the second directory entry, it's a
|
|
|
|
* duplicate entry that should be removed.
|
|
|
|
*/
|
|
|
|
problem = PR_2_DUP_DOT_DOT;
|
2002-09-28 17:16:28 +04:00
|
|
|
} else if ((dot_state > 1) &&
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
(dirent->inode == EXT2_ROOT_INO)) {
|
|
|
|
/*
|
|
|
|
* Don't allow links to the root directory.
|
|
|
|
* We check this specially to make sure we
|
|
|
|
* catch this error case even if the root
|
|
|
|
* directory hasn't been created yet.
|
|
|
|
*/
|
|
|
|
problem = PR_2_LINK_ROOT;
|
2013-06-08 19:26:14 +04:00
|
|
|
} else if ((dot_state > 1) && (name_len == 0)) {
|
1999-10-26 01:03:34 +04:00
|
|
|
/*
|
|
|
|
* Don't allow zero-length directory names.
|
|
|
|
*/
|
|
|
|
problem = PR_2_NULL_NAME;
|
1997-04-29 20:15:03 +04:00
|
|
|
}
|
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (problem) {
|
|
|
|
if (fix_problem(ctx, problem, &cd->pctx)) {
|
1997-04-29 20:15:03 +04:00
|
|
|
dirent->inode = 0;
|
|
|
|
dir_modified++;
|
|
|
|
goto next;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
} else {
|
|
|
|
ext2fs_unmark_valid(fs);
|
|
|
|
if (problem == PR_2_BAD_INO)
|
|
|
|
goto next;
|
1997-04-29 20:15:03 +04:00
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the inode was marked as having bad fields in
|
|
|
|
* pass1, process it and offer to fix/clear it.
|
|
|
|
* (We wait until now so that we can display the
|
|
|
|
* pathname to the user.)
|
|
|
|
*/
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (ctx->inode_bad_map &&
|
2009-08-23 06:29:02 +04:00
|
|
|
ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode)) {
|
ChangeLog, e2fsck.h, pass1.c, pass2.c, pass4.c, swapfs.c:
e2fsck.h:
pass1.c (pass1_get_blocks, pass1_read_inode, pass1_write_inode,
pass1_check_directory, e2fsck_use_inode_shortcuts): Make pass1_* be
private static functions, and create new function
e2fsck_use_inode_shortcuts which sets and clears the inode shortcut
functions in the fs structure.
e2fsck.h:
pass2.c (e2fsck_process_bad_inode): Make process_bad_inode() an
exported function.
pass4.c (e2fsck_pass4): Call e2fsck_process_bad_inode to check if a
disconnected inode has any problems before connecting it to
/lost+found. Bug and suggested fix by Pavel Machek <pavel@bug.ucw.cz>
ChangeLog, swapfs.c:
swapfs.c (ext2fs_swap_inode): Add compatibility for Linux 2.3 kernels
that use i_generation instead of i_version. Patch supplied by Jon
Bright <sircus@sircus.demon.co.uk>.
ChangeLog, mke2fs.8.in:
mke2fs.8.in: Fix typo in man page which caused the badblocks command
to not show up in the "SEE ALSO" section.
ChangeLog, expect.1, expect.2, image.gz, name:
f_recnect_bad: New test which checks the case where a disconnect inode
also bad inode fields; we need to make sure e2fsck offers to fix the
inode (or clear the inode, as necessary).
1999-06-25 19:40:18 +04:00
|
|
|
if (e2fsck_process_bad_inode(ctx, ino,
|
2002-05-21 17:14:17 +04:00
|
|
|
dirent->inode,
|
|
|
|
buf + fs->blocksize)) {
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode = 0;
|
|
|
|
dir_modified++;
|
|
|
|
goto next;
|
|
|
|
}
|
1998-02-24 23:22:23 +03:00
|
|
|
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
|
1997-11-03 22:42:40 +03:00
|
|
|
return DIRENT_ABORT;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2007-10-22 06:04:03 +04:00
|
|
|
group = ext2fs_group_of_ino(fs, dirent->inode);
|
|
|
|
first_unused_inode = group * fs->super->s_inodes_per_group +
|
|
|
|
1 + fs->super->s_inodes_per_group -
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
ext2fs_bg_itable_unused(fs, group);
|
2007-10-22 06:04:03 +04:00
|
|
|
cd->pctx.group = group;
|
|
|
|
|
|
|
|
/*
|
2008-11-27 04:41:26 +03:00
|
|
|
* Check if the inode was missed out because
|
|
|
|
* _INODE_UNINIT flag was set or bg_itable_unused was
|
|
|
|
* incorrect. If so, clear the _INODE_UNINIT flag and
|
|
|
|
* restart e2fsck. In the future it would be nice if
|
|
|
|
* we could call a function in pass1.c that checks the
|
|
|
|
* newly visible inodes.
|
2007-10-22 06:04:03 +04:00
|
|
|
*/
|
2009-10-26 04:42:12 +03:00
|
|
|
if (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)) {
|
2009-05-28 10:39:49 +04:00
|
|
|
pctx.num = dirent->inode;
|
2007-10-22 06:04:03 +04:00
|
|
|
if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT,
|
|
|
|
&cd->pctx)){
|
libext2fs: clean up ext2fs_bg_flags_ interfaces
The ext2fs_bg_flag* functions were confusing.
Currently we have this:
void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags);
void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group,__u16 bg_flags);
(_set (unused) sets exactly bg_flags; _clear clears all and ignores bg_flags)
and these, which can twiddle individual bits in bg_flags:
void ext2fs_bg_flag_set(ext2_filsys fs, dgrp_t group, __u16 bg_flag);
void ext2fs_bg_flag_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flag);
A better interface, after the patch below, is just:
ext2fs_bg_flags_zap(fs, group) /* zeros bg_flags */
ext2fs_bg_flags_set(fs, group, flags) /* adds flags to bg_flags */
ext2fs_bg_flags_clear(fs, group, flags) /* clears flags in bg_flags */
and remove the original ext2fs_bg_flags_set / ext2fs_bg_flags_clear.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:41:32 +03:00
|
|
|
ext2fs_bg_flags_clear(fs, group,
|
2009-09-08 05:15:12 +04:00
|
|
|
EXT2_BG_INODE_UNINIT);
|
2008-11-27 04:41:26 +03:00
|
|
|
ext2fs_mark_super_dirty(fs);
|
2009-05-28 10:39:49 +04:00
|
|
|
ctx->flags |= E2F_FLAG_RESTART_LATER;
|
2007-10-22 06:04:03 +04:00
|
|
|
} else {
|
|
|
|
ext2fs_unmark_valid(fs);
|
|
|
|
if (problem == PR_2_BAD_INO)
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
} else if (dirent->inode >= first_unused_inode) {
|
2009-05-28 10:39:49 +04:00
|
|
|
pctx.num = dirent->inode;
|
2007-10-22 06:04:03 +04:00
|
|
|
if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
ext2fs_bg_itable_unused_set(fs, group, 0);
|
2007-10-22 06:04:03 +04:00
|
|
|
ext2fs_mark_super_dirty(fs);
|
2009-05-28 10:39:49 +04:00
|
|
|
ctx->flags |= E2F_FLAG_RESTART_LATER;
|
2007-10-22 06:04:03 +04:00
|
|
|
} else {
|
|
|
|
ext2fs_unmark_valid(fs);
|
|
|
|
if (problem == PR_2_BAD_INO)
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-11 23:12:52 +04:00
|
|
|
/*
|
|
|
|
* Offer to clear unused inodes; if we are going to be
|
|
|
|
* restarting the scan due to bg_itable_unused being
|
|
|
|
* wrong, then don't clear any inodes to avoid zapping
|
|
|
|
* inodes that were skipped during pass1 due to an
|
|
|
|
* incorrect bg_itable_unused; we'll get any real
|
|
|
|
* problems after we restart.
|
|
|
|
*/
|
|
|
|
if (!(ctx->flags & E2F_FLAG_RESTART_LATER) &&
|
2010-06-07 20:42:40 +04:00
|
|
|
!(ext2fs_test_inode_bitmap2(ctx->inode_used_map,
|
|
|
|
dirent->inode)))
|
2007-10-22 06:04:03 +04:00
|
|
|
problem = PR_2_UNUSED_INODE;
|
|
|
|
|
|
|
|
if (problem) {
|
|
|
|
if (fix_problem(ctx, problem, &cd->pctx)) {
|
|
|
|
dirent->inode = 0;
|
|
|
|
dir_modified++;
|
|
|
|
goto next;
|
|
|
|
} else {
|
|
|
|
ext2fs_unmark_valid(fs);
|
|
|
|
if (problem == PR_2_BAD_INO)
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 15:31:51 +03:00
|
|
|
if (!encrypted && check_name(ctx, dirent, &cd->pctx))
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
dir_modified++;
|
|
|
|
|
2015-07-17 00:19:38 +03:00
|
|
|
if (encrypted && (dot_state) > 1 &&
|
|
|
|
encrypted_check_name(ctx, dirent, &cd->pctx)) {
|
|
|
|
dir_modified++;
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
Many files:
pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
bitmap, don't check to see if it is disconnected from the inode tree
(because it almost certainly will be). Free inode_imagic_map at the
end of pass 4.
pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
set, check the directory entry's filetype information field, and
fix/set it if necessary. (e2fsck_pass2): Free the inode_reg_map
bitmap at the end of pass 2.
pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
information for inode_reg_map and inode_imagic_map, which indicates
which inodes are regular files and AFS inodes, respectively.
Since only the master superblock is written during a restart, force
that superblock to be used after a restart; otherwise changes to the
block group descriptors end up getting ignored.
problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
for "no". Add support for a new flag, PR_NO_NOMSG, which supresses
the problem message if e2fsck is run with the -n option.
problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
problem codes.
message.c (expand_dirent_expression): Add support for %dt which prints
the dirent type information.
e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
inode_imagic_map).
e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
context structure.
ChangeLog, nt_io.c:
nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
Add support for non-Unix compiles
1999-10-21 23:33:18 +04:00
|
|
|
if (check_filetype(ctx, dirent, ino, &cd->pctx))
|
|
|
|
dir_modified++;
|
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
if (dx_db) {
|
2015-05-03 21:48:25 +03:00
|
|
|
ext2fs_dirhash(dx_dir->hashversion, dirent->name,
|
|
|
|
ext2fs_dirent_name_len(dirent),
|
|
|
|
fs->super->s_hash_seed, &hash, 0);
|
2002-06-26 07:26:34 +04:00
|
|
|
if (hash < dx_db->min_hash)
|
|
|
|
dx_db->min_hash = hash;
|
|
|
|
if (hash > dx_db->max_hash)
|
|
|
|
dx_db->max_hash = hash;
|
|
|
|
}
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* If this is a directory, then mark its parent in its
|
|
|
|
* dir_info structure. If the parent field is already
|
|
|
|
* filled in, then this directory has more than one
|
|
|
|
* hard link. We assume the first link is correct,
|
|
|
|
* and ask the user if he/she wants to clear this one.
|
|
|
|
*/
|
2002-09-28 17:16:28 +04:00
|
|
|
if ((dot_state > 1) &&
|
2009-08-23 06:29:02 +04:00
|
|
|
(ext2fs_test_inode_bitmap2(ctx->inode_dir_map,
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode))) {
|
2007-04-05 06:33:31 +04:00
|
|
|
if (e2fsck_dir_info_get_parent(ctx, dirent->inode,
|
|
|
|
&subdir_parent)) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
cd->pctx.ino = dirent->inode;
|
|
|
|
fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
|
2003-03-15 06:19:10 +03:00
|
|
|
goto abort_free_dict;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2007-04-05 06:33:31 +04:00
|
|
|
if (subdir_parent) {
|
|
|
|
cd->pctx.ino2 = subdir_parent;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, PR_2_LINK_DIR,
|
1997-04-29 20:15:03 +04:00
|
|
|
&cd->pctx)) {
|
1997-04-26 17:21:57 +04:00
|
|
|
dirent->inode = 0;
|
|
|
|
dir_modified++;
|
|
|
|
goto next;
|
1997-04-29 20:15:03 +04:00
|
|
|
}
|
|
|
|
cd->pctx.ino2 = 0;
|
2007-04-05 06:33:31 +04:00
|
|
|
} else {
|
2008-08-28 07:07:54 +04:00
|
|
|
(void) e2fsck_dir_info_set_parent(ctx,
|
2007-04-05 06:33:31 +04:00
|
|
|
dirent->inode, ino);
|
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2003-03-15 06:19:10 +03:00
|
|
|
|
|
|
|
if (dups_found) {
|
|
|
|
;
|
|
|
|
} else if (dict_lookup(&de_dict, dirent)) {
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
pctx.ino = ino;
|
|
|
|
pctx.dirent = dirent;
|
|
|
|
fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
|
2012-08-03 01:27:43 +04:00
|
|
|
e2fsck_rehash_dir_later(ctx, ino);
|
2003-03-15 06:19:10 +03:00
|
|
|
dups_found++;
|
|
|
|
} else
|
|
|
|
dict_alloc_insert(&de_dict, dirent, dirent);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
ext2fs_icount_increment(ctx->inode_count, dirent->inode,
|
|
|
|
&links);
|
1997-04-29 20:15:03 +04:00
|
|
|
if (links > 1)
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
ctx->fs_links_count++;
|
|
|
|
ctx->fs_total_count++;
|
1997-04-26 17:21:57 +04:00
|
|
|
next:
|
2002-09-28 17:16:28 +04:00
|
|
|
prev = dirent;
|
2008-08-26 05:08:19 +04:00
|
|
|
if (dir_modified)
|
2009-06-22 05:07:38 +04:00
|
|
|
(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
|
2014-03-03 10:02:44 +04:00
|
|
|
if (!inline_data_size || dot_state > 1) {
|
|
|
|
offset += rec_len;
|
|
|
|
} else {
|
2014-08-11 02:50:38 +04:00
|
|
|
if (dot_state == 1) {
|
2014-03-03 10:02:44 +04:00
|
|
|
offset = 4;
|
2014-08-11 02:50:38 +04:00
|
|
|
/*
|
|
|
|
* If we get here, we're checking an inline
|
|
|
|
* directory and we've just checked a (fake)
|
|
|
|
* dotdot entry that we created on the stack.
|
|
|
|
* Therefore set 'prev' to NULL so that if we
|
|
|
|
* call salvage_directory on the next entry,
|
|
|
|
* it won't try to absorb the next entry into
|
|
|
|
* the on-stack dotdot entry.
|
|
|
|
*/
|
|
|
|
prev = NULL;
|
|
|
|
}
|
2014-03-03 10:02:44 +04:00
|
|
|
}
|
2002-09-28 17:16:28 +04:00
|
|
|
dot_state++;
|
2015-01-28 17:00:13 +03:00
|
|
|
} while (offset < max_block_size);
|
1997-04-26 17:21:57 +04:00
|
|
|
#if 0
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
2002-06-26 07:26:34 +04:00
|
|
|
if (dx_db) {
|
|
|
|
#ifdef DX_DEBUG
|
|
|
|
printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
|
|
|
|
db->blockcnt, dx_db->type,
|
|
|
|
dx_db->min_hash, dx_db->max_hash);
|
|
|
|
#endif
|
2002-07-20 08:28:07 +04:00
|
|
|
cd->pctx.dir = cd->pctx.ino;
|
2002-06-26 07:26:34 +04:00
|
|
|
if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
|
|
|
|
(dx_db->type == DX_DIRBLOCK_NODE))
|
2012-08-03 01:27:43 +04:00
|
|
|
parse_int_node(fs, db, cd, dx_dir, buf, failed_csum);
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
2012-08-03 01:27:43 +04:00
|
|
|
|
2015-01-28 17:00:13 +03:00
|
|
|
if (offset != max_block_size) {
|
|
|
|
cd->pctx.num = rec_len + offset - max_block_size;
|
|
|
|
if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
|
|
|
|
dirent->rec_len = cd->pctx.num;
|
|
|
|
dir_modified++;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
if (dir_modified) {
|
e2fsck: correctly preserve fs flags when modifying ignore-csum-error flag
When we need to modify the "ignore checksum error" behavior flag to
get us past a library call, it's possible that the library call can
result in other flag bits being changed. Therefore, it is not correct
to restore unconditionally the previous flags value, since this will
have unintended side effects on the other fs->flags; nor is it correct
to assume that we can unconditionally set (or clear) the "ignore csum
error" flag bit. Therefore, we must merge the previous value of the
"ignore csum error" flag with the value of flags after the call.
Note that we want to leave checksum verification on as much as
possible because doing so exposes e2fsck bugs where two metadata
blocks are "sharing" the same disk block, and attempting to fix one
before relocating the other causes major filesystem damage. The
damage is much more obvious when a previously checked piece of
metadata suddenly fails in a subsequent pass.
The modifications to the pass 2, 3, and 3A code are justified as
follows: When e2fsck encounters a block of directory entries and
cannot find the placeholder entry at the end that contains the
checksum, it will try to insert the placeholder. If that fails, it
will schedule the directory for a pass 3A reconstruction. Until that
happens, we don't want directory block writing (pass 2), block
iteration (pass 3), or block reading (pass 3A) to fail due to checksum
errors, because failing to find the placeholder is itself a checksum
verification error, which causes e2fsck to abort without fixing
anything.
The e2fsck call to ext2fs_read_bitmaps must never fail due to a
checksum error because e2fsck subsequently (a) verifies the bitmaps
itself; or (b) decides that they don't match what has been observed,
and rewrites them.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2014-08-03 06:48:21 +04:00
|
|
|
int flags, will_rehash;
|
2012-08-03 01:27:43 +04:00
|
|
|
/* leaf block with no tail? Rehash dirs later. */
|
2015-10-24 07:43:19 +03:00
|
|
|
if (ext2fs_has_feature_metadata_csum(fs->super) &&
|
2012-08-03 01:27:43 +04:00
|
|
|
is_leaf &&
|
2014-07-27 01:13:31 +04:00
|
|
|
!inline_data_size &&
|
|
|
|
!ext2fs_dirent_has_tail(fs, (struct ext2_dir_entry *)buf)) {
|
|
|
|
if (insert_dirent_tail(fs, buf) == 0)
|
|
|
|
goto write_and_fix;
|
2012-08-03 01:27:43 +04:00
|
|
|
e2fsck_rehash_dir_later(ctx, ino);
|
2014-07-27 01:13:31 +04:00
|
|
|
}
|
2012-08-03 01:27:43 +04:00
|
|
|
|
|
|
|
write_and_fix:
|
e2fsck: correctly preserve fs flags when modifying ignore-csum-error flag
When we need to modify the "ignore checksum error" behavior flag to
get us past a library call, it's possible that the library call can
result in other flag bits being changed. Therefore, it is not correct
to restore unconditionally the previous flags value, since this will
have unintended side effects on the other fs->flags; nor is it correct
to assume that we can unconditionally set (or clear) the "ignore csum
error" flag bit. Therefore, we must merge the previous value of the
"ignore csum error" flag with the value of flags after the call.
Note that we want to leave checksum verification on as much as
possible because doing so exposes e2fsck bugs where two metadata
blocks are "sharing" the same disk block, and attempting to fix one
before relocating the other causes major filesystem damage. The
damage is much more obvious when a previously checked piece of
metadata suddenly fails in a subsequent pass.
The modifications to the pass 2, 3, and 3A code are justified as
follows: When e2fsck encounters a block of directory entries and
cannot find the placeholder entry at the end that contains the
checksum, it will try to insert the placeholder. If that fails, it
will schedule the directory for a pass 3A reconstruction. Until that
happens, we don't want directory block writing (pass 2), block
iteration (pass 3), or block reading (pass 3A) to fail due to checksum
errors, because failing to find the placeholder is itself a checksum
verification error, which causes e2fsck to abort without fixing
anything.
The e2fsck call to ext2fs_read_bitmaps must never fail due to a
checksum error because e2fsck subsequently (a) verifies the bitmaps
itself; or (b) decides that they don't match what has been observed,
and rewrites them.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2014-08-03 06:48:21 +04:00
|
|
|
will_rehash = e2fsck_dir_will_be_rehashed(ctx, ino);
|
|
|
|
if (will_rehash) {
|
|
|
|
flags = ctx->fs->flags;
|
2012-08-03 01:27:43 +04:00
|
|
|
ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
e2fsck: correctly preserve fs flags when modifying ignore-csum-error flag
When we need to modify the "ignore checksum error" behavior flag to
get us past a library call, it's possible that the library call can
result in other flag bits being changed. Therefore, it is not correct
to restore unconditionally the previous flags value, since this will
have unintended side effects on the other fs->flags; nor is it correct
to assume that we can unconditionally set (or clear) the "ignore csum
error" flag bit. Therefore, we must merge the previous value of the
"ignore csum error" flag with the value of flags after the call.
Note that we want to leave checksum verification on as much as
possible because doing so exposes e2fsck bugs where two metadata
blocks are "sharing" the same disk block, and attempting to fix one
before relocating the other causes major filesystem damage. The
damage is much more obvious when a previously checked piece of
metadata suddenly fails in a subsequent pass.
The modifications to the pass 2, 3, and 3A code are justified as
follows: When e2fsck encounters a block of directory entries and
cannot find the placeholder entry at the end that contains the
checksum, it will try to insert the placeholder. If that fails, it
will schedule the directory for a pass 3A reconstruction. Until that
happens, we don't want directory block writing (pass 2), block
iteration (pass 3), or block reading (pass 3A) to fail due to checksum
errors, because failing to find the placeholder is itself a checksum
verification error, which causes e2fsck to abort without fixing
anything.
The e2fsck call to ext2fs_read_bitmaps must never fail due to a
checksum error because e2fsck subsequently (a) verifies the bitmaps
itself; or (b) decides that they don't match what has been observed,
and rewrites them.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2014-08-03 06:48:21 +04:00
|
|
|
}
|
2014-03-03 10:02:44 +04:00
|
|
|
if (inline_data_size) {
|
2015-01-28 17:00:13 +03:00
|
|
|
buf = ibuf;
|
2014-08-11 02:22:54 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2015-01-28 17:00:13 +03:00
|
|
|
if (db->blockcnt)
|
|
|
|
goto skip_first_write_swab;
|
2014-08-11 02:22:54 +04:00
|
|
|
*((__u32 *)buf) = ext2fs_le32_to_cpu(*((__u32 *)buf));
|
|
|
|
cd->pctx.errcode = ext2fs_dirent_swab_out2(fs,
|
|
|
|
buf + EXT4_INLINE_DATA_DOTDOT_SIZE,
|
2015-01-28 17:00:13 +03:00
|
|
|
EXT4_MIN_INLINE_DATA_SIZE -
|
2014-08-11 02:22:54 +04:00
|
|
|
EXT4_INLINE_DATA_DOTDOT_SIZE,
|
|
|
|
0);
|
2015-01-28 17:00:13 +03:00
|
|
|
if (cd->pctx.errcode)
|
|
|
|
goto skip_second_write_swab;
|
|
|
|
skip_first_write_swab:
|
|
|
|
if (inline_data_size <= EXT4_MIN_INLINE_DATA_SIZE ||
|
|
|
|
!db->blockcnt)
|
|
|
|
goto skip_second_write_swab;
|
|
|
|
cd->pctx.errcode = ext2fs_dirent_swab_out2(fs,
|
|
|
|
buf + EXT4_MIN_INLINE_DATA_SIZE,
|
|
|
|
inline_data_size -
|
|
|
|
EXT4_MIN_INLINE_DATA_SIZE,
|
|
|
|
0);
|
|
|
|
skip_second_write_swab:
|
2014-08-11 02:22:54 +04:00
|
|
|
if (cd->pctx.errcode &&
|
|
|
|
!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, &cd->pctx))
|
|
|
|
goto abort_free_dict;
|
|
|
|
#endif
|
2014-03-03 10:02:44 +04:00
|
|
|
cd->pctx.errcode =
|
|
|
|
ext2fs_inline_data_set(fs, ino, 0, buf,
|
|
|
|
inline_data_size);
|
|
|
|
} else
|
|
|
|
cd->pctx.errcode = ext2fs_write_dir_block4(fs, block_nr,
|
|
|
|
buf, 0, ino);
|
e2fsck: correctly preserve fs flags when modifying ignore-csum-error flag
When we need to modify the "ignore checksum error" behavior flag to
get us past a library call, it's possible that the library call can
result in other flag bits being changed. Therefore, it is not correct
to restore unconditionally the previous flags value, since this will
have unintended side effects on the other fs->flags; nor is it correct
to assume that we can unconditionally set (or clear) the "ignore csum
error" flag bit. Therefore, we must merge the previous value of the
"ignore csum error" flag with the value of flags after the call.
Note that we want to leave checksum verification on as much as
possible because doing so exposes e2fsck bugs where two metadata
blocks are "sharing" the same disk block, and attempting to fix one
before relocating the other causes major filesystem damage. The
damage is much more obvious when a previously checked piece of
metadata suddenly fails in a subsequent pass.
The modifications to the pass 2, 3, and 3A code are justified as
follows: When e2fsck encounters a block of directory entries and
cannot find the placeholder entry at the end that contains the
checksum, it will try to insert the placeholder. If that fails, it
will schedule the directory for a pass 3A reconstruction. Until that
happens, we don't want directory block writing (pass 2), block
iteration (pass 3), or block reading (pass 3A) to fail due to checksum
errors, because failing to find the placeholder is itself a checksum
verification error, which causes e2fsck to abort without fixing
anything.
The e2fsck call to ext2fs_read_bitmaps must never fail due to a
checksum error because e2fsck subsequently (a) verifies the bitmaps
itself; or (b) decides that they don't match what has been observed,
and rewrites them.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2014-08-03 06:48:21 +04:00
|
|
|
if (will_rehash)
|
|
|
|
ctx->fs->flags = (flags &
|
|
|
|
EXT2_FLAG_IGNORE_CSUM_ERRORS) |
|
|
|
|
(ctx->fs->flags &
|
|
|
|
~EXT2_FLAG_IGNORE_CSUM_ERRORS);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (cd->pctx.errcode) {
|
1997-11-03 22:42:40 +03:00
|
|
|
if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
|
2003-03-15 06:19:10 +03:00
|
|
|
&cd->pctx))
|
|
|
|
goto abort_free_dict;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
ext2fs_mark_changed(fs);
|
2012-08-03 01:27:43 +04:00
|
|
|
} else if (is_leaf && failed_csum && !dir_modified) {
|
|
|
|
/*
|
|
|
|
* If a leaf node that fails csum makes it this far without
|
|
|
|
* alteration, ask the user if the checksum should be fixed.
|
|
|
|
*/
|
|
|
|
if (fix_problem(ctx, PR_2_LEAF_NODE_ONLY_CSUM_INVALID,
|
|
|
|
&cd->pctx))
|
|
|
|
goto write_and_fix;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2003-03-15 06:19:10 +03:00
|
|
|
dict_free_nodes(&de_dict);
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
2003-03-15 06:19:10 +03:00
|
|
|
abort_free_dict:
|
|
|
|
ctx->flags |= E2F_FLAG_ABORT;
|
2007-10-22 06:04:03 +04:00
|
|
|
dict_free_nodes(&de_dict);
|
2003-03-15 06:19:10 +03:00
|
|
|
return DIRENT_ABORT;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2011-07-20 22:40:06 +04:00
|
|
|
struct del_block {
|
|
|
|
e2fsck_t ctx;
|
|
|
|
e2_blkcnt_t num;
|
|
|
|
};
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* This function is called to deallocate a block, and is an interator
|
|
|
|
* functioned called by deallocate inode via ext2fs_iterate_block().
|
|
|
|
*/
|
|
|
|
static int deallocate_inode_block(ext2_filsys fs,
|
2010-06-14 01:00:00 +04:00
|
|
|
blk64_t *block_nr,
|
2003-12-07 09:28:50 +03:00
|
|
|
e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
|
2010-06-14 01:00:00 +04:00
|
|
|
blk64_t ref_block EXT2FS_ATTR((unused)),
|
2003-12-07 09:28:50 +03:00
|
|
|
int ref_offset EXT2FS_ATTR((unused)),
|
ChangeLog, message.c, pass1b.c, pass2.c, pass3.c, problem.c, problem.h:
pass1b.c: Change routines to use PR_1B_BLOCK_ITERATE when reporting
problems rather than using com_err directly.
problem.c, problem.h (PR_1B_BLOCK_ITERATE): Add new problem code.
message.c (expand_percent_expression): Add safety check. If ctx->str
is NULL, print "NULL" instead of dereferencing the null pointer.
pass1b.c, pass2.c, pass3.c: Change calls to ext2fs_block_iterate to
ext2fs_block_iterate2, to support 64-bit filesizes and to speed things
up slightly by avoiding the use of the ext2fs_block_iterate's
compatibility shim layer.
version.h:
Update for WIP release.
2000-11-17 08:40:49 +03:00
|
|
|
void *priv_data)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2011-07-20 22:40:06 +04:00
|
|
|
struct del_block *p = priv_data;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2015-04-12 15:22:07 +03:00
|
|
|
if (*block_nr == 0)
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
2004-01-30 09:48:06 +03:00
|
|
|
if ((*block_nr < fs->super->s_first_data_block) ||
|
2009-09-08 04:46:34 +04:00
|
|
|
(*block_nr >= ext2fs_blocks_count(fs->super)))
|
2004-01-30 09:48:06 +03:00
|
|
|
return 0;
|
2014-07-27 00:28:58 +04:00
|
|
|
if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0)
|
|
|
|
ext2fs_block_alloc_stats2(fs, *block_nr, -1);
|
2011-07-20 22:40:06 +04:00
|
|
|
p->num++;
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* This fuction deallocates an inode
|
|
|
|
*/
|
2001-01-12 23:25:50 +03:00
|
|
|
static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
ext2_filsys fs = ctx->fs;
|
1997-04-26 17:21:57 +04:00
|
|
|
struct ext2_inode inode;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
struct problem_context pctx;
|
2002-08-17 18:19:44 +04:00
|
|
|
__u32 count;
|
2011-07-20 22:40:06 +04:00
|
|
|
struct del_block del_block;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-11-03 22:42:40 +03:00
|
|
|
e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
clear_problem_context(&pctx);
|
|
|
|
pctx.ino = ino;
|
1997-04-26 17:34:30 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Fix up the bitmaps...
|
|
|
|
*/
|
Many files:
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c: Add calls to the progress
indicator function.
pass1.c (scan_callback): Add call to the progress feedback function
(if it exists).
super.c (check_super_block): Skip the device size check if the
get_device_size returns EXT2_EXT_UNIMPLEMENTED.
iscan.c (main): Don't use fatal_error() anymore.
pass1b.c, swapfs.c, badblocks.c: Set E2F_FLAG_ABORT instead of calling
fatal_error(0).
problem.c, pass3.c (PR_3_ROOT_NOT_DIR_ABORT,
PR_3_NO_ROOT_INODE_ABORT): New problem codes.
problem.c, pass2.c (PR_2_SPLIT_DOT): New problem code.
problem.c, pass1.c (PR_1_SUPPRESS_MESSAGES): New problem code.
problemP.h: New file which separates out the private fix_problem data
structures.
util.c, dirinfo.c, pass1.c, pass1b.c, pass2.c, pass5.c, super.c,
swapfs.c util.c: allocate_memory() now takes a e2fsck context as its
first argument, and rename it to be e2fsck_allocate_memory().
problemP.h:
New file which contains the private problem abstraction definitions.
Makefile.pq:
Remove include of MAKEFILE.STD, which doesn't exist at this point.
1997-11-14 08:23:04 +03:00
|
|
|
e2fsck_read_bitmaps(ctx);
|
2002-08-17 18:19:44 +04:00
|
|
|
ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
|
|
|
|
|
2011-10-17 04:29:00 +04:00
|
|
|
if (ext2fs_file_acl_block(fs, &inode) &&
|
2015-10-24 07:43:19 +03:00
|
|
|
ext2fs_has_feature_xattr(fs->super)) {
|
2012-08-03 04:47:44 +04:00
|
|
|
pctx.errcode = ext2fs_adjust_ea_refcount3(fs,
|
|
|
|
ext2fs_file_acl_block(fs, &inode),
|
|
|
|
block_buf, -1, &count, ino);
|
2002-08-17 18:19:44 +04:00
|
|
|
if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
|
|
|
|
pctx.errcode = 0;
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
if (pctx.errcode) {
|
2011-10-17 04:29:00 +04:00
|
|
|
pctx.blk = ext2fs_file_acl_block(fs, &inode);
|
2002-08-17 18:19:44 +04:00
|
|
|
fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
|
|
|
|
ctx->flags |= E2F_FLAG_ABORT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (count == 0) {
|
2009-10-26 04:46:58 +03:00
|
|
|
ext2fs_block_alloc_stats2(fs,
|
2011-10-17 04:29:00 +04:00
|
|
|
ext2fs_file_acl_block(fs, &inode), -1);
|
2002-08-17 18:19:44 +04:00
|
|
|
}
|
2011-10-17 04:29:00 +04:00
|
|
|
ext2fs_file_acl_block_set(fs, &inode, 0);
|
2002-08-17 18:19:44 +04:00
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
|
2011-10-17 04:29:00 +04:00
|
|
|
if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
|
e2fsck: correctly deallocate invalid extent-mapped symlinks
The function deallocate_inode() in e2fsck/pass2.c was buggy in that it
would clear out the inode's mode and flags fields before trying to
deallocate any blocks which might belong to the inode.
The good news is that deallocate_inode() is mostly used to free inodes
which do not have blocks: device inodes, FIFO's, Unix-domain sockets.
The bad news is that if deallocate_inode() tried to free an invalid
extent-mapped inode, it would try to interpret the root of the extent
node as block numbers, and would therefore mark various file system
metadata blocks (the superblock, block group descriptors, the root
directory, etc.) as free and available for allocation. This was
unfortunate.
(Try running an older e2fsck against the test file system image in the
new test f_invalid_extent_symlink, and then run e2fsck a second time
on the fs image, and weep.)
Fortunately, this kind of file system image corruption appears to be
fairly rare in actual practice, since it would require a very unlucky
set of bits to be flipped, or a buggy file system implementation.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2013-07-29 05:49:38 +04:00
|
|
|
goto clear_inode;
|
2001-08-09 12:14:04 +04:00
|
|
|
|
2014-08-11 02:40:21 +04:00
|
|
|
/* Inline data inodes don't have blocks to iterate */
|
|
|
|
if (inode.i_flags & EXT4_INLINE_DATA_FL)
|
|
|
|
goto clear_inode;
|
|
|
|
|
2013-12-11 05:18:27 +04:00
|
|
|
if (LINUX_S_ISREG(inode.i_mode) &&
|
|
|
|
ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode)))
|
2001-08-09 12:14:04 +04:00
|
|
|
ctx->large_files--;
|
|
|
|
|
2011-07-20 22:40:06 +04:00
|
|
|
del_block.ctx = ctx;
|
|
|
|
del_block.num = 0;
|
2010-06-14 01:00:00 +04:00
|
|
|
pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
|
2011-07-20 22:40:06 +04:00
|
|
|
deallocate_inode_block,
|
|
|
|
&del_block);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (pctx.errcode) {
|
|
|
|
fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
|
1997-11-03 22:42:40 +03:00
|
|
|
ctx->flags |= E2F_FLAG_ABORT;
|
|
|
|
return;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
}
|
e2fsck: correctly deallocate invalid extent-mapped symlinks
The function deallocate_inode() in e2fsck/pass2.c was buggy in that it
would clear out the inode's mode and flags fields before trying to
deallocate any blocks which might belong to the inode.
The good news is that deallocate_inode() is mostly used to free inodes
which do not have blocks: device inodes, FIFO's, Unix-domain sockets.
The bad news is that if deallocate_inode() tried to free an invalid
extent-mapped inode, it would try to interpret the root of the extent
node as block numbers, and would therefore mark various file system
metadata blocks (the superblock, block group descriptors, the root
directory, etc.) as free and available for allocation. This was
unfortunate.
(Try running an older e2fsck against the test file system image in the
new test f_invalid_extent_symlink, and then run e2fsck a second time
on the fs image, and weep.)
Fortunately, this kind of file system image corruption appears to be
fairly rare in actual practice, since it would require a very unlucky
set of bits to be flipped, or a buggy file system implementation.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2013-07-29 05:49:38 +04:00
|
|
|
clear_inode:
|
|
|
|
/* Inode may have changed by block_iterate, so reread it */
|
|
|
|
e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
|
|
|
|
e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
/*
|
|
|
|
* This fuction clears the htree flag on an inode
|
|
|
|
*/
|
|
|
|
static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
|
|
|
|
{
|
|
|
|
struct ext2_inode inode;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2002-06-26 07:26:34 +04:00
|
|
|
e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
|
|
|
|
inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
|
|
|
|
e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
|
2002-07-20 08:28:07 +04:00
|
|
|
if (ctx->dirs_to_hash)
|
|
|
|
ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
|
2002-06-26 07:26:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-17 03:56:36 +04:00
|
|
|
int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
|
|
|
|
ext2_ino_t ino, char *buf)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
ext2_filsys fs = ctx->fs;
|
1997-04-26 17:21:57 +04:00
|
|
|
struct ext2_inode inode;
|
|
|
|
int inode_modified = 0;
|
2005-01-27 22:28:41 +03:00
|
|
|
int not_fixed = 0;
|
1997-04-29 18:53:37 +04:00
|
|
|
unsigned char *frag, *fsize;
|
1997-04-29 20:15:03 +04:00
|
|
|
struct problem_context pctx;
|
2013-12-03 05:52:43 +04:00
|
|
|
problem_t problem = 0;
|
1997-04-26 17:21:57 +04:00
|
|
|
|
1997-11-03 22:42:40 +03:00
|
|
|
e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
|
1997-04-29 20:15:03 +04:00
|
|
|
|
|
|
|
clear_problem_context(&pctx);
|
|
|
|
pctx.ino = ino;
|
|
|
|
pctx.dir = dir;
|
|
|
|
pctx.inode = &inode;
|
|
|
|
|
2011-10-17 04:29:00 +04:00
|
|
|
if (ext2fs_file_acl_block(fs, &inode) &&
|
2015-10-24 07:43:19 +03:00
|
|
|
!ext2fs_has_feature_xattr(fs->super)) {
|
2005-07-04 21:53:36 +04:00
|
|
|
if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
|
2011-10-17 04:29:00 +04:00
|
|
|
ext2fs_file_acl_block_set(fs, &inode, 0);
|
2005-07-04 21:53:36 +04:00
|
|
|
inode_modified++;
|
|
|
|
} else
|
|
|
|
not_fixed++;
|
|
|
|
}
|
2005-01-27 22:28:41 +03:00
|
|
|
|
1997-04-26 17:58:21 +04:00
|
|
|
if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
|
|
|
|
!LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
|
|
|
|
!LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
|
1997-11-03 22:42:40 +03:00
|
|
|
!(LINUX_S_ISSOCK(inode.i_mode)))
|
|
|
|
problem = PR_2_BAD_MODE;
|
2001-06-02 08:26:26 +04:00
|
|
|
else if (LINUX_S_ISCHR(inode.i_mode)
|
2002-08-17 18:19:44 +04:00
|
|
|
&& !e2fsck_pass1_check_device_inode(fs, &inode))
|
1997-11-03 22:42:40 +03:00
|
|
|
problem = PR_2_BAD_CHAR_DEV;
|
2001-06-02 08:26:26 +04:00
|
|
|
else if (LINUX_S_ISBLK(inode.i_mode)
|
2002-08-17 18:19:44 +04:00
|
|
|
&& !e2fsck_pass1_check_device_inode(fs, &inode))
|
1997-11-03 22:42:40 +03:00
|
|
|
problem = PR_2_BAD_BLOCK_DEV;
|
2001-06-02 08:26:26 +04:00
|
|
|
else if (LINUX_S_ISFIFO(inode.i_mode)
|
2002-08-17 18:19:44 +04:00
|
|
|
&& !e2fsck_pass1_check_device_inode(fs, &inode))
|
ChangeLog, mke2fs.c, tune2fs.8.in:
tune2fs.8.in: Fix minor display bug in the nroff.
mke2fs.c (show_stats, write_inode_tables): Use the log10 function to
calculate the display of block numbers so that things look nice on an
80 character display.
mke2fs.c (usage): Add the sparse-super-flag to the usage message.
ChangeLog, e2fsck.c, pass1.c, pass2.c, problem.c, problem.h, unix.c:
unix.c (main): Move ext2fs_close() after e2fsck_free_context() since
e2fsck_free_context may reference data in ctx->fs.
e2fsck.c (e2fsck_reset_context): Make sure ctx->fs is non-NULL before
checking ctx->fs->dblist.
pass1.c (e2fsck_pass1): Use the device check subroutine on FIFO's and
Socket's, so that we catch bogus immutable inodes.
pass2.c (process_bad_inode): Process bad socket and fifo's.
problem.h, problem.c: Define new problem codes PR_2_BAD_FIFO and
PR_2_BAD_SOCKET.
1998-11-14 07:18:28 +03:00
|
|
|
problem = PR_2_BAD_FIFO;
|
2001-06-02 08:26:26 +04:00
|
|
|
else if (LINUX_S_ISSOCK(inode.i_mode)
|
2002-08-17 18:19:44 +04:00
|
|
|
&& !e2fsck_pass1_check_device_inode(fs, &inode))
|
ChangeLog, mke2fs.c, tune2fs.8.in:
tune2fs.8.in: Fix minor display bug in the nroff.
mke2fs.c (show_stats, write_inode_tables): Use the log10 function to
calculate the display of block numbers so that things look nice on an
80 character display.
mke2fs.c (usage): Add the sparse-super-flag to the usage message.
ChangeLog, e2fsck.c, pass1.c, pass2.c, problem.c, problem.h, unix.c:
unix.c (main): Move ext2fs_close() after e2fsck_free_context() since
e2fsck_free_context may reference data in ctx->fs.
e2fsck.c (e2fsck_reset_context): Make sure ctx->fs is non-NULL before
checking ctx->fs->dblist.
pass1.c (e2fsck_pass1): Use the device check subroutine on FIFO's and
Socket's, so that we catch bogus immutable inodes.
pass2.c (process_bad_inode): Process bad socket and fifo's.
problem.h, problem.c: Define new problem codes PR_2_BAD_FIFO and
PR_2_BAD_SOCKET.
1998-11-14 07:18:28 +03:00
|
|
|
problem = PR_2_BAD_SOCKET;
|
2001-06-02 08:26:26 +04:00
|
|
|
else if (LINUX_S_ISLNK(inode.i_mode)
|
2008-03-14 06:05:00 +03:00
|
|
|
&& !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
|
2002-05-21 17:14:17 +04:00
|
|
|
problem = PR_2_INVALID_SYMLINK;
|
2001-08-04 10:51:18 +04:00
|
|
|
}
|
ChangeLog, mke2fs.c, tune2fs.8.in:
tune2fs.8.in: Fix minor display bug in the nroff.
mke2fs.c (show_stats, write_inode_tables): Use the log10 function to
calculate the display of block numbers so that things look nice on an
80 character display.
mke2fs.c (usage): Add the sparse-super-flag to the usage message.
ChangeLog, e2fsck.c, pass1.c, pass2.c, problem.c, problem.h, unix.c:
unix.c (main): Move ext2fs_close() after e2fsck_free_context() since
e2fsck_free_context may reference data in ctx->fs.
e2fsck.c (e2fsck_reset_context): Make sure ctx->fs is non-NULL before
checking ctx->fs->dblist.
pass1.c (e2fsck_pass1): Use the device check subroutine on FIFO's and
Socket's, so that we catch bogus immutable inodes.
pass2.c (process_bad_inode): Process bad socket and fifo's.
problem.h, problem.c: Define new problem codes PR_2_BAD_FIFO and
PR_2_BAD_SOCKET.
1998-11-14 07:18:28 +03:00
|
|
|
|
1997-11-03 22:42:40 +03:00
|
|
|
if (problem) {
|
|
|
|
if (fix_problem(ctx, problem, &pctx)) {
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
deallocate_inode(ctx, ino, 0);
|
1998-02-24 23:22:23 +03:00
|
|
|
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
|
1997-11-03 22:42:40 +03:00
|
|
|
return 0;
|
1997-08-14 21:17:16 +04:00
|
|
|
return 1;
|
2005-01-27 22:28:41 +03:00
|
|
|
} else
|
|
|
|
not_fixed++;
|
1997-11-03 22:42:40 +03:00
|
|
|
problem = 0;
|
1997-08-14 21:17:16 +04:00
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2005-01-27 22:28:41 +03:00
|
|
|
if (inode.i_faddr) {
|
|
|
|
if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
|
|
|
|
inode.i_faddr = 0;
|
|
|
|
inode_modified++;
|
|
|
|
} else
|
|
|
|
not_fixed++;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
1997-04-29 18:53:37 +04:00
|
|
|
|
|
|
|
switch (fs->super->s_creator_os) {
|
|
|
|
case EXT2_OS_HURD:
|
|
|
|
frag = &inode.osd2.hurd2.h_i_frag;
|
|
|
|
fsize = &inode.osd2.hurd2.h_i_fsize;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
frag = fsize = 0;
|
|
|
|
}
|
1997-04-29 20:15:03 +04:00
|
|
|
if (frag && *frag) {
|
|
|
|
pctx.num = *frag;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
|
1997-04-29 20:15:03 +04:00
|
|
|
*frag = 0;
|
|
|
|
inode_modified++;
|
2005-01-28 05:40:53 +03:00
|
|
|
} else
|
|
|
|
not_fixed++;
|
1997-04-29 20:15:03 +04:00
|
|
|
pctx.num = 0;
|
|
|
|
}
|
|
|
|
if (fsize && *fsize) {
|
|
|
|
pctx.num = *fsize;
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
|
1997-04-29 20:15:03 +04:00
|
|
|
*fsize = 0;
|
|
|
|
inode_modified++;
|
2005-01-27 22:28:41 +03:00
|
|
|
} else
|
|
|
|
not_fixed++;
|
1997-04-29 20:15:03 +04:00
|
|
|
pctx.num = 0;
|
|
|
|
}
|
|
|
|
|
2006-11-11 14:32:03 +03:00
|
|
|
if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
|
2015-10-24 07:43:19 +03:00
|
|
|
!ext2fs_has_feature_huge_file(fs->super) &&
|
2006-11-11 14:32:03 +03:00
|
|
|
(inode.osd2.linux2.l_i_blocks_hi != 0)) {
|
|
|
|
pctx.num = inode.osd2.linux2.l_i_blocks_hi;
|
|
|
|
if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
|
|
|
|
inode.osd2.linux2.l_i_blocks_hi = 0;
|
|
|
|
inode_modified++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:15:57 +03:00
|
|
|
if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
|
2015-10-24 07:43:19 +03:00
|
|
|
!ext2fs_has_feature_64bit(fs->super) &&
|
2009-04-24 05:31:16 +04:00
|
|
|
inode.osd2.linux2.l_i_file_acl_high != 0) {
|
|
|
|
pctx.num = inode.osd2.linux2.l_i_file_acl_high;
|
|
|
|
if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
|
|
|
|
inode.osd2.linux2.l_i_file_acl_high = 0;
|
|
|
|
inode_modified++;
|
|
|
|
} else
|
|
|
|
not_fixed++;
|
|
|
|
}
|
|
|
|
|
2011-10-17 04:29:00 +04:00
|
|
|
if (ext2fs_file_acl_block(fs, &inode) &&
|
|
|
|
((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) ||
|
|
|
|
(ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) {
|
2005-01-27 22:28:41 +03:00
|
|
|
if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
|
2011-10-17 04:29:00 +04:00
|
|
|
ext2fs_file_acl_block_set(fs, &inode, 0);
|
2005-01-27 22:28:41 +03:00
|
|
|
inode_modified++;
|
|
|
|
} else
|
|
|
|
not_fixed++;
|
2001-07-02 19:54:09 +04:00
|
|
|
}
|
1997-04-29 20:15:03 +04:00
|
|
|
if (inode.i_dir_acl &&
|
2005-01-27 22:28:41 +03:00
|
|
|
LINUX_S_ISDIR(inode.i_mode)) {
|
|
|
|
if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
|
|
|
|
inode.i_dir_acl = 0;
|
|
|
|
inode_modified++;
|
|
|
|
} else
|
|
|
|
not_fixed++;
|
1997-04-29 20:15:03 +04:00
|
|
|
}
|
2005-01-27 22:28:41 +03:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
if (inode_modified)
|
1997-11-03 22:42:40 +03:00
|
|
|
e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
|
2005-07-04 21:53:36 +04:00
|
|
|
if (!not_fixed && ctx->inode_bad_map)
|
2009-08-23 06:29:02 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-04-26 17:58:21 +04:00
|
|
|
/*
|
|
|
|
* allocate_dir_block --- this function allocates a new directory
|
|
|
|
* block for a particular inode; this is done if a directory has
|
|
|
|
* a "hole" in it, or if a directory has a illegal block number
|
|
|
|
* that was zeroed out and now needs to be replaced.
|
|
|
|
*/
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
static int allocate_dir_block(e2fsck_t ctx,
|
2010-06-14 01:00:00 +04:00
|
|
|
struct ext2_db_entry2 *db,
|
2008-08-28 07:07:54 +04:00
|
|
|
char *buf EXT2FS_ATTR((unused)),
|
2003-12-07 09:28:50 +03:00
|
|
|
struct problem_context *pctx)
|
1997-04-26 17:58:21 +04:00
|
|
|
{
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
ext2_filsys fs = ctx->fs;
|
2014-07-26 04:33:57 +04:00
|
|
|
blk64_t blk = 0;
|
1997-04-26 17:58:21 +04:00
|
|
|
char *block;
|
|
|
|
struct ext2_inode inode;
|
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
|
1997-04-26 17:58:21 +04:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the inode and block bitmaps in; we'll be messing with
|
|
|
|
* them.
|
|
|
|
*/
|
Many files:
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c: Add calls to the progress
indicator function.
pass1.c (scan_callback): Add call to the progress feedback function
(if it exists).
super.c (check_super_block): Skip the device size check if the
get_device_size returns EXT2_EXT_UNIMPLEMENTED.
iscan.c (main): Don't use fatal_error() anymore.
pass1b.c, swapfs.c, badblocks.c: Set E2F_FLAG_ABORT instead of calling
fatal_error(0).
problem.c, pass3.c (PR_3_ROOT_NOT_DIR_ABORT,
PR_3_NO_ROOT_INODE_ABORT): New problem codes.
problem.c, pass2.c (PR_2_SPLIT_DOT): New problem code.
problem.c, pass1.c (PR_1_SUPPRESS_MESSAGES): New problem code.
problemP.h: New file which separates out the private fix_problem data
structures.
util.c, dirinfo.c, pass1.c, pass1b.c, pass2.c, pass5.c, super.c,
swapfs.c util.c: allocate_memory() now takes a e2fsck context as its
first argument, and rename it to be e2fsck_allocate_memory().
problemP.h:
New file which contains the private problem abstraction definitions.
Makefile.pq:
Remove include of MAKEFILE.STD, which doesn't exist at this point.
1997-11-14 08:23:04 +03:00
|
|
|
e2fsck_read_bitmaps(ctx);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:58:21 +04:00
|
|
|
/*
|
|
|
|
* First, find a free block
|
|
|
|
*/
|
2014-07-26 04:33:57 +04:00
|
|
|
e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
|
|
|
|
pctx->errcode = ext2fs_map_cluster_block(fs, db->ino, &inode,
|
|
|
|
db->blockcnt, &blk);
|
|
|
|
if (pctx->errcode || blk == 0) {
|
2014-12-14 04:00:36 +03:00
|
|
|
blk = ext2fs_find_inode_goal(fs, db->ino, &inode, db->blockcnt);
|
|
|
|
pctx->errcode = ext2fs_new_block2(fs, blk,
|
2014-07-26 04:33:57 +04:00
|
|
|
ctx->block_found_map, &blk);
|
|
|
|
if (pctx->errcode) {
|
|
|
|
pctx->str = "ext2fs_new_block";
|
|
|
|
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
|
|
|
|
return 1;
|
|
|
|
}
|
1997-04-26 17:58:21 +04:00
|
|
|
}
|
2009-08-23 06:29:02 +04:00
|
|
|
ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
|
|
|
|
ext2fs_mark_block_bitmap2(fs->block_map, blk);
|
1997-04-26 17:58:21 +04:00
|
|
|
ext2fs_mark_bb_dirty(fs);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now let's create the actual data block for the inode
|
|
|
|
*/
|
|
|
|
if (db->blockcnt)
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
|
1997-04-26 17:58:21 +04:00
|
|
|
else
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
|
|
|
|
EXT2_ROOT_INO, &block);
|
1997-04-26 17:58:21 +04:00
|
|
|
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (pctx->errcode) {
|
|
|
|
pctx->str = "ext2fs_new_dir_block";
|
|
|
|
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
|
1997-04-26 17:58:21 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-08-03 01:27:43 +04:00
|
|
|
pctx->errcode = ext2fs_write_dir_block4(fs, blk, block, 0, db->ino);
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&block);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (pctx->errcode) {
|
|
|
|
pctx->str = "ext2fs_write_dir_block";
|
|
|
|
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
|
1997-04-26 17:58:21 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the inode block count
|
|
|
|
*/
|
2008-04-09 19:39:11 +04:00
|
|
|
ext2fs_iblk_add_blocks(fs, &inode, 1);
|
2016-05-29 20:36:20 +03:00
|
|
|
if (EXT2_I_SIZE(&inode) < ((__u64) db->blockcnt+1) * fs->blocksize) {
|
2014-07-26 22:34:56 +04:00
|
|
|
pctx->errcode = ext2fs_inode_size_set(fs, &inode,
|
|
|
|
(db->blockcnt+1) * fs->blocksize);
|
|
|
|
if (pctx->errcode) {
|
|
|
|
pctx->str = "ext2fs_inode_size_set";
|
|
|
|
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
1997-11-03 22:42:40 +03:00
|
|
|
e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
|
1997-04-26 17:58:21 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally, update the block pointers for the inode
|
|
|
|
*/
|
|
|
|
db->blk = blk;
|
2010-01-31 05:22:17 +03:00
|
|
|
pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET,
|
|
|
|
db->blockcnt, 0, &blk);
|
Many files:
pass*.c, super.c: Massive changes to avoid using printf and com_err
routines. All diagnostic messages are now routed through the
fix_problem interface.
pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
problem.c: Added new problem codes for some of the superblock
corruption checks, and for the pass header messages. ("Pass
1: xxxxx")
util.c (print_resource_track): Now takes a description argument.
super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c. e2fsck.c now
contains the global e2fsck context management routines, and
super.c contains the "pass 0" initial validation of the
superblock and global block group descriptors.
pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
Updated tests to align with e2fsck problem.c changes.
1997-10-03 21:48:10 +04:00
|
|
|
if (pctx->errcode) {
|
|
|
|
pctx->str = "ext2fs_block_iterate";
|
|
|
|
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
|
1997-04-26 17:58:21 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|