Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / fs / jbd / checkpoint.c
index 2615ad1..3f5102b 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 
 /*
- * Unlink a buffer from a transaction. 
+ * Unlink a buffer from a transaction.
  *
  * Called with j_list_lock held.
  */
@@ -85,7 +85,7 @@ void __log_wait_for_space(journal_t *journal)
                if (journal->j_flags & JFS_ABORT)
                        return;
                spin_unlock(&journal->j_state_lock);
-               down(&journal->j_checkpoint_sem);
+               mutex_lock(&journal->j_checkpoint_mutex);
 
                /*
                 * Test again, another process may have checkpointed while we
@@ -98,7 +98,7 @@ void __log_wait_for_space(journal_t *journal)
                        log_do_checkpoint(journal);
                        spin_lock(&journal->j_state_lock);
                }
-               up(&journal->j_checkpoint_sem);
+               mutex_unlock(&journal->j_checkpoint_mutex);
        }
 }
 
@@ -117,10 +117,10 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
 }
 
 /*
- * Clean up a transaction's checkpoint list.  
+ * Clean up a transaction's checkpoint list.
  *
  * We wait for any pending IO to complete and make sure any clean
- * buffers are removed from the transaction. 
+ * buffers are removed from the transaction.
  *
  * Return 1 if we performed any actions which might have destroyed the
  * checkpoint.  (journal_remove_checkpoint() deletes the transaction when
@@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
                } else {
                        jbd_unlock_bh_state(bh);
                }
-               jh = next_jh;
        } while (jh != last_jh);
 
        return ret;
@@ -205,7 +204,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
        int i;
 
        spin_unlock(&journal->j_list_lock);
-       ll_rw_block(WRITE, *batch_count, bhs);
+       ll_rw_block(SWRITE, *batch_count, bhs);
        spin_lock(&journal->j_list_lock);
        for (i = 0; i < *batch_count; i++) {
                struct buffer_head *bh = bhs[i];
@@ -277,7 +276,7 @@ static int __flush_buffer(journal_t *journal, struct journal_head *jh,
  * 
  * However, we _do_ take into account the amount requested so that once
  * the IO has been queued, we can return as soon as enough of it has
- * completed to disk.  
+ * completed to disk.
  *
  * The journal should be locked before calling this function.
  */
@@ -333,10 +332,16 @@ int log_do_checkpoint(journal_t *journal)
                                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)
+               if (batch_count) {
                        __flush_batch(journal, bhs, &batch_count);
+                       retry = 1;
+               }
 
                /*
                 * If someone cleaned up this transaction while we slept, we're
@@ -355,7 +360,7 @@ int log_do_checkpoint(journal_t *journal)
                /*
                 * We have walked the whole transaction list without
                 * finding anything to write to disk.  We had better be
-                * able to make some progress or we are in trouble. 
+                * able to make some progress or we are in trouble.
                 */
                cleanup_ret = __cleanup_transaction(journal, transaction);
                J_ASSERT(drop_count != 0 || cleanup_ret != 0);
@@ -487,6 +492,14 @@ int __journal_clean_checkpoint_list(journal_t *journal)
                                /* Use trylock because of the ranknig */
                                if (jbd_trylock_bh_state(jh2bh(jh)))
                                        ret += __try_to_free_cp_buf(jh);
+                               /*
+                                * This function only frees up some memory
+                                * if possible so we dont have an obligation
+                                * to finish processing. Bail out if preemption
+                                * requested:
+                                */
+                               if (need_resched())
+                                       goto out;
                        } while (jh != last_jh);
                }
        } while (transaction != last_transaction);
@@ -505,7 +518,7 @@ out:
  * transaction need to be maintained on the transaction's checkpoint
  * list until they have been rewritten, at which point this function is
  * called to remove the buffer from the existing transaction's
- * checkpoint list.  
+ * checkpoint list.
  *
  * This function is called with the journal locked.
  * This function is called with j_list_lock held.
@@ -616,7 +629,6 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
        J_ASSERT(transaction->t_log_list == NULL);
        J_ASSERT(transaction->t_checkpoint_list == NULL);
        J_ASSERT(transaction->t_updates == 0);
-       J_ASSERT(list_empty(&transaction->t_jcb));
        J_ASSERT(journal->j_committing_transaction != transaction);
        J_ASSERT(journal->j_running_transaction != transaction);