From: Greg Kroah-Hartman Date: Wed, 2 Aug 2023 06:45:36 +0000 (+0200) Subject: drop some jbd2 patches from 6.4, 6.1, and 5.15 queues X-Git-Tag: v5.15.124~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=28724f9795baec09ca4a0ac19c2945768f4ab1df;p=thirdparty%2Fkernel%2Fstable-queue.git drop some jbd2 patches from 6.4, 6.1, and 5.15 queues --- diff --git a/queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch b/queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch deleted file mode 100644 index f169b4a44e3..00000000000 --- a/queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch +++ /dev/null @@ -1,150 +0,0 @@ -From b756a018ae344b7a50133eec86185342030b7e89 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:27 +0800 -Subject: jbd2: fix a race when checking checkpoint buffer busy - -From: Zhang Yi - -[ Upstream commit 46f881b5b1758dc4a35fba4a643c10717d0cf427 ] - -Before removing checkpoint buffer from the t_checkpoint_list, we have to -check both BH_Dirty and BH_Lock bits together to distinguish buffers -have not been or were being written back. But __cp_buffer_busy() checks -them separately, it first check lock state and then check dirty, the -window between these two checks could be raced by writing back -procedure, which locks buffer and clears buffer dirty before I/O -completes. So it cannot guarantee checkpointing buffers been written -back to disk if some error happens later. Finally, it may clean -checkpoint transactions and lead to inconsistent filesystem. - -jbd2_journal_forget() and __journal_try_to_free_buffer() also have the -same problem (journal_unmap_buffer() escape from this issue since it's -running under the buffer lock), so fix them through introducing a new -helper to try holding the buffer lock and remove really clean buffer. - -Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 -Cc: stable@vger.kernel.org -Suggested-by: Jan Kara -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-6-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 38 +++++++++++++++++++++++++++++++++++--- - fs/jbd2/transaction.c | 17 +++++------------ - include/linux/jbd2.h | 1 + - 3 files changed, 41 insertions(+), 15 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index ab72aeb766a74..fc6989e7a8c51 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -376,11 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - jh = next_jh; - next_jh = jh->b_cpnext; - -- if (!destroy && __cp_buffer_busy(jh)) -- continue; -+ if (destroy) { -+ ret = __jbd2_journal_remove_checkpoint(jh); -+ } else { -+ ret = jbd2_journal_try_remove_checkpoint(jh); -+ if (ret < 0) -+ continue; -+ } - - nr_freed++; -- ret = __jbd2_journal_remove_checkpoint(jh); - if (ret) { - *released = true; - break; -@@ -616,6 +620,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) - return 1; - } - -+/* -+ * Check the checkpoint buffer and try to remove it from the checkpoint -+ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if -+ * it frees the transaction, 0 otherwise. -+ * -+ * This function is called with j_list_lock held. -+ */ -+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh) -+{ -+ struct buffer_head *bh = jh2bh(jh); -+ -+ if (!trylock_buffer(bh)) -+ return -EBUSY; -+ if (buffer_dirty(bh)) { -+ unlock_buffer(bh); -+ return -EBUSY; -+ } -+ unlock_buffer(bh); -+ -+ /* -+ * Buffer is clean and the IO has finished (we held the buffer -+ * lock) so the checkpoint is done. We can safely remove the -+ * buffer from this transaction. -+ */ -+ JBUFFER_TRACE(jh, "remove from checkpoint list"); -+ return __jbd2_journal_remove_checkpoint(jh); -+} -+ - /* - * journal_insert_checkpoint: put a committed buffer onto a checkpoint - * list so that we know when it is safe to clean the transaction out of -diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c -index ce4a5ccadeff4..62e68c5b8ec3d 100644 ---- a/fs/jbd2/transaction.c -+++ b/fs/jbd2/transaction.c -@@ -1775,8 +1775,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh) - * Otherwise, if the buffer has been written to disk, - * it is safe to remove the checkpoint and drop it. - */ -- if (!buffer_dirty(bh)) { -- __jbd2_journal_remove_checkpoint(jh); -+ if (jbd2_journal_try_remove_checkpoint(jh) >= 0) { - spin_unlock(&journal->j_list_lock); - goto drop; - } -@@ -2103,20 +2102,14 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) - - jh = bh2jh(bh); - -- if (buffer_locked(bh) || buffer_dirty(bh)) -- goto out; -- - if (jh->b_next_transaction != NULL || jh->b_transaction != NULL) -- goto out; -+ return; - - spin_lock(&journal->j_list_lock); -- if (jh->b_cp_transaction != NULL) { -- /* written-back checkpointed metadata buffer */ -- JBUFFER_TRACE(jh, "remove from checkpoint list"); -- __jbd2_journal_remove_checkpoint(jh); -- } -+ /* Remove written-back checkpointed metadata buffer */ -+ if (jh->b_cp_transaction != NULL) -+ jbd2_journal_try_remove_checkpoint(jh); - spin_unlock(&journal->j_list_lock); --out: - return; - } - -diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h -index e6cfbcde96f29..ade8a6d7acff9 100644 ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -1441,6 +1441,7 @@ extern void jbd2_journal_commit_transaction(journal_t *); - void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); - unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan); - int __jbd2_journal_remove_checkpoint(struct journal_head *); -+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh); - void jbd2_journal_destroy_checkpoint(journal_t *journal); - void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); - --- -2.39.2 - diff --git a/queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch b/queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch deleted file mode 100644 index 7bdc682848a..00000000000 --- a/queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch +++ /dev/null @@ -1,235 +0,0 @@ -From aecb975234f28cd552c2716b840cb4df901d3027 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:25 +0800 -Subject: jbd2: remove journal_clean_one_cp_list() - -From: Zhang Yi - -[ Upstream commit b98dba273a0e47dbfade89c9af73c5b012a4eabb ] - -journal_clean_one_cp_list() and journal_shrink_one_cp_list() are almost -the same, so merge them into journal_shrink_one_cp_list(), remove the -nr_to_scan parameter, always scan and try to free the whole checkpoint -list. - -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-4-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 75 +++++++++---------------------------- - include/trace/events/jbd2.h | 12 ++---- - 2 files changed, 21 insertions(+), 66 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index c1f543e86170a..ab72aeb766a74 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -349,50 +349,10 @@ int jbd2_cleanup_journal_tail(journal_t *journal) - - /* Checkpoint list management */ - --/* -- * journal_clean_one_cp_list -- * -- * Find all the written-back checkpoint buffers in the given list and -- * release them. If 'destroy' is set, clean all buffers unconditionally. -- * -- * Called with j_list_lock held. -- * Returns 1 if we freed the transaction, 0 otherwise. -- */ --static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) --{ -- struct journal_head *last_jh; -- struct journal_head *next_jh = jh; -- -- if (!jh) -- return 0; -- -- last_jh = jh->b_cpprev; -- do { -- jh = next_jh; -- next_jh = jh->b_cpnext; -- -- if (!destroy && __cp_buffer_busy(jh)) -- return 0; -- -- if (__jbd2_journal_remove_checkpoint(jh)) -- return 1; -- /* -- * This function only frees up some memory -- * if possible so we dont have an obligation -- * to finish processing. Bail out if preemption -- * requested: -- */ -- if (need_resched()) -- return 0; -- } while (jh != last_jh); -- -- return 0; --} -- - /* - * journal_shrink_one_cp_list - * -- * Find 'nr_to_scan' written-back checkpoint buffers in the given list -+ * Find all the written-back checkpoint buffers in the given list - * and try to release them. If the whole transaction is released, set - * the 'released' parameter. Return the number of released checkpointed - * buffers. -@@ -400,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) - * Called with j_list_lock held. - */ - static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, -- unsigned long *nr_to_scan, -- bool *released) -+ bool destroy, bool *released) - { - struct journal_head *last_jh; - struct journal_head *next_jh = jh; - unsigned long nr_freed = 0; - int ret; - -- if (!jh || *nr_to_scan == 0) -+ *released = false; -+ if (!jh) - return 0; - - last_jh = jh->b_cpprev; -@@ -416,8 +376,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - jh = next_jh; - next_jh = jh->b_cpnext; - -- (*nr_to_scan)--; -- if (__cp_buffer_busy(jh)) -+ if (!destroy && __cp_buffer_busy(jh)) - continue; - - nr_freed++; -@@ -429,7 +388,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - - if (need_resched()) - break; -- } while (jh != last_jh && *nr_to_scan); -+ } while (jh != last_jh); - - return nr_freed; - } -@@ -447,11 +406,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - unsigned long *nr_to_scan) - { - transaction_t *transaction, *last_transaction, *next_transaction; -- bool released; -+ bool __maybe_unused released; - tid_t first_tid = 0, last_tid = 0, next_tid = 0; - tid_t tid = 0; - unsigned long nr_freed = 0; -- unsigned long nr_scanned = *nr_to_scan; -+ unsigned long freed; - - again: - spin_lock(&journal->j_list_lock); -@@ -480,10 +439,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - transaction = next_transaction; - next_transaction = transaction->t_cpnext; - tid = transaction->t_tid; -- released = false; - -- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list, -- nr_to_scan, &released); -+ freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list, -+ false, &released); -+ nr_freed += freed; -+ (*nr_to_scan) -= min(*nr_to_scan, freed); - if (*nr_to_scan == 0) - break; - if (need_resched() || spin_needbreak(&journal->j_list_lock)) -@@ -504,9 +464,8 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - if (*nr_to_scan && next_tid) - goto again; - out: -- nr_scanned -= *nr_to_scan; - trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid, -- nr_freed, nr_scanned, next_tid); -+ nr_freed, next_tid); - - return nr_freed; - } -@@ -522,7 +481,7 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - { - transaction_t *transaction, *last_transaction, *next_transaction; -- int ret; -+ bool released; - - transaction = journal->j_checkpoint_transactions; - if (!transaction) -@@ -533,8 +492,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - do { - transaction = next_transaction; - next_transaction = transaction->t_cpnext; -- ret = journal_clean_one_cp_list(transaction->t_checkpoint_list, -- destroy); -+ journal_shrink_one_cp_list(transaction->t_checkpoint_list, -+ destroy, &released); - /* - * This function only frees up some memory if possible so we - * dont have an obligation to finish processing. Bail out if -@@ -547,7 +506,7 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - * avoids pointless scanning of transactions which still - * weren't checkpointed. - */ -- if (!ret) -+ if (!released) - return; - } while (transaction != last_transaction); - } -diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h -index 29414288ea3e0..34ce197bd76e0 100644 ---- a/include/trace/events/jbd2.h -+++ b/include/trace/events/jbd2.h -@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit, - TRACE_EVENT(jbd2_shrink_checkpoint_list, - - TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid, -- unsigned long nr_freed, unsigned long nr_scanned, -- tid_t next_tid), -+ unsigned long nr_freed, tid_t next_tid), - -- TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, -- nr_scanned, next_tid), -+ TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid), - - TP_STRUCT__entry( - __field(dev_t, dev) -@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, - __field(tid_t, tid) - __field(tid_t, last_tid) - __field(unsigned long, nr_freed) -- __field(unsigned long, nr_scanned) - __field(tid_t, next_tid) - ), - -@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, - __entry->tid = tid; - __entry->last_tid = last_tid; - __entry->nr_freed = nr_freed; -- __entry->nr_scanned = nr_scanned; - __entry->next_tid = next_tid; - ), - - TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu " -- "scanned %lu next transaction %u", -+ "next transaction %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->first_tid, __entry->tid, __entry->last_tid, -- __entry->nr_freed, __entry->nr_scanned, __entry->next_tid) -+ __entry->nr_freed, __entry->next_tid) - ); - - #endif /* _TRACE_JBD2_H */ --- -2.39.2 - diff --git a/queue-5.15/jbd2-remove-t_checkpoint_io_list.patch b/queue-5.15/jbd2-remove-t_checkpoint_io_list.patch deleted file mode 100644 index a399ebafb8c..00000000000 --- a/queue-5.15/jbd2-remove-t_checkpoint_io_list.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 92d4d5454f0734d09f34beaae5f86cf3dcc3087f Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:24 +0800 -Subject: jbd2: remove t_checkpoint_io_list - -From: Zhang Yi - -[ Upstream commit be22255360f80d3af789daad00025171a65424a5 ] - -Since t_checkpoint_io_list was stop using in jbd2_log_do_checkpoint() -now, it's time to remove the whole t_checkpoint_io_list logic. - -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-3-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 42 ++---------------------------------------- - fs/jbd2/commit.c | 3 +-- - include/linux/jbd2.h | 6 ------ - 3 files changed, 3 insertions(+), 48 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index d2aba55833f92..c1f543e86170a 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -27,7 +27,7 @@ - * - * Called with j_list_lock held. - */ --static inline void __buffer_unlink_first(struct journal_head *jh) -+static inline void __buffer_unlink(struct journal_head *jh) - { - transaction_t *transaction = jh->b_cp_transaction; - -@@ -40,23 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh) - } - } - --/* -- * Unlink a buffer from a transaction checkpoint(io) list. -- * -- * Called with j_list_lock held. -- */ --static inline void __buffer_unlink(struct journal_head *jh) --{ -- transaction_t *transaction = jh->b_cp_transaction; -- -- __buffer_unlink_first(jh); -- if (transaction->t_checkpoint_io_list == jh) { -- transaction->t_checkpoint_io_list = jh->b_cpnext; -- if (transaction->t_checkpoint_io_list == jh) -- transaction->t_checkpoint_io_list = NULL; -- } --} -- - /* - * Check a checkpoint buffer could be release or not. - * -@@ -505,15 +488,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - break; - if (need_resched() || spin_needbreak(&journal->j_list_lock)) - break; -- if (released) -- continue; -- -- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list, -- nr_to_scan, &released); -- if (*nr_to_scan == 0) -- break; -- if (need_resched() || spin_needbreak(&journal->j_list_lock)) -- break; - } while (transaction != last_transaction); - - if (transaction != last_transaction) { -@@ -568,17 +542,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - */ - if (need_resched()) - return; -- if (ret) -- continue; -- /* -- * It is essential that we are as careful as in the case of -- * t_checkpoint_list with removing the buffer from the list as -- * we can possibly see not yet submitted buffers on io_list -- */ -- ret = journal_clean_one_cp_list(transaction-> -- t_checkpoint_io_list, destroy); -- if (need_resched()) -- return; - /* - * Stop scanning if we couldn't free the transaction. This - * avoids pointless scanning of transactions which still -@@ -663,7 +626,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) - jbd2_journal_put_journal_head(jh); - - /* Is this transaction empty? */ -- if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list) -+ if (transaction->t_checkpoint_list) - return 0; - - /* -@@ -755,7 +718,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact - J_ASSERT(transaction->t_forget == NULL); - J_ASSERT(transaction->t_shadow_list == NULL); - J_ASSERT(transaction->t_checkpoint_list == NULL); -- J_ASSERT(transaction->t_checkpoint_io_list == NULL); - J_ASSERT(atomic_read(&transaction->t_updates) == 0); - J_ASSERT(journal->j_committing_transaction != transaction); - J_ASSERT(journal->j_running_transaction != transaction); -diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c -index ac328e3321242..20294c1bbeab7 100644 ---- a/fs/jbd2/commit.c -+++ b/fs/jbd2/commit.c -@@ -1184,8 +1184,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) - spin_lock(&journal->j_list_lock); - commit_transaction->t_state = T_FINISHED; - /* Check if the transaction can be dropped now that we are finished */ -- if (commit_transaction->t_checkpoint_list == NULL && -- commit_transaction->t_checkpoint_io_list == NULL) { -+ if (commit_transaction->t_checkpoint_list == NULL) { - __jbd2_journal_drop_transaction(journal, commit_transaction); - jbd2_journal_free_transaction(commit_transaction); - } -diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h -index d63b8106796e2..e6cfbcde96f29 100644 ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -626,12 +626,6 @@ struct transaction_s - */ - struct journal_head *t_checkpoint_list; - -- /* -- * Doubly-linked circular list of all buffers submitted for IO while -- * checkpointing. [j_list_lock] -- */ -- struct journal_head *t_checkpoint_io_list; -- - /* - * Doubly-linked circular list of metadata buffers being - * shadowed by log IO. The IO buffers on the iobuf list and --- -2.39.2 - diff --git a/queue-5.15/series b/queue-5.15/series index 2cc8d3790f7..2950e60139f 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -43,9 +43,6 @@ scsi-qla2xxx-add-debug-prints-in-the-device-remove-p.patch scsi-qla2xxx-fix-hang-in-task-management.patch drm-amdgpu-fix-vkms-crtc-settings.patch drm-amdgpu-vkms-relax-timer-deactivation-by-hrtimer_.patch -jbd2-remove-t_checkpoint_io_list.patch -jbd2-remove-journal_clean_one_cp_list.patch -jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch phy-qcom-snps-use-dev_err_probe-to-simplify-code.patch phy-qcom-snps-correct-struct-qcom_snps_hsphy-kerneld.patch phy-qcom-snps-femto-v2-keep-cfg_ahb_clk-enabled-duri.patch diff --git a/queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch b/queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch deleted file mode 100644 index 6dc28c30675..00000000000 --- a/queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 4925d566f7e303289ee5d4aabcf8e2f24544331b Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:27 +0800 -Subject: jbd2: fix a race when checking checkpoint buffer busy - -From: Zhang Yi - -[ Upstream commit 46f881b5b1758dc4a35fba4a643c10717d0cf427 ] - -Before removing checkpoint buffer from the t_checkpoint_list, we have to -check both BH_Dirty and BH_Lock bits together to distinguish buffers -have not been or were being written back. But __cp_buffer_busy() checks -them separately, it first check lock state and then check dirty, the -window between these two checks could be raced by writing back -procedure, which locks buffer and clears buffer dirty before I/O -completes. So it cannot guarantee checkpointing buffers been written -back to disk if some error happens later. Finally, it may clean -checkpoint transactions and lead to inconsistent filesystem. - -jbd2_journal_forget() and __journal_try_to_free_buffer() also have the -same problem (journal_unmap_buffer() escape from this issue since it's -running under the buffer lock), so fix them through introducing a new -helper to try holding the buffer lock and remove really clean buffer. - -Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 -Cc: stable@vger.kernel.org -Suggested-by: Jan Kara -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-6-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 38 +++++++++++++++++++++++++++++++++++--- - fs/jbd2/transaction.c | 17 +++++------------ - include/linux/jbd2.h | 1 + - 3 files changed, 41 insertions(+), 15 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index 42b34cab64fbd..9ec91017a7f3c 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -376,11 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - jh = next_jh; - next_jh = jh->b_cpnext; - -- if (!destroy && __cp_buffer_busy(jh)) -- continue; -+ if (destroy) { -+ ret = __jbd2_journal_remove_checkpoint(jh); -+ } else { -+ ret = jbd2_journal_try_remove_checkpoint(jh); -+ if (ret < 0) -+ continue; -+ } - - nr_freed++; -- ret = __jbd2_journal_remove_checkpoint(jh); - if (ret) { - *released = true; - break; -@@ -616,6 +620,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) - return 1; - } - -+/* -+ * Check the checkpoint buffer and try to remove it from the checkpoint -+ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if -+ * it frees the transaction, 0 otherwise. -+ * -+ * This function is called with j_list_lock held. -+ */ -+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh) -+{ -+ struct buffer_head *bh = jh2bh(jh); -+ -+ if (!trylock_buffer(bh)) -+ return -EBUSY; -+ if (buffer_dirty(bh)) { -+ unlock_buffer(bh); -+ return -EBUSY; -+ } -+ unlock_buffer(bh); -+ -+ /* -+ * Buffer is clean and the IO has finished (we held the buffer -+ * lock) so the checkpoint is done. We can safely remove the -+ * buffer from this transaction. -+ */ -+ JBUFFER_TRACE(jh, "remove from checkpoint list"); -+ return __jbd2_journal_remove_checkpoint(jh); -+} -+ - /* - * journal_insert_checkpoint: put a committed buffer onto a checkpoint - * list so that we know when it is safe to clean the transaction out of -diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c -index 18611241f4513..6ef5022949c46 100644 ---- a/fs/jbd2/transaction.c -+++ b/fs/jbd2/transaction.c -@@ -1784,8 +1784,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh) - * Otherwise, if the buffer has been written to disk, - * it is safe to remove the checkpoint and drop it. - */ -- if (!buffer_dirty(bh)) { -- __jbd2_journal_remove_checkpoint(jh); -+ if (jbd2_journal_try_remove_checkpoint(jh) >= 0) { - spin_unlock(&journal->j_list_lock); - goto drop; - } -@@ -2112,20 +2111,14 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) - - jh = bh2jh(bh); - -- if (buffer_locked(bh) || buffer_dirty(bh)) -- goto out; -- - if (jh->b_next_transaction != NULL || jh->b_transaction != NULL) -- goto out; -+ return; - - spin_lock(&journal->j_list_lock); -- if (jh->b_cp_transaction != NULL) { -- /* written-back checkpointed metadata buffer */ -- JBUFFER_TRACE(jh, "remove from checkpoint list"); -- __jbd2_journal_remove_checkpoint(jh); -- } -+ /* Remove written-back checkpointed metadata buffer */ -+ if (jh->b_cp_transaction != NULL) -+ jbd2_journal_try_remove_checkpoint(jh); - spin_unlock(&journal->j_list_lock); --out: - return; - } - -diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h -index 67912fe08fbbd..ebb1608d9dcd2 100644 ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -1435,6 +1435,7 @@ extern void jbd2_journal_commit_transaction(journal_t *); - void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); - unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan); - int __jbd2_journal_remove_checkpoint(struct journal_head *); -+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh); - void jbd2_journal_destroy_checkpoint(journal_t *journal); - void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); - --- -2.39.2 - diff --git a/queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch b/queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch deleted file mode 100644 index 222f59bc977..00000000000 --- a/queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch +++ /dev/null @@ -1,235 +0,0 @@ -From 7f2e7e3be85c2c0af0b6cd4c8b69de00ec06408c Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:25 +0800 -Subject: jbd2: remove journal_clean_one_cp_list() - -From: Zhang Yi - -[ Upstream commit b98dba273a0e47dbfade89c9af73c5b012a4eabb ] - -journal_clean_one_cp_list() and journal_shrink_one_cp_list() are almost -the same, so merge them into journal_shrink_one_cp_list(), remove the -nr_to_scan parameter, always scan and try to free the whole checkpoint -list. - -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-4-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 75 +++++++++---------------------------- - include/trace/events/jbd2.h | 12 ++---- - 2 files changed, 21 insertions(+), 66 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index 723b4eb112828..42b34cab64fbd 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -349,50 +349,10 @@ int jbd2_cleanup_journal_tail(journal_t *journal) - - /* Checkpoint list management */ - --/* -- * journal_clean_one_cp_list -- * -- * Find all the written-back checkpoint buffers in the given list and -- * release them. If 'destroy' is set, clean all buffers unconditionally. -- * -- * Called with j_list_lock held. -- * Returns 1 if we freed the transaction, 0 otherwise. -- */ --static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) --{ -- struct journal_head *last_jh; -- struct journal_head *next_jh = jh; -- -- if (!jh) -- return 0; -- -- last_jh = jh->b_cpprev; -- do { -- jh = next_jh; -- next_jh = jh->b_cpnext; -- -- if (!destroy && __cp_buffer_busy(jh)) -- return 0; -- -- if (__jbd2_journal_remove_checkpoint(jh)) -- return 1; -- /* -- * This function only frees up some memory -- * if possible so we dont have an obligation -- * to finish processing. Bail out if preemption -- * requested: -- */ -- if (need_resched()) -- return 0; -- } while (jh != last_jh); -- -- return 0; --} -- - /* - * journal_shrink_one_cp_list - * -- * Find 'nr_to_scan' written-back checkpoint buffers in the given list -+ * Find all the written-back checkpoint buffers in the given list - * and try to release them. If the whole transaction is released, set - * the 'released' parameter. Return the number of released checkpointed - * buffers. -@@ -400,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) - * Called with j_list_lock held. - */ - static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, -- unsigned long *nr_to_scan, -- bool *released) -+ bool destroy, bool *released) - { - struct journal_head *last_jh; - struct journal_head *next_jh = jh; - unsigned long nr_freed = 0; - int ret; - -- if (!jh || *nr_to_scan == 0) -+ *released = false; -+ if (!jh) - return 0; - - last_jh = jh->b_cpprev; -@@ -416,8 +376,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - jh = next_jh; - next_jh = jh->b_cpnext; - -- (*nr_to_scan)--; -- if (__cp_buffer_busy(jh)) -+ if (!destroy && __cp_buffer_busy(jh)) - continue; - - nr_freed++; -@@ -429,7 +388,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - - if (need_resched()) - break; -- } while (jh != last_jh && *nr_to_scan); -+ } while (jh != last_jh); - - return nr_freed; - } -@@ -447,11 +406,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - unsigned long *nr_to_scan) - { - transaction_t *transaction, *last_transaction, *next_transaction; -- bool released; -+ bool __maybe_unused released; - tid_t first_tid = 0, last_tid = 0, next_tid = 0; - tid_t tid = 0; - unsigned long nr_freed = 0; -- unsigned long nr_scanned = *nr_to_scan; -+ unsigned long freed; - - again: - spin_lock(&journal->j_list_lock); -@@ -480,10 +439,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - transaction = next_transaction; - next_transaction = transaction->t_cpnext; - tid = transaction->t_tid; -- released = false; - -- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list, -- nr_to_scan, &released); -+ freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list, -+ false, &released); -+ nr_freed += freed; -+ (*nr_to_scan) -= min(*nr_to_scan, freed); - if (*nr_to_scan == 0) - break; - if (need_resched() || spin_needbreak(&journal->j_list_lock)) -@@ -504,9 +464,8 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - if (*nr_to_scan && next_tid) - goto again; - out: -- nr_scanned -= *nr_to_scan; - trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid, -- nr_freed, nr_scanned, next_tid); -+ nr_freed, next_tid); - - return nr_freed; - } -@@ -522,7 +481,7 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - { - transaction_t *transaction, *last_transaction, *next_transaction; -- int ret; -+ bool released; - - transaction = journal->j_checkpoint_transactions; - if (!transaction) -@@ -533,8 +492,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - do { - transaction = next_transaction; - next_transaction = transaction->t_cpnext; -- ret = journal_clean_one_cp_list(transaction->t_checkpoint_list, -- destroy); -+ journal_shrink_one_cp_list(transaction->t_checkpoint_list, -+ destroy, &released); - /* - * This function only frees up some memory if possible so we - * dont have an obligation to finish processing. Bail out if -@@ -547,7 +506,7 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - * avoids pointless scanning of transactions which still - * weren't checkpointed. - */ -- if (!ret) -+ if (!released) - return; - } while (transaction != last_transaction); - } -diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h -index 8f5ee380d3093..5646ae15a957a 100644 ---- a/include/trace/events/jbd2.h -+++ b/include/trace/events/jbd2.h -@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit, - TRACE_EVENT(jbd2_shrink_checkpoint_list, - - TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid, -- unsigned long nr_freed, unsigned long nr_scanned, -- tid_t next_tid), -+ unsigned long nr_freed, tid_t next_tid), - -- TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, -- nr_scanned, next_tid), -+ TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid), - - TP_STRUCT__entry( - __field(dev_t, dev) -@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, - __field(tid_t, tid) - __field(tid_t, last_tid) - __field(unsigned long, nr_freed) -- __field(unsigned long, nr_scanned) - __field(tid_t, next_tid) - ), - -@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, - __entry->tid = tid; - __entry->last_tid = last_tid; - __entry->nr_freed = nr_freed; -- __entry->nr_scanned = nr_scanned; - __entry->next_tid = next_tid; - ), - - TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu " -- "scanned %lu next transaction %u", -+ "next transaction %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->first_tid, __entry->tid, __entry->last_tid, -- __entry->nr_freed, __entry->nr_scanned, __entry->next_tid) -+ __entry->nr_freed, __entry->next_tid) - ); - - #endif /* _TRACE_JBD2_H */ --- -2.39.2 - diff --git a/queue-6.1/jbd2-remove-t_checkpoint_io_list.patch b/queue-6.1/jbd2-remove-t_checkpoint_io_list.patch deleted file mode 100644 index 1a5ecd82264..00000000000 --- a/queue-6.1/jbd2-remove-t_checkpoint_io_list.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0c9838fba04567f1905865f0b3a659724945c8a8 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:24 +0800 -Subject: jbd2: remove t_checkpoint_io_list - -From: Zhang Yi - -[ Upstream commit be22255360f80d3af789daad00025171a65424a5 ] - -Since t_checkpoint_io_list was stop using in jbd2_log_do_checkpoint() -now, it's time to remove the whole t_checkpoint_io_list logic. - -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-3-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 42 ++---------------------------------------- - fs/jbd2/commit.c | 3 +-- - include/linux/jbd2.h | 6 ------ - 3 files changed, 3 insertions(+), 48 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index c4e0da6db7195..723b4eb112828 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -27,7 +27,7 @@ - * - * Called with j_list_lock held. - */ --static inline void __buffer_unlink_first(struct journal_head *jh) -+static inline void __buffer_unlink(struct journal_head *jh) - { - transaction_t *transaction = jh->b_cp_transaction; - -@@ -40,23 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh) - } - } - --/* -- * Unlink a buffer from a transaction checkpoint(io) list. -- * -- * Called with j_list_lock held. -- */ --static inline void __buffer_unlink(struct journal_head *jh) --{ -- transaction_t *transaction = jh->b_cp_transaction; -- -- __buffer_unlink_first(jh); -- if (transaction->t_checkpoint_io_list == jh) { -- transaction->t_checkpoint_io_list = jh->b_cpnext; -- if (transaction->t_checkpoint_io_list == jh) -- transaction->t_checkpoint_io_list = NULL; -- } --} -- - /* - * Check a checkpoint buffer could be release or not. - * -@@ -505,15 +488,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - break; - if (need_resched() || spin_needbreak(&journal->j_list_lock)) - break; -- if (released) -- continue; -- -- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list, -- nr_to_scan, &released); -- if (*nr_to_scan == 0) -- break; -- if (need_resched() || spin_needbreak(&journal->j_list_lock)) -- break; - } while (transaction != last_transaction); - - if (transaction != last_transaction) { -@@ -568,17 +542,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - */ - if (need_resched()) - return; -- if (ret) -- continue; -- /* -- * It is essential that we are as careful as in the case of -- * t_checkpoint_list with removing the buffer from the list as -- * we can possibly see not yet submitted buffers on io_list -- */ -- ret = journal_clean_one_cp_list(transaction-> -- t_checkpoint_io_list, destroy); -- if (need_resched()) -- return; - /* - * Stop scanning if we couldn't free the transaction. This - * avoids pointless scanning of transactions which still -@@ -663,7 +626,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) - jbd2_journal_put_journal_head(jh); - - /* Is this transaction empty? */ -- if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list) -+ if (transaction->t_checkpoint_list) - return 0; - - /* -@@ -755,7 +718,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact - J_ASSERT(transaction->t_forget == NULL); - J_ASSERT(transaction->t_shadow_list == NULL); - J_ASSERT(transaction->t_checkpoint_list == NULL); -- J_ASSERT(transaction->t_checkpoint_io_list == NULL); - J_ASSERT(atomic_read(&transaction->t_updates) == 0); - J_ASSERT(journal->j_committing_transaction != transaction); - J_ASSERT(journal->j_running_transaction != transaction); -diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c -index 885a7a6cc53e6..f1d9db6686e31 100644 ---- a/fs/jbd2/commit.c -+++ b/fs/jbd2/commit.c -@@ -1171,8 +1171,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) - spin_lock(&journal->j_list_lock); - commit_transaction->t_state = T_FINISHED; - /* Check if the transaction can be dropped now that we are finished */ -- if (commit_transaction->t_checkpoint_list == NULL && -- commit_transaction->t_checkpoint_io_list == NULL) { -+ if (commit_transaction->t_checkpoint_list == NULL) { - __jbd2_journal_drop_transaction(journal, commit_transaction); - jbd2_journal_free_transaction(commit_transaction); - } -diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h -index 0b7242370b567..67912fe08fbbd 100644 ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -622,12 +622,6 @@ struct transaction_s - */ - struct journal_head *t_checkpoint_list; - -- /* -- * Doubly-linked circular list of all buffers submitted for IO while -- * checkpointing. [j_list_lock] -- */ -- struct journal_head *t_checkpoint_io_list; -- - /* - * Doubly-linked circular list of metadata buffers being - * shadowed by log IO. The IO buffers on the iobuf list and --- -2.39.2 - diff --git a/queue-6.1/series b/queue-6.1/series index 1391d2992ef..1404aa1f9fb 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -68,9 +68,6 @@ drm-amd-display-add-fams-validation-before-trying-to.patch drm-amd-display-update-extended-blank-for-dcn314-onw.patch drm-amd-display-fix-possible-underflow-for-displays-.patch drm-amd-display-prevent-vtotal-from-being-set-to-0.patch -jbd2-remove-t_checkpoint_io_list.patch -jbd2-remove-journal_clean_one_cp_list.patch -jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch phy-phy-mtk-dp-fix-an-error-code-in-probe.patch phy-qcom-snps-correct-struct-qcom_snps_hsphy-kerneld.patch phy-qcom-snps-femto-v2-keep-cfg_ahb_clk-enabled-duri.patch diff --git a/queue-6.4/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch b/queue-6.4/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch deleted file mode 100644 index b30cf78d3db..00000000000 --- a/queue-6.4/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 091939319a56dbd39ddf118c5e9ffa2d348df215 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:27 +0800 -Subject: jbd2: fix a race when checking checkpoint buffer busy - -From: Zhang Yi - -[ Upstream commit 46f881b5b1758dc4a35fba4a643c10717d0cf427 ] - -Before removing checkpoint buffer from the t_checkpoint_list, we have to -check both BH_Dirty and BH_Lock bits together to distinguish buffers -have not been or were being written back. But __cp_buffer_busy() checks -them separately, it first check lock state and then check dirty, the -window between these two checks could be raced by writing back -procedure, which locks buffer and clears buffer dirty before I/O -completes. So it cannot guarantee checkpointing buffers been written -back to disk if some error happens later. Finally, it may clean -checkpoint transactions and lead to inconsistent filesystem. - -jbd2_journal_forget() and __journal_try_to_free_buffer() also have the -same problem (journal_unmap_buffer() escape from this issue since it's -running under the buffer lock), so fix them through introducing a new -helper to try holding the buffer lock and remove really clean buffer. - -Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 -Cc: stable@vger.kernel.org -Suggested-by: Jan Kara -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-6-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 38 +++++++++++++++++++++++++++++++++++--- - fs/jbd2/transaction.c | 17 +++++------------ - include/linux/jbd2.h | 1 + - 3 files changed, 41 insertions(+), 15 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index 42b34cab64fbd..9ec91017a7f3c 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -376,11 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - jh = next_jh; - next_jh = jh->b_cpnext; - -- if (!destroy && __cp_buffer_busy(jh)) -- continue; -+ if (destroy) { -+ ret = __jbd2_journal_remove_checkpoint(jh); -+ } else { -+ ret = jbd2_journal_try_remove_checkpoint(jh); -+ if (ret < 0) -+ continue; -+ } - - nr_freed++; -- ret = __jbd2_journal_remove_checkpoint(jh); - if (ret) { - *released = true; - break; -@@ -616,6 +620,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) - return 1; - } - -+/* -+ * Check the checkpoint buffer and try to remove it from the checkpoint -+ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if -+ * it frees the transaction, 0 otherwise. -+ * -+ * This function is called with j_list_lock held. -+ */ -+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh) -+{ -+ struct buffer_head *bh = jh2bh(jh); -+ -+ if (!trylock_buffer(bh)) -+ return -EBUSY; -+ if (buffer_dirty(bh)) { -+ unlock_buffer(bh); -+ return -EBUSY; -+ } -+ unlock_buffer(bh); -+ -+ /* -+ * Buffer is clean and the IO has finished (we held the buffer -+ * lock) so the checkpoint is done. We can safely remove the -+ * buffer from this transaction. -+ */ -+ JBUFFER_TRACE(jh, "remove from checkpoint list"); -+ return __jbd2_journal_remove_checkpoint(jh); -+} -+ - /* - * journal_insert_checkpoint: put a committed buffer onto a checkpoint - * list so that we know when it is safe to clean the transaction out of -diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c -index 18611241f4513..6ef5022949c46 100644 ---- a/fs/jbd2/transaction.c -+++ b/fs/jbd2/transaction.c -@@ -1784,8 +1784,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh) - * Otherwise, if the buffer has been written to disk, - * it is safe to remove the checkpoint and drop it. - */ -- if (!buffer_dirty(bh)) { -- __jbd2_journal_remove_checkpoint(jh); -+ if (jbd2_journal_try_remove_checkpoint(jh) >= 0) { - spin_unlock(&journal->j_list_lock); - goto drop; - } -@@ -2112,20 +2111,14 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) - - jh = bh2jh(bh); - -- if (buffer_locked(bh) || buffer_dirty(bh)) -- goto out; -- - if (jh->b_next_transaction != NULL || jh->b_transaction != NULL) -- goto out; -+ return; - - spin_lock(&journal->j_list_lock); -- if (jh->b_cp_transaction != NULL) { -- /* written-back checkpointed metadata buffer */ -- JBUFFER_TRACE(jh, "remove from checkpoint list"); -- __jbd2_journal_remove_checkpoint(jh); -- } -+ /* Remove written-back checkpointed metadata buffer */ -+ if (jh->b_cp_transaction != NULL) -+ jbd2_journal_try_remove_checkpoint(jh); - spin_unlock(&journal->j_list_lock); --out: - return; - } - -diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h -index 91a2cf4bc5756..c212da35a052c 100644 ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -1443,6 +1443,7 @@ extern void jbd2_journal_commit_transaction(journal_t *); - void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); - unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan); - int __jbd2_journal_remove_checkpoint(struct journal_head *); -+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh); - void jbd2_journal_destroy_checkpoint(journal_t *journal); - void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); - --- -2.39.2 - diff --git a/queue-6.4/jbd2-remove-journal_clean_one_cp_list.patch b/queue-6.4/jbd2-remove-journal_clean_one_cp_list.patch deleted file mode 100644 index a3aa373b575..00000000000 --- a/queue-6.4/jbd2-remove-journal_clean_one_cp_list.patch +++ /dev/null @@ -1,235 +0,0 @@ -From 71da043e7bda0b64713cf3496d168b8bc5b75c0c Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:25 +0800 -Subject: jbd2: remove journal_clean_one_cp_list() - -From: Zhang Yi - -[ Upstream commit b98dba273a0e47dbfade89c9af73c5b012a4eabb ] - -journal_clean_one_cp_list() and journal_shrink_one_cp_list() are almost -the same, so merge them into journal_shrink_one_cp_list(), remove the -nr_to_scan parameter, always scan and try to free the whole checkpoint -list. - -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-4-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 75 +++++++++---------------------------- - include/trace/events/jbd2.h | 12 ++---- - 2 files changed, 21 insertions(+), 66 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index 723b4eb112828..42b34cab64fbd 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -349,50 +349,10 @@ int jbd2_cleanup_journal_tail(journal_t *journal) - - /* Checkpoint list management */ - --/* -- * journal_clean_one_cp_list -- * -- * Find all the written-back checkpoint buffers in the given list and -- * release them. If 'destroy' is set, clean all buffers unconditionally. -- * -- * Called with j_list_lock held. -- * Returns 1 if we freed the transaction, 0 otherwise. -- */ --static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) --{ -- struct journal_head *last_jh; -- struct journal_head *next_jh = jh; -- -- if (!jh) -- return 0; -- -- last_jh = jh->b_cpprev; -- do { -- jh = next_jh; -- next_jh = jh->b_cpnext; -- -- if (!destroy && __cp_buffer_busy(jh)) -- return 0; -- -- if (__jbd2_journal_remove_checkpoint(jh)) -- return 1; -- /* -- * This function only frees up some memory -- * if possible so we dont have an obligation -- * to finish processing. Bail out if preemption -- * requested: -- */ -- if (need_resched()) -- return 0; -- } while (jh != last_jh); -- -- return 0; --} -- - /* - * journal_shrink_one_cp_list - * -- * Find 'nr_to_scan' written-back checkpoint buffers in the given list -+ * Find all the written-back checkpoint buffers in the given list - * and try to release them. If the whole transaction is released, set - * the 'released' parameter. Return the number of released checkpointed - * buffers. -@@ -400,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) - * Called with j_list_lock held. - */ - static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, -- unsigned long *nr_to_scan, -- bool *released) -+ bool destroy, bool *released) - { - struct journal_head *last_jh; - struct journal_head *next_jh = jh; - unsigned long nr_freed = 0; - int ret; - -- if (!jh || *nr_to_scan == 0) -+ *released = false; -+ if (!jh) - return 0; - - last_jh = jh->b_cpprev; -@@ -416,8 +376,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - jh = next_jh; - next_jh = jh->b_cpnext; - -- (*nr_to_scan)--; -- if (__cp_buffer_busy(jh)) -+ if (!destroy && __cp_buffer_busy(jh)) - continue; - - nr_freed++; -@@ -429,7 +388,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, - - if (need_resched()) - break; -- } while (jh != last_jh && *nr_to_scan); -+ } while (jh != last_jh); - - return nr_freed; - } -@@ -447,11 +406,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - unsigned long *nr_to_scan) - { - transaction_t *transaction, *last_transaction, *next_transaction; -- bool released; -+ bool __maybe_unused released; - tid_t first_tid = 0, last_tid = 0, next_tid = 0; - tid_t tid = 0; - unsigned long nr_freed = 0; -- unsigned long nr_scanned = *nr_to_scan; -+ unsigned long freed; - - again: - spin_lock(&journal->j_list_lock); -@@ -480,10 +439,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - transaction = next_transaction; - next_transaction = transaction->t_cpnext; - tid = transaction->t_tid; -- released = false; - -- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list, -- nr_to_scan, &released); -+ freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list, -+ false, &released); -+ nr_freed += freed; -+ (*nr_to_scan) -= min(*nr_to_scan, freed); - if (*nr_to_scan == 0) - break; - if (need_resched() || spin_needbreak(&journal->j_list_lock)) -@@ -504,9 +464,8 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - if (*nr_to_scan && next_tid) - goto again; - out: -- nr_scanned -= *nr_to_scan; - trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid, -- nr_freed, nr_scanned, next_tid); -+ nr_freed, next_tid); - - return nr_freed; - } -@@ -522,7 +481,7 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - { - transaction_t *transaction, *last_transaction, *next_transaction; -- int ret; -+ bool released; - - transaction = journal->j_checkpoint_transactions; - if (!transaction) -@@ -533,8 +492,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - do { - transaction = next_transaction; - next_transaction = transaction->t_cpnext; -- ret = journal_clean_one_cp_list(transaction->t_checkpoint_list, -- destroy); -+ journal_shrink_one_cp_list(transaction->t_checkpoint_list, -+ destroy, &released); - /* - * This function only frees up some memory if possible so we - * dont have an obligation to finish processing. Bail out if -@@ -547,7 +506,7 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - * avoids pointless scanning of transactions which still - * weren't checkpointed. - */ -- if (!ret) -+ if (!released) - return; - } while (transaction != last_transaction); - } -diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h -index 8f5ee380d3093..5646ae15a957a 100644 ---- a/include/trace/events/jbd2.h -+++ b/include/trace/events/jbd2.h -@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit, - TRACE_EVENT(jbd2_shrink_checkpoint_list, - - TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid, -- unsigned long nr_freed, unsigned long nr_scanned, -- tid_t next_tid), -+ unsigned long nr_freed, tid_t next_tid), - -- TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, -- nr_scanned, next_tid), -+ TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid), - - TP_STRUCT__entry( - __field(dev_t, dev) -@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, - __field(tid_t, tid) - __field(tid_t, last_tid) - __field(unsigned long, nr_freed) -- __field(unsigned long, nr_scanned) - __field(tid_t, next_tid) - ), - -@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, - __entry->tid = tid; - __entry->last_tid = last_tid; - __entry->nr_freed = nr_freed; -- __entry->nr_scanned = nr_scanned; - __entry->next_tid = next_tid; - ), - - TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu " -- "scanned %lu next transaction %u", -+ "next transaction %u", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->first_tid, __entry->tid, __entry->last_tid, -- __entry->nr_freed, __entry->nr_scanned, __entry->next_tid) -+ __entry->nr_freed, __entry->next_tid) - ); - - #endif /* _TRACE_JBD2_H */ --- -2.39.2 - diff --git a/queue-6.4/jbd2-remove-t_checkpoint_io_list.patch b/queue-6.4/jbd2-remove-t_checkpoint_io_list.patch deleted file mode 100644 index 171ae0d42a2..00000000000 --- a/queue-6.4/jbd2-remove-t_checkpoint_io_list.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 9772b6005d10a0cfe725dba954d66e8ee6fa1e10 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 6 Jun 2023 21:59:24 +0800 -Subject: jbd2: remove t_checkpoint_io_list - -From: Zhang Yi - -[ Upstream commit be22255360f80d3af789daad00025171a65424a5 ] - -Since t_checkpoint_io_list was stop using in jbd2_log_do_checkpoint() -now, it's time to remove the whole t_checkpoint_io_list logic. - -Signed-off-by: Zhang Yi -Reviewed-by: Jan Kara -Link: https://lore.kernel.org/r/20230606135928.434610-3-yi.zhang@huaweicloud.com -Signed-off-by: Theodore Ts'o -Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") -Signed-off-by: Sasha Levin ---- - fs/jbd2/checkpoint.c | 42 ++---------------------------------------- - fs/jbd2/commit.c | 3 +-- - include/linux/jbd2.h | 6 ------ - 3 files changed, 3 insertions(+), 48 deletions(-) - -diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index c4e0da6db7195..723b4eb112828 100644 ---- a/fs/jbd2/checkpoint.c -+++ b/fs/jbd2/checkpoint.c -@@ -27,7 +27,7 @@ - * - * Called with j_list_lock held. - */ --static inline void __buffer_unlink_first(struct journal_head *jh) -+static inline void __buffer_unlink(struct journal_head *jh) - { - transaction_t *transaction = jh->b_cp_transaction; - -@@ -40,23 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh) - } - } - --/* -- * Unlink a buffer from a transaction checkpoint(io) list. -- * -- * Called with j_list_lock held. -- */ --static inline void __buffer_unlink(struct journal_head *jh) --{ -- transaction_t *transaction = jh->b_cp_transaction; -- -- __buffer_unlink_first(jh); -- if (transaction->t_checkpoint_io_list == jh) { -- transaction->t_checkpoint_io_list = jh->b_cpnext; -- if (transaction->t_checkpoint_io_list == jh) -- transaction->t_checkpoint_io_list = NULL; -- } --} -- - /* - * Check a checkpoint buffer could be release or not. - * -@@ -505,15 +488,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, - break; - if (need_resched() || spin_needbreak(&journal->j_list_lock)) - break; -- if (released) -- continue; -- -- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list, -- nr_to_scan, &released); -- if (*nr_to_scan == 0) -- break; -- if (need_resched() || spin_needbreak(&journal->j_list_lock)) -- break; - } while (transaction != last_transaction); - - if (transaction != last_transaction) { -@@ -568,17 +542,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) - */ - if (need_resched()) - return; -- if (ret) -- continue; -- /* -- * It is essential that we are as careful as in the case of -- * t_checkpoint_list with removing the buffer from the list as -- * we can possibly see not yet submitted buffers on io_list -- */ -- ret = journal_clean_one_cp_list(transaction-> -- t_checkpoint_io_list, destroy); -- if (need_resched()) -- return; - /* - * Stop scanning if we couldn't free the transaction. This - * avoids pointless scanning of transactions which still -@@ -663,7 +626,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) - jbd2_journal_put_journal_head(jh); - - /* Is this transaction empty? */ -- if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list) -+ if (transaction->t_checkpoint_list) - return 0; - - /* -@@ -755,7 +718,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact - J_ASSERT(transaction->t_forget == NULL); - J_ASSERT(transaction->t_shadow_list == NULL); - J_ASSERT(transaction->t_checkpoint_list == NULL); -- J_ASSERT(transaction->t_checkpoint_io_list == NULL); - J_ASSERT(atomic_read(&transaction->t_updates) == 0); - J_ASSERT(journal->j_committing_transaction != transaction); - J_ASSERT(journal->j_running_transaction != transaction); -diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c -index b33155dd70017..1073259902a60 100644 ---- a/fs/jbd2/commit.c -+++ b/fs/jbd2/commit.c -@@ -1141,8 +1141,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) - spin_lock(&journal->j_list_lock); - commit_transaction->t_state = T_FINISHED; - /* Check if the transaction can be dropped now that we are finished */ -- if (commit_transaction->t_checkpoint_list == NULL && -- commit_transaction->t_checkpoint_io_list == NULL) { -+ if (commit_transaction->t_checkpoint_list == NULL) { - __jbd2_journal_drop_transaction(journal, commit_transaction); - jbd2_journal_free_transaction(commit_transaction); - } -diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h -index f619bae1dcc5d..91a2cf4bc5756 100644 ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -622,12 +622,6 @@ struct transaction_s - */ - struct journal_head *t_checkpoint_list; - -- /* -- * Doubly-linked circular list of all buffers submitted for IO while -- * checkpointing. [j_list_lock] -- */ -- struct journal_head *t_checkpoint_io_list; -- - /* - * Doubly-linked circular list of metadata buffers being - * shadowed by log IO. The IO buffers on the iobuf list and --- -2.39.2 - diff --git a/queue-6.4/series b/queue-6.4/series index b5e40f477fb..ea6418716e2 100644 --- a/queue-6.4/series +++ b/queue-6.4/series @@ -43,9 +43,6 @@ drm-amd-display-add-fams-validation-before-trying-to.patch drm-amd-display-update-extended-blank-for-dcn314-onw.patch drm-amd-display-fix-possible-underflow-for-displays-.patch drm-amd-display-prevent-vtotal-from-being-set-to-0.patch -jbd2-remove-t_checkpoint_io_list.patch -jbd2-remove-journal_clean_one_cp_list.patch -jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch ext4-add-ext4_mb_hint_goal_only-test-in-ext4_mb_use_.patch ext4-mballoc-remove-useless-setting-of-ac_criteria.patch ext4-fix-rbtree-traversal-bug-in-ext4_mb_use_preallo.patch