this patch turns the j_list_lock spinlock into a mutex.
Builds/boots/works fine on x86.

Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>

--- linux/fs/jbd/checkpoint.c.orig
+++ linux/fs/jbd/checkpoint.c
@@ -26,7 +26,7 @@
 /*
  * Unlink a buffer from a transaction. 
  *
- * Called with j_list_lock held.
+ * Called with j_list_sem held.
  */
 
 static inline void __buffer_unlink(struct journal_head *jh)
@@ -47,7 +47,7 @@ static inline void __buffer_unlink(struc
 /*
  * Try to release a checkpointed buffer from its transaction.
  * Returns 1 if we released it.
- * Requires j_list_lock
+ * Requires j_list_sem
  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
  */
 static int __try_to_free_cp_buf(struct journal_head *jh)
@@ -102,14 +102,14 @@ void __log_wait_for_space(journal_t *jou
 }
 
 /*
- * We were unable to perform jbd_trylock_bh_state() inside j_list_lock.
+ * We were unable to perform jbd_trylock_bh_state() inside j_list_sem.
  * The caller must restart a list walk.  Wait for someone else to run
  * jbd_unlock_bh_state().
  */
 static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
 {
        get_bh(bh);
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        jbd_lock_bh_state(bh);
        jbd_unlock_bh_state(bh);
        put_bh(bh);
@@ -125,7 +125,7 @@ static void jbd_sync_bh(journal_t *journ
  * checkpoint.  (journal_remove_checkpoint() deletes the transaction when
  * the last checkpoint buffer is cleansed)
  *
- * Called with j_list_lock held.
+ * Called with j_list_sem held.
  */
 static int __cleanup_transaction(journal_t *journal, transaction_t 
*transaction)
 {
@@ -133,7 +133,6 @@ static int __cleanup_transaction(journal
        struct buffer_head *bh;
        int ret = 0;
 
-       assert_spin_locked(&journal->j_list_lock);
        jh = transaction->t_checkpoint_list;
        if (!jh)
                return 0;
@@ -145,7 +144,7 @@ static int __cleanup_transaction(journal
                bh = jh2bh(jh);
                if (buffer_locked(bh)) {
                        atomic_inc(&bh->b_count);
-                       spin_unlock(&journal->j_list_lock);
+                       up(&journal->j_list_sem);
                        wait_on_buffer(bh);
                        /* the journal_head may have gone by now */
                        BUFFER_TRACE(bh, "brelse");
@@ -165,7 +164,7 @@ static int __cleanup_transaction(journal
                        transaction_t *t = jh->b_transaction;
                        tid_t tid = t->t_tid;
 
-                       spin_unlock(&journal->j_list_lock);
+                       up(&journal->j_list_sem);
                        jbd_unlock_bh_state(bh);
                        log_start_commit(journal, tid);
                        log_wait_commit(journal, tid);
@@ -192,7 +191,7 @@ static int __cleanup_transaction(journal
 
        return ret;
 out_return_1:
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        return 1;
 }
 
@@ -203,9 +202,9 @@ __flush_batch(journal_t *journal, struct
 {
        int i;
 
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        ll_rw_block(WRITE, *batch_count, bhs);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        for (i = 0; i < *batch_count; i++) {
                struct buffer_head *bh = bhs[i];
                clear_buffer_jwrite(bh);
@@ -221,7 +220,7 @@ __flush_batch(journal_t *journal, struct
  * Return 1 if something happened which requires us to abort the current
  * scan of the checkpoint list.  
  *
- * Called with j_list_lock held.
+ * Called with j_list_sem held.
  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
  */
 static int __flush_buffer(journal_t *journal, struct journal_head *jh,
@@ -306,7 +305,7 @@ int log_do_checkpoint(journal_t *journal
         * AKPM: check this code.  I had a feeling a while back that it
         * degenerates into a busy loop at unmount time.
         */
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        while (journal->j_checkpoint_transactions) {
                transaction_t *transaction;
                struct journal_head *jh, *last_jh, *next_jh;
@@ -327,15 +326,11 @@ int log_do_checkpoint(journal_t *journal
                        bh = jh2bh(jh);
                        if (!jbd_trylock_bh_state(bh)) {
                                jbd_sync_bh(journal, bh);
-                               spin_lock(&journal->j_list_lock);
+                               down(&journal->j_list_sem);
                                retry = 1;
                                break;
                        }
                        retry = __flush_buffer(journal, jh, bhs, &batch_count, 
&drop_count);
-                       if (cond_resched_lock(&journal->j_list_lock)) {
-                               retry = 1;
-                               break;
-                       }
                } while (jh != last_jh && !retry);
 
                if (batch_count)
@@ -365,7 +360,7 @@ int log_do_checkpoint(journal_t *journal
                if (journal->j_checkpoint_transactions != transaction)
                        break;
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        result = cleanup_journal_tail(journal);
        if (result < 0)
                return result;
@@ -404,7 +399,7 @@ int cleanup_journal_tail(journal_t *jour
         * start. */
 
        down(&journal->j_state_sem);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        transaction = journal->j_checkpoint_transactions;
        if (transaction) {
                first_tid = transaction->t_tid;
@@ -419,7 +414,7 @@ int cleanup_journal_tail(journal_t *jour
                first_tid = journal->j_transaction_sequence;
                blocknr = journal->j_head;
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        J_ASSERT(blocknr != 0);
 
        /* If the oldest pinned transaction is at the tail of the log
@@ -459,7 +454,7 @@ int cleanup_journal_tail(journal_t *jour
  * Find all the written-back checkpoint buffers in the journal and release 
them.
  *
  * Called with the journal locked.
- * Called with j_list_lock held.
+ * Called with j_list_sem held.
  * Returns number of bufers reaped (for debug)
  */
 
@@ -519,7 +514,7 @@ out:
  * checkpoint list.  
  *
  * This function is called with the journal locked.
- * This function is called with j_list_lock held.
+ * This function is called with j_list_sem held.
  */
 
 void __journal_remove_checkpoint(struct journal_head *jh)
@@ -573,7 +568,7 @@ out:
  * the log.
  *
  * Called with the journal locked.
- * Called with j_list_lock held.
+ * Called with j_list_sem held.
  */
 void __journal_insert_checkpoint(struct journal_head *jh, 
                               transaction_t *transaction)
@@ -602,12 +597,11 @@ void __journal_insert_checkpoint(struct 
  * point.
  *
  * Called with the journal locked.
- * Called with j_list_lock held.
+ * Called with j_list_sem held.
  */
 
 void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
 {
-       assert_spin_locked(&journal->j_list_lock);
        if (transaction->t_cpnext) {
                transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
                transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
--- linux/fs/jbd/transaction.c.orig
+++ linux/fs/jbd/transaction.c
@@ -485,7 +485,7 @@ void journal_unlock_updates (journal_t *
  * continuing as gracefully as possible.  #
  *
  * The caller should already hold the journal lock and
- * j_list_lock spinlock: most callers will need those anyway
+ * j_list_sem mutex: most callers will need those anyway
  * in order to probe the buffer's journaling state safely.
  */
 static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
@@ -694,9 +694,9 @@ repeat:
                J_ASSERT_JH(jh, !jh->b_next_transaction);
                jh->b_transaction = transaction;
                JBUFFER_TRACE(jh, "file as BJ_Reserved");
-               spin_lock(&journal->j_list_lock);
+               down(&journal->j_list_sem);
                __journal_file_buffer(jh, transaction, BJ_Reserved);
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
        }
 
 done:
@@ -796,7 +796,7 @@ int journal_get_create_access(handle_t *
         * reused here.
         */
        jbd_lock_bh_state(bh);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        J_ASSERT_JH(jh, (jh->b_transaction == transaction ||
                jh->b_transaction == NULL ||
                (jh->b_transaction == journal->j_committing_transaction &&
@@ -813,7 +813,7 @@ int journal_get_create_access(handle_t *
                JBUFFER_TRACE(jh, "set next transaction");
                jh->b_next_transaction = transaction;
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        jbd_unlock_bh_state(bh);
 
        /*
@@ -962,7 +962,7 @@ int journal_dirty_data(handle_t *handle,
         * about it in this layer.
         */
        jbd_lock_bh_state(bh);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        if (jh->b_transaction) {
                JBUFFER_TRACE(jh, "has transaction");
                if (jh->b_transaction != handle->h_transaction) {
@@ -1018,12 +1018,12 @@ int journal_dirty_data(handle_t *handle,
                         */
                        if (buffer_dirty(bh)) {
                                get_bh(bh);
-                               spin_unlock(&journal->j_list_lock);
+                               up(&journal->j_list_sem);
                                jbd_unlock_bh_state(bh);
                                need_brelse = 1;
                                sync_dirty_buffer(bh);
                                jbd_lock_bh_state(bh);
-                               spin_lock(&journal->j_list_lock);
+                               down(&journal->j_list_sem);
                                /* The buffer may become locked again at any
                                   time if it is redirtied */
                        }
@@ -1055,7 +1055,7 @@ int journal_dirty_data(handle_t *handle,
                __journal_file_buffer(jh, handle->h_transaction, BJ_SyncData);
        }
 no_journal:
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        jbd_unlock_bh_state(bh);
        if (need_brelse) {
                BUFFER_TRACE(bh, "brelse");
@@ -1145,9 +1145,9 @@ int journal_dirty_metadata(handle_t *han
        J_ASSERT_JH(jh, jh->b_frozen_data == 0);
 
        JBUFFER_TRACE(jh, "file as BJ_Metadata");
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        __journal_file_buffer(jh, handle->h_transaction, BJ_Metadata);
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 out_unlock_bh:
        jbd_unlock_bh_state(bh);
 out:
@@ -1194,7 +1194,7 @@ int journal_forget (handle_t *handle, st
        BUFFER_TRACE(bh, "entry");
 
        jbd_lock_bh_state(bh);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
 
        if (!buffer_jbd(bh))
                goto not_jbd;
@@ -1246,7 +1246,7 @@ int journal_forget (handle_t *handle, st
                        journal_remove_journal_head(bh);
                        __brelse(bh);
                        if (!buffer_jbd(bh)) {
-                               spin_unlock(&journal->j_list_lock);
+                               up(&journal->j_list_sem);
                                jbd_unlock_bh_state(bh);
                                __bforget(bh);
                                goto drop;
@@ -1269,7 +1269,7 @@ int journal_forget (handle_t *handle, st
        }
 
 not_jbd:
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        jbd_unlock_bh_state(bh);
        __brelse(bh);
 drop:
@@ -1416,7 +1416,7 @@ int journal_force_commit(journal_t *jour
  * Append a buffer to a transaction list, given the transaction's list head
  * pointer.
  *
- * j_list_lock is held.
+ * j_list_sem is held.
  *
  * jbd_lock_bh_state(jh2bh(jh)) is held.
  */
@@ -1440,7 +1440,7 @@ __blist_add_buffer(struct journal_head *
  * 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.
+ * Called with j_list_sem held, and the journal may not be locked.
  *
  * jbd_lock_bh_state(jh2bh(jh)) is held.
  */
@@ -1466,7 +1466,7 @@ __blist_del_buffer(struct journal_head *
  * 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.
  *
- * Called under j_list_lock.  The journal may not be locked.
+ * Called under j_list_sem.  The journal may not be locked.
  */
 void __journal_unfile_buffer(struct journal_head *jh)
 {
@@ -1476,8 +1476,6 @@ void __journal_unfile_buffer(struct jour
 
        J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
        transaction = jh->b_transaction;
-       if (transaction)
-               assert_spin_locked(&transaction->t_journal->j_list_lock);
 
        J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
        if (jh->b_jlist != BJ_None)
@@ -1525,9 +1523,9 @@ out:
 void journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
 {
        jbd_lock_bh_state(jh2bh(jh));
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        __journal_unfile_buffer(jh);
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        jbd_unlock_bh_state(jh2bh(jh));
 }
 
@@ -1549,7 +1547,7 @@ __journal_try_to_free_buffer(journal_t *
        if (jh->b_next_transaction != 0)
                goto out;
 
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) {
                if (jh->b_jlist == BJ_SyncData || jh->b_jlist == BJ_Locked) {
                        /* A written-back ordered data buffer */
@@ -1567,7 +1565,7 @@ __journal_try_to_free_buffer(journal_t *
                        __brelse(bh);
                }
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 out:
        return;
 }
@@ -1650,7 +1648,7 @@ busy:
  * release it.
  * Returns non-zero if JBD no longer has an interest in the buffer.
  *
- * Called under j_list_lock.
+ * Called under j_list_sem.
  *
  * Called under jbd_lock_bh_state(bh).
  */
@@ -1731,7 +1729,7 @@ static int journal_unmap_buffer(journal_
        BUFFER_TRACE(bh, "entry");
 
        /*
-        * It is safe to proceed here without the j_list_lock because the
+        * It is safe to proceed here without the j_list_sem because the
         * buffers cannot be stolen by try_to_free_buffers as long as we are
         * holding the page lock. --sct
         */
@@ -1741,7 +1739,7 @@ static int journal_unmap_buffer(journal_
 
        down(&journal->j_state_sem);
        jbd_lock_bh_state(bh);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
 
        jh = journal_grab_journal_head(bh);
        if (!jh)
@@ -1774,7 +1772,7 @@ static int journal_unmap_buffer(journal_
                        JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
                        ret = __dispose_buffer(jh,
                                        journal->j_running_transaction);
-                       spin_unlock(&journal->j_list_lock);
+                       up(&journal->j_list_sem);
                        jbd_unlock_bh_state(bh);
                        up(&journal->j_state_sem);
                        journal_put_journal_head(jh);
@@ -1788,7 +1786,7 @@ static int journal_unmap_buffer(journal_
                                JBUFFER_TRACE(jh, "give to committing trans");
                                ret = __dispose_buffer(jh,
                                        journal->j_committing_transaction);
-                               spin_unlock(&journal->j_list_lock);
+                               up(&journal->j_list_sem);
                                jbd_unlock_bh_state(bh);
                                up(&journal->j_state_sem);
                                journal_put_journal_head(jh);
@@ -1812,7 +1810,7 @@ static int journal_unmap_buffer(journal_
                                        journal->j_running_transaction);
                        jh->b_next_transaction = NULL;
                }
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
                jbd_unlock_bh_state(bh);
                up(&journal->j_state_sem);
                journal_put_journal_head(jh);
@@ -1831,7 +1829,7 @@ static int journal_unmap_buffer(journal_
 zap_buffer:
        journal_put_journal_head(jh);
 zap_buffer_no_jh:
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        jbd_unlock_bh_state(bh);
        up(&journal->j_state_sem);
 zap_buffer_unlocked:
@@ -1907,8 +1905,6 @@ void __journal_file_buffer(struct journa
        struct buffer_head *bh = jh2bh(jh);
 
        J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
-       assert_spin_locked(&transaction->t_journal->j_list_lock);
-
        J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
        J_ASSERT_JH(jh, jh->b_transaction == transaction ||
                                jh->b_transaction == 0);
@@ -1974,9 +1970,9 @@ void journal_file_buffer(struct journal_
                                transaction_t *transaction, int jlist)
 {
        jbd_lock_bh_state(jh2bh(jh));
-       spin_lock(&transaction->t_journal->j_list_lock);
+       down(&transaction->t_journal->j_list_sem);
        __journal_file_buffer(jh, transaction, jlist);
-       spin_unlock(&transaction->t_journal->j_list_lock);
+       up(&transaction->t_journal->j_list_sem);
        jbd_unlock_bh_state(jh2bh(jh));
 }
 
@@ -1986,7 +1982,7 @@ void journal_file_buffer(struct journal_
  * already started to be used by a subsequent transaction, refile the
  * buffer on that transaction's metadata list.
  *
- * Called under journal->j_list_lock
+ * Called under journal->j_list_sem
  *
  * Called under jbd_lock_bh_state(jh2bh(jh))
  */
@@ -1996,8 +1992,6 @@ void __journal_refile_buffer(struct jour
        struct buffer_head *bh = jh2bh(jh);
 
        J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
-       if (jh->b_transaction)
-               assert_spin_locked(&jh->b_transaction->t_journal->j_list_lock);
 
        /* If the buffer is now unused, just drop it. */
        if (jh->b_next_transaction == NULL) {
@@ -2040,12 +2034,12 @@ void journal_refile_buffer(journal_t *jo
        struct buffer_head *bh = jh2bh(jh);
 
        jbd_lock_bh_state(bh);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
 
        __journal_refile_buffer(jh);
        jbd_unlock_bh_state(bh);
        journal_remove_journal_head(bh);
 
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        __brelse(bh);
 }
--- linux/fs/jbd/commit.c.orig
+++ linux/fs/jbd/commit.c
@@ -79,14 +79,14 @@ nope:
 }
 
 /*
- * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is
+ * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_sem is
  * held.  For ranking reasons we must trylock.  If we lose, schedule away and
- * return 0.  j_list_lock is dropped in this case.
+ * return 0.  j_list_sem is dropped in this case.
  */
 static int inverted_lock(journal_t *journal, struct buffer_head *bh)
 {
        if (!jbd_trylock_bh_state(bh)) {
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
                schedule();
                return 0;
        }
@@ -189,9 +189,9 @@ void journal_commit_transaction(journal_
         */
 
 #ifdef COMMIT_STATS
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        summarise_journal_usage(journal);
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 #endif
 
        /* Do we need to erase the effects of a prior journal_flush? */
@@ -275,9 +275,9 @@ void journal_commit_transaction(journal_
         * checkpoint lists.  We do this *before* commit because it potentially
         * frees some memory
         */
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        __journal_clean_checkpoint_list(journal);
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 
        jbd_debug (3, "JBD: commit phase 1\n");
 
@@ -299,7 +299,7 @@ void journal_commit_transaction(journal_
         * First, drop modified flag: all accesses to the buffers
         * will be tracked for a new trasaction only -bzzz
         */
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        if (commit_transaction->t_buffers) {
                new_jh = jh = commit_transaction->t_buffers->b_tnext;
                do {
@@ -309,7 +309,7 @@ void journal_commit_transaction(journal_
                        new_jh = new_jh->b_tnext;
                } while (new_jh != jh);
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 
        /*
         * Now start flushing things to disk, in the order they appear
@@ -329,7 +329,7 @@ void journal_commit_transaction(journal_
         */
 write_out_data:
        cond_resched();
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
 
        while (commit_transaction->t_sync_datalist) {
                struct buffer_head *bh;
@@ -345,10 +345,6 @@ write_out_data:
                        __journal_file_buffer(jh, commit_transaction,
                                                BJ_Locked);
                        jbd_unlock_bh_state(bh);
-                       if (lock_need_resched(&journal->j_list_lock)) {
-                               spin_unlock(&journal->j_list_lock);
-                               goto write_out_data;
-                       }
                } else {
                        if (buffer_dirty(bh)) {
                                BUFFER_TRACE(bh, "start journal writeout");
@@ -357,7 +353,7 @@ write_out_data:
                                if (bufs == journal->j_wbufsize) {
                                        jbd_debug(2, "submit %d writes\n",
                                                        bufs);
-                                       spin_unlock(&journal->j_list_lock);
+                                       up(&journal->j_list_sem);
                                        ll_rw_block(WRITE, bufs, wbuf);
                                        journal_brelse_array(wbuf, bufs);
                                        bufs = 0;
@@ -371,19 +367,15 @@ write_out_data:
                                jbd_unlock_bh_state(bh);
                                journal_remove_journal_head(bh);
                                put_bh(bh);
-                               if (lock_need_resched(&journal->j_list_lock)) {
-                                       spin_unlock(&journal->j_list_lock);
-                                       goto write_out_data;
-                               }
                        }
                }
        }
 
        if (bufs) {
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
                ll_rw_block(WRITE, bufs, wbuf);
                journal_brelse_array(wbuf, bufs);
-               spin_lock(&journal->j_list_lock);
+               down(&journal->j_list_sem);
        }
 
        /*
@@ -396,15 +388,15 @@ write_out_data:
                bh = jh2bh(jh);
                get_bh(bh);
                if (buffer_locked(bh)) {
-                       spin_unlock(&journal->j_list_lock);
+                       up(&journal->j_list_sem);
                        wait_on_buffer(bh);
                        if (unlikely(!buffer_uptodate(bh)))
                                err = -EIO;
-                       spin_lock(&journal->j_list_lock);
+                       down(&journal->j_list_sem);
                }
                if (!inverted_lock(journal, bh)) {
                        put_bh(bh);
-                       spin_lock(&journal->j_list_lock);
+                       down(&journal->j_list_sem);
                        continue;
                }
                if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) {
@@ -416,9 +408,8 @@ write_out_data:
                        jbd_unlock_bh_state(bh);
                }
                put_bh(bh);
-               cond_resched_lock(&journal->j_list_lock);
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 
        if (err)
                __journal_abort_hard(journal);
@@ -614,7 +605,7 @@ start_journal_io:
        jbd_debug(3, "JBD: commit phase 4\n");
 
        /*
-        * akpm: these are BJ_IO, and j_list_lock is not needed.
+        * akpm: these are BJ_IO, and j_list_sem is not needed.
         * See __journal_try_to_free_buffer.
         */
 wait_for_iobuf:
@@ -752,7 +743,7 @@ restart_loop:
                        jh->b_frozen_data = NULL;
                }
 
-               spin_lock(&journal->j_list_lock);
+               down(&journal->j_list_sem);
                cp_transaction = jh->b_cp_transaction;
                if (cp_transaction) {
                        JBUFFER_TRACE(jh, "remove from old cp transaction");
@@ -792,7 +783,7 @@ restart_loop:
                        journal_remove_journal_head(bh);  /* needs a brelse */
                        release_buffer_page(bh);
                }
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
                if (cond_resched())
                        goto restart_loop;
        }
@@ -804,13 +795,13 @@ restart_loop:
        J_ASSERT(commit_transaction->t_state == T_COMMIT);
 
        /*
-        * This is a bit sleazy.  We borrow j_list_lock to protect
+        * This is a bit sleazy.  We borrow j_list_sem to protect
         * journal->j_committing_transaction in __journal_remove_checkpoint.
         * Really, __jornal_remove_checkpoint should be using j_state_sem but
         * it's a bit hassle to hold that across __journal_remove_checkpoint
         */
        down(&journal->j_state_sem);
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        commit_transaction->t_state = T_FINISHED;
        J_ASSERT(commit_transaction == journal->j_committing_transaction);
        journal->j_commit_sequence = commit_transaction->t_tid;
@@ -835,7 +826,7 @@ restart_loop:
                                commit_transaction;
                }
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 
        jbd_debug(1, "JBD: commit %d complete, head %d\n",
                  journal->j_commit_sequence, journal->j_tail_sequence);
--- linux/fs/jbd/journal.c.orig
+++ linux/fs/jbd/journal.c
@@ -672,7 +672,7 @@ static journal_t * journal_init_common (
        init_MUTEX(&journal->j_barrier);
        init_MUTEX(&journal->j_checkpoint_sem);
        spin_lock_init(&journal->j_revoke_lock);
-       spin_lock_init(&journal->j_list_lock);
+       init_MUTEX(&journal->j_list_sem);
        init_MUTEX(&journal->j_state_sem);
 
        journal->j_commit_interval = (HZ * JBD_DEFAULT_MAX_COMMIT_AGE);
@@ -1139,17 +1139,17 @@ void journal_destroy(journal_t *journal)
        /* Force any old transactions to disk */
 
        /* Totally anal locking here... */
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        while (journal->j_checkpoint_transactions != NULL) {
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
                log_do_checkpoint(journal);
-               spin_lock(&journal->j_list_lock);
+               down(&journal->j_list_sem);
        }
 
        J_ASSERT(journal->j_running_transaction == NULL);
        J_ASSERT(journal->j_committing_transaction == NULL);
        J_ASSERT(journal->j_checkpoint_transactions == NULL);
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
 
        /* We can now mark the journal as empty. */
        journal->j_tail = 0;
@@ -1361,13 +1361,13 @@ int journal_flush(journal_t *journal)
        }
 
        /* ...and flush everything in the log out to disk. */
-       spin_lock(&journal->j_list_lock);
+       down(&journal->j_list_sem);
        while (!err && journal->j_checkpoint_transactions != NULL) {
-               spin_unlock(&journal->j_list_lock);
+               up(&journal->j_list_sem);
                err = log_do_checkpoint(journal);
-               spin_lock(&journal->j_list_lock);
+               down(&journal->j_list_sem);
        }
-       spin_unlock(&journal->j_list_lock);
+       up(&journal->j_list_sem);
        cleanup_journal_tail(journal);
 
        /* Finally, mark the journal as really needing no recovery.
--- linux/include/linux/jbd.h.orig
+++ linux/include/linux/jbd.h
@@ -413,20 +413,20 @@ struct handle_s 
 /*
  * Lock ranking:
  *
- *    j_list_lock
+ *    j_list_sem
  *      ->jbd_lock_bh_journal_head()   (This is "innermost")
  *
  *    j_state_sem
  *    ->jbd_lock_bh_state()
  *
  *    jbd_lock_bh_state()
- *    ->j_list_lock
+ *    ->j_list_sem
  *
  *    j_state_sem
  *    ->t_handle_lock
  *
  *    j_state_sem
- *    ->j_list_lock                    (journal_unmap_buffer)
+ *    ->j_list_sem                     (journal_unmap_buffer)
  *
  */
 
@@ -458,62 +458,62 @@ struct transaction_s 
         */
        unsigned long           t_log_start;
 
-       /* Number of buffers on the t_buffers list [j_list_lock] */
+       /* Number of buffers on the t_buffers list [j_list_sem] */
        int                     t_nr_buffers;
 
        /*
         * Doubly-linked circular list of all buffers reserved but not yet
-        * modified by this transaction [j_list_lock]
+        * modified by this transaction [j_list_sem]
         */
        struct journal_head     *t_reserved_list;
 
        /*
         * Doubly-linked circular list of all buffers under writeout during
-        * commit [j_list_lock]
+        * commit [j_list_sem]
         */
        struct journal_head     *t_locked_list;
 
        /*
         * Doubly-linked circular list of all metadata buffers owned by this
-        * transaction [j_list_lock]
+        * transaction [j_list_sem]
         */
        struct journal_head     *t_buffers;
 
        /*
         * Doubly-linked circular list of all data buffers still to be
-        * flushed before this transaction can be committed [j_list_lock]
+        * flushed before this transaction can be committed [j_list_sem]
         */
        struct journal_head     *t_sync_datalist;
 
        /*
         * Doubly-linked circular list of all forget buffers (superseded
         * buffers which we can un-checkpoint once this transaction commits)
-        * [j_list_lock]
+        * [j_list_sem]
         */
        struct journal_head     *t_forget;
 
        /*
         * Doubly-linked circular list of all buffers still to be flushed before
-        * this transaction can be checkpointed. [j_list_lock]
+        * this transaction can be checkpointed. [j_list_sem]
         */
        struct journal_head     *t_checkpoint_list;
 
        /*
         * Doubly-linked circular list of temporary buffers currently undergoing
-        * IO in the log [j_list_lock]
+        * IO in the log [j_list_sem]
         */
        struct journal_head     *t_iobuf_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]
+        * list match each other one for one at all times. [j_list_sem]
         */
        struct journal_head     *t_shadow_list;
 
        /*
         * Doubly-linked circular list of control buffers being written to the
-        * log. [j_list_lock]
+        * log. [j_list_sem]
         */
        struct journal_head     *t_log_list;
 
@@ -536,7 +536,7 @@ struct transaction_s 
 
        /*
         * Forward and backward links for the circular list of all transactions
-        * awaiting checkpoint. [j_list_lock]
+        * awaiting checkpoint. [j_list_sem]
         */
        transaction_t           *t_cpnext, *t_cpprev;
 
@@ -590,7 +590,7 @@ struct transaction_s 
  * @j_fs_dev: Device which holds the client fs.  For internal journal this will
  *     be equal to j_dev
  * @j_maxlen: Total maximum capacity of the journal region on disk.
- * @j_list_lock: Protects the buffer lists and internal buffer state.
+ * @j_list_sem: Protects the buffer lists and internal buffer state.
  * @j_inode: Optional inode where we store the journal.  If present, all 
journal
  *     block numbers are mapped into this inode via bmap().
  * @j_tail_sequence:  Sequence number of the oldest transaction in the log 
@@ -658,7 +658,7 @@ struct journal_s
 
        /*
         * ... and a linked circular list of all transactions waiting for
-        * checkpointing. [j_list_lock]
+        * checkpointing. [j_list_sem]
         */
        transaction_t           *j_checkpoint_transactions;
 
@@ -731,7 +731,7 @@ struct journal_s
        /*
         * Protects the buffer lists and internal buffer state.
         */
-       spinlock_t              j_list_lock;
+       struct semaphore        j_list_sem;
 
        /* Optional inode where we store the journal.  If present, all */
        /* journal block numbers are mapped into this inode via */
--- linux/include/linux/journal-head.h.orig
+++ linux/include/linux/journal-head.h
@@ -56,7 +56,7 @@ struct journal_head {
         * metadata: either the running transaction or the committing
         * transaction (if there is one).  Only applies to buffers on a
         * transaction's data or metadata journaling list.
-        * [j_list_lock] [jbd_lock_bh_state()]
+        * [j_list_sem] [jbd_lock_bh_state()]
         */
        transaction_t *b_transaction;
 
@@ -77,14 +77,14 @@ struct journal_head {
        /*
         * Pointer to the compound transaction against which this buffer
         * is checkpointed.  Only dirty buffers can be checkpointed.
-        * [j_list_lock]
+        * [j_list_sem]
         */
        transaction_t *b_cp_transaction;
 
        /*
         * Doubly-linked list of buffers still remaining to be flushed
         * before an old transaction can be checkpointed.
-        * [j_list_lock]
+        * [j_list_sem]
         */
        struct journal_head *b_cpnext, *b_cpprev;
 };
-
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