Skip to content

Commit 14ff628

Browse files
jankaratytso
authored andcommitted
jbd2: avoid leaking transaction credits when unreserving handle
When reserved transaction handle is unused, we subtract its reserved credits in __jbd2_journal_unreserve_handle() called from jbd2_journal_stop(). However this function forgets to remove reserved credits from transaction->t_outstanding_credits and thus the transaction space that was reserved remains effectively leaked. The leaked transaction space can be quite significant in some cases and leads to unnecessarily small transactions and thus reducing throughput of the journalling machinery. E.g. fsmark workload creating lots of 4k files was observed to have about 20% lower throughput due to this when ext4 is mounted with dioread_nolock mount option. Subtract reserved credits from t_outstanding_credits as well. CC: [email protected] Fixes: 8f7d89f ("jbd2: transaction reservation support") Reviewed-by: Andreas Dilger <[email protected]> Signed-off-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent dfcd448 commit 14ff628

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

fs/jbd2/transaction.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -541,17 +541,24 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
541541
}
542542
EXPORT_SYMBOL(jbd2_journal_start);
543543

544-
static void __jbd2_journal_unreserve_handle(handle_t *handle)
544+
static void __jbd2_journal_unreserve_handle(handle_t *handle, transaction_t *t)
545545
{
546546
journal_t *journal = handle->h_journal;
547547

548548
WARN_ON(!handle->h_reserved);
549549
sub_reserved_credits(journal, handle->h_total_credits);
550+
if (t)
551+
atomic_sub(handle->h_total_credits, &t->t_outstanding_credits);
550552
}
551553

552554
void jbd2_journal_free_reserved(handle_t *handle)
553555
{
554-
__jbd2_journal_unreserve_handle(handle);
556+
journal_t *journal = handle->h_journal;
557+
558+
/* Get j_state_lock to pin running transaction if it exists */
559+
read_lock(&journal->j_state_lock);
560+
__jbd2_journal_unreserve_handle(handle, journal->j_running_transaction);
561+
read_unlock(&journal->j_state_lock);
555562
jbd2_free_handle(handle);
556563
}
557564
EXPORT_SYMBOL(jbd2_journal_free_reserved);
@@ -722,7 +729,8 @@ static void stop_this_handle(handle_t *handle)
722729
atomic_sub(handle->h_total_credits,
723730
&transaction->t_outstanding_credits);
724731
if (handle->h_rsv_handle)
725-
__jbd2_journal_unreserve_handle(handle->h_rsv_handle);
732+
__jbd2_journal_unreserve_handle(handle->h_rsv_handle,
733+
transaction);
726734
if (atomic_dec_and_test(&transaction->t_updates))
727735
wake_up(&journal->j_wait_updates);
728736

0 commit comments

Comments
 (0)