summaryrefslogtreecommitdiffstats
path: root/fs/jbd/commit.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-04-07 11:05:19 +0200
committerJan Kara <jack@suse.cz>2012-05-15 23:34:37 +0200
commitfd2cbd4dfa3db477dd6226d387d3f1911d36a6a9 (patch)
treeb0ada946d14cdcf5db6da2d177be9590a3449e9a /fs/jbd/commit.c
parentjbd: protect all log tail updates with j_checkpoint_mutex (diff)
downloadlinux-fd2cbd4dfa3db477dd6226d387d3f1911d36a6a9.tar.xz
linux-fd2cbd4dfa3db477dd6226d387d3f1911d36a6a9.zip
jbd: Write journal superblock with WRITE_FUA after checkpointing
If journal superblock is written only in disk's caches and other transaction starts reusing space of the transaction cleaned from the log, it can happen blocks of a new transaction reach the disk before journal superblock. When power failure happens in such case, 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>
Diffstat (limited to 'fs/jbd/commit.c')
-rw-r--r--fs/jbd/commit.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 1b27f46e6108..52c15c776029 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -309,7 +309,14 @@ void journal_commit_transaction(journal_t *journal)
if (journal->j_flags & JFS_FLUSHED) {
jbd_debug(3, "super block updated\n");
mutex_lock(&journal->j_checkpoint_mutex);
- journal_update_sb_log_tail(journal);
+ /*
+ * We hold j_checkpoint_mutex so tail cannot change under us.
+ * We don't need any special data guarantees for writing sb
+ * since journal is empty and it is ok for write to be
+ * flushed only with transaction commit.
+ */
+ journal_update_sb_log_tail(journal, journal->j_tail_sequence,
+ journal->j_tail, WRITE_SYNC);
mutex_unlock(&journal->j_checkpoint_mutex);
} else {
jbd_debug(3, "superblock not updated\n");