--- linux-2.4.18/fs/jbd/checkpoint.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 +++ linux-2.4.18-alexey/fs/jbd/checkpoint.c Mon Jul 28 14:03:59 2003 @@ -77,19 +77,23 @@ static int __try_to_free_cp_buf(struct j * to wait for a checkpoint to free up some space in the log. */ -void log_wait_for_space(journal_t *journal, int nblocks) +void log_wait_for_space(journal_t *journal) { + int nblocks; + + nblocks = jbd_space_needed(journal); while (log_space_left(journal) < nblocks) { if (journal->j_flags & JFS_ABORT) return; unlock_journal(journal); down(&journal->j_checkpoint_sem); lock_journal(journal); + nblocks = jbd_space_needed(journal); /* Test again, another process may have checkpointed * while we were waiting for the checkpoint lock */ if (log_space_left(journal) < nblocks) { - log_do_checkpoint(journal, nblocks); + log_do_checkpoint(journal); } up(&journal->j_checkpoint_sem); } @@ -260,8 +264,7 @@ static int __flush_buffer(journal_t *jou * The journal should be locked before calling this function. */ -/* @@@ `nblocks' is unused. Should it be used? */ -int log_do_checkpoint (journal_t *journal, int nblocks) +int log_do_checkpoint (journal_t *journal) { transaction_t *transaction, *last_transaction, *next_transaction; int result; @@ -315,6 +318,8 @@ repeat: retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); } while (jh != last_jh && !retry); + if (journal->j_checkpoint_transactions != transaction) + goto done; if (batch_count) { __flush_batch(bhs, &batch_count); goto repeat; @@ -328,6 +333,8 @@ repeat: */ cleanup_ret = __cleanup_transaction(journal, transaction); J_ASSERT(drop_count != 0 || cleanup_ret != 0); + if (journal->j_checkpoint_transactions != transaction) + goto done; goto repeat; /* __cleanup may have dropped lock */ } while (transaction != last_transaction); --- linux-2.4.18/fs/jbd/journal.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 +++ linux-2.4.18-alexey/fs/jbd/journal.c Mon Jul 28 14:03:59 2003 @@ -1115,7 +1115,7 @@ void journal_destroy (journal_t *journal /* Force any old transactions to disk */ lock_journal(journal); while (journal->j_checkpoint_transactions != NULL) - log_do_checkpoint(journal, 1); + log_do_checkpoint(journal); J_ASSERT(journal->j_running_transaction == NULL); J_ASSERT(journal->j_committing_transaction == NULL); @@ -1302,7 +1302,7 @@ int journal_flush (journal_t *journal) /* ...and flush everything in the log out to disk. */ lock_journal(journal); while (!err && journal->j_checkpoint_transactions != NULL) - err = log_do_checkpoint(journal, journal->j_maxlen); + err = log_do_checkpoint(journal); cleanup_journal_tail(journal); /* Finally, mark the journal as really needing no recovery. --- linux-2.4.18/fs/jbd/transaction.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 +++ linux-2.4.18-alexey/fs/jbd/transaction.c Mon Jul 28 14:03:59 2003 @@ -182,14 +182,9 @@ repeat_locked: * Also, this test is inconsitent with the matching one in * journal_extend(). */ - needed = journal->j_max_transaction_buffers; - if (journal->j_committing_transaction) - needed += journal->j_committing_transaction-> - t_outstanding_credits; - - if (log_space_left(journal) < needed) { + if (log_space_left(journal) < jbd_space_needed(journal)) { jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); - log_wait_for_space(journal, needed); + log_wait_for_space(journal); goto repeat_locked; } --- linux-2.4.18/include/linux/jbd.h~jbd-commit-tricks Mon Jul 28 13:52:17 2003 +++ linux-2.4.18-alexey/include/linux/jbd.h Mon Jul 28 14:03:59 2003 @@ -740,9 +740,9 @@ extern void journal_brelse_array(stru extern int log_space_left (journal_t *); /* Called with journal locked */ extern tid_t log_start_commit (journal_t *, transaction_t *); extern int log_wait_commit (journal_t *, tid_t); -extern int log_do_checkpoint (journal_t *, int); +extern int log_do_checkpoint (journal_t *); -extern void log_wait_for_space(journal_t *, int nblocks); +extern void log_wait_for_space(journal_t *); extern void __journal_drop_transaction(journal_t *, transaction_t *); extern int cleanup_journal_tail(journal_t *); @@ -815,6 +815,19 @@ static inline int tid_geq(tid_t x, tid_t } extern int journal_blocks_per_page(struct inode *inode); + +/* + * Return the minimum number of blocks which must be free in the journal + * before a new transaction may be started. Must be called under j_state_lock. + */ +static inline int jbd_space_needed(journal_t *journal) +{ + int nblocks = journal->j_max_transaction_buffers; + if (journal->j_committing_transaction) + nblocks += journal->j_committing_transaction-> + t_outstanding_credits; + return nblocks; +} /* * Definitions which augment the buffer_head layer _