---
fs/jbd2/checkpoint.c | 2 +-
fs/jbd2/commit.c | 6 +++---
fs/jbd2/journal.c | 16 +++++++++-------
include/linux/jbd2.h | 9 ++++++++-
4 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index c125d662777c..1729d6298895 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -404,7 +404,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
if (journal->j_flags & JBD2_BARRIER)
blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
- return __jbd2_update_log_tail(journal, first_tid, blocknr);
+ return jbd2_update_log_tail(journal, first_tid, blocknr);
}
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 150cc030b4d7..f139f5465687 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -383,9 +383,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
/* Do we need to erase the effects of a prior jbd2_journal_flush? */
if (journal->j_flags & JBD2_FLUSHED) {
jbd_debug(3, "super block updated\n");
- mutex_lock_io(&journal->j_checkpoint_mutex);
+ mutex_lock_io(&journal->j_loginfo_mutex);
/*
- * We hold j_checkpoint_mutex so tail cannot change under us.
+ * We hold j_loginfo_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.
@@ -394,7 +394,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
journal->j_tail_sequence,
journal->j_tail,
REQ_SYNC);
- mutex_unlock(&journal->j_checkpoint_mutex);
+ mutex_unlock(&journal->j_loginfo_mutex);
} else {
jbd_debug(3, "superblock not updated\n");
}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 8ef6b6daaa7a..be2c10ff5bae 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -940,8 +940,6 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
unsigned long freed;
int ret;
- BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
-
/*
* We cannot afford for write to remain in drive's caches since as
* soon as we update j_tail, next transaction can start reusing journal
@@ -978,12 +976,16 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
* provided log tail and locks j_checkpoint_mutex. So it is safe against races
* with other threads updating log tail.
*/
-void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
+int jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
{
- mutex_lock_io(&journal->j_checkpoint_mutex);
+ int ret = 0;
+
+ mutex_lock_io(&journal->j_loginfo_mutex);
if (tid_gt(tid, journal->j_tail_sequence))
- __jbd2_update_log_tail(journal, tid, block);
- mutex_unlock(&journal->j_checkpoint_mutex);
+ ret = __jbd2_update_log_tail(journal, tid, block);
+ mutex_unlock(&journal->j_loginfo_mutex);
+
+ return ret;
}
struct jbd2_stats_proc_session {
@@ -1147,6 +1149,7 @@ static journal_t *journal_init_common(struct block_device *bdev,
init_waitqueue_head(&journal->j_wait_reserved);
mutex_init(&journal->j_barrier);
mutex_init(&journal->j_checkpoint_mutex);
+ mutex_init(&journal->j_loginfo_mutex);
spin_lock_init(&journal->j_revoke_lock);
spin_lock_init(&journal->j_list_lock);
rwlock_init(&journal->j_state_lock);
@@ -1420,7 +1423,6 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
if (is_journal_aborted(journal))
return -EIO;
- BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
tail_block, tail_tid);
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index b708e5169d1d..a9c2928aea35 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -862,6 +862,13 @@ struct journal_s
*/
struct buffer_head *j_chkpt_bhs[JBD2_NR_BATCH];
+ /**
+ * @j_loginfo_mutex:
+ *
+ * Semaphore for locking against concurrent update journal info.
+ */
+ struct mutex j_loginfo_mutex;
+
/**
* @j_head:
*
@@ -1265,7 +1272,7 @@ 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);
int __jbd2_update_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);
+int jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block);
/* Commit management */
extern void jbd2_journal_commit_transaction(journal_t *);
--
2.14.4.44.g2045bb6