summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChangwei Ge <gechangwei@live.cn>2019-09-23 18:33:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-24 18:54:07 -0400
commitd7283b39dbf3de4fe54870f07d7975effa3188da (patch)
tree80119ce1cfdcc2cb64c22446837c5a7175bea6d0
parent0a3775e4f883912944481cf2ef36eb6383a9cc74 (diff)
ocfs2: checkpoint appending truncate log transaction before flushing
Appending truncate log(TA) and and flushing truncate log(TF) are two separated transactions. They can be both committed but not checkpointed. If crash occurs then, both transaction will be replayed with several already released to global bitmap clusters. Then truncate log will be replayed resulting in cluster double free. To reproduce this issue, just crash the host while punching hole to files. Signed-off-by: Changwei Ge <gechangwei@live.cn> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> Cc: Mark Fasheh <mark@fasheh.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Junxiao Bi <junxiao.bi@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ocfs2/alloc.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index f5d2bd15e0ca..f9baefc76cf9 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -5993,6 +5993,7 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
5993 struct buffer_head *data_alloc_bh = NULL; 5993 struct buffer_head *data_alloc_bh = NULL;
5994 struct ocfs2_dinode *di; 5994 struct ocfs2_dinode *di;
5995 struct ocfs2_truncate_log *tl; 5995 struct ocfs2_truncate_log *tl;
5996 struct ocfs2_journal *journal = osb->journal;
5996 5997
5997 BUG_ON(inode_trylock(tl_inode)); 5998 BUG_ON(inode_trylock(tl_inode));
5998 5999
@@ -6013,6 +6014,20 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
6013 goto out; 6014 goto out;
6014 } 6015 }
6015 6016
6017 /* Appending truncate log(TA) and and flushing truncate log(TF) are
6018 * two separated transactions. They can be both committed but not
6019 * checkpointed. If crash occurs then, both two transaction will be
6020 * replayed with several already released to global bitmap clusters.
6021 * Then truncate log will be replayed resulting in cluster double free.
6022 */
6023 jbd2_journal_lock_updates(journal->j_journal);
6024 status = jbd2_journal_flush(journal->j_journal);
6025 jbd2_journal_unlock_updates(journal->j_journal);
6026 if (status < 0) {
6027 mlog_errno(status);
6028 goto out;
6029 }
6030
6016 data_alloc_inode = ocfs2_get_system_file_inode(osb, 6031 data_alloc_inode = ocfs2_get_system_file_inode(osb,
6017 GLOBAL_BITMAP_SYSTEM_INODE, 6032 GLOBAL_BITMAP_SYSTEM_INODE,
6018 OCFS2_INVALID_SLOT); 6033 OCFS2_INVALID_SLOT);