On Tue 08-03-22 02:51:10, Harshad Shirwadkar wrote: > 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> Looks mostly good. Just some notes below. > 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); Why do you need to call ext4_fc_track_inode() here? Calls in ext4_map_blocks() and ext4_mark_iloc_dirty() should be enough, shouldn't they? > + return handle; > +} > + > int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) > { > struct super_block *sb; ... > @@ -519,6 +525,33 @@ 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; > + > + spin_lock(&ei->i_fc_lock); > + 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); > + spin_unlock(&ei->i_fc_lock); > + > + schedule(); > + finish_wait(wq, &wait.wq_entry); > + spin_lock(&ei->i_fc_lock); > + } > + spin_unlock(&ei->i_fc_lock); Hum, we operate inode state with atomic bitops. So I think there's no real need for ei->i_fc_lock here. You just need to be careful and check inode state again after prepare_to_wait() call. Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR