X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjbd%2Fcheckpoint.c;h=3f5102b069dbef82e1c3f17f443f00f9b986bb1e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=2615ad1d86ed827fc2f311463a6d44afade8e353;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 2615ad1d8..3f5102b06 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -24,7 +24,7 @@ #include /* - * 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);