diff options
Diffstat (limited to 'fs/jbd2/commit.c')
-rw-r--r-- | fs/jbd2/commit.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index c067a8cae63b..17f557f01cf0 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -331,6 +331,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
331 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | 331 | struct buffer_head *cbh = NULL; /* For transactional checksums */ |
332 | __u32 crc32_sum = ~0; | 332 | __u32 crc32_sum = ~0; |
333 | struct blk_plug plug; | 333 | struct blk_plug plug; |
334 | /* Tail of the journal */ | ||
335 | unsigned long first_block; | ||
336 | tid_t first_tid; | ||
337 | int update_tail; | ||
334 | 338 | ||
335 | /* | 339 | /* |
336 | * First job: lock down the current transaction and wait for | 340 | * First job: lock down the current transaction and wait for |
@@ -340,7 +344,18 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
340 | /* Do we need to erase the effects of a prior jbd2_journal_flush? */ | 344 | /* Do we need to erase the effects of a prior jbd2_journal_flush? */ |
341 | if (journal->j_flags & JBD2_FLUSHED) { | 345 | if (journal->j_flags & JBD2_FLUSHED) { |
342 | jbd_debug(3, "super block updated\n"); | 346 | jbd_debug(3, "super block updated\n"); |
343 | jbd2_journal_update_superblock(journal, 1); | 347 | mutex_lock(&journal->j_checkpoint_mutex); |
348 | /* | ||
349 | * We hold j_checkpoint_mutex so tail cannot change under us. | ||
350 | * We don't need any special data guarantees for writing sb | ||
351 | * since journal is empty and it is ok for write to be | ||
352 | * flushed only with transaction commit. | ||
353 | */ | ||
354 | jbd2_journal_update_sb_log_tail(journal, | ||
355 | journal->j_tail_sequence, | ||
356 | journal->j_tail, | ||
357 | WRITE_SYNC); | ||
358 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
344 | } else { | 359 | } else { |
345 | jbd_debug(3, "superblock not updated\n"); | 360 | jbd_debug(3, "superblock not updated\n"); |
346 | } | 361 | } |
@@ -677,10 +692,30 @@ start_journal_io: | |||
677 | err = 0; | 692 | err = 0; |
678 | } | 693 | } |
679 | 694 | ||
695 | /* | ||
696 | * Get current oldest transaction in the log before we issue flush | ||
697 | * to the filesystem device. After the flush we can be sure that | ||
698 | * blocks of all older transactions are checkpointed to persistent | ||
699 | * storage and we will be safe to update journal start in the | ||
700 | * superblock with the numbers we get here. | ||
701 | */ | ||
702 | update_tail = | ||
703 | jbd2_journal_get_log_tail(journal, &first_tid, &first_block); | ||
704 | |||
680 | write_lock(&journal->j_state_lock); | 705 | write_lock(&journal->j_state_lock); |
706 | if (update_tail) { | ||
707 | long freed = first_block - journal->j_tail; | ||
708 | |||
709 | if (first_block < journal->j_tail) | ||
710 | freed += journal->j_last - journal->j_first; | ||
711 | /* Update tail only if we free significant amount of space */ | ||
712 | if (freed < journal->j_maxlen / 4) | ||
713 | update_tail = 0; | ||
714 | } | ||
681 | J_ASSERT(commit_transaction->t_state == T_COMMIT); | 715 | J_ASSERT(commit_transaction->t_state == T_COMMIT); |
682 | commit_transaction->t_state = T_COMMIT_DFLUSH; | 716 | commit_transaction->t_state = T_COMMIT_DFLUSH; |
683 | write_unlock(&journal->j_state_lock); | 717 | write_unlock(&journal->j_state_lock); |
718 | |||
684 | /* | 719 | /* |
685 | * If the journal is not located on the file system device, | 720 | * If the journal is not located on the file system device, |
686 | * then we must flush the file system device before we issue | 721 | * then we must flush the file system device before we issue |
@@ -831,6 +866,14 @@ wait_for_iobuf: | |||
831 | if (err) | 866 | if (err) |
832 | jbd2_journal_abort(journal, err); | 867 | jbd2_journal_abort(journal, err); |
833 | 868 | ||
869 | /* | ||
870 | * Now disk caches for filesystem device are flushed so we are safe to | ||
871 | * erase checkpointed transactions from the log by updating journal | ||
872 | * superblock. | ||
873 | */ | ||
874 | if (update_tail) | ||
875 | jbd2_update_log_tail(journal, first_tid, first_block); | ||
876 | |||
834 | /* End of a transaction! Finally, we can do checkpoint | 877 | /* End of a transaction! Finally, we can do checkpoint |
835 | processing: any buffers committed as a result of this | 878 | processing: any buffers committed as a result of this |
836 | transaction can be removed from any checkpoint list it was on | 879 | transaction can be removed from any checkpoint list it was on |
@@ -1048,7 +1091,7 @@ restart_loop: | |||
1048 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", | 1091 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", |
1049 | journal->j_commit_sequence, journal->j_tail_sequence); | 1092 | journal->j_commit_sequence, journal->j_tail_sequence); |
1050 | if (to_free) | 1093 | if (to_free) |
1051 | kfree(commit_transaction); | 1094 | jbd2_journal_free_transaction(commit_transaction); |
1052 | 1095 | ||
1053 | wake_up(&journal->j_wait_done_commit); | 1096 | wake_up(&journal->j_wait_done_commit); |
1054 | } | 1097 | } |