From: Harshad Shirwadkar <harshadshirwadkar@xxxxxxxxx> If the inode that's being requested to track using ext4_fc_track_inode is being committed, then wait until the inode finishes the commit. Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@xxxxxxxxx> --- fs/ext4/ext4_jbd2.c | 12 ++++++++++++ fs/ext4/ext4_jbd2.h | 13 ++++--------- fs/ext4/fast_commit.c | 28 ++++++++++++++++++++++++++++ fs/ext4/inode.c | 3 ++- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 3477a16d08ae..7fa301b0a35a 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -106,6 +106,18 @@ handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, GFP_NOFS, type, line); } +handle_t *__ext4_journal_start(struct inode *inode, unsigned int line, + int type, int blocks, int rsv_blocks, + int revoke_creds) +{ + handle_t *handle = __ext4_journal_start_sb(inode->i_sb, line, + type, blocks, rsv_blocks, + revoke_creds); + if (ext4_handle_valid(handle) && !IS_ERR(handle)) + ext4_fc_track_inode(handle, inode); + return handle; +} + int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) { struct super_block *sb; diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index db2ae4a2b38d..e408622fe896 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -302,6 +302,10 @@ static inline int ext4_trans_default_revoke_credits(struct super_block *sb) return ext4_free_metadata_revoke_credits(sb, 8); } +handle_t *__ext4_journal_start(struct inode *inode, unsigned int line, + int type, int blocks, int rsv_blocks, + int revoke_creds); + #define ext4_journal_start_sb(sb, type, nblocks) \ __ext4_journal_start_sb((sb), __LINE__, (type), (nblocks), 0, \ ext4_trans_default_revoke_credits(sb)) @@ -318,15 +322,6 @@ static inline int ext4_trans_default_revoke_credits(struct super_block *sb) __ext4_journal_start((inode), __LINE__, (type), (blocks), 0, \ (revoke_creds)) -static inline handle_t *__ext4_journal_start(struct inode *inode, - unsigned int line, int type, - int blocks, int rsv_blocks, - int revoke_creds) -{ - return __ext4_journal_start_sb(inode->i_sb, line, type, blocks, - rsv_blocks, revoke_creds); -} - #define ext4_journal_stop(handle) \ __ext4_journal_stop(__func__, __LINE__, (handle)) diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index 9913de655b61..be8c5b3456ec 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -551,8 +551,14 @@ static int __track_inode(struct inode *inode, void *arg, bool update) return 0; } +/* + * Track inode as part of the next fast commit. If the inode is being + * committed, this function will wait for the commit to finish. + */ void ext4_fc_track_inode(handle_t *handle, struct inode *inode) { + struct ext4_inode_info *ei = EXT4_I(inode); + wait_queue_head_t *wq; int ret; if (S_ISDIR(inode->i_mode)) @@ -564,6 +570,28 @@ void ext4_fc_track_inode(handle_t *handle, struct inode *inode) return; } + if (!test_opt2(inode->i_sb, JOURNAL_FAST_COMMIT) || + (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)) + return; + + while (ext4_test_inode_state(inode, EXT4_STATE_FC_COMMITTING)) { +#if (BITS_PER_LONG < 64) + DEFINE_WAIT_BIT(wait, &ei->i_state_flags, + EXT4_STATE_FC_COMMITTING); + wq = bit_waitqueue(&ei->i_state_flags, + EXT4_STATE_FC_COMMITTING); +#else + DEFINE_WAIT_BIT(wait, &ei->i_flags, + EXT4_STATE_FC_COMMITTING); + wq = bit_waitqueue(&ei->i_flags, + EXT4_STATE_FC_COMMITTING); +#endif + prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE); + if (ext4_test_inode_state(inode, EXT4_STATE_FC_COMMITTING)) + schedule(); + finish_wait(wq, &wait.wq_entry); + } + ret = ext4_fc_track_template(handle, inode, __track_inode, NULL, 1); trace_ext4_fc_track_inode(inode, ret); } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 531a94f48637..7a01f5bd377c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -629,6 +629,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, * with create == 1 flag. */ down_write(&EXT4_I(inode)->i_data_sem); + ext4_fc_track_inode(handle, inode); /* * We need to check for EXT4 here because migrate @@ -5690,7 +5691,6 @@ int ext4_mark_iloc_dirty(handle_t *handle, put_bh(iloc->bh); return -EIO; } - ext4_fc_track_inode(handle, inode); if (IS_I_VERSION(inode)) inode_inc_iversion(inode); @@ -5727,6 +5727,7 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode, brelse(iloc->bh); iloc->bh = NULL; } + ext4_fc_track_inode(handle, inode); } ext4_std_error(inode->i_sb, err); return err; -- 2.35.1.616.g0bdcbb4464-goog