mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Merge tag 'ext4_for_linus-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o: "Many cleanups and bug fixes in ext4, especially for the fast commit feature. Also some performance improvements; in particular, improving IOPS and throughput on fast devices running Async Direct I/O by up to 20% by optimizing jbd2_transaction_committed()" * tag 'ext4_for_linus-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (40 commits) ext4: make sure the first directory block is not a hole ext4: check dot and dotdot of dx_root before making dir indexed ext4: sanity check for NULL pointer after ext4_force_shutdown jbd2: increase maximum transaction size jbd2: drop pointless shrinker batch initialization jbd2: avoid infinite transaction commit loop jbd2: precompute number of transaction descriptor blocks jbd2: make jbd2_journal_get_max_txn_bufs() internal jbd2: avoid mount failed when commit block is partial submitted ext4: avoid writing unitialized memory to disk in EA inodes ext4: don't track ranges in fast_commit if inode has inlined data ext4: fix possible tid_t sequence overflows ext4: use ext4_update_inode_fsync_trans() helper in inode creation ext4: add missing MODULE_DESCRIPTION() jbd2: add missing MODULE_DESCRIPTION() ext4: use memtostr_pad() for s_volume_name jbd2: speed up jbd2_transaction_committed() ext4: make ext4_da_map_blocks() buffer_head unaware ext4: make ext4_insert_delayed_block() insert multi-blocks ext4: factor out a helper to check the cluster allocation state ...
This commit is contained in:
@@ -151,10 +151,11 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
|
||||
|
||||
return bh;
|
||||
}
|
||||
if (!bh && (type == INDEX || type == DIRENT_HTREE)) {
|
||||
/* The first directory block must not be a hole. */
|
||||
if (!bh && (type == INDEX || type == DIRENT_HTREE || block == 0)) {
|
||||
ext4_error_inode(inode, func, line, block,
|
||||
"Directory hole found for htree %s block",
|
||||
(type == INDEX) ? "index" : "leaf");
|
||||
"Directory hole found for htree %s block %u",
|
||||
(type == INDEX) ? "index" : "leaf", block);
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
}
|
||||
if (!bh)
|
||||
@@ -2172,6 +2173,52 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
||||
return err ? err : err2;
|
||||
}
|
||||
|
||||
static bool ext4_check_dx_root(struct inode *dir, struct dx_root *root)
|
||||
{
|
||||
struct fake_dirent *fde;
|
||||
const char *error_msg;
|
||||
unsigned int rlen;
|
||||
unsigned int blocksize = dir->i_sb->s_blocksize;
|
||||
char *blockend = (char *)root + dir->i_sb->s_blocksize;
|
||||
|
||||
fde = &root->dot;
|
||||
if (unlikely(fde->name_len != 1)) {
|
||||
error_msg = "invalid name_len for '.'";
|
||||
goto corrupted;
|
||||
}
|
||||
if (unlikely(strncmp(root->dot_name, ".", fde->name_len))) {
|
||||
error_msg = "invalid name for '.'";
|
||||
goto corrupted;
|
||||
}
|
||||
rlen = ext4_rec_len_from_disk(fde->rec_len, blocksize);
|
||||
if (unlikely((char *)fde + rlen >= blockend)) {
|
||||
error_msg = "invalid rec_len for '.'";
|
||||
goto corrupted;
|
||||
}
|
||||
|
||||
fde = &root->dotdot;
|
||||
if (unlikely(fde->name_len != 2)) {
|
||||
error_msg = "invalid name_len for '..'";
|
||||
goto corrupted;
|
||||
}
|
||||
if (unlikely(strncmp(root->dotdot_name, "..", fde->name_len))) {
|
||||
error_msg = "invalid name for '..'";
|
||||
goto corrupted;
|
||||
}
|
||||
rlen = ext4_rec_len_from_disk(fde->rec_len, blocksize);
|
||||
if (unlikely((char *)fde + rlen >= blockend)) {
|
||||
error_msg = "invalid rec_len for '..'";
|
||||
goto corrupted;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
corrupted:
|
||||
EXT4_ERROR_INODE(dir, "Corrupt dir, %s, running e2fsck is recommended",
|
||||
error_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This converts a one block unindexed directory to a 3 block indexed
|
||||
* directory, and adds the dentry to the indexed directory.
|
||||
@@ -2206,17 +2253,17 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
|
||||
brelse(bh);
|
||||
return retval;
|
||||
}
|
||||
|
||||
root = (struct dx_root *) bh->b_data;
|
||||
if (!ext4_check_dx_root(dir, root)) {
|
||||
brelse(bh);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/* The 0th block becomes the root, move the dirents out */
|
||||
fde = &root->dotdot;
|
||||
de = (struct ext4_dir_entry_2 *)((char *)fde +
|
||||
ext4_rec_len_from_disk(fde->rec_len, blocksize));
|
||||
if ((char *) de >= (((char *) root) + blocksize)) {
|
||||
EXT4_ERROR_INODE(dir, "invalid rec_len for '..'");
|
||||
brelse(bh);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
len = ((char *) root) + (blocksize - csum_size) - (char *) de;
|
||||
|
||||
/* Allocate new block for the 0th block's dirents */
|
||||
@@ -3038,10 +3085,7 @@ bool ext4_empty_dir(struct inode *inode)
|
||||
EXT4_ERROR_INODE(inode, "invalid size");
|
||||
return false;
|
||||
}
|
||||
/* The first directory block must not be a hole,
|
||||
* so treat it as DIRENT_HTREE
|
||||
*/
|
||||
bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
|
||||
bh = ext4_read_dirblock(inode, 0, EITHER);
|
||||
if (IS_ERR(bh))
|
||||
return false;
|
||||
|
||||
@@ -3483,10 +3527,7 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
|
||||
struct ext4_dir_entry_2 *de;
|
||||
unsigned int offset;
|
||||
|
||||
/* The first directory block must not be a hole, so
|
||||
* treat it as DIRENT_HTREE
|
||||
*/
|
||||
bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
|
||||
bh = ext4_read_dirblock(inode, 0, EITHER);
|
||||
if (IS_ERR(bh)) {
|
||||
*retval = PTR_ERR(bh);
|
||||
return NULL;
|
||||
|
||||
Reference in New Issue
Block a user