[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240820072609.570513-1-zhaoyang.huang@unisoc.com>
Date: Tue, 20 Aug 2024 15:26:09 +0800
From: "zhaoyang.huang" <zhaoyang.huang@...soc.com>
To: "Theodore Ts'o" <tytso@....edu>, Jan Kara <jack@...e.com>,
<linux-fsdevel@...r.kernel.org>, <linux-ext4@...r.kernel.org>,
Zhaoyang Huang
<huangzhaoyang@...il.com>, <steve.kang@...soc.com>
Subject: [RFC PATCH 1/1] fs: jbd2: try to launch cp transaction when bh refer cma
From: Zhaoyang Huang <zhaoyang.huang@...soc.com>
cma_alloc() keep failed when an bunch of IO operations happened on an
journal enabled ext4 device which is caused by a jh->bh->b_page
can not be migrated out of CMA area as the jh has one cp_transaction
pending on it. We solve this by launching jbd2_log_do_checkpoint forcefully
somewhere. Since journal is common mechanism to all JFSs and
cp_transaction has a little fewer opportunity to be launched, this patch
would like to introduce a timing point at which the
cp_transaction->t_checkpoint_list is shrunk if CMA page used for
journalling.
Signed-off-by: Zhaoyang Huang <zhaoyang.huang@...soc.com>
---
fs/jbd2/checkpoint.c | 27 +++++++++++++++++++++++++++
fs/jbd2/journal.c | 4 ++++
include/linux/jbd2.h | 2 ++
3 files changed, 33 insertions(+)
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 951f78634adf..8c6c1dba1f0f 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <trace/events/jbd2.h>
+#include <linux/mm.h>
/*
* Unlink a buffer from a transaction checkpoint list.
@@ -137,6 +138,32 @@ __flush_batch(journal_t *journal, int *batch_count)
*batch_count = 0;
}
+#ifdef CONFIG_CMA
+void drain_cma_bh(journal_t *journal)
+{
+ struct journal_head *jh;
+ struct buffer_head *bh;
+
+ if (!journal->j_checkpoint_transactions)
+ return;
+
+ jh = journal->j_checkpoint_transactions->t_checkpoint_list;
+ while (jh) {
+ bh = jh2bh(jh);
+
+ if (bh && get_pageblock_migratetype(bh->b_page) == MIGRATE_CMA) {
+ mutex_lock_io(&journal->j_checkpoint_mutex);
+ jbd2_log_do_checkpoint(journal);
+ mutex_unlock(&journal->j_checkpoint_mutex);
+ return;
+ }
+
+ jh = jh->b_cpnext;
+ }
+}
+#else
+void drain_cma_bh(journal_t *journal) {}
+#endif
/*
* Perform an actual checkpoint. We take the first transaction on the
* list of transactions to be checkpointed and send all its buffers
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 1ebf2393bfb7..dd92cb7404fc 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -41,6 +41,7 @@
#include <linux/bitops.h>
#include <linux/ratelimit.h>
#include <linux/sched/mm.h>
+#include <linux/swap.h>
#define CREATE_TRACE_POINTS
#include <trace/events/jbd2.h>
@@ -1273,6 +1274,9 @@ static unsigned long jbd2_journal_shrink_scan(struct shrinker *shrink,
count = percpu_counter_read_positive(&journal->j_checkpoint_jh_count);
trace_jbd2_shrink_scan_enter(journal, sc->nr_to_scan, count);
+ if (current_is_kswapd())
+ drain_cma_bh(journal);
+
nr_shrunk = jbd2_journal_shrink_checkpoint_list(journal, &nr_to_scan);
count = percpu_counter_read_positive(&journal->j_checkpoint_jh_count);
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 5157d92b6f23..fc152382a6ae 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -105,6 +105,8 @@ typedef struct jbd2_journal_handle handle_t; /* Atomic operation type */
typedef struct journal_s journal_t; /* Journal control structure */
#endif
+void drain_cma_bh(journal_t *journal);
+
/*
* Internal structures used by the logging mechanism:
*/
--
2.25.1
Powered by blists - more mailing lists