aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-03-13 22:22:54 -0400
committerBen Hutchings <ben@decadent.org.uk>2015-08-12 16:33:15 +0200
commita3ceb22921615827bfed39d7612a9a370bff0edb (patch)
treef068d9991d554ad8cba128636e4d25a459d16c4d /include
parentdd8ff32c1e7ed10fb0e168b4431983e09acbeb2f (diff)
downloadkernel_samsung_smdk4412-a3ceb22921615827bfed39d7612a9a370bff0edb.zip
kernel_samsung_smdk4412-a3ceb22921615827bfed39d7612a9a370bff0edb.tar.gz
kernel_samsung_smdk4412-a3ceb22921615827bfed39d7612a9a370bff0edb.tar.bz2
jbd2: issue cache flush after checkpointing even with internal journal
commit 79feb521a44705262d15cc819a4117a447b11ea7 upstream. When we reach jbd2_cleanup_journal_tail(), there is no guarantee that checkpointed buffers are on a stable storage - especially if buffers were written out by jbd2_log_do_checkpoint(), they are likely to be only in disk's caches. Thus when we update journal superblock effectively removing old transaction from journal, this write of superblock can get to stable storage before those checkpointed buffers which can result in filesystem corruption after a crash. Thus we must unconditionally issue a cache flush before we update journal superblock in these cases. A similar problem can also occur if journal superblock is written only in disk's caches, other transaction starts reusing space of the transaction cleaned from the log and power failure happens. Subsequent journal replay would still try to replay the old transaction but some of it's blocks may be already overwritten by the new transaction. For this reason we must use WRITE_FUA when updating log tail and we must first write new log tail to disk and update in-memory information only after that. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> [bwh: Prerequisite for "jbd2: fix ocfs2 corrupt when updating journal superblock fails". Backported to 3.2: - Adjust context - Drop changes to jbd2_journal_update_sb_log_tail trace event] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'include')
-rw-r--r--include/linux/jbd2.h6
-rw-r--r--include/trace/events/jbd2.h2
2 files changed, 6 insertions, 2 deletions
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 9d75499..5e29682 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -972,6 +972,9 @@ extern void __journal_clean_data_list(transaction_t *transaction);
/* Log buffer allocation */
extern struct journal_head * jbd2_journal_get_descriptor_buffer(journal_t *);
int jbd2_journal_next_log_block(journal_t *, unsigned long long *);
+int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid,
+ unsigned long *block);
+void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block);
/* Commit management */
extern void jbd2_journal_commit_transaction(journal_t *);
@@ -1083,7 +1086,8 @@ extern int jbd2_journal_destroy (journal_t *);
extern int jbd2_journal_recover (journal_t *journal);
extern int jbd2_journal_wipe (journal_t *, int);
extern int jbd2_journal_skip_recovery (journal_t *);
-extern void jbd2_journal_update_sb_log_tail (journal_t *);
+extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t,
+ unsigned long, int);
extern void __jbd2_journal_abort_hard (journal_t *);
extern void jbd2_journal_abort (journal_t *, int);
extern int jbd2_journal_errno (journal_t *);
diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
index 7596441..5c74007 100644
--- a/include/trace/events/jbd2.h
+++ b/include/trace/events/jbd2.h
@@ -200,7 +200,7 @@ TRACE_EVENT(jbd2_checkpoint_stats,
__entry->forced_to_close, __entry->written, __entry->dropped)
);
-TRACE_EVENT(jbd2_cleanup_journal_tail,
+TRACE_EVENT(jbd2_update_log_tail,
TP_PROTO(journal_t *journal, tid_t first_tid,
unsigned long block_nr, unsigned long freed),