use struct list_head for doubly-linked list of buffers still remaining to be
flushed before an old transaction can be checkpointed.

Signed-off-by: Akinobu Mita <[EMAIL PROTECTED]>

---

 fs/jbd/checkpoint.c          |  119 +++++++------------------------------------
 fs/jbd/commit.c              |    4 -
 fs/jbd/journal.c             |    1 
 fs/jbd/transaction.c         |    2 
 include/linux/jbd.h          |    4 -
 include/linux/journal-head.h |    2 
 6 files changed, 30 insertions(+), 102 deletions(-)

diff -X 2.6.13-mm1/Documentation/dontdiff -Nurp 
2.6.13-mm1.old/fs/jbd/checkpoint.c 2.6.13-mm1/fs/jbd/checkpoint.c
--- 2.6.13-mm1.old/fs/jbd/checkpoint.c  2005-09-05 03:21:20.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/checkpoint.c      2005-09-05 03:21:33.000000000 +0900
@@ -22,71 +22,7 @@
 #include <linux/jbd.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-
-/*
- * Unlink a buffer from a transaction checkpoint list.
- *
- * Called with j_list_lock held.
- */
-
-static void __buffer_unlink_first(struct journal_head *jh)
-{
-       transaction_t *transaction;
-
-       transaction = jh->b_cp_transaction;
-
-       jh->b_cpnext->b_cpprev = jh->b_cpprev;
-       jh->b_cpprev->b_cpnext = jh->b_cpnext;
-       if (transaction->t_checkpoint_list == jh) {
-               transaction->t_checkpoint_list = jh->b_cpnext;
-               if (transaction->t_checkpoint_list == jh)
-                       transaction->t_checkpoint_list = NULL;
-       }
-}
-
-/*
- * Unlink a buffer from a transaction checkpoint(io) list.
- *
- * Called with j_list_lock held.
- */
-
-static inline void __buffer_unlink(struct journal_head *jh)
-{
-       transaction_t *transaction;
-
-       transaction = jh->b_cp_transaction;
-
-       __buffer_unlink_first(jh);
-       if (transaction->t_checkpoint_io_list == jh) {
-               transaction->t_checkpoint_io_list = jh->b_cpnext;
-               if (transaction->t_checkpoint_io_list == jh)
-                       transaction->t_checkpoint_io_list = NULL;
-       }
-}
-
-/*
- * Move a buffer from the checkpoint list to the checkpoint io list
- *
- * Called with j_list_lock held
- */
-
-static inline void __buffer_relink_io(struct journal_head *jh)
-{
-       transaction_t *transaction;
-
-       transaction = jh->b_cp_transaction;
-       __buffer_unlink_first(jh);
-
-       if (!transaction->t_checkpoint_io_list) {
-               jh->b_cpnext = jh->b_cpprev = jh;
-       } else {
-               jh->b_cpnext = transaction->t_checkpoint_io_list;
-               jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
-               jh->b_cpprev->b_cpnext = jh;
-               jh->b_cpnext->b_cpprev = jh;
-       }
-       transaction->t_checkpoint_io_list = jh;
-}
+#include <linux/list.h>
 
 /*
  * Try to release a checkpointed buffer from its transaction.
@@ -185,8 +121,9 @@ restart:
                        t_cplist) != transaction ||
            transaction->t_tid != this_tid)
                return;
-       while (!released && transaction->t_checkpoint_io_list) {
-               jh = transaction->t_checkpoint_io_list;
+       while (!released && !list_empty(&transaction->t_checkpoint_io_list)) {
+               jh = list_entry(transaction->t_checkpoint_io_list.next,
+                               struct journal_head, b_cplist);
                bh = jh2bh(jh);
                if (!jbd_trylock_bh_state(bh)) {
                        jbd_sync_bh(journal, bh);
@@ -288,7 +225,9 @@ static int __process_buffer(journal_t *j
                J_ASSERT_BH(bh, !buffer_jwrite(bh));
                set_buffer_jwrite(bh);
                bhs[*batch_count] = bh;
-               __buffer_relink_io(jh);
+               list_del(&jh->b_cplist);
+               list_add(&jh->b_cplist,
+                        &jh->b_cp_transaction->t_checkpoint_io_list);
                jbd_unlock_bh_state(bh);
                (*batch_count)++;
                if (*batch_count == NR_BATCH) {
@@ -350,10 +289,11 @@ restart:
                struct journal_head *jh;
                int retry = 0;
 
-               while (!retry && transaction->t_checkpoint_list) {
+               while (!retry && !list_empty(&transaction->t_checkpoint_list)) {
                        struct buffer_head *bh;
 
-                       jh = transaction->t_checkpoint_list;
+                       jh = list_entry(transaction->t_checkpoint_list.next,
+                                       struct journal_head, b_cplist);
                        bh = jh2bh(jh);
                        if (!jbd_trylock_bh_state(bh)) {
                                jbd_sync_bh(journal, bh);
@@ -488,20 +428,14 @@ int cleanup_journal_tail(journal_t *jour
  * Returns number of bufers reaped (for debug)
  */
 
