[-mm PATCH 6/6] jbd: use list_head for a transaction checkpoint list

Akinobu Mita
Fri, 09 Sep 2005 08:50:07 -0000

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 <mita at miraclelinux.com>

---

 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 */