kbuild, deb-pkg: fix install scripts for posix sh
[safe/jmp/linux-2.6] / fs / jbd2 / commit.c
index c8a1bac..7b4088b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/marker.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
@@ -25,6 +24,8 @@
 #include <linux/crc32.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
+#include <linux/bio.h>
+#include <trace/events/jbd2.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
@@ -137,7 +138,7 @@ static int journal_submit_commit_record(journal_t *journal,
                set_buffer_ordered(bh);
                barrier_done = 1;
        }
-       ret = submit_bh(WRITE, bh);
+       ret = submit_bh(WRITE_SYNC_PLUG, bh);
        if (barrier_done)
                clear_buffer_ordered(bh);
 
@@ -158,7 +159,7 @@ static int journal_submit_commit_record(journal_t *journal,
                lock_buffer(bh);
                set_buffer_uptodate(bh);
                clear_buffer_dirty(bh);
-               ret = submit_bh(WRITE, bh);
+               ret = submit_bh(WRITE_SYNC_PLUG, bh);
        }
        *cbh = bh;
        return ret;
@@ -168,12 +169,34 @@ static int journal_submit_commit_record(journal_t *journal,
  * This function along with journal_submit_commit_record
  * allows to write the commit record asynchronously.
  */
-static int journal_wait_on_commit_record(struct buffer_head *bh)
+static int journal_wait_on_commit_record(journal_t *journal,
+                                        struct buffer_head *bh)
 {
        int ret = 0;
 
+retry:
        clear_buffer_dirty(bh);
        wait_on_buffer(bh);
+       if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) {
+               printk(KERN_WARNING
+                      "JBD2: wait_on_commit_record: sync failed on %s - "
+                      "disabling barriers\n", journal->j_devname);
+               spin_lock(&journal->j_state_lock);
+               journal->j_flags &= ~JBD2_BARRIER;
+               spin_unlock(&journal->j_state_lock);
+
+               lock_buffer(bh);
+               clear_buffer_dirty(bh);
+               set_buffer_uptodate(bh);
+               bh->b_end_io = journal_end_buffer_io_sync;
+
+               ret = submit_bh(WRITE_SYNC_PLUG, bh);
+               if (ret) {
+                       unlock_buffer(bh);
+                       return ret;
+               }
+               goto retry;
+       }
 
        if (unlikely(!buffer_uptodate(bh)))
                ret = -EIO;
@@ -230,6 +253,7 @@ static int journal_submit_data_buffers(journal_t *journal,
                 * block allocation  with delalloc. We need to write
                 * only allocated blocks here.
                 */
+               trace_jbd2_submit_inode_data(jinode->i_vfs_inode);
                err = journal_submit_inode_data_buffers(mapping);
                if (!ret)
                        ret = err;
@@ -332,16 +356,19 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        int flags;
        int err;
        unsigned long long blocknr;
+       ktime_t start_time;
+       u64 commit_time;
        char *tagp = NULL;
        journal_header_t *header;
        journal_block_tag_t *tag = NULL;
        int space_left = 0;
        int first_tag = 0;
        int tag_flag;
-       int i;
+       int i, to_free = 0;
        int tag_bytes = journal_tag_bytes(journal);
        struct buffer_head *cbh = NULL; /* For transactional checksums */
        __u32 crc32_sum = ~0;
+       int write_op = WRITE;
 
        /*
         * First job: lock down the current transaction and wait for
@@ -368,14 +395,21 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        commit_transaction = journal->j_running_transaction;
        J_ASSERT(commit_transaction->t_state == T_RUNNING);
 
-       trace_mark(jbd2_start_commit, "dev %s transaction %d",
-                  journal->j_devname, commit_transaction->t_tid);
+       trace_jbd2_start_commit(journal, commit_transaction);
        jbd_debug(1, "JBD: starting commit of transaction %d\n",
                        commit_transaction->t_tid);
 
        spin_lock(&journal->j_state_lock);
        commit_transaction->t_state = T_LOCKED;
 
+       /*
+        * Use plugged writes here, since we want to submit several before
+        * we unplug the device. We don't do explicit unplugging in here,
+        * instead we rely on sync_buffer() doing the unplug for us.
+        */
+       if (commit_transaction->t_synchronous_commit)
+               write_op = WRITE_SYNC_PLUG;
+       trace_jbd2_commit_locking(journal, commit_transaction);
        stats.u.run.rs_wait = commit_transaction->t_max_wait;
        stats.u.run.rs_locked = jiffies;
        stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
@@ -451,6 +485,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
         */
        jbd2_journal_switch_revoke_table(journal);
 
+       trace_jbd2_commit_flushing(journal, commit_transaction);
        stats.u.run.rs_flushing = jiffies;
        stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
                                               stats.u.run.rs_flushing);
@@ -458,6 +493,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        commit_transaction->t_state = T_FLUSH;
        journal->j_committing_transaction = commit_transaction;
        journal->j_running_transaction = NULL;
+       start_time = ktime_get();
        commit_transaction->t_log_start = journal->j_head;
        wake_up(&journal->j_wait_transaction_locked);
        spin_unlock(&journal->j_state_lock);
@@ -472,7 +508,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        if (err)
                jbd2_journal_abort(journal, err);
 
-       jbd2_journal_write_revoke_records(journal, commit_transaction);
+       jbd2_journal_write_revoke_records(journal, commit_transaction,
+                                         write_op);
 
        jbd_debug(3, "JBD: commit phase 2\n");
 
@@ -485,6 +522,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        commit_transaction->t_state = T_COMMIT;
        spin_unlock(&journal->j_state_lock);
 
+       trace_jbd2_commit_logging(journal, commit_transaction);
        stats.u.run.rs_logging = jiffies;
        stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
                                                 stats.u.run.rs_logging);
