mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Merge tag 'ext4-for_linus-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o:
"Ext4 bug fixes and cleanups, including:
- hardening against maliciously fuzzed file systems
- backwards compatibility for the brief period when we attempted to
ignore zero-width characters
- avoid potentially BUG'ing if there is a file system corruption
found during the file system unmount
- fix free space reporting by statfs when project quotas are enabled
and the free space is less than the remaining project quota
Also improve performance when replaying a journal with a very large
number of revoke records (applicable for Lustre volumes)"
* tag 'ext4-for_linus-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (71 commits)
ext4: fix OOB read when checking dotdot dir
ext4: on a remount, only log the ro or r/w state when it has changed
ext4: correct the error handle in ext4_fallocate()
ext4: Make sb update interval tunable
ext4: avoid journaling sb update on error if journal is destroying
ext4: define ext4_journal_destroy wrapper
ext4: hash: simplify kzalloc(n * 1, ...) to kzalloc(n, ...)
jbd2: add a missing data flush during file and fs synchronization
ext4: don't over-report free space or inodes in statvfs
ext4: clear DISCARD flag if device does not support discard
jbd2: remove jbd2_journal_unfile_buffer()
ext4: reorder capability check last
ext4: update the comment about mb_optimize_scan
jbd2: fix off-by-one while erasing journal
ext4: remove references to bh->b_page
ext4: goto right label 'out_mmap_sem' in ext4_setattr()
ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all()
ext4: introduce ITAIL helper
jbd2: remove redundant function jbd2_journal_has_csum_v2or3_feature
ext4: remove redundant function ext4_has_metadata_csum
...
This commit is contained in:
117
fs/ext4/namei.c
117
fs/ext4/namei.c
@@ -176,7 +176,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
|
||||
brelse(bh);
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
}
|
||||
if (!ext4_has_metadata_csum(inode->i_sb) ||
|
||||
if (!ext4_has_feature_metadata_csum(inode->i_sb) ||
|
||||
buffer_verified(bh))
|
||||
return bh;
|
||||
|
||||
@@ -291,36 +291,6 @@ struct dx_tail {
|
||||
__le32 dt_checksum; /* crc32c(uuid+inum+dirblock) */
|
||||
};
|
||||
|
||||
static inline ext4_lblk_t dx_get_block(struct dx_entry *entry);
|
||||
static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value);
|
||||
static inline unsigned dx_get_hash(struct dx_entry *entry);
|
||||
static void dx_set_hash(struct dx_entry *entry, unsigned value);
|
||||
static unsigned dx_get_count(struct dx_entry *entries);
|
||||
static unsigned dx_get_limit(struct dx_entry *entries);
|
||||
static void dx_set_count(struct dx_entry *entries, unsigned value);
|
||||
static void dx_set_limit(struct dx_entry *entries, unsigned value);
|
||||
static unsigned dx_root_limit(struct inode *dir, unsigned infosize);
|
||||
static unsigned dx_node_limit(struct inode *dir);
|
||||
static struct dx_frame *dx_probe(struct ext4_filename *fname,
|
||||
struct inode *dir,
|
||||
struct dx_hash_info *hinfo,
|
||||
struct dx_frame *frame);
|
||||
static void dx_release(struct dx_frame *frames);
|
||||
static int dx_make_map(struct inode *dir, struct buffer_head *bh,
|
||||
struct dx_hash_info *hinfo,
|
||||
struct dx_map_entry *map_tail);
|
||||
static void dx_sort_map(struct dx_map_entry *map, unsigned count);
|
||||
static struct ext4_dir_entry_2 *dx_move_dirents(struct inode *dir, char *from,
|
||||
char *to, struct dx_map_entry *offsets,
|
||||
int count, unsigned int blocksize);
|
||||
static struct ext4_dir_entry_2 *dx_pack_dirents(struct inode *dir, char *base,
|
||||
unsigned int blocksize);
|
||||
static void dx_insert_block(struct dx_frame *frame,
|
||||
u32 hash, ext4_lblk_t block);
|
||||
static int ext4_htree_next_block(struct inode *dir, __u32 hash,
|
||||
struct dx_frame *frame,
|
||||
struct dx_frame *frames,
|
||||
__u32 *start_hash);
|
||||
static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
||||
struct ext4_filename *fname,
|
||||
struct ext4_dir_entry_2 **res_dir);
|
||||
@@ -398,7 +368,7 @@ int ext4_dirblock_csum_verify(struct inode *inode, struct buffer_head *bh)
|
||||
{
|
||||
struct ext4_dir_entry_tail *t;
|
||||
|
||||
if (!ext4_has_metadata_csum(inode->i_sb))
|
||||
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
return 1;
|
||||
|
||||
t = get_dirent_tail(inode, bh);
|
||||
@@ -419,7 +389,7 @@ static void ext4_dirblock_csum_set(struct inode *inode,
|
||||
{
|
||||
struct ext4_dir_entry_tail *t;
|
||||
|
||||
if (!ext4_has_metadata_csum(inode->i_sb))
|
||||
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
return;
|
||||
|
||||
t = get_dirent_tail(inode, bh);
|
||||
@@ -494,7 +464,7 @@ static int ext4_dx_csum_verify(struct inode *inode,
|
||||
struct dx_tail *t;
|
||||
int count_offset, limit, count;
|
||||
|
||||
if (!ext4_has_metadata_csum(inode->i_sb))
|
||||
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
return 1;
|
||||
|
||||
c = get_dx_countlimit(inode, dirent, &count_offset);
|
||||
@@ -523,7 +493,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
|
||||
struct dx_tail *t;
|
||||
int count_offset, limit, count;
|
||||
|
||||
if (!ext4_has_metadata_csum(inode->i_sb))
|
||||
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
return;
|
||||
|
||||
c = get_dx_countlimit(inode, dirent, &count_offset);
|
||||
@@ -612,7 +582,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
|
||||
ext4_dir_rec_len(1, NULL) -
|
||||
ext4_dir_rec_len(2, NULL) - infosize;
|
||||
|
||||
if (ext4_has_metadata_csum(dir->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(dir->i_sb))
|
||||
entry_space -= sizeof(struct dx_tail);
|
||||
return entry_space / sizeof(struct dx_entry);
|
||||
}
|
||||
@@ -622,7 +592,7 @@ static inline unsigned dx_node_limit(struct inode *dir)
|
||||
unsigned int entry_space = dir->i_sb->s_blocksize -
|
||||
ext4_dir_rec_len(0, dir);
|
||||
|
||||
if (ext4_has_metadata_csum(dir->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(dir->i_sb))
|
||||
entry_space -= sizeof(struct dx_tail);
|
||||
return entry_space / sizeof(struct dx_entry);
|
||||
}
|
||||
@@ -1076,7 +1046,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
||||
struct ext4_dir_entry_2 *de, *top;
|
||||
int err = 0, count = 0;
|
||||
struct fscrypt_str fname_crypto_str = FSTR_INIT(NULL, 0), tmp_str;
|
||||
int csum = ext4_has_metadata_csum(dir->i_sb);
|
||||
int csum = ext4_has_feature_metadata_csum(dir->i_sb);
|
||||
|
||||
dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
|
||||
(unsigned long)block));
|
||||
@@ -1320,7 +1290,7 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh,
|
||||
struct dx_hash_info h = *hinfo;
|
||||
int blocksize = EXT4_BLOCK_SIZE(dir->i_sb);
|
||||
|
||||
if (ext4_has_metadata_csum(dir->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(dir->i_sb))
|
||||
buflen -= sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
while ((char *) de < base + buflen) {
|
||||
@@ -1462,7 +1432,8 @@ static bool ext4_match(struct inode *parent,
|
||||
* sure cf_name was properly initialized before
|
||||
* considering the calculated hash.
|
||||
*/
|
||||
if (IS_ENCRYPTED(parent) && fname->cf_name.name &&
|
||||
if (sb_no_casefold_compat_fallback(parent->i_sb) &&
|
||||
IS_ENCRYPTED(parent) && fname->cf_name.name &&
|
||||
(fname->hinfo.hash != EXT4_DIRENT_HASH(de) ||
|
||||
fname->hinfo.minor_hash != EXT4_DIRENT_MINOR_HASH(de)))
|
||||
return false;
|
||||
@@ -1595,10 +1566,15 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
|
||||
* return. Otherwise, fall back to doing a search the
|
||||
* old fashioned way.
|
||||
*/
|
||||
if (!IS_ERR(ret) || PTR_ERR(ret) != ERR_BAD_DX_DIR)
|
||||
if (IS_ERR(ret) && PTR_ERR(ret) == ERR_BAD_DX_DIR)
|
||||
dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
|
||||
"falling back\n"));
|
||||
else if (!sb_no_casefold_compat_fallback(dir->i_sb) &&
|
||||
*res_dir == NULL && IS_CASEFOLDED(dir))
|
||||
dxtrace(printk(KERN_DEBUG "ext4_find_entry: casefold "
|
||||
"failed, falling back\n"));
|
||||
else
|
||||
goto cleanup_and_exit;
|
||||
dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
|
||||
"falling back\n"));
|
||||
ret = NULL;
|
||||
}
|
||||
nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb);
|
||||
@@ -1945,7 +1921,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
||||
int csum_size = 0;
|
||||
int err = 0, i;
|
||||
|
||||
if (ext4_has_metadata_csum(dir->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(dir->i_sb))
|
||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
bh2 = ext4_append(handle, dir, &newblock);
|
||||
@@ -2060,8 +2036,7 @@ out:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
||||
struct buffer_head *bh,
|
||||
int ext4_find_dest_de(struct inode *dir, struct buffer_head *bh,
|
||||
void *buf, int buf_size,
|
||||
struct ext4_filename *fname,
|
||||
struct ext4_dir_entry_2 **dest_de)
|
||||
@@ -2143,11 +2118,11 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
||||
int csum_size = 0;
|
||||
int err, err2;
|
||||
|
||||
if (ext4_has_metadata_csum(inode->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
if (!de) {
|
||||
err = ext4_find_dest_de(dir, inode, bh, bh->b_data,
|
||||
err = ext4_find_dest_de(dir, bh, bh->b_data,
|
||||
blocksize - csum_size, fname, &de);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -2252,7 +2227,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
|
||||
struct fake_dirent *fde;
|
||||
int csum_size = 0;
|
||||
|
||||
if (ext4_has_metadata_csum(inode->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
blocksize = dir->i_sb->s_blocksize;
|
||||
@@ -2396,7 +2371,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||
ext4_lblk_t block, blocks;
|
||||
int csum_size = 0;
|
||||
|
||||
if (ext4_has_metadata_csum(inode->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(inode->i_sb))
|
||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
sb = dir->i_sb;
|
||||
@@ -2427,7 +2402,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||
if (!retval || (retval != ERR_BAD_DX_DIR))
|
||||
goto out;
|
||||
/* Can we just ignore htree data? */
|
||||
if (ext4_has_metadata_csum(sb)) {
|
||||
if (ext4_has_feature_metadata_csum(sb)) {
|
||||
EXT4_ERROR_INODE(dir,
|
||||
"Directory has corrupted htree index.");
|
||||
retval = -EFSCORRUPTED;
|
||||
@@ -2577,8 +2552,10 @@ again:
|
||||
BUFFER_TRACE(frame->bh, "get_write_access");
|
||||
err = ext4_journal_get_write_access(handle, sb, frame->bh,
|
||||
EXT4_JTR_NONE);
|
||||
if (err)
|
||||
if (err) {
|
||||
brelse(bh2);
|
||||
goto journal_error;
|
||||
}
|
||||
if (!add_level) {
|
||||
unsigned icount1 = icount/2, icount2 = icount - icount1;
|
||||
unsigned hash2 = dx_get_hash(entries + icount1);
|
||||
@@ -2589,8 +2566,10 @@ again:
|
||||
err = ext4_journal_get_write_access(handle, sb,
|
||||
(frame - 1)->bh,
|
||||
EXT4_JTR_NONE);
|
||||
if (err)
|
||||
if (err) {
|
||||
brelse(bh2);
|
||||
goto journal_error;
|
||||
}
|
||||
|
||||
memcpy((char *) entries2, (char *) (entries + icount1),
|
||||
icount2 * sizeof(struct dx_entry));
|
||||
@@ -2609,8 +2588,10 @@ again:
|
||||
dxtrace(dx_show_index("node",
|
||||
((struct dx_node *) bh2->b_data)->entries));
|
||||
err = ext4_handle_dirty_dx_node(handle, dir, bh2);
|
||||
if (err)
|
||||
if (err) {
|
||||
brelse(bh2);
|
||||
goto journal_error;
|
||||
}
|
||||
brelse (bh2);
|
||||
err = ext4_handle_dirty_dx_node(handle, dir,
|
||||
(frame - 1)->bh);
|
||||
@@ -2635,8 +2616,10 @@ again:
|
||||
"Creating %d level index...\n",
|
||||
dxroot->info.indirect_levels));
|
||||
err = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
|
||||
if (err)
|
||||
if (err) {
|
||||
brelse(bh2);
|
||||
goto journal_error;
|
||||
}
|
||||
err = ext4_handle_dirty_dx_node(handle, dir, bh2);
|
||||
brelse(bh2);
|
||||
restart = 1;
|
||||
@@ -2733,7 +2716,7 @@ static int ext4_delete_entry(handle_t *handle,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ext4_has_metadata_csum(dir->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(dir->i_sb))
|
||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
BUFFER_TRACE(bh, "get_write_access");
|
||||
@@ -2973,7 +2956,7 @@ int ext4_init_new_dir(handle_t *handle, struct inode *dir,
|
||||
int csum_size = 0;
|
||||
int err;
|
||||
|
||||
if (ext4_has_metadata_csum(dir->i_sb))
|
||||
if (ext4_has_feature_metadata_csum(dir->i_sb))
|
||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||
|
||||
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
|
||||
@@ -3151,8 +3134,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
struct ext4_dir_entry_2 *de;
|
||||
handle_t *handle = NULL;
|
||||
|
||||
if (unlikely(ext4_forced_shutdown(dir->i_sb)))
|
||||
return -EIO;
|
||||
retval = ext4_emergency_state(dir->i_sb);
|
||||
if (unlikely(retval))
|
||||
return retval;
|
||||
|
||||
/* Initialize quotas before so that eventual writes go in
|
||||
* separate transaction */
|
||||
@@ -3309,8 +3293,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (unlikely(ext4_forced_shutdown(dir->i_sb)))
|
||||
return -EIO;
|
||||
retval = ext4_emergency_state(dir->i_sb);
|
||||
if (unlikely(retval))
|
||||
return retval;
|
||||
|
||||
trace_ext4_unlink_enter(dir, dentry);
|
||||
/*
|
||||
@@ -3376,8 +3361,9 @@ static int ext4_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct fscrypt_str disk_link;
|
||||
int retries = 0;
|
||||
|
||||
if (unlikely(ext4_forced_shutdown(dir->i_sb)))
|
||||
return -EIO;
|
||||
err = ext4_emergency_state(dir->i_sb);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
|
||||
&disk_link);
|
||||
@@ -4199,8 +4185,9 @@ static int ext4_rename2(struct mnt_idmap *idmap,
|
||||
{
|
||||
int err;
|
||||
|
||||
if (unlikely(ext4_forced_shutdown(old_dir->i_sb)))
|
||||
return -EIO;
|
||||
err = ext4_emergency_state(old_dir->i_sb);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
|
||||
return -EINVAL;
|
||||
|
||||
Reference in New Issue
Block a user