From 5112e9a540fb4a63184850c6570f30ae13b5f5e3 Mon Sep 17 00:00:00 2001 From: Harshad Shirwadkar Date: Fri, 23 Oct 2020 09:13:39 -0700 Subject: ext4: fix double locking in ext4_fc_commit_dentry_updates() Fixed double locking of sbi->s_fc_lock in the above function as reported by kernel-test-robot. Signed-off-by: Harshad Shirwadkar Link: https://lore.kernel.org/r/20201023161339.1449437-1-harshadshirwadkar@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/fast_commit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/ext4/fast_commit.c') diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index 447c8d93f480..1d72f8f13a05 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -964,7 +964,6 @@ static int ext4_fc_commit_dentry_updates(journal_t *journal, u32 *crc) fc_dentry->fcd_parent, fc_dentry->fcd_ino, fc_dentry->fcd_name.len, fc_dentry->fcd_name.name, crc)) { - spin_lock(&sbi->s_fc_lock); ret = -ENOSPC; goto lock_and_exit; } -- cgit From e029c5f2798720b463e8df0e184a4d1036311b43 Mon Sep 17 00:00:00 2001 From: Harshad Shirwadkar Date: Mon, 26 Oct 2020 21:49:14 -0700 Subject: ext4: make num of fast commit blocks configurable This patch reserves a field in the jbd2 superblock for number of fast commit blocks. When this value is non-zero, Ext4 uses this field to set the number of fast commit blocks. Fixes: 6866d7b3f2bb ("ext4/jbd2: add fast commit initialization") Signed-off-by: Harshad Shirwadkar Link: https://lore.kernel.org/r/20201027044915.2553163-2-harshadshirwadkar@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/fast_commit.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'fs/ext4/fast_commit.c') diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index 1d72f8f13a05..dd7931400474 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -2077,6 +2077,8 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh, void ext4_fc_init(struct super_block *sb, journal_t *journal) { + int num_fc_blocks; + /* * We set replay callback even if fast commit disabled because we may * could still have fast commit blocks that need to be replayed even if @@ -2086,7 +2088,15 @@ void ext4_fc_init(struct super_block *sb, journal_t *journal) if (!test_opt2(sb, JOURNAL_FAST_COMMIT)) return; journal->j_fc_cleanup_callback = ext4_fc_cleanup; - if (jbd2_fc_init(journal, EXT4_NUM_FC_BLKS)) { + if (!buffer_uptodate(journal->j_sb_buffer) + && ext4_read_bh_lock(journal->j_sb_buffer, REQ_META | REQ_PRIO, + true)) { + ext4_msg(sb, KERN_ERR, "I/O error on journal"); + return; + } + num_fc_blocks = be32_to_cpu(journal->j_superblock->s_num_fc_blks); + if (jbd2_fc_init(journal, num_fc_blocks ? num_fc_blocks : + EXT4_NUM_FC_BLKS)) { pr_warn("Error while enabling fast commits, turning off."); ext4_clear_feature_fast_commit(sb); } -- cgit From ababea77bc50e004f7cc2792f0ec8d26b7574c3e Mon Sep 17 00:00:00 2001 From: Harshad Shirwadkar Date: Mon, 26 Oct 2020 21:49:15 -0700 Subject: ext4: use s_mount_flags instead of s_mount_state for fast commit state Ext4's fast commit related transient states should use sb->s_mount_flags instead of persistent sb->s_mount_state. Fixes: 8016e29f4362 ("ext4: fast commit recovery path") Signed-off-by: Harshad Shirwadkar Link: https://lore.kernel.org/r/20201027044915.2553163-3-harshadshirwadkar@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/fast_commit.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'fs/ext4/fast_commit.c') diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index dd7931400474..3ee43fd6d5aa 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -269,7 +269,7 @@ void ext4_fc_mark_ineligible(struct super_block *sb, int reason) (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) return; - sbi->s_mount_state |= EXT4_FC_INELIGIBLE; + sbi->s_mount_flags |= EXT4_MF_FC_INELIGIBLE; WARN_ON(reason >= EXT4_FC_REASON_MAX); sbi->s_fc_stats.fc_ineligible_reason_count[reason]++; } @@ -292,7 +292,7 @@ void ext4_fc_start_ineligible(struct super_block *sb, int reason) } /* - * Stop a fast commit ineligible update. We set EXT4_FC_INELIGIBLE flag here + * Stop a fast commit ineligible update. We set EXT4_MF_FC_INELIGIBLE flag here * to ensure that after stopping the ineligible update, at least one full * commit takes place. */ @@ -302,13 +302,13 @@ void ext4_fc_stop_ineligible(struct super_block *sb) (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) return; - EXT4_SB(sb)->s_mount_state |= EXT4_FC_INELIGIBLE; + EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FC_INELIGIBLE; atomic_dec(&EXT4_SB(sb)->s_fc_ineligible_updates); } static inline int ext4_fc_is_ineligible(struct super_block *sb) { - return (EXT4_SB(sb)->s_mount_state & EXT4_FC_INELIGIBLE) || + return (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FC_INELIGIBLE) || atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates); } @@ -358,7 +358,7 @@ static int ext4_fc_track_template( spin_lock(&sbi->s_fc_lock); if (list_empty(&EXT4_I(inode)->i_fc_list)) list_add_tail(&EXT4_I(inode)->i_fc_list, - (sbi->s_mount_state & EXT4_FC_COMMITTING) ? + (sbi->s_mount_flags & EXT4_MF_FC_COMMITTING) ? &sbi->s_fc_q[FC_Q_STAGING] : &sbi->s_fc_q[FC_Q_MAIN]); spin_unlock(&sbi->s_fc_lock); @@ -411,7 +411,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) node->fcd_name.len = dentry->d_name.len; spin_lock(&sbi->s_fc_lock); - if (sbi->s_mount_state & EXT4_FC_COMMITTING) + if (sbi->s_mount_flags & EXT4_MF_FC_COMMITTING) list_add_tail(&node->fcd_list, &sbi->s_fc_dentry_q[FC_Q_STAGING]); else @@ -846,7 +846,7 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal) int ret = 0; spin_lock(&sbi->s_fc_lock); - sbi->s_mount_state |= EXT4_FC_COMMITTING; + sbi->s_mount_flags |= 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); ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING); @@ -1190,8 +1190,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full) list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], &sbi->s_fc_q[FC_Q_STAGING]); - sbi->s_mount_state &= ~EXT4_FC_COMMITTING; - sbi->s_mount_state &= ~EXT4_FC_INELIGIBLE; + sbi->s_mount_flags &= ~EXT4_MF_FC_COMMITTING; + sbi->s_mount_flags &= ~EXT4_MF_FC_INELIGIBLE; if (full) sbi->s_fc_bytes = 0; -- cgit From 8c9be1e58a8dc03ef815ca51ece95c5e6862b25e Mon Sep 17 00:00:00 2001 From: Harshad Shirwadkar Date: Tue, 27 Oct 2020 13:43:42 -0700 Subject: ext4: use IS_ERR() for error checking of path With this fix, fast commit recovery code uses IS_ERR() for path returned by ext4_find_extent. Fixes: 8016e29f4362 ("ext4: fast commit recovery path") Reported-by: Dan Carpenter Signed-off-by: Harshad Shirwadkar Link: https://lore.kernel.org/r/20201027204342.2794949-1-harshadshirwadkar@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/fast_commit.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/ext4/fast_commit.c') diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index 3ee43fd6d5aa..8d43058386c3 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -1616,8 +1616,10 @@ static int ext4_fc_replay_add_range(struct super_block *sb, if (ret == 0) { /* Range is not mapped */ path = ext4_find_extent(inode, cur, NULL, 0); - if (!path) - continue; + if (IS_ERR(path)) { + iput(inode); + return 0; + } memset(&newex, 0, sizeof(newex)); newex.ee_block = cpu_to_le32(cur); ext4_ext_store_pblock( -- cgit