On May 18, 2020, at 3:21 AM, Jan Kara wrote: > > 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: stable@vger.kernel.org > Fixes: 8f7d89f36829 ("jbd2: transaction reservation support") > Signed-off-by: Jan Kara Patch looks reasonable, with one minor nit below. Reviewed-by: Andreas Dilger > --- > fs/jbd2/transaction.c | 17 +++++++++++++---- > 1 file changed, 13 insertions(+), 4 deletions(-) > > diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c > index 3dccc23cf010..b49a103cff1f 100644 > --- a/fs/jbd2/transaction.c > +++ b/fs/jbd2/transaction.c > @@ -541,17 +541,24 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) > } > EXPORT_SYMBOL(jbd2_journal_start); > > -static void __jbd2_journal_unreserve_handle(handle_t *handle) > +static void __jbd2_journal_unreserve_handle(handle_t *handle, transaction_t *t) > { > journal_t *journal = handle->h_journal; > > WARN_ON(!handle->h_reserved); > sub_reserved_credits(journal, handle->h_total_credits); > + if (t) > + atomic_sub(handle->h_total_credits, &t->t_outstanding_credits); > } > > void jbd2_journal_free_reserved(handle_t *handle) > { > - __jbd2_journal_unreserve_handle(handle); > + journal_t *journal = handle->h_journal; > + > + /* Get j_state_lock to pin running transaction if it exists */ > + read_lock(&journal->j_state_lock); > + __jbd2_journal_unreserve_handle(handle, journal->j_running_transaction); > + read_unlock(&journal->j_state_lock); > jbd2_free_handle(handle); > } > EXPORT_SYMBOL(jbd2_journal_free_reserved); > @@ -721,8 +728,10 @@ static void stop_this_handle(handle_t *handle) > } > atomic_sub(handle->h_total_credits, > &transaction->t_outstanding_credits); > - if (handle->h_rsv_handle) > - __jbd2_journal_unreserve_handle(handle->h_rsv_handle); > + if (handle->h_rsv_handle) { > + __jbd2_journal_unreserve_handle(handle->h_rsv_handle, > + transaction); > + } There isn't any need for braces {} around this one-line if-block. Cheers, Andreas