Skip to content

Commit

Permalink
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/tytso/ext4

Pull ext4 updates from Ted Ts'o:
 "Miscellaneous ext4 cleanups and bug fixes. Pretty boring this cycle..."

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: add .kunitconfig fragment to enable ext4-specific tests
  ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
  ext4: reset retry counter when ext4_alloc_file_blocks() makes progress
  ext4: fix potential htree index checksum corruption
  ext4: factor out htree rep invariant check
  ext4: Change list_for_each* to list_for_each_entry*
  ext4: don't try to processed freed blocks until mballoc is initialized
  ext4: use DEFINE_MUTEX() for mutex lock
  • Loading branch information
torvalds committed Feb 25, 2021
2 parents 5b47b10 + 0a76945 commit 6f9972b
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 49 deletions.
3 changes: 3 additions & 0 deletions fs/ext4/.kunitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CONFIG_KUNIT=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_KUNIT_TESTS=y
3 changes: 1 addition & 2 deletions fs/ext4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ config EXT4_DEBUG

config EXT4_KUNIT_TESTS
tristate "KUnit tests for ext4" if !KUNIT_ALL_TESTS
select EXT4_FS
depends on KUNIT
depends on EXT4_FS && KUNIT
default KUNIT_ALL_TESTS
help
This builds the ext4 KUnit tests.
Expand Down
16 changes: 8 additions & 8 deletions fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -4382,8 +4382,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
{
struct inode *inode = file_inode(file);
handle_t *handle;
int ret = 0;
int ret2 = 0, ret3 = 0;
int ret, ret2 = 0, ret3 = 0;
int retries = 0;
int depth = 0;
struct ext4_map_blocks map;
Expand All @@ -4408,7 +4407,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
depth = ext_depth(inode);

retry:
while (ret >= 0 && len) {
while (len) {
/*
* Recalculate credits when extent tree depth changes.
*/
Expand All @@ -4430,9 +4429,13 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
inode->i_ino, map.m_lblk,
map.m_len, ret);
ext4_mark_inode_dirty(handle, inode);
ret2 = ext4_journal_stop(handle);
ext4_journal_stop(handle);
break;
}
/*
* allow a full retry cycle for any remaining allocations
*/
retries = 0;
map.m_lblk += ret;
map.m_len = len = len - ret;
epos = (loff_t)map.m_lblk << inode->i_blkbits;
Expand All @@ -4450,11 +4453,8 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
if (unlikely(ret2))
break;
}
if (ret == -ENOSPC &&
ext4_should_retry_alloc(inode->i_sb, &retries)) {
ret = 0;
if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
goto retry;
}

return ret > 0 ? ret2 : ret;
}
Expand Down
29 changes: 11 additions & 18 deletions fs/ext4/fast_commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,13 +915,11 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal)
struct super_block *sb = (struct super_block *)(journal->j_private);
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_inode_info *ei;
struct list_head *pos;
int ret = 0;

