ext4: fix extent sanity checking code with AGGRESSIVE_TEST
The extents sanity-checking code depends on the ext4_ext_space_*() functions returning the maximum alloable size for eh_max; however, when the debugging #ifdef AGGRESSIVE_TEST is enabled to test the extent tree handling code, this prevents a normally created ext4 filesystem from being mounted with the errors: Aug 26 15:43:50 bsd086 kernel: [ 96.070277] EXT4-fs error (device sda8): ext4_ext_check_inode: bad header/extent in inode #8: too large eh_max - magic f30a, entries 1, max 4(3), depth 0(0) Aug 26 15:43:50 bsd086 kernel: [ 96.070526] EXT4-fs (sda8): no journal found Bug reported by Akira Fujita. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
a36b44988c
commit
55ad63bf3a
|
@ -229,57 +229,65 @@ ext4_ext_new_meta_block(handle_t *handle, struct inode *inode,
|
||||||
return newblock;
|
return newblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_ext_space_block(struct inode *inode)
|
static inline int ext4_ext_space_block(struct inode *inode, int check)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
|
size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
|
||||||
/ sizeof(struct ext4_extent);
|
/ sizeof(struct ext4_extent);
|
||||||
|
if (!check) {
|
||||||
#ifdef AGGRESSIVE_TEST
|
#ifdef AGGRESSIVE_TEST
|
||||||
if (size > 6)
|
if (size > 6)
|
||||||
size = 6;
|
size = 6;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_ext_space_block_idx(struct inode *inode)
|
static inline int ext4_ext_space_block_idx(struct inode *inode, int check)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
|
size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
|
||||||
/ sizeof(struct ext4_extent_idx);
|
/ sizeof(struct ext4_extent_idx);
|
||||||
|
if (!check) {
|
||||||
#ifdef AGGRESSIVE_TEST
|
#ifdef AGGRESSIVE_TEST
|
||||||
if (size > 5)
|
if (size > 5)
|
||||||
size = 5;
|
size = 5;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_ext_space_root(struct inode *inode)
|
static inline int ext4_ext_space_root(struct inode *inode, int check)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = sizeof(EXT4_I(inode)->i_data);
|
size = sizeof(EXT4_I(inode)->i_data);
|
||||||
size -= sizeof(struct ext4_extent_header);
|
size -= sizeof(struct ext4_extent_header);
|
||||||
size /= sizeof(struct ext4_extent);
|
size /= sizeof(struct ext4_extent);
|
||||||
|
if (!check) {
|
||||||
#ifdef AGGRESSIVE_TEST
|
#ifdef AGGRESSIVE_TEST
|
||||||
if (size > 3)
|
if (size > 3)
|
||||||
size = 3;
|
size = 3;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_ext_space_root_idx(struct inode *inode)
|
static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = sizeof(EXT4_I(inode)->i_data);
|
size = sizeof(EXT4_I(inode)->i_data);
|
||||||
size -= sizeof(struct ext4_extent_header);
|
size -= sizeof(struct ext4_extent_header);
|
||||||
size /= sizeof(struct ext4_extent_idx);
|
size /= sizeof(struct ext4_extent_idx);
|
||||||
|
if (!check) {
|
||||||
#ifdef AGGRESSIVE_TEST
|
#ifdef AGGRESSIVE_TEST
|
||||||
if (size > 4)
|
if (size > 4)
|
||||||
size = 4;
|
size = 4;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,9 +301,9 @@ int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks)
|
||||||
int lcap, icap, rcap, leafs, idxs, num;
|
int lcap, icap, rcap, leafs, idxs, num;
|
||||||
int newextents = blocks;
|
int newextents = blocks;
|
||||||
|
|
||||||
rcap = ext4_ext_space_root_idx(inode);
|
rcap = ext4_ext_space_root_idx(inode, 0);
|
||||||
lcap = ext4_ext_space_block(inode);
|
lcap = ext4_ext_space_block(inode, 0);
|
||||||
icap = ext4_ext_space_block_idx(inode);
|
icap = ext4_ext_space_block_idx(inode, 0);
|
||||||
|
|
||||||
/* number of new leaf blocks needed */
|
/* number of new leaf blocks needed */
|
||||||
num = leafs = (newextents + lcap - 1) / lcap;
|
num = leafs = (newextents + lcap - 1) / lcap;
|
||||||
|
@ -320,14 +328,14 @@ ext4_ext_max_entries(struct inode *inode, int depth)
|
||||||
|
|
||||||
if (depth == ext_depth(inode)) {
|
if (depth == ext_depth(inode)) {
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
max = ext4_ext_space_root(inode);
|
max = ext4_ext_space_root(inode, 1);
|
||||||
else
|
else
|
||||||
max = ext4_ext_space_root_idx(inode);
|
max = ext4_ext_space_root_idx(inode, 1);
|
||||||
} else {
|
} else {
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
max = ext4_ext_space_block(inode);
|
max = ext4_ext_space_block(inode, 1);
|
||||||
else
|
else
|
||||||
max = ext4_ext_space_block_idx(inode);
|
max = ext4_ext_space_block_idx(inode, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
|
@ -626,7 +634,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
|
||||||
eh->eh_depth = 0;
|
eh->eh_depth = 0;
|
||||||
eh->eh_entries = 0;
|
eh->eh_entries = 0;
|
||||||
eh->eh_magic = EXT4_EXT_MAGIC;
|
eh->eh_magic = EXT4_EXT_MAGIC;
|
||||||
eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode));
|
eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0));
|
||||||
ext4_mark_inode_dirty(handle, inode);
|
ext4_mark_inode_dirty(handle, inode);
|
||||||
ext4_ext_invalidate_cache(inode);
|
ext4_ext_invalidate_cache(inode);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -851,7 +859,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
|
||||||
|
|
||||||
neh = ext_block_hdr(bh);
|
neh = ext_block_hdr(bh);
|
||||||
neh->eh_entries = 0;
|
neh->eh_entries = 0;
|
||||||
neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode));
|
neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0));
|
||||||
neh->eh_magic = EXT4_EXT_MAGIC;
|
neh->eh_magic = EXT4_EXT_MAGIC;
|
||||||
neh->eh_depth = 0;
|
neh->eh_depth = 0;
|
||||||
ex = EXT_FIRST_EXTENT(neh);
|
ex = EXT_FIRST_EXTENT(neh);
|
||||||
|
@ -927,7 +935,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
|
||||||
neh = ext_block_hdr(bh);
|
neh = ext_block_hdr(bh);
|
||||||
neh->eh_entries = cpu_to_le16(1);
|
neh->eh_entries = cpu_to_le16(1);
|
||||||
neh->eh_magic = EXT4_EXT_MAGIC;
|
neh->eh_magic = EXT4_EXT_MAGIC;
|
||||||
neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode));
|
neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0));
|
||||||
neh->eh_depth = cpu_to_le16(depth - i);
|
neh->eh_depth = cpu_to_le16(depth - i);
|
||||||
fidx = EXT_FIRST_INDEX(neh);
|
fidx = EXT_FIRST_INDEX(neh);
|
||||||
fidx->ei_block = border;
|
fidx->ei_block = border;
|
||||||
|
@ -1052,9 +1060,9 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
|
||||||
/* old root could have indexes or leaves
|
/* old root could have indexes or leaves
|
||||||
* so calculate e_max right way */
|
* so calculate e_max right way */
|
||||||
if (ext_depth(inode))
|
if (ext_depth(inode))
|
||||||
neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode));
|
neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0));
|
||||||
else
|
else
|
||||||
neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode));
|
neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0));
|
||||||
neh->eh_magic = EXT4_EXT_MAGIC;
|
neh->eh_magic = EXT4_EXT_MAGIC;
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
|
@ -1069,7 +1077,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
|
curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
|
||||||
curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode));
|
curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
|
||||||
curp->p_hdr->eh_entries = cpu_to_le16(1);
|
curp->p_hdr->eh_entries = cpu_to_le16(1);
|
||||||
curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
|
curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
|
||||||
|
|
||||||
|
@ -2348,7 +2356,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
ext_inode_hdr(inode)->eh_depth = 0;
|
ext_inode_hdr(inode)->eh_depth = 0;
|
||||||
ext_inode_hdr(inode)->eh_max =
|
ext_inode_hdr(inode)->eh_max =
|
||||||
cpu_to_le16(ext4_ext_space_root(inode));
|
cpu_to_le16(ext4_ext_space_root(inode, 0));
|
||||||
err = ext4_ext_dirty(handle, inode, path);
|
err = ext4_ext_dirty(handle, inode, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue