FAILED: patch "[PATCH] ext4: fast commit may miss file actions" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From bdc8a53a6f2f0b1cb5f991440f2100732299eb93 Mon Sep 17 00:00:00 2001
From: Xin Yin <[email protected]>
Date: Mon, 17 Jan 2022 17:36:55 +0800
Subject: [PATCH] ext4: fast commit may miss file actions
in the follow scenario:
1. jbd start transaction n
2. task A get new handle for transaction n+1
3. task A do some actions and add inode to FC_Q_MAIN fc_q
4. jbd complete transaction n and clear FC_Q_MAIN fc_q
5. task A call fsync
Fast commit will lost the file actions during a full commit.
we should also add updates to staging queue during a full commit. and in ext4_fc_cleanup(), when reset a inode's fc track range, check it's i_sync_tid, if it bigger than current transaction tid, do not rest it, or we will lost the track range.
And EXT4_MF_FC_COMMITTING is not needed anymore, so drop it.
fs/ext4/ext4.h +1 -4
@@ -1795,10 +1795,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)enum {EXT4_MF_MNTDIR_SAMPLED ,EXT4_MF_FS_ABORTED ,/* Fatal error detected */ -EXT4_MF_FC_INELIGIBLE ,/* Fast commit ineligible */ -EXT4_MF_FC_COMMITTING /* File system underoing a fast -* commit. -*/ +EXT4_MF_FC_INELIGIBLE /* Fast commit ineligible */ };static inline void ext4_set_mount_flag (struct super_block *sb,int bit)
fs/ext4/fast_commit.c +6 -5
@@ -375,7 +375,8 @@ 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, - (ext4_test_mount_flag (inode->i_sb,EXT4_MF_FC_COMMITTING )) ? + (sbi->s_journal->j_flags &JBD2_FULL_COMMIT_ONGOING || + sbi->s_journal->j_flags &JBD2_FAST_COMMIT_ONGOING ) ? &sbi->s_fc_q[FC_Q_STAGING ] : &sbi->s_fc_q[FC_Q_MAIN ]);spin_unlock (&sbi->s_fc_lock);
@@ -428,7 +429,8 @@ 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 (ext4_test_mount_flag (inode->i_sb,EXT4_MF_FC_COMMITTING )) +if (sbi->s_journal->j_flags &JBD2_FULL_COMMIT_ONGOING || + sbi->s_journal->j_flags &JBD2_FAST_COMMIT_ONGOING )list_add_tail (&node->fcd_list, &sbi->s_fc_dentry_q[FC_Q_STAGING ]);else
@@ -893,7 +895,6 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal)int ret =0 ;spin_lock (&sbi->s_fc_lock); -ext4_set_mount_flag (sb,EXT4_MF_FC_COMMITTING );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)) {
@@ -1211,7 +1212,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full, tid_t tid)list_del_init (&iter->i_fc_list);ext4_clear_inode_state (&iter->vfs_inode,EXT4_STATE_FC_COMMITTING ); -ext4_fc_reset_inode (&iter->vfs_inode); +if (iter->i_sync_tid <= tid) +ext4_fc_reset_inode (&iter->vfs_inode);/* Make sure EXT4_STATE_FC_COMMITTING bit is clear */ smp_mb ();#if (BITS_PER_LONG <64 )
@@ -1240,7 +1242,6 @@ static void ext4_fc_cleanup(journal_t *journal, int full, tid_t tid)list_splice_init (&sbi->s_fc_q[FC_Q_STAGING ], &sbi->s_fc_q[FC_Q_MAIN ]); -ext4_clear_mount_flag (sb,EXT4_MF_FC_COMMITTING );if (tid >= sbi->s_fc_ineligible_tid) { sbi->s_fc_ineligible_tid =0 ;ext4_clear_mount_flag (sb,EXT4_MF_FC_INELIGIBLE );
fs/ext4/super.c +0 -1
@@ -5083,7 +5083,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)INIT_LIST_HEAD (&sbi->s_fc_dentry_q[FC_Q_STAGING ]); sbi->s_fc_bytes =0 ;ext4_clear_mount_flag (sb,EXT4_MF_FC_INELIGIBLE ); -ext4_clear_mount_flag (sb,EXT4_MF_FC_COMMITTING ); sbi->s_fc_ineligible_tid =0 ;spin_lock_init (&sbi->s_fc_lock);memset (&sbi->s_fc_stats,0 ,sizeof (sbi->s_fc_stats));