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 | |
| 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')
| -rw-r--r-- | fs/jbd/commit.c | 2 | ||||
| -rw-r--r-- | fs/jbd/journal.c | 16 |
2 files changed, 17 insertions, 1 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index dba9cfd75f1a..1b27f46e6108 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
| @@ -308,7 +308,9 @@ void journal_commit_transaction(journal_t *journal) | |||
| 308 | /* Do we need to erase the effects of a prior journal_flush? */ | 308 | /* Do we need to erase the effects of a prior journal_flush? */ |
| 309 | if (journal->j_flags & JFS_FLUSHED) { | 309 | if (journal->j_flags & JFS_FLUSHED) { |
| 310 | jbd_debug(3, "super block updated\n"); | 310 | jbd_debug(3, "super block updated\n"); |
| 311 | mutex_lock(&journal->j_checkpoint_mutex); | ||
| 311 | journal_update_sb_log_tail(journal); | 312 | journal_update_sb_log_tail(journal); |
| 313 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
| 312 | } else { | 314 | } else { |
| 313 | jbd_debug(3, "superblock not updated\n"); | 315 | jbd_debug(3, "superblock not updated\n"); |
| 314 | } | 316 | } |
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; |
