lkml.org 
[lkml]   [2005]   [Sep]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 4/6] jbd: use list_head for the list of buffers on a transaction's data
use struct list_head for doubly-linked list of buffers on a transaction's
data, metadata or forget queue.

Signed-off-by: Akinobu Mita <mita@miraclelinux.com>

---

fs/jbd/checkpoint.c | 12 ++--
fs/jbd/commit.c | 79 ++++++++++++++++--------------
fs/jbd/journal.c | 1
fs/jbd/transaction.c | 110 ++++++++-----------------------------------
include/linux/jbd.h | 20 +++----
include/linux/journal-head.h | 2
6 files changed, 80 insertions(+), 144 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:15:17.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/checkpoint.c 2005-09-05 03:15:35.000000000 +0900
@@ -684,12 +684,12 @@ void __journal_drop_transaction(journal_
}

J_ASSERT(transaction->t_state == T_FINISHED);
- J_ASSERT(transaction->t_buffers == NULL);
- J_ASSERT(transaction->t_sync_datalist == NULL);
- J_ASSERT(transaction->t_forget == NULL);
- J_ASSERT(transaction->t_iobuf_list == NULL);
- J_ASSERT(transaction->t_shadow_list == NULL);
- J_ASSERT(transaction->t_log_list == NULL);
+ J_ASSERT(list_empty(&transaction->t_metadata_list));
+ J_ASSERT(list_empty(&transaction->t_syncdata_list));
+ J_ASSERT(list_empty(&transaction->t_forget_list));
+ 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(transaction->t_updates == 0);
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:16:12.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/commit.c 2005-09-05 03:15:35.000000000 +0900
@@ -250,8 +250,9 @@ void journal_commit_transaction(journal_
* that multiple journal_get_write_access() calls to the same
* buffer are perfectly permissable.
*/
- while (commit_transaction->t_reserved_list) {
- jh = commit_transaction->t_reserved_list;
+ while (!list_empty(&commit_transaction->t_reserved_list)) {
+ jh = list_entry(commit_transaction->t_reserved_list.next,
+ struct journal_head, b_list);
JBUFFER_TRACE(jh, "reserved, unused: refile");
/*
* A journal_get_undo_access()+journal_release_buffer() may
@@ -300,14 +301,9 @@ void journal_commit_transaction(journal_
* will be tracked for a new trasaction only -bzzz
*/
spin_lock(&journal->j_list_lock);
- if (commit_transaction->t_buffers) {
- new_jh = jh = commit_transaction->t_buffers->b_tnext;
- do {
- J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
- new_jh->b_modified == 0);
- new_jh->b_modified = 0;
- new_jh = new_jh->b_tnext;
- } while (new_jh != jh);
+ list_for_each_entry(jh, &commit_transaction->t_metadata_list, b_list) {
+ J_ASSERT_JH(jh, jh->b_modified == 1 || jh->b_modified == 0);
+ jh->b_modified = 0;
}
spin_unlock(&journal->j_list_lock);

@@ -319,7 +315,7 @@ void journal_commit_transaction(journal_
err = 0;
/*
* Whenever we unlock the journal and sleep, things can get added
- * onto ->t_sync_datalist, so we have to keep looping back to
+ * onto ->t_syncdata_list, so we have to keep looping back to
* write_out_data until we *know* that the list is empty.
*/
bufs = 0;
@@ -331,11 +327,12 @@ write_out_data:
cond_resched();
spin_lock(&journal->j_list_lock);

- while (commit_transaction->t_sync_datalist) {
+ while (!list_empty(&commit_transaction->t_syncdata_list)) {
struct buffer_head *bh;

- jh = commit_transaction->t_sync_datalist;
- commit_transaction->t_sync_datalist = jh->b_tnext;
+ jh = list_entry(commit_transaction->t_syncdata_list.next,
+ struct journal_head, b_list);
+ list_move_tail(&jh->b_list, &commit_transaction->t_syncdata_list);
bh = jh2bh(jh);
if (buffer_locked(bh)) {
BUFFER_TRACE(bh, "locked");
@@ -389,10 +386,11 @@ write_out_data:
/*
* Wait for all previously submitted IO to complete.
*/
- while (commit_transaction->t_locked_list) {
+ while (!list_empty(&commit_transaction->t_locked_list)) {
struct buffer_head *bh;

- jh = commit_transaction->t_locked_list->b_tprev;
+ jh = list_entry(commit_transaction->t_locked_list.prev,
+ struct journal_head, b_list);
bh = jh2bh(jh);
get_bh(bh);
if (buffer_locked(bh)) {
@@ -431,7 +429,7 @@ write_out_data:
* any then journal_clean_data_list should have wiped the list
* clean by now, so check that it is in fact empty.
*/
- J_ASSERT (commit_transaction->t_sync_datalist == NULL);
+ J_ASSERT (list_empty(&commit_transaction->t_syncdata_list));

jbd_debug (3, "JBD: commit phase 3\n");

@@ -444,11 +442,12 @@ write_out_data:

descriptor = NULL;
bufs = 0;
- while (commit_transaction->t_buffers) {
+ while (!list_empty(&commit_transaction->t_metadata_list)) {

/* Find the next buffer to be journaled... */

- jh = commit_transaction->t_buffers;
+ jh = list_entry(commit_transaction->t_metadata_list.next,
+ struct journal_head, b_list);

/* If we're in abort mode, we just un-journal the buffer and
release it for background writing. */
@@ -460,7 +459,7 @@ write_out_data:
* any descriptor buffers which may have been
* already allocated, even if we are now
* aborting. */
- if (!commit_transaction->t_buffers)
+ if (list_empty(&commit_transaction->t_metadata_list))
goto start_journal_io;
continue;
}
@@ -569,7 +568,7 @@ write_out_data:
let the IO rip! */

if (bufs == journal->j_wbufsize ||
- commit_transaction->t_buffers == NULL ||
+ list_empty(&commit_transaction->t_metadata_list) ||
space_left < sizeof(journal_block_tag_t) + 16) {

jbd_debug(4, "JBD: Submit %d IOs\n", bufs);
@@ -601,8 +600,8 @@ start_journal_io:
/* Lo and behold: we have just managed to send a transaction to
the log. Before we can commit it, wait for the IO so far to
complete. Control buffers being written are on the
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
+ transaction's t_logctl_list queue, and metadata buffers are on
+ the t_io_list queue.

Wait for the buffers in reverse order. That way we are
less likely to be woken up until all IOs have completed, and
@@ -616,10 +615,11 @@ start_journal_io:
* See __journal_try_to_free_buffer.
*/
wait_for_iobuf:
- while (commit_transaction->t_iobuf_list != NULL) {
+ while (!list_empty(&commit_transaction->t_io_list)) {
struct buffer_head *bh;

- jh = commit_transaction->t_iobuf_list->b_tprev;
+ jh = list_entry(commit_transaction->t_io_list.prev,
+ struct journal_head, b_list);
bh = jh2bh(jh);
if (buffer_locked(bh)) {
wait_on_buffer(bh);
@@ -637,7 +637,7 @@ wait_for_iobuf:
journal_unfile_buffer(journal, jh);

/*
- * ->t_iobuf_list should contain only dummy buffer_heads
+ * ->t_io_list should contain only dummy buffer_heads
* which were created by journal_write_metadata_buffer().
*/
BUFFER_TRACE(bh, "dumping temporary bh");
@@ -648,7 +648,8 @@ wait_for_iobuf:

/* We also have to unlock and free the corresponding
shadowed buffer */
- jh = commit_transaction->t_shadow_list->b_tprev;
+ jh = list_entry(commit_transaction->t_shadow_list.prev,
+ struct journal_head, b_list);
bh = jh2bh(jh);
clear_bit(BH_JWrite, &bh->b_state);
J_ASSERT_BH(bh, buffer_jbddirty(bh));
@@ -666,16 +667,17 @@ wait_for_iobuf:
__brelse(bh);
}

- J_ASSERT (commit_transaction->t_shadow_list == NULL);
+ J_ASSERT (list_empty(&commit_transaction->t_shadow_list));

jbd_debug(3, "JBD: commit phase 5\n");

/* Here we wait for the revoke record and descriptor record buffers */
wait_for_ctlbuf:
- while (commit_transaction->t_log_list != NULL) {
+ while (!list_empty(&commit_transaction->t_logctl_list)) {
struct buffer_head *bh;

- jh = commit_transaction->t_log_list->b_tprev;
+ jh = list_entry(commit_transaction->t_logctl_list.prev,
+ struct journal_head, b_list);
bh = jh2bh(jh);
if (buffer_locked(bh)) {
wait_on_buffer(bh);
@@ -710,12 +712,12 @@ wait_for_iobuf:

jbd_debug(3, "JBD: commit phase 7\n");

- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
- J_ASSERT(commit_transaction->t_buffers == NULL);
+ 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(commit_transaction->t_iobuf_list == NULL);
- J_ASSERT(commit_transaction->t_shadow_list == NULL);
- J_ASSERT(commit_transaction->t_log_list == NULL);
+ 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));

restart_loop:
/*
@@ -723,11 +725,12 @@ restart_loop:
* to this list we have to be careful and hold the j_list_lock.
*/
spin_lock(&journal->j_list_lock);
- while (commit_transaction->t_forget) {
+ while (!list_empty(&commit_transaction->t_forget_list)) {
transaction_t *cp_transaction;
struct buffer_head *bh;

- jh = commit_transaction->t_forget;
+ jh = list_entry(commit_transaction->t_forget_list.next,
+ struct journal_head, b_list);
spin_unlock(&journal->j_list_lock);
bh = jh2bh(jh);
jbd_lock_bh_state(bh);
@@ -811,7 +814,7 @@ restart_loop:
* Now recheck if some buffers did not get attached to the transaction
* while the lock was dropped...
*/
- if (commit_transaction->t_forget) {
+ if (!list_empty(&commit_transaction->t_forget_list)) {
spin_unlock(&journal->j_list_lock);
spin_unlock(&journal->j_state_lock);
goto restart_loop;
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:15:17.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/journal.c 2005-09-05 03:15:39.000000000 +0900
@@ -1761,6 +1761,7 @@ repeat:
set_buffer_jbd(bh);
bh->b_private = jh;
jh->b_bh = bh;
+ INIT_LIST_HEAD(&jh->b_list);
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:15:17.000000000 +0900
+++ 2.6.13-mm1/fs/jbd/transaction.c 2005-09-05 03:15:35.000000000 +0900
@@ -51,6 +51,14 @@ get_transaction(journal_t *journal, tran
transaction->t_tid = journal->j_transaction_sequence++;
transaction->t_expires = jiffies + journal->j_commit_interval;
spin_lock_init(&transaction->t_handle_lock);
+ INIT_LIST_HEAD(&transaction->t_reserved_list);
+ INIT_LIST_HEAD(&transaction->t_locked_list);
+ INIT_LIST_HEAD(&transaction->t_metadata_list);
+ INIT_LIST_HEAD(&transaction->t_syncdata_list);
+ INIT_LIST_HEAD(&transaction->t_forget_list);
+ INIT_LIST_HEAD(&transaction->t_io_list);
+ INIT_LIST_HEAD(&transaction->t_shadow_list);
+ INIT_LIST_HEAD(&transaction->t_logctl_list);

/* Set up the commit timer for the new transaction. */
journal->j_commit_timer->expires = transaction->t_expires;
@@ -1414,64 +1422,12 @@ int journal_force_commit(journal_t *jour
return ret;
}

-/*
- *
- * List management code snippets: various functions for manipulating the
- * transaction buffer lists.
- *
- */
-
-/*
- * Append a buffer to a transaction list, given the transaction's list head
- * pointer.
- *
- * j_list_lock is held.
- *
- * jbd_lock_bh_state(jh2bh(jh)) is held.
- */
-
-static inline void
-__blist_add_buffer(struct journal_head **list, struct journal_head *jh)
-{
- if (!*list) {
- jh->b_tnext = jh->b_tprev = jh;
- *list = jh;
- } else {
- /* Insert at the tail of the list to preserve order */
- struct journal_head *first = *list, *last = first->b_tprev;
- jh->b_tprev = last;
- jh->b_tnext = first;
- last->b_tnext = first->b_tprev = jh;
- }
-}
-
-/*
- * Remove a buffer from a transaction list, given the transaction's list
- * head pointer.
- *
- * Called with j_list_lock held, and the journal may not be locked.
- *
- * jbd_lock_bh_state(jh2bh(jh)) is held.
- */
-
-static inline void
-__blist_del_buffer(struct journal_head **list, struct journal_head *jh)
-{
- if (*list == jh) {
- *list = jh->b_tnext;
- if (*list == jh)
- *list = NULL;
- }
- jh->b_tprev->b_tnext = jh->b_tnext;
- jh->b_tnext->b_tprev = jh->b_tprev;
-}
-
/*
* Remove a buffer from the appropriate transaction list.
*
* Note that this function can *change* the value of
- * bh->b_transaction->t_sync_datalist, t_buffers, t_forget,
- * t_iobuf_list, t_shadow_list, t_log_list or t_reserved_list. If the caller
+ * bh->b_transaction->t_syncdata_list, t_metadata_list, t_forget_list,
+ * t_io_list, t_shadow_list, t_logctl_list or t_reserved_list. If the caller
* is holding onto a copy of one of thee pointers, it could go bad.
* Generally the caller needs to re-read the pointer from the transaction_t.
*
@@ -1479,7 +1435,6 @@ __blist_del_buffer(struct journal_head *
*/
void __journal_temp_unlink_buffer(struct journal_head *jh)
{
- struct journal_head **list = NULL;
transaction_t *transaction;
struct buffer_head *bh = jh2bh(jh);

@@ -1495,35 +1450,12 @@ void __journal_temp_unlink_buffer(struct
switch (jh->b_jlist) {
case BJ_None:
return;
- case BJ_SyncData:
- list = &transaction->t_sync_datalist;
- break;
case BJ_Metadata:
- transaction->t_nr_buffers--;
- J_ASSERT_JH(jh, transaction->t_nr_buffers >= 0);
- list = &transaction->t_buffers;
- break;
- case BJ_Forget:
- list = &transaction->t_forget;
- break;
- case BJ_IO:
- list = &transaction->t_iobuf_list;
- break;
- case BJ_Shadow:
- list = &transaction->t_shadow_list;
- break;
- case BJ_LogCtl:
- list = &transaction->t_log_list;
- break;
- case BJ_Reserved:
- list = &transaction->t_reserved_list;
- break;
- case BJ_Locked:
- list = &transaction->t_locked_list;
+ transaction->t_nr_metadata--;
+ J_ASSERT_JH(jh, transaction->t_nr_metadata >= 0);
break;
}
-
- __blist_del_buffer(list, jh);
+ list_del(&jh->b_list);
jh->b_jlist = BJ_None;
if (test_clear_buffer_jbddirty(bh))
mark_buffer_dirty(bh); /* Expose it to the VM */
@@ -1924,7 +1856,7 @@ int journal_invalidatepage(journal_t *jo
void __journal_file_buffer(struct journal_head *jh,
transaction_t *transaction, int jlist)
{
- struct journal_head **list = NULL;
+ struct list_head *list = NULL;
int was_dirty = 0;
struct buffer_head *bh = jh2bh(jh);

@@ -1959,23 +1891,23 @@ void __journal_file_buffer(struct journa
J_ASSERT_JH(jh, !jh->b_frozen_data);
return;
case BJ_SyncData:
- list = &transaction->t_sync_datalist;
+ list = &transaction->t_syncdata_list;
break;
case BJ_Metadata:
- transaction->t_nr_buffers++;
- list = &transaction->t_buffers;
+ transaction->t_nr_metadata++;
+ list = &transaction->t_metadata_list;
break;
case BJ_Forget:
- list = &transaction->t_forget;
+ list = &transaction->t_forget_list;
break;
case BJ_IO:
- list = &transaction->t_iobuf_list;
+ list = &transaction->t_io_list;
break;
case BJ_Shadow:
list = &transaction->t_shadow_list;
break;
case BJ_LogCtl:
- list = &transaction->t_log_list;
+ list = &transaction->t_logctl_list;
break;
case BJ_Reserved:
list = &transaction->t_reserved_list;
@@ -1985,7 +1917,7 @@ void __journal_file_buffer(struct journa
break;
}

- __blist_add_buffer(list, jh);
+ list_add_tail(&jh->b_list, list);
jh->b_jlist = jlist;

if (was_dirty)
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:15:24.000000000 +0900
+++ 2.6.13-mm1/include/linux/jbd.h 2005-09-05 03:15:35.000000000 +0900
@@ -459,39 +459,39 @@ struct transaction_s
*/
unsigned long t_log_start;

- /* Number of buffers on the t_buffers list [j_list_lock] */
- int t_nr_buffers;
+ /* Number of buffers on the t_metadata_list [j_list_lock] */
+ int t_nr_metadata;

/*
* Doubly-linked circular list of all buffers reserved but not yet
* modified by this transaction [j_list_lock]
*/
- struct journal_head *t_reserved_list;
+ struct list_head t_reserved_list;

/*
* Doubly-linked circular list of all buffers under writeout during
* commit [j_list_lock]
*/
- struct journal_head *t_locked_list;
+ struct list_head t_locked_list;

/*
* Doubly-linked circular list of all metadata buffers owned by this
* transaction [j_list_lock]
*/
- struct journal_head *t_buffers;
+ struct list_head t_metadata_list;

/*
* Doubly-linked circular list of all data buffers still to be
* flushed before this transaction can be committed [j_list_lock]
*/
- struct journal_head *t_sync_datalist;
+ struct list_head t_syncdata_list;

/*
* Doubly-linked circular list of all forget buffers (superseded
* buffers which we can un-checkpoint once this transaction commits)
* [j_list_lock]
*/
- struct journal_head *t_forget;
+ struct list_head t_forget_list;

/*
* Doubly-linked circular list of all buffers still to be flushed before
@@ -509,20 +509,20 @@ struct transaction_s
* Doubly-linked circular list of temporary buffers currently undergoing
* IO in the log [j_list_lock]
*/
- struct journal_head *t_iobuf_list;
+ struct list_head t_io_list;

/*
* Doubly-linked circular list of metadata buffers being shadowed by log
* IO. The IO buffers on the iobuf list and the shadow buffers on this
* list match each other one for one at all times. [j_list_lock]
*/
- struct journal_head *t_shadow_list;
+ struct list_head t_shadow_list;

/*
* Doubly-linked circular list of control buffers being written to the
* log. [j_list_lock]
*/
- struct journal_head *t_log_list;
+ struct list_head t_logctl_list;

/*
* Protects info related to handles
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:15:24.000000000 +0900
+++ 2.6.13-mm1/include/linux/journal-head.h 2005-09-05 03:15:35.000000000 +0900
@@ -72,7 +72,7 @@ struct journal_head {
* Doubly-linked list of buffers on a transaction's data, metadata or
* forget queue. [t_list_lock] [jbd_lock_bh_state()]
*/
- struct journal_head *b_tnext, *b_tprev;
+ struct list_head b_list;

/*
* Pointer to the compound transaction against which this buffer
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-09-09 10:53    [W:0.947 / U:0.452 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site