-static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
+static int journal_clean_one_cp_list(struct list_head *head, int *released)
 {
-       struct journal_head *last_jh;
-       struct journal_head *next_jh = jh;
+       struct journal_head *jh, *next_jh;
        int ret, freed = 0;
 
        *released = 0;
-       if (!jh)
-               return 0;
 
-       last_jh = jh->b_cpprev;
-       do {
-               jh = next_jh;
-               next_jh = jh->b_cpnext;
+       list_for_each_entry_safe(jh, next_jh, head, b_cplist) {
                /* Use trylock because of the ranking */
                if (jbd_trylock_bh_state(jh2bh(jh))) {
                        ret = __try_to_free_cp_buf(jh);
@@ -520,7 +454,7 @@ static int journal_clean_one_cp_list(str
                 */
                if (need_resched())
                        return freed;
-       } while (jh != last_jh);
+       }
 
        return freed;
 }
@@ -542,7 +476,7 @@ int __journal_clean_checkpoint_list(jour
 
        list_for_each_entry_safe(transaction, next_transaction,
                                &journal->j_checkpoint_transactions, t_cplist) {
-               ret += journal_clean_one_cp_list(transaction->
+               ret += journal_clean_one_cp_list(&transaction->
                                t_checkpoint_list, &released);
                if (need_resched())
                        goto out;
@@ -553,7 +487,7 @@ int __journal_clean_checkpoint_list(jour
                 * t_checkpoint_list with removing the buffer from the list as
                 * we can possibly see not yet submitted buffers on io_list
                 */
-               ret += journal_clean_one_cp_list(transaction->
+               ret += journal_clean_one_cp_list(&transaction->
                                t_checkpoint_io_list, &released);
                if (need_resched())
                        goto out;
@@ -596,11 +530,11 @@ int __journal_remove_checkpoint(struct j
        }
        journal = transaction->t_journal;
 
-       __buffer_unlink(jh);
+       list_del(&jh->b_cplist);
        jh->b_cp_transaction = NULL;
 
-       if (transaction->t_checkpoint_list != NULL ||
-           transaction->t_checkpoint_io_list != NULL)
+       if (!list_empty(&transaction->t_checkpoint_list) ||
+           !list_empty(&transaction->t_checkpoint_io_list))
                goto out;
        JBUFFER_TRACE(jh, "transaction has no more buffers");
 
@@ -648,16 +582,7 @@ void __journal_insert_checkpoint(struct 
        J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
 
        jh->b_cp_transaction = transaction;
-
-       if (!transaction->t_checkpoint_list) {
-               jh->b_cpnext = jh->b_cpprev = jh;
-       } else {
-               jh->b_cpnext = transaction->t_checkpoint_list;
-               jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
-               jh->b_cpprev->b_cpnext = jh;
-               jh->b_cpnext->b_cpprev = jh;
-       }
-       transaction->t_checkpoint_list = jh;
+       list_add(&jh->b_cplist, &transaction->t_checkpoint_list);
 }
 
 /*
@@ -682,8 +607,8 @@ void __journal_drop_transaction(journal_
        J_ASSERT(list_empty(&transaction->t_io_list));
        J_ASSERT(list_empty(&transaction->t_shadow_list));
        J_ASSERT(list_empty(&transaction->t_logctl_list));
-       J_ASSERT(transaction->t_checkpoint_list == NULL);
-       J_ASSERT(transaction->t_checkpoint_io_list == NULL);
+       J_ASSERT(list_empty(&transaction->t_checkpoint_list));
+       J_ASSERT(list_empty(&transaction->t_checkpoint_io_list));
        J_ASSERT(transaction->t_updates == 0);
        J_ASSERT(journal->j_committing_transaction != transaction);
        J_ASSERT(journal->j_running_transaction != transaction);
diff -X 2.6.13-mm1/Documentation/dontdiff -Nurp 2.6.13-mm1.old/fs/jbd/commit.c 
2.6.13-mm1/fs/jbd/commit.c
--- 2.6.13-mm1.old/fs/jbd/commit.c      2005-09-05 03:21:20.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/commit.c  2005-09-05 03:21:33.000000000 +0900
@@ -714,7 +714,7 @@ wait_for_iobuf:
 
        J_ASSERT(list_empty(&commit_transaction->t_syncdata_list));
        J_ASSERT(list_empty(&commit_transaction->t_metadata_list));
-       J_ASSERT(commit_transaction->t_checkpoint_list == NULL);
+       J_ASSERT(list_empty(&commit_transaction->t_checkpoint_list));
        J_ASSERT(list_empty(&commit_transaction->t_io_list));
        J_ASSERT(list_empty(&commit_transaction->t_shadow_list));
        J_ASSERT(list_empty(&commit_transaction->t_logctl_list));
@@ -832,7 +832,7 @@ restart_loop:
        journal->j_committing_transaction = NULL;
        spin_unlock(&journal->j_state_lock);
 
-       if (commit_transaction->t_checkpoint_list == NULL) {
+       if (list_empty(&commit_transaction->t_checkpoint_list)) {
                __journal_drop_transaction(journal, commit_transaction);
        } else {
                list_add_tail(&commit_transaction->t_cplist,
diff -X 2.6.13-mm1/Documentation/dontdiff -Nurp 2.6.13-mm1.old/fs/jbd/journal.c 
2.6.13-mm1/fs/jbd/journal.c
--- 2.6.13-mm1.old/fs/jbd/journal.c     2005-09-05 03:21:20.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/journal.c 2005-09-05 03:21:36.000000000 +0900
@@ -1763,6 +1763,7 @@ repeat:
                bh->b_private = jh;
                jh->b_bh = bh;
                INIT_LIST_HEAD(&jh->b_list);
+               INIT_LIST_HEAD(&jh->b_cplist);
                get_bh(bh);
                BUFFER_TRACE(bh, "added journal_head");
        }
diff -X 2.6.13-mm1/Documentation/dontdiff -Nurp 
2.6.13-mm1.old/fs/jbd/transaction.c 2.6.13-mm1/fs/jbd/transaction.c
--- 2.6.13-mm1.old/fs/jbd/transaction.c 2005-09-05 03:21:20.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/transaction.c     2005-09-05 03:21:36.000000000 +0900
@@ -60,6 +60,8 @@ get_transaction(journal_t *journal, tran
        INIT_LIST_HEAD(&transaction->t_shadow_list);
        INIT_LIST_HEAD(&transaction->t_logctl_list);
        INIT_LIST_HEAD(&transaction->t_cplist);
+       INIT_LIST_HEAD(&transaction->t_checkpoint_list);
+       INIT_LIST_HEAD(&transaction->t_checkpoint_io_list);
 
        /* Set up the commit timer for the new transaction. */
        journal->j_commit_timer->expires = transaction->t_expires;
diff -X 2.6.13-mm1/Documentation/dontdiff -Nurp 
2.6.13-mm1.old/include/linux/jbd.h 2.6.13-mm1/include/linux/jbd.h
--- 2.6.13-mm1.old/include/linux/jbd.h  2005-09-05 03:21:20.000000000 +0900
+++ 2.6.13-mm1/include/linux/jbd.h      2005-09-05 03:21:33.000000000 +0900
@@ -497,13 +497,13 @@ struct transaction_s 
         * Doubly-linked circular list of all buffers still to be flushed before
         * this transaction can be checkpointed. [j_list_lock]
         */
-       struct journal_head     *t_checkpoint_list;
+       struct list_head        t_checkpoint_list;
 
        /*
         * Doubly-linked circular list of all buffers submitted for IO while
         * checkpointing. [j_list_lock]
         */
-       struct journal_head     *t_checkpoint_io_list;
+       struct list_head        t_checkpoint_io_list;
 
        /*
         * Doubly-linked circular list of temporary buffers currently undergoing
diff -X 2.6.13-mm1/Documentation/dontdiff -Nurp 
2.6.13-mm1.old/include/linux/journal-head.h 
2.6.13-mm1/include/linux/journal-head.h
--- 2.6.13-mm1.old/include/linux/journal-head.h 2005-09-05 03:20:41.000000000 
+0900
+++ 2.6.13-mm1/include/linux/journal-head.h     2005-09-05 03:21:33.000000000 
+0900
@@ -86,7 +86,7 @@ struct journal_head {
         * before an old transaction can be checkpointed.
         * [j_list_lock]
         */
-       struct journal_head *b_cpnext, *b_cpprev;
+       struct list_head b_cplist;
 };
 
 #endif         /* JOURNAL_HEAD_H_INCLUDED */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to