@@ -654,7 +692,7 @@ start_journal_io:
                                clear_buffer_dirty(bh);
                                set_buffer_uptodate(bh);
                                bh->b_end_io = journal_end_buffer_io_sync;
-                               submit_bh(WRITE, bh);
+                               submit_bh(write_op, bh);
                        }
                        cond_resched();
                        stats.u.run.rs_blocks_logged += bufs;
@@ -803,7 +841,7 @@ wait_for_iobuf:
                        __jbd2_journal_abort_hard(journal);
        }
        if (!err && !is_journal_aborted(journal))
-               err = journal_wait_on_commit_record(cbh);
+               err = journal_wait_on_commit_record(journal, cbh);
 
        if (err)
                jbd2_journal_abort(journal, err);
@@ -981,14 +1019,23 @@ restart_loop:
        J_ASSERT(commit_transaction == journal->j_committing_transaction);
        journal->j_commit_sequence = commit_transaction->t_tid;
        journal->j_committing_transaction = NULL;
-       spin_unlock(&journal->j_state_lock);
+       commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time));
 
-       if (journal->j_commit_callback)
-               journal->j_commit_callback(journal, commit_transaction);
+       /*
+        * weight the commit time higher than the average time so we don't
+        * react too strongly to vast changes in the commit time
+        */
+       if (likely(journal->j_average_commit_time))
+               journal->j_average_commit_time = (commit_time +
+                               journal->j_average_commit_time*3) / 4;
+       else
+               journal->j_average_commit_time = commit_time;
+       spin_unlock(&journal->j_state_lock);
 
        if (commit_transaction->t_checkpoint_list == NULL &&
            commit_transaction->t_checkpoint_io_list == NULL) {
                __jbd2_journal_drop_transaction(journal, commit_transaction);
+               to_free = 1;
        } else {
                if (journal->j_checkpoint_transactions == NULL) {
                        journal->j_checkpoint_transactions = commit_transaction;
@@ -1007,11 +1054,14 @@ restart_loop:
        }
        spin_unlock(&journal->j_list_lock);
 
-       trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
-                  journal->j_devname, journal->j_commit_sequence,
-                  journal->j_tail_sequence);
+       if (journal->j_commit_callback)
+               journal->j_commit_callback(journal, commit_transaction);
+
+       trace_jbd2_end_commit(journal, commit_transaction);
        jbd_debug(1, "JBD: commit %d complete, head %d\n",
                  journal->j_commit_sequence, journal->j_tail_sequence);
+       if (to_free)
+               kfree(commit_transaction);
 
        wake_up(&journal->j_wait_done_commit);
 }