X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fjbd2%2Fcheckpoint.c;h=6914598022ce836e10a13aa8be50aab1ec3bdc74;hb=13a6ddb08e58a1bd344da7898c4e2f13bdf18c2f;hp=0208cc7ac5d0f0835ed0bceb206cce2baef5fae5;hpb=470decc613ab2048b619a01028072d932d9086ee;p=linux-2.6 diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 0208cc7ac5..6914598022 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -1,5 +1,5 @@ /* - * linux/fs/checkpoint.c + * linux/fs/jbd2/checkpoint.c * * Written by Stephen C. Tweedie , 1999 * @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -95,9 +95,9 @@ static int __try_to_free_cp_buf(struct journal_head *jh) if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { JBUFFER_TRACE(jh, "remove from checkpoint list"); - ret = __journal_remove_checkpoint(jh) + 1; + ret = __jbd2_journal_remove_checkpoint(jh) + 1; jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); + jbd2_journal_remove_journal_head(bh); BUFFER_TRACE(bh, "release"); __brelse(bh); } else { @@ -107,19 +107,19 @@ static int __try_to_free_cp_buf(struct journal_head *jh) } /* - * __log_wait_for_space: wait until there is space in the journal. + * __jbd2_log_wait_for_space: wait until there is space in the journal. * * Called under j-state_lock *only*. It will be unlocked if we have to wait * for a checkpoint to free up some space in the log. */ -void __log_wait_for_space(journal_t *journal) +void __jbd2_log_wait_for_space(journal_t *journal) { int nblocks; assert_spin_locked(&journal->j_state_lock); nblocks = jbd_space_needed(journal); - while (__log_space_left(journal) < nblocks) { - if (journal->j_flags & JFS_ABORT) + while (__jbd2_log_space_left(journal) < nblocks) { + if (journal->j_flags & JBD2_ABORT) return; spin_unlock(&journal->j_state_lock); mutex_lock(&journal->j_checkpoint_mutex); @@ -130,9 +130,9 @@ void __log_wait_for_space(journal_t *journal) */ spin_lock(&journal->j_state_lock); nblocks = jbd_space_needed(journal); - if (__log_space_left(journal) < nblocks) { + if (__jbd2_log_space_left(journal) < nblocks) { spin_unlock(&journal->j_state_lock); - log_do_checkpoint(journal); + jbd2_log_do_checkpoint(journal); spin_lock(&journal->j_state_lock); } mutex_unlock(&journal->j_checkpoint_mutex); @@ -198,9 +198,9 @@ restart: * Now in whatever state the buffer currently is, we know that * it has been written out and so we can drop it from the list */ - released = __journal_remove_checkpoint(jh); + released = __jbd2_journal_remove_checkpoint(jh); jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); + jbd2_journal_remove_journal_head(bh); __brelse(bh); } } @@ -232,7 +232,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it */ static int __process_buffer(journal_t *journal, struct journal_head *jh, - struct buffer_head **bhs, int *batch_count) + struct buffer_head **bhs, int *batch_count, + transaction_t *transaction) { struct buffer_head *bh = jh2bh(jh); int ret = 0; @@ -250,18 +251,19 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, transaction_t *t = jh->b_transaction; tid_t tid = t->t_tid; + transaction->t_chp_stats.cs_forced_to_close++; spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); - log_start_commit(journal, tid); - log_wait_commit(journal, tid); + jbd2_log_start_commit(journal, tid); + jbd2_log_wait_commit(journal, tid); ret = 1; } else if (!buffer_dirty(bh)) { J_ASSERT_JH(jh, !buffer_jbddirty(bh)); BUFFER_TRACE(bh, "remove from checkpoint"); - __journal_remove_checkpoint(jh); + __jbd2_journal_remove_checkpoint(jh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); + jbd2_journal_remove_journal_head(bh); __brelse(bh); ret = 1; } else { @@ -279,6 +281,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, bhs[*batch_count] = bh; __buffer_relink_io(jh); jbd_unlock_bh_state(bh); + transaction->t_chp_stats.cs_written++; (*batch_count)++; if (*batch_count == NR_BATCH) { spin_unlock(&journal->j_list_lock); @@ -296,7 +299,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, * * The journal should be locked before calling this function. */ -int log_do_checkpoint(journal_t *journal) +int jbd2_log_do_checkpoint(journal_t *journal) { transaction_t *transaction; tid_t this_tid; @@ -309,7 +312,7 @@ int log_do_checkpoint(journal_t *journal) * don't need checkpointing, just eliminate them from the * journal straight away. */ - result = cleanup_journal_tail(journal); + result = jbd2_cleanup_journal_tail(journal); jbd_debug(1, "cleanup_journal_tail returned %d\n", result); if (result <= 0) return result; @@ -322,6 +325,8 @@ int log_do_checkpoint(journal_t *journal) if (!journal->j_checkpoint_transactions) goto out; transaction = journal->j_checkpoint_transactions; + if (transaction->t_chp_stats.cs_chp_time == 0) + transaction->t_chp_stats.cs_chp_time = jiffies; this_tid = transaction->t_tid; restart: /* @@ -346,8 +351,10 @@ restart: retry = 1; break; } - retry = __process_buffer(journal, jh, bhs,&batch_count); - if (!retry && lock_need_resched(&journal->j_list_lock)){ + retry = __process_buffer(journal, jh, bhs, &batch_count, + transaction); + if (!retry && (need_resched() || + spin_needbreak(&journal->j_list_lock))) { spin_unlock(&journal->j_list_lock); retry = 1; break; @@ -374,7 +381,7 @@ restart: } out: spin_unlock(&journal->j_list_lock); - result = cleanup_journal_tail(journal); + result = jbd2_cleanup_journal_tail(journal); if (result < 0) return result; return 0; @@ -397,7 +404,7 @@ out: * we have an abort error outstanding. */ -int cleanup_journal_tail(journal_t *journal) +int jbd2_cleanup_journal_tail(journal_t *journal) { transaction_t * transaction; tid_t first_tid; @@ -452,8 +459,8 @@ int cleanup_journal_tail(journal_t *journal) journal->j_tail_sequence = first_tid; journal->j_tail = blocknr; spin_unlock(&journal->j_state_lock); - if (!(journal->j_flags & JFS_ABORT)) - journal_update_superblock(journal, 1); + if (!(journal->j_flags & JBD2_ABORT)) + jbd2_journal_update_superblock(journal, 1); return 0; } @@ -518,7 +525,7 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released) * Returns number of buffers reaped (for debug) */ -int __journal_clean_checkpoint_list(journal_t *journal) +int __jbd2_journal_clean_checkpoint_list(journal_t *journal) { transaction_t *transaction, *last_transaction, *next_transaction; int ret = 0; @@ -578,7 +585,7 @@ out: * This function is called with jbd_lock_bh_state(jh2bh(jh)) */ -int __journal_remove_checkpoint(struct journal_head *jh) +int __jbd2_journal_remove_checkpoint(struct journal_head *jh) { transaction_t *transaction; journal_t *journal; @@ -602,22 +609,22 @@ int __journal_remove_checkpoint(struct journal_head *jh) /* * There is one special case to worry about: if we have just pulled the - * buffer off a committing transaction's forget list, then even if the - * checkpoint list is empty, the transaction obviously cannot be - * dropped! + * buffer off a running or committing transaction's checkpoing list, + * then even if the checkpoint list is empty, the transaction obviously + * cannot be dropped! * - * The locking here around j_committing_transaction is a bit sleazy. - * See the comment at the end of journal_commit_transaction(). + * The locking here around t_state is a bit sleazy. + * See the comment at the end of jbd2_journal_commit_transaction(). */ - if (transaction == journal->j_committing_transaction) { - JBUFFER_TRACE(jh, "belongs to committing transaction"); + if (transaction->t_state != T_FINISHED) { + JBUFFER_TRACE(jh, "belongs to running/committing transaction"); goto out; } /* OK, that was the last buffer for the transaction: we can now safely remove this transaction from the log */ - __journal_drop_transaction(journal, transaction); + __jbd2_journal_drop_transaction(journal, transaction); /* Just in case anybody was waiting for more transactions to be checkpointed... */ @@ -636,7 +643,7 @@ out: * Called with the journal locked. * Called with j_list_lock held. */ -void __journal_insert_checkpoint(struct journal_head *jh, +void __jbd2_journal_insert_checkpoint(struct journal_head *jh, transaction_t *transaction) { JBUFFER_TRACE(jh, "entry"); @@ -666,7 +673,7 @@ void __journal_insert_checkpoint(struct journal_head *jh, * Called with j_list_lock held. */ -void __journal_drop_transaction(journal_t *journal, transaction_t *transaction) +void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transaction) { assert_spin_locked(&journal->j_list_lock); if (transaction->t_cpnext) {