]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/jbd2/transaction.c
slub: Fallback to kmalloc_large for failing higher order allocs
[linux-2.6-omap-h63xx.git] / fs / jbd2 / transaction.c
index e347d8c078bc73e47c6f1f30b088d40b5e5868e3..b9b0b6f899b91b2000cc4f34e72c97931670fe53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/fs/transaction.c
+ * linux/fs/jbd2/transaction.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
  *
@@ -54,11 +54,13 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
        spin_lock_init(&transaction->t_handle_lock);
 
        /* Set up the commit timer for the new transaction. */
-       journal->j_commit_timer.expires = transaction->t_expires;
+       journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
        add_timer(&journal->j_commit_timer);
 
        J_ASSERT(journal->j_running_transaction == NULL);
        journal->j_running_transaction = transaction;
+       transaction->t_max_wait = 0;
+       transaction->t_start = jiffies;
 
        return transaction;
 }
@@ -85,6 +87,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
        int nblocks = handle->h_buffer_credits;
        transaction_t *new_transaction = NULL;
        int ret = 0;
+       unsigned long ts = jiffies;
 
        if (nblocks > journal->j_max_transaction_buffers) {
                printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
@@ -96,13 +99,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
 
 alloc_transaction:
        if (!journal->j_running_transaction) {
-               new_transaction = jbd_kmalloc(sizeof(*new_transaction),
-                                               GFP_NOFS);
+               new_transaction = kzalloc(sizeof(*new_transaction),
+                                               GFP_NOFS|__GFP_NOFAIL);
                if (!new_transaction) {
                        ret = -ENOMEM;
                        goto out;
                }
-               memset(new_transaction, 0, sizeof(*new_transaction));
        }
 
        jbd_debug(3, "New handle %p going live.\n", handle);
@@ -218,6 +220,12 @@ repeat_locked:
        /* OK, account for the buffers that this operation expects to
         * use and add the handle to the running transaction. */
 
+       if (time_after(transaction->t_start, ts)) {
+               ts = jbd2_time_diff(ts, transaction->t_start);
+               if (ts > transaction->t_max_wait)
+                       transaction->t_max_wait = ts;
+       }
+
        handle->h_transaction = transaction;
        transaction->t_outstanding_credits += nblocks;
        transaction->t_updates++;
@@ -233,16 +241,21 @@ out:
        return ret;
 }
 
+static struct lock_class_key jbd2_handle_key;
+
 /* Allocate a new handle.  This should probably be in a slab... */
 static handle_t *new_handle(int nblocks)
 {
-       handle_t *handle = jbd_alloc_handle(GFP_NOFS);
+       handle_t *handle = jbd2_alloc_handle(GFP_NOFS);
        if (!handle)
                return NULL;
        memset(handle, 0, sizeof(*handle));
        handle->h_buffer_credits = nblocks;
        handle->h_ref = 1;
 
+       lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
+                                               &jbd2_handle_key, 0);
+
        return handle;
 }
 
@@ -282,10 +295,14 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
 
        err = start_this_handle(journal, handle);
        if (err < 0) {
-               jbd_free_handle(handle);
+               jbd2_free_handle(handle);
                current->journal_info = NULL;
                handle = ERR_PTR(err);
+               goto out;
        }
+
+       lock_acquire(&handle->h_lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+out:
        return handle;
 }
 
@@ -668,7 +685,7 @@ repeat:
                                JBUFFER_TRACE(jh, "allocate memory for buffer");
                                jbd_unlock_bh_state(bh);
                                frozen_buffer =
-                                       jbd2_slab_alloc(jh2bh(jh)->b_size,
+                                       jbd2_alloc(jh2bh(jh)->b_size,
                                                         GFP_NOFS);
                                if (!frozen_buffer) {
                                        printk(KERN_EMERG
@@ -728,7 +745,7 @@ done:
 
 out:
        if (unlikely(frozen_buffer))    /* It's usually NULL */
-               jbd2_slab_free(frozen_buffer, bh->b_size);
+               jbd2_free(frozen_buffer, bh->b_size);
 
        JBUFFER_TRACE(jh, "exit");
        return error;
@@ -881,7 +898,7 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
 
 repeat:
        if (!jh->b_committed_data) {
-               committed_data = jbd2_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS);
+               committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
                        printk(KERN_EMERG "%s: No memory for committed data\n",
                                __FUNCTION__);
@@ -908,7 +925,7 @@ repeat:
 out:
        jbd2_journal_put_journal_head(jh);
        if (unlikely(committed_data))
-               jbd2_slab_free(committed_data, bh->b_size);
+               jbd2_free(committed_data, bh->b_size);
        return err;
 }
 
@@ -1165,7 +1182,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
        }
 
        /* That test should have eliminated the following case: */
-       J_ASSERT_JH(jh, jh->b_frozen_data == 0);
+       J_ASSERT_JH(jh, jh->b_frozen_data == NULL);
 
        JBUFFER_TRACE(jh, "file as BJ_Metadata");
        spin_lock(&journal->j_list_lock);
@@ -1411,7 +1428,9 @@ int jbd2_journal_stop(handle_t *handle)
                spin_unlock(&journal->j_state_lock);
        }
 
-       jbd_free_handle(handle);
+       lock_release(&handle->h_lockdep_map, 1, _THIS_IP_);
+
+       jbd2_free_handle(handle);
        return err;
 }
 
@@ -1513,7 +1532,7 @@ void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh)
 
        J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
        if (jh->b_jlist != BJ_None)
-               J_ASSERT_JH(jh, transaction != 0);
+               J_ASSERT_JH(jh, transaction != NULL);
 
        switch (jh->b_jlist) {
        case BJ_None:
@@ -1582,11 +1601,11 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
        if (buffer_locked(bh) || buffer_dirty(bh))
                goto out;
 
-       if (jh->b_next_transaction != 0)
+       if (jh->b_next_transaction != NULL)
                goto out;
 
        spin_lock(&journal->j_list_lock);
-       if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) {
+       if (jh->b_transaction != NULL && jh->b_cp_transaction == NULL) {
                if (jh->b_jlist == BJ_SyncData || jh->b_jlist == BJ_Locked) {
                        /* A written-back ordered data buffer */
                        JBUFFER_TRACE(jh, "release data");
@@ -1594,7 +1613,7 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
                        jbd2_journal_remove_journal_head(bh);
                        __brelse(bh);
                }
-       } else if (jh->b_cp_transaction != 0 && jh->b_transaction == 0) {
+       } else if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) {
                /* written-back checkpointed metadata buffer */
                if (jh->b_jlist == BJ_None) {
                        JBUFFER_TRACE(jh, "remove from checkpoint list");
@@ -1954,7 +1973,7 @@ void __jbd2_journal_file_buffer(struct journal_head *jh,
 
        J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
        J_ASSERT_JH(jh, jh->b_transaction == transaction ||
-                               jh->b_transaction == 0);
+                               jh->b_transaction == NULL);
 
        if (jh->b_transaction && jh->b_jlist == jlist)
                return;