aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/commit.c32
-rw-r--r--fs/jbd2/journal.c13
-rw-r--r--include/linux/jbd2.h1
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 */
829void 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
824struct jbd2_stats_proc_session { 837struct 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 *);
974int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, 974int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid,
975 unsigned long *block); 975 unsigned long *block);
976void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); 976void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block);
977void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block);
977 978
978/* Commit management */ 979/* Commit management */
979extern void jbd2_journal_commit_transaction(journal_t *); 980extern void jbd2_journal_commit_transaction(journal_t *);