diff options
author | Jan Kara <jack@suse.cz> | 2012-04-07 06:50:13 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2012-05-15 17:34:36 -0400 |
commit | 1ce8486dcc00c1e095af8d155fa4451936b89013 (patch) | |
tree | 416fc385dc25993f0a968d1a78fb07dd0b79be34 /fs/jbd/journal.c | |
parent | 9754e39c7bc51328f145e933bfb0df47cd67b6e9 (diff) |
jbd: 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 journal_commit_transaction() and journal_flush() can really race
with other log tail updates (e.g. someone doing journal_flush() with someone
running cleanup_journal_tail()). So protect all log tail updates with
j_checkpoint_mutex.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/jbd/journal.c')
-rw-r--r-- | fs/jbd/journal.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 44c104abfb36..b29c7678525d 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -936,8 +936,11 @@ static int journal_reset(journal_t *journal) | |||
936 | journal->j_errno); | 936 | journal->j_errno); |
937 | journal->j_flags |= JFS_FLUSHED; | 937 | journal->j_flags |= JFS_FLUSHED; |
938 | } else { | 938 | } else { |
939 | /* Lock here to make assertions happy... */ | ||
940 | mutex_lock(&journal->j_checkpoint_mutex); | ||
939 | /* Add the dynamic fields and write it to disk. */ | 941 | /* Add the dynamic fields and write it to disk. */ |
940 | journal_update_sb_log_tail(journal); | 942 | journal_update_sb_log_tail(journal); |
943 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
941 | } | 944 | } |
942 | return journal_start_thread(journal); | 945 | return journal_start_thread(journal); |
943 | } | 946 | } |
@@ -1061,6 +1064,7 @@ void journal_update_sb_log_tail(journal_t *journal) | |||
1061 | { | 1064 | { |
1062 | journal_superblock_t *sb = journal->j_superblock; | 1065 | journal_superblock_t *sb = journal->j_superblock; |
1063 | 1066 | ||
1067 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); | ||
1064 | spin_lock(&journal->j_state_lock); | 1068 | spin_lock(&journal->j_state_lock); |
1065 | jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", | 1069 | jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", |
1066 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); | 1070 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); |
@@ -1089,6 +1093,7 @@ static void mark_journal_empty(journal_t *journal) | |||
1089 | { | 1093 | { |
1090 | journal_superblock_t *sb = journal->j_superblock; | 1094 | journal_superblock_t *sb = journal->j_superblock; |
1091 | 1095 | ||
1096 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); | ||
1092 | spin_lock(&journal->j_state_lock); | 1097 | spin_lock(&journal->j_state_lock); |
1093 | jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n", | 1098 | jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n", |
1094 | journal->j_tail_sequence); | 1099 | journal->j_tail_sequence); |
@@ -1293,6 +1298,8 @@ int journal_destroy(journal_t *journal) | |||
1293 | 1298 | ||
1294 | /* Force any old transactions to disk */ | 1299 | /* Force any old transactions to disk */ |
1295 | 1300 | ||
1301 | /* We cannot race with anybody but must keep assertions happy */ | ||
1302 | mutex_lock(&journal->j_checkpoint_mutex); | ||
1296 | /* Totally anal locking here... */ | 1303 | /* Totally anal locking here... */ |
1297 | spin_lock(&journal->j_list_lock); | 1304 | spin_lock(&journal->j_list_lock); |
1298 | while (journal->j_checkpoint_transactions != NULL) { | 1305 | while (journal->j_checkpoint_transactions != NULL) { |
@@ -1315,6 +1322,7 @@ int journal_destroy(journal_t *journal) | |||
1315 | err = -EIO; | 1322 | err = -EIO; |
1316 | brelse(journal->j_sb_buffer); | 1323 | brelse(journal->j_sb_buffer); |
1317 | } | 1324 | } |
1325 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
1318 | 1326 | ||
1319 | if (journal->j_inode) | 1327 | if (journal->j_inode) |
1320 | iput(journal->j_inode); | 1328 | iput(journal->j_inode); |
@@ -1528,6 +1536,7 @@ int journal_flush(journal_t *journal) | |||
1528 | if (is_journal_aborted(journal)) | 1536 | if (is_journal_aborted(journal)) |
1529 | return -EIO; | 1537 | return -EIO; |
1530 | 1538 | ||
1539 | mutex_lock(&journal->j_checkpoint_mutex); | ||
1531 | cleanup_journal_tail(journal); | 1540 | cleanup_journal_tail(journal); |
1532 | 1541 | ||
1533 | /* Finally, mark the journal as really needing no recovery. | 1542 | /* Finally, mark the journal as really needing no recovery. |
@@ -1536,6 +1545,7 @@ int journal_flush(journal_t *journal) | |||
1536 | * commits of data to the journal will restore the current | 1545 | * commits of data to the journal will restore the current |
1537 | * s_start value. */ | 1546 | * s_start value. */ |
1538 | mark_journal_empty(journal); | 1547 | mark_journal_empty(journal); |
1548 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
1539 | spin_lock(&journal->j_state_lock); | 1549 | spin_lock(&journal->j_state_lock); |
1540 | J_ASSERT(!journal->j_running_transaction); | 1550 | J_ASSERT(!journal->j_running_transaction); |
1541 | J_ASSERT(!journal->j_committing_transaction); | 1551 | J_ASSERT(!journal->j_committing_transaction); |
@@ -1576,8 +1586,12 @@ int journal_wipe(journal_t *journal, int write) | |||
1576 | write ? "Clearing" : "Ignoring"); | 1586 | write ? "Clearing" : "Ignoring"); |
1577 | 1587 | ||
1578 | err = journal_skip_recovery(journal); | 1588 | err = journal_skip_recovery(journal); |
1579 | if (write) | 1589 | if (write) { |
1590 | /* Lock to make assertions happy... */ | ||
1591 | mutex_lock(&journal->j_checkpoint_mutex); | ||
1580 | mark_journal_empty(journal); | 1592 | mark_journal_empty(journal); |
1593 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
1594 | } | ||
1581 | 1595 | ||
1582 | no_recovery: | 1596 | no_recovery: |
1583 | return err; | 1597 | return err; |