diff options
-rw-r--r-- | fs/jbd2/commit.c | 32 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 13 | ||||
-rw-r--r-- | include/linux/jbd2.h | 1 |
3 files changed, 46 insertions, 0 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index b89ef84786a7..1dfcb207ea69 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 |
@@ -688,10 +692,30 @@ start_journal_io: | |||
688 | err = 0; | 692 | err = 0; |
689 | } | 693 | } |
690 | 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 | |||
691 | 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 | } | ||
692 | J_ASSERT(commit_transaction->t_state == T_COMMIT); | 715 | J_ASSERT(commit_transaction->t_state == T_COMMIT); |
693 | commit_transaction->t_state = T_COMMIT_DFLUSH; | 716 | commit_transaction->t_state = T_COMMIT_DFLUSH; |
694 | write_unlock(&journal->j_state_lock); | 717 | write_unlock(&journal->j_state_lock); |
718 | |||
695 | /* | 719 | /* |
696 | * If the journal is not located on the file system device, | 720 | * If the journal is not located on the file system device, |
697 | * then we must flush the file system device before we issue | 721 | * then we must flush the file system device before we issue |
@@ -842,6 +866,14 @@ wait_for_iobuf: | |||
842 | if (err) | 866 | if (err) |
843 | jbd2_journal_abort(journal, err); | 867 | jbd2_journal_abort(journal, err); |
844 | 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 | |||
845 | /* End of a transaction! Finally, we can do checkpoint | 877 | /* End of a transaction! Finally, we can do checkpoint |
846 | processing: any buffers committed as a result of this | 878 | processing: any buffers committed as a result of this |
847 | transaction can be removed from any checkpoint list it was on | 879 | transaction can be removed from any checkpoint list it was on |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index c5ff177400ff..bda564f63864 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -821,6 +821,19 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) | |||
821 | write_unlock(&journal->j_state_lock); | 821 | write_unlock(&journal->j_state_lock); |
822 | } | 822 | } |
823 | 823 | ||
824 | /* | ||
825 | * This is a variaon of __jbd2_update_log_tail which checks for validity of | ||
826 | * provided log tail and locks j_checkpoint_mutex. So it is safe against races | ||
827 | * with other threads updating log tail. | ||
828 | */ | ||
829 | void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) | ||
830 | { | ||
831 | mutex_lock(&journal->j_checkpoint_mutex); | ||
832 | if (tid_gt(tid, journal->j_tail_sequence)) | ||
833 | __jbd2_update_log_tail(journal, tid, block); | ||
834 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
835 | } | ||
836 | |||
824 | struct jbd2_stats_proc_session { | 837 | struct jbd2_stats_proc_session { |
825 | journal_t *journal; | 838 | journal_t *journal; |
826 | struct transaction_stats_s *stats; | 839 | struct transaction_stats_s *stats; |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 876a7d87192b..912c30a8ddb1 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -974,6 +974,7 @@ int jbd2_journal_next_log_block(journal_t *, unsigned long long *); | |||
974 | int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, | 974 | int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, |
975 | unsigned long *block); | 975 | unsigned long *block); |
976 | void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); | 976 | void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); |
977 | void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); | ||
977 | 978 | ||
978 | /* Commit management */ | 979 | /* Commit management */ |
979 | extern void jbd2_journal_commit_transaction(journal_t *); | 980 | extern void jbd2_journal_commit_transaction(journal_t *); |