jbd2: use GFP_NOFS for blkdev_issue_flush
[firefly-linux-kernel-4.4.55.git] / fs / jbd2 / commit.c
index c067a8cae63bf322067763ff02687ae24c216008..840f70f507924a0ac4db70a9d729f715783b49be 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/blkdev.h>
 #include <linux/bitops.h>
 #include <trace/events/jbd2.h>
-#include <asm/system.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
@@ -331,6 +330,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        struct buffer_head *cbh = NULL; /* For transactional checksums */
        __u32 crc32_sum = ~0;
        struct blk_plug plug;
+       /* Tail of the journal */
+       unsigned long first_block;
+       tid_t first_tid;
+       int update_tail;
 
        /*
         * First job: lock down the current transaction and wait for
@@ -340,7 +343,18 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        /* Do we need to erase the effects of a prior jbd2_journal_flush? */
        if (journal->j_flags & JBD2_FLUSHED) {
                jbd_debug(3, "super block updated\n");
-               jbd2_journal_update_superblock(journal, 1);
+               mutex_lock(&journal->j_checkpoint_mutex);
+               /*
+                * We hold j_checkpoint_mutex so tail cannot change under us.
+                * We don't need any special data guarantees for writing sb
+                * since journal is empty and it is ok for write to be
+                * flushed only with transaction commit.
+                */
+               jbd2_journal_update_sb_log_tail(journal,
+                                               journal->j_tail_sequence,
+                                               journal->j_tail,
+                                               WRITE_SYNC);
+               mutex_unlock(&journal->j_checkpoint_mutex);
        } else {
                jbd_debug(3, "superblock not updated\n");
        }
@@ -677,10 +691,30 @@ start_journal_io:
                err = 0;
        }
 
+       /*
+        * Get current oldest transaction in the log before we issue flush
+        * to the filesystem device. After the flush we can be sure that
+        * blocks of all older transactions are checkpointed to persistent
+        * storage and we will be safe to update journal start in the
+        * superblock with the numbers we get here.
+        */
+       update_tail =
+               jbd2_journal_get_log_tail(journal, &first_tid, &first_block);
+
        write_lock(&journal->j_state_lock);
+       if (update_tail) {
+               long freed = first_block - journal->j_tail;
+
+               if (first_block < journal->j_tail)
+                       freed += journal->j_last - journal->j_first;
+               /* Update tail only if we free significant amount of space */
+               if (freed < journal->j_maxlen / 4)
+                       update_tail = 0;
+       }
        J_ASSERT(commit_transaction->t_state == T_COMMIT);
        commit_transaction->t_state = T_COMMIT_DFLUSH;
        write_unlock(&journal->j_state_lock);
+
        /* 
         * If the journal is not located on the file system device,
         * then we must flush the file system device before we issue
@@ -689,7 +723,7 @@ start_journal_io:
        if (commit_transaction->t_need_data_flush &&
            (journal->j_fs_dev != journal->j_dev) &&
            (journal->j_flags & JBD2_BARRIER))
-               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+               blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
 
        /* Done it all: now write the commit record asynchronously. */
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
@@ -825,12 +859,20 @@ wait_for_iobuf:
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
                                      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
            journal->j_flags & JBD2_BARRIER) {
-               blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL);
+               blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL);
        }
 
        if (err)
                jbd2_journal_abort(journal, err);
 
+       /*
+        * Now disk caches for filesystem device are flushed so we are safe to
+        * erase checkpointed transactions from the log by updating journal
+        * superblock.
+        */
+       if (update_tail)
+               jbd2_update_log_tail(journal, first_tid, first_block);
+
        /* End of a transaction!  Finally, we can do checkpoint
            processing: any buffers committed as a result of this
            transaction can be removed from any checkpoint list it was on
@@ -1048,7 +1090,7 @@ restart_loop:
        jbd_debug(1, "JBD2: commit %d complete, head %d\n",
                  journal->j_commit_sequence, journal->j_tail_sequence);
        if (to_free)
-               kfree(commit_transaction);
+               jbd2_journal_free_transaction(commit_transaction);
 
        wake_up(&journal->j_wait_done_commit);
 }