From: Greg Kroah-Hartman Date: Tue, 28 Apr 2026 11:48:02 +0000 (-0600) Subject: 6.6-stable patches X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=4fbfd99a606bb34495e3c5ddb6fbbfaf02bac258;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: ocfs2-split-transactions-in-dio-completion-to-avoid-credit-exhaustion.patch --- diff --git a/queue-6.6/ocfs2-split-transactions-in-dio-completion-to-avoid-credit-exhaustion.patch b/queue-6.6/ocfs2-split-transactions-in-dio-completion-to-avoid-credit-exhaustion.patch new file mode 100644 index 0000000000..1761330a36 --- /dev/null +++ b/queue-6.6/ocfs2-split-transactions-in-dio-completion-to-avoid-credit-exhaustion.patch @@ -0,0 +1,180 @@ +From d647c5b2fbf81560818dacade360abc8c00a9665 Mon Sep 17 00:00:00 2001 +From: Heming Zhao +Date: Thu, 2 Apr 2026 21:43:27 +0800 +Subject: ocfs2: split transactions in dio completion to avoid credit exhaustion + +From: Heming Zhao + +commit d647c5b2fbf81560818dacade360abc8c00a9665 upstream. + +During ocfs2 dio operations, JBD2 may report warnings via following +call trace: +ocfs2_dio_end_io_write + ocfs2_mark_extent_written + ocfs2_change_extent_flag + ocfs2_split_extent + ocfs2_try_to_merge_extent + ocfs2_extend_rotate_transaction + ocfs2_extend_trans + jbd2__journal_restart + start_this_handle + output: JBD2: kworker/6:2 wants too many credits credits:5450 rsv_credits:0 max:5449 + +To prevent exceeding the credits limit, modify ocfs2_dio_end_io_write() to +handle extents in a batch of transaction. + +Additionally, relocate ocfs2_del_inode_from_orphan(). The orphan inode +should only be removed from the orphan list after the extent tree update +is complete. This ensures that if a crash occurs in the middle of extent +tree updates, we won't leave stale blocks beyond EOF. + +This patch also changes the logic for updating the inode size and removing +orphan, making it similar to ext4_dio_write_end_io(). Both operations are +performed only when everything looks good. + +Finally, thanks to Jans and Joseph for providing the bug fix prototype and +suggestions. + +Link: https://lkml.kernel.org/r/20260402134328.27334-2-heming.zhao@suse.com +Signed-off-by: Heming Zhao +Suggested-by: Jan Kara +Suggested-by: Joseph Qi +Reviewed-by: Jan Kara +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/aops.c | 74 ++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 45 insertions(+), 29 deletions(-) + +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -37,6 +37,8 @@ + #include "namei.h" + #include "sysfile.h" + ++#define OCFS2_DIO_MARK_EXTENT_BATCH 200 ++ + static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { +@@ -2305,7 +2307,7 @@ static int ocfs2_dio_end_io_write(struct + struct ocfs2_alloc_context *meta_ac = NULL; + handle_t *handle = NULL; + loff_t end = offset + bytes; +- int ret = 0, credits = 0; ++ int ret = 0, credits = 0, batch = 0; + + ocfs2_init_dealloc_ctxt(&dealloc); + +@@ -2322,18 +2324,6 @@ static int ocfs2_dio_end_io_write(struct + goto out; + } + +- /* Delete orphan before acquire i_rwsem. */ +- if (dwc->dw_orphaned) { +- BUG_ON(dwc->dw_writer_pid != task_pid_nr(current)); +- +- end = end > i_size_read(inode) ? end : 0; +- +- ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh, +- !!end, end); +- if (ret < 0) +- mlog_errno(ret); +- } +- + down_write(&oi->ip_alloc_sem); + di = (struct ocfs2_dinode *)di_bh->b_data; + +@@ -2354,24 +2344,25 @@ static int ocfs2_dio_end_io_write(struct + + credits = ocfs2_calc_extend_credits(inode->i_sb, &di->id2.i_list); + +- handle = ocfs2_start_trans(osb, credits); +- if (IS_ERR(handle)) { +- ret = PTR_ERR(handle); +- mlog_errno(ret); +- goto unlock; +- } +- ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, +- OCFS2_JOURNAL_ACCESS_WRITE); +- if (ret) { +- mlog_errno(ret); +- goto commit; +- } +- + list_for_each_entry(ue, &dwc->dw_zero_list, ue_node) { ++ if (!handle) { ++ handle = ocfs2_start_trans(osb, credits); ++ if (IS_ERR(handle)) { ++ ret = PTR_ERR(handle); ++ mlog_errno(ret); ++ goto unlock; ++ } ++ ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, ++ OCFS2_JOURNAL_ACCESS_WRITE); ++ if (ret) { ++ mlog_errno(ret); ++ goto commit; ++ } ++ } + ret = ocfs2_assure_trans_credits(handle, credits); + if (ret < 0) { + mlog_errno(ret); +- break; ++ goto commit; + } + ret = ocfs2_mark_extent_written(inode, &et, handle, + ue->ue_cpos, 1, +@@ -2379,19 +2370,44 @@ static int ocfs2_dio_end_io_write(struct + meta_ac, &dealloc); + if (ret < 0) { + mlog_errno(ret); +- break; ++ goto commit; ++ } ++ ++ if (++batch == OCFS2_DIO_MARK_EXTENT_BATCH) { ++ ocfs2_commit_trans(osb, handle); ++ handle = NULL; ++ batch = 0; + } + } + + if (end > i_size_read(inode)) { ++ if (!handle) { ++ handle = ocfs2_start_trans(osb, credits); ++ if (IS_ERR(handle)) { ++ ret = PTR_ERR(handle); ++ mlog_errno(ret); ++ goto unlock; ++ } ++ } + ret = ocfs2_set_inode_size(handle, inode, di_bh, end); + if (ret < 0) + mlog_errno(ret); + } ++ + commit: +- ocfs2_commit_trans(osb, handle); ++ if (handle) ++ ocfs2_commit_trans(osb, handle); + unlock: + up_write(&oi->ip_alloc_sem); ++ ++ /* everything looks good, let's start the cleanup */ ++ if (!ret && dwc->dw_orphaned) { ++ BUG_ON(dwc->dw_writer_pid != task_pid_nr(current)); ++ ++ ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh, 0, 0); ++ if (ret < 0) ++ mlog_errno(ret); ++ } + ocfs2_inode_unlock(inode, 1); + brelse(di_bh); + out: diff --git a/queue-6.6/series b/queue-6.6/series index 234d28b944..c6bfe4e297 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -18,3 +18,4 @@ drm-amdgpu-use-vmemdup_array_user-in-amdgpu_bo_creat.patch drm-amdgpu-limit-bo-list-entry-count-to-prevent-reso.patch regset-use-kvzalloc-for-regset_get_alloc.patch device-property-make-modifications-of-fwnode-flags-thread-safe.patch +ocfs2-split-transactions-in-dio-completion-to-avoid-credit-exhaustion.patch