spin_lock(&sbi->s_fc_lock);
ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING);
list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) {
ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING);
while (atomic_read(&ei->i_fc_updates)) {
DEFINE_WAIT(wait);
Expand Down Expand Up @@ -978,17 +976,15 @@ __releases(&sbi->s_fc_lock)
{
struct super_block *sb = (struct super_block *)(journal->j_private);
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_fc_dentry_update *fc_dentry;
struct ext4_fc_dentry_update *fc_dentry, *fc_dentry_n;
struct inode *inode;
struct list_head *pos, *n, *fcd_pos, *fcd_n;
struct ext4_inode_info *ei;
struct ext4_inode_info *ei, *ei_n;
int ret;

if (list_empty(&sbi->s_fc_dentry_q[FC_Q_MAIN]))
return 0;
list_for_each_safe(fcd_pos, fcd_n, &sbi->s_fc_dentry_q[FC_Q_MAIN]) {
fc_dentry = list_entry(fcd_pos, struct ext4_fc_dentry_update,
fcd_list);
list_for_each_entry_safe(fc_dentry, fc_dentry_n,
&sbi->s_fc_dentry_q[FC_Q_MAIN], fcd_list) {
if (fc_dentry->fcd_op != EXT4_FC_TAG_CREAT) {
spin_unlock(&sbi->s_fc_lock);
if (!ext4_fc_add_dentry_tlv(
Expand All @@ -1004,8 +1000,8 @@ __releases(&sbi->s_fc_lock)
}

inode = NULL;
list_for_each_safe(pos, n, &sbi->s_fc_q[FC_Q_MAIN]) {
ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
list_for_each_entry_safe(ei, ei_n, &sbi->s_fc_q[FC_Q_MAIN],
i_fc_list) {
if (ei->vfs_inode.i_ino == fc_dentry->fcd_ino) {
inode = &ei->vfs_inode;
break;
Expand Down Expand Up @@ -1057,7 +1053,6 @@ static int ext4_fc_perform_commit(journal_t *journal)
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_inode_info *iter;
struct ext4_fc_head head;
struct list_head *pos;
struct inode *inode;
struct blk_plug plug;
int ret = 0;
Expand Down Expand Up @@ -1099,8 +1094,7 @@ static int ext4_fc_perform_commit(journal_t *journal)
goto out;
}

list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
iter = list_entry(pos, struct ext4_inode_info, i_fc_list);
list_for_each_entry(iter, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) {
inode = &iter->vfs_inode;
if (!ext4_test_inode_state(inode, EXT4_STATE_FC_COMMITTING))
continue;
Expand Down Expand Up @@ -1226,18 +1220,17 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
{
struct super_block *sb = journal->j_private;
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_inode_info *iter;
struct ext4_inode_info *iter, *iter_n;
struct ext4_fc_dentry_update *fc_dentry;
struct list_head *pos, *n;

if (full && sbi->s_fc_bh)
sbi->s_fc_bh = NULL;

jbd2_fc_release_bufs(journal);

spin_lock(&sbi->s_fc_lock);
list_for_each_safe(pos, n, &sbi->s_fc_q[FC_Q_MAIN]) {
iter = list_entry(pos, struct ext4_inode_info, i_fc_list);
list_for_each_entry_safe(iter, iter_n, &sbi->s_fc_q[FC_Q_MAIN],
i_fc_list) {
list_del_init(&iter->i_fc_list);
ext4_clear_inode_state(&iter->vfs_inode,
EXT4_STATE_FC_COMMITTING);
Expand Down
45 changes: 27 additions & 18 deletions fs/ext4/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,29 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
(space/bcount)*100/blocksize);
return (struct stats) { names, space, bcount};
}

/*
* Linear search cross check
*/
static inline void htree_rep_invariant_check(struct dx_entry *at,
struct dx_entry *target,
u32 hash, unsigned int n)
{
while (n--) {
dxtrace(printk(KERN_CONT ","));
if (dx_get_hash(++at) > hash) {
at--;
break;
}
}
ASSERT(at == target - 1);
}
#else /* DX_DEBUG */
static inline void htree_rep_invariant_check(struct dx_entry *at,
struct dx_entry *target,
u32 hash, unsigned int n)
{
}
#endif /* DX_DEBUG */

/*
Expand Down Expand Up @@ -827,20 +850,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
p = m + 1;
}

if (0) { // linear search cross check
unsigned n = count - 1;
at = entries;
while (n--)
{
dxtrace(printk(KERN_CONT ","));
if (dx_get_hash(++at) > hash)
{
at--;
break;
}
}
ASSERT(at == p - 1);
}
htree_rep_invariant_check(entries, p, hash, count - 1);

at = p - 1;
dxtrace(printk(KERN_CONT " %x->%u\n",
Expand Down Expand Up @@ -2401,11 +2411,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
(frame - 1)->bh);
if (err)
goto journal_error;
if (restart) {
err = ext4_handle_dirty_dx_node(handle, dir,
frame->bh);
err = ext4_handle_dirty_dx_node(handle, dir,
frame->bh);
if (err)
goto journal_error;
}
} else {
struct dx_root *dxroot;
memcpy((char *) entries2, (char *) entries,
Expand Down
12 changes: 9 additions & 3 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
#include <trace/events/ext4.h>

static struct ext4_lazy_init *ext4_li_info;
static struct mutex ext4_li_mtx;
static DEFINE_MUTEX(ext4_li_mtx);
static struct ratelimit_state ext4_mount_msg_ratelimit;

static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
Expand Down Expand Up @@ -4875,7 +4875,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)

set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);

sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
sbi->s_journal->j_submit_inode_data_buffers =
ext4_journal_submit_inode_data_buffers;
sbi->s_journal->j_finish_inode_data_buffers =
Expand Down Expand Up @@ -4987,6 +4986,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount5;
}

/*
* We can only set up the journal commit callback once
* mballoc is initialized
*/
if (sbi->s_journal)
sbi->s_journal->j_commit_callback =
ext4_journal_commit_callback;

block = ext4_count_free_clusters(sb);
ext4_free_blocks_count_set(sbi->s_es,
EXT4_C2B(sbi, block));
Expand Down Expand Up @@ -6667,7 +6674,6 @@ static int __init ext4_init_fs(void)

ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);
ext4_li_info = NULL;
mutex_init(&ext4_li_mtx);

/* Build-time check for flags consistency */
ext4_check_flag_values();
Expand Down

0 comments on commit 6f9972b

Please sign in to comment.