From bde91cb26fccd714b4b85bda67b2bb0f0e08615a Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 4 Aug 2015 11:29:51 -0400 Subject: [PATCH] add patch limit-number-of-reserved-credits --- limit-number-of-reserved-credits | 92 ++++++++++++++++++++++++++++++++++++++++ series | 1 + timestamps | 9 ++-- 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 limit-number-of-reserved-credits diff --git a/limit-number-of-reserved-credits b/limit-number-of-reserved-credits new file mode 100644 index 00000000..b26d6cbe --- /dev/null +++ b/limit-number-of-reserved-credits @@ -0,0 +1,92 @@ +jbd2: limit number of reserved credits + +From: Lukas Czerner + +Currently there is no limitation on number of reserved credits we can +ask for. If we ask for more reserved credits than 1/2 of maximum +transaction size, or if total number of credits exceeds the maximum +transaction size per operation (which is currently only possible with +the former) we will spin forever in start_this_handle(). + +Fix this by adding this limitation at the start of start_this_handle(). + +This patch also removes the credit limitation 1/2 of maximum transaction +size, since we really only want to limit the number of reserved credits. +There is not much point to limit the credits if there is still space in +the journal. + +This accidentally also fixes the online resize, where due to the +limitation of the journal credits we're unable to grow file systems with +1k block size and size between 16M and 32M. It has been partially fixed +by 2c869b262a10ca99cb866d04087d75311587a30c, but not entirely. + +Thanks Jan Kara for helping me getting the correct fix. + +Signed-off-by: Lukas Czerner +Reviewed-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- +v2: added wait event Jan suggested + + fs/jbd2/transaction.c | 36 +++++++++++++++++++++++++++--------- + 1 file changed, 27 insertions(+), 9 deletions(-) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index f3d0617..f8183d4 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -204,6 +204,20 @@ static int add_transaction_credits(journal_t *journal, int blocks, + * attach this handle to a new transaction. + */ + atomic_sub(total, &t->t_outstanding_credits); ++ ++ /* ++ * Is the number of reserved credits in the current transaction too ++ * big to fit this handle? Wait until reserved credits are freed. ++ */ ++ if (atomic_read(&journal->j_reserved_credits) + total > ++ journal->j_max_transaction_buffers) { ++ read_unlock(&journal->j_state_lock); ++ wait_event(journal->j_wait_reserved, ++ atomic_read(&journal->j_reserved_credits) + total <= ++ journal->j_max_transaction_buffers); ++ return 1; ++ } ++ + wait_transaction_locked(journal); + return 1; + } +@@ -262,20 +276,24 @@ static int start_this_handle(journal_t *journal, handle_t *handle, + int rsv_blocks = 0; + unsigned long ts = jiffies; + ++ if (handle->h_rsv_handle) ++ rsv_blocks = handle->h_rsv_handle->h_buffer_credits; ++ + /* +- * 1/2 of transaction can be reserved so we can practically handle +- * only 1/2 of maximum transaction size per operation ++ * Limit the number of reserved credits to 1/2 of maximum transaction ++ * size and limit the number of total credits to not exceed maximum ++ * transaction size per operation. + */ +- if (WARN_ON(blocks > journal->j_max_transaction_buffers / 2)) { +- printk(KERN_ERR "JBD2: %s wants too many credits (%d > %d)\n", +- current->comm, blocks, +- journal->j_max_transaction_buffers / 2); ++ if ((rsv_blocks > journal->j_max_transaction_buffers / 2) || ++ (rsv_blocks + blocks > journal->j_max_transaction_buffers)) { ++ printk(KERN_ERR "JBD2: %s wants too many credits " ++ "credits:%d rsv_credits:%d max:%d\n", ++ current->comm, blocks, rsv_blocks, ++ journal->j_max_transaction_buffers); ++ WARN_ON(1); + return -ENOSPC; + } + +- if (handle->h_rsv_handle) +- rsv_blocks = handle->h_rsv_handle->h_buffer_credits; +- + alloc_transaction: + if (!journal->j_running_transaction) { + /* diff --git a/series b/series index 38c6ddf8..91a953fc 100644 --- a/series +++ b/series @@ -12,6 +12,7 @@ add-REQ_FUQ-flag-when-recording-an-error avoid-infinite-loop-when-destroying-aborted-journal update-cmtime-on-truncate-up remove-duplicate-header-file +limit-number-of-reserved-credits ########################################## # unstable patches diff --git a/timestamps b/timestamps index 05de0f34..77d49946 100755 --- a/timestamps +++ b/timestamps @@ -25,8 +25,8 @@ touch -d @1436139294 dump-in-use-buffers touch -d @1436139354 akpm-jbd2-locking-fix touch -d @1436739090 speedup-jbd2_journal_dirty_metadata touch -d @1437146207 use-transaction-when-adding-crypto-policy +touch -d @1437146975 replace-ext4_io_submit-io_op-with-io_wbc touch -d @1437147196 detect-short-encrypted-directories -touch -d @1437537024 replace-ext4_io_submit-io_op-with-io_wbc touch -d @1437537086 implement-cgroup-writeback-support touch -d @1437537479 reject-journal-options-for-ext2-mounts touch -d @1437538088 exit-cleanly-if-ext4_derive_key_aes-fails @@ -36,6 +36,7 @@ touch -d @1437659231 stable-boundary touch -d @1438109834 avoid-infinite-loop-when-destroying-aborted-journal touch -d @1438110521 update-cmtime-on-truncate-up touch -d @1438110738 remove-duplicate-header-file -touch -d @1438110782 series -touch -d @1438110784 status -touch -d @1438110790 timestamps +touch -d @1438701712 limit-number-of-reserved-credits +touch -d @1438701735 series +touch -d @1438701738 status +touch -d @1438702167 timestamps -- 2.11.4.GIT