aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-03-13 15:43:04 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-03-13 15:43:04 -0400
commita78bb11d7acd525623c6a0c2ff4e213d527573fa (patch)
tree6e2e228cc51a2138046b499d6d9002f35f6d56d0 /fs/jbd2
parent24bcc89c7e7c64982e6192b4952a0a92379fc341 (diff)
jbd2: protect all log tail updates with j_checkpoint_mutex
There are some log tail updates that are not protected by j_checkpoint_mutex. Some of these are harmless because they happen during startup or shutdown but updates in jbd2_journal_commit_transaction() and jbd2_journal_flush() can really race with other log tail updates (e.g. someone doing jbd2_journal_flush() with someone running jbd2_cleanup_journal_tail()). So protect all log tail updates with j_checkpoint_mutex. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2')
-rw-r--r--fs/jbd2/commit.c2
-rw-r--r--fs/jbd2/journal.c19
2 files changed, 18 insertions, 3 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 19371a8a9015..6705717d9b7f 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -340,7 +340,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
340 /* Do we need to erase the effects of a prior jbd2_journal_flush? */ 340 /* Do we need to erase the effects of a prior jbd2_journal_flush? */
341 if (journal->j_flags & JBD2_FLUSHED) { 341 if (journal->j_flags & JBD2_FLUSHED) {
342 jbd_debug(3, "super block updated\n"); 342 jbd_debug(3, "super block updated\n");
343 mutex_lock(&journal->j_checkpoint_mutex);
343 jbd2_journal_update_sb_log_tail(journal); 344 jbd2_journal_update_sb_log_tail(journal);
345 mutex_unlock(&journal->j_checkpoint_mutex);
344 } else { 346 } else {
345 jbd_debug(3, "superblock not updated\n"); 347 jbd_debug(3, "superblock not updated\n");
346 } 348 }
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 6e75fbd75bad..fc5f2acc9f18 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1123,8 +1123,11 @@ static int journal_reset(journal_t *journal)
1123 journal->j_errno); 1123 journal->j_errno);
1124 journal->j_flags |= JBD2_FLUSHED; 1124 journal->j_flags |= JBD2_FLUSHED;
1125 } else { 1125 } else {
1126 /* Lock here to make assertions happy... */
1127 mutex_lock(&journal->j_checkpoint_mutex);
1126 /* Add the dynamic fields and write it to disk. */ 1128 /* Add the dynamic fields and write it to disk. */
1127 jbd2_journal_update_sb_log_tail(journal); 1129 jbd2_journal_update_sb_log_tail(journal);
1130 mutex_unlock(&journal->j_checkpoint_mutex);
1128 } 1131 }
1129 return jbd2_journal_start_thread(journal); 1132 return jbd2_journal_start_thread(journal);
1130} 1133}
@@ -1173,6 +1176,7 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal)
1173{ 1176{
1174 journal_superblock_t *sb = journal->j_superblock; 1177 journal_superblock_t *sb = journal->j_superblock;
1175 1178
1179 BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
1176 read_lock(&journal->j_state_lock); 1180 read_lock(&journal->j_state_lock);
1177 jbd_debug(1, "JBD2: updating superblock (start %ld, seq %d)\n", 1181 jbd_debug(1, "JBD2: updating superblock (start %ld, seq %d)\n",
1178 journal->j_tail, journal->j_tail_sequence); 1182 journal->j_tail, journal->j_tail_sequence);
@@ -1201,6 +1205,7 @@ static void jbd2_mark_journal_empty(journal_t *journal)
1201{ 1205{
1202 journal_superblock_t *sb = journal->j_superblock; 1206 journal_superblock_t *sb = journal->j_superblock;
1203 1207
1208 BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
1204 read_lock(&journal->j_state_lock); 1209 read_lock(&journal->j_state_lock);
1205 jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", 1210 jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
1206 journal->j_tail_sequence); 1211 journal->j_tail_sequence);
@@ -1434,9 +1439,11 @@ int jbd2_journal_destroy(journal_t *journal)
1434 spin_unlock(&journal->j_list_lock); 1439 spin_unlock(&journal->j_list_lock);
1435 1440
1436 if (journal->j_sb_buffer) { 1441 if (journal->j_sb_buffer) {
1437 if (!is_journal_aborted(journal)) 1442 if (!is_journal_aborted(journal)) {
1443 mutex_lock(&journal->j_checkpoint_mutex);
1438 jbd2_mark_journal_empty(journal); 1444 jbd2_mark_journal_empty(journal);
1439 else 1445 mutex_unlock(&journal->j_checkpoint_mutex);
1446 } else
1440 err = -EIO; 1447 err = -EIO;
1441 brelse(journal->j_sb_buffer); 1448 brelse(journal->j_sb_buffer);
1442 } 1449 }
@@ -1630,6 +1637,7 @@ int jbd2_journal_flush(journal_t *journal)
1630 if (is_journal_aborted(journal)) 1637 if (is_journal_aborted(journal))
1631 return -EIO; 1638 return -EIO;
1632 1639
1640 mutex_lock(&journal->j_checkpoint_mutex);
1633 jbd2_cleanup_journal_tail(journal); 1641 jbd2_cleanup_journal_tail(journal);
1634 1642
1635 /* Finally, mark the journal as really needing no recovery. 1643 /* Finally, mark the journal as really needing no recovery.
@@ -1638,6 +1646,7 @@ int jbd2_journal_flush(journal_t *journal)
1638 * commits of data to the journal will restore the current 1646 * commits of data to the journal will restore the current
1639 * s_start value. */ 1647 * s_start value. */
1640 jbd2_mark_journal_empty(journal); 1648 jbd2_mark_journal_empty(journal);
1649 mutex_unlock(&journal->j_checkpoint_mutex);
1641 write_lock(&journal->j_state_lock); 1650 write_lock(&journal->j_state_lock);
1642 J_ASSERT(!journal->j_running_transaction); 1651 J_ASSERT(!journal->j_running_transaction);
1643 J_ASSERT(!journal->j_committing_transaction); 1652 J_ASSERT(!journal->j_committing_transaction);
@@ -1678,8 +1687,12 @@ int jbd2_journal_wipe(journal_t *journal, int write)
1678 write ? "Clearing" : "Ignoring"); 1687 write ? "Clearing" : "Ignoring");
1679 1688
1680 err = jbd2_journal_skip_recovery(journal); 1689 err = jbd2_journal_skip_recovery(journal);
1681 if (write) 1690 if (write) {
1691 /* Lock to make assertions happy... */
1692 mutex_lock(&journal->j_checkpoint_mutex);
1682 jbd2_mark_journal_empty(journal); 1693 jbd2_mark_journal_empty(journal);
1694 mutex_unlock(&journal->j_checkpoint_mutex);
1695 }
1683 1696
1684 no_recovery: 1697 no_recovery:
1685 return err; 1698 return err;