1 jbd2: avoid pointless scanning of checkpoint lists
3 From: Jan Kara <jack@suse.cz>
5 Yuanhan has reported that when he is running fsync(2) heavy workload
6 creating new files over ramdisk, significant amount of time is spent in
7 __jbd2_journal_clean_checkpoint_list() trying to clean old transactions
8 (but they cannot be cleaned up because flusher hasn't yet checkpointed
9 those buffers). The workload can be generated by:
10 fs_mark -d /fs/ram0/1 -D 2 -N 2560 -n 1000000 -L 1 -S 1 -s 4096
12 Reduce the amount of scanning by stopping to scan the transaction list
13 once we find a transaction that cannot be checkpointed. Note that this
14 way of cleaning is still enough to keep freeing space in the journal
15 after fully checkpointed transactions.
17 Reported-and-tested-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
18 Signed-off-by: Jan Kara <jack@suse.cz>
19 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
21 fs/jbd2/checkpoint.c | 32 ++++++++++++++++++--------------
22 1 file changed, 18 insertions(+), 14 deletions(-)
24 diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
25 index 7f34f4716165..e39b2d0e1079 100644
26 --- a/fs/jbd2/checkpoint.c
27 +++ b/fs/jbd2/checkpoint.c
28 @@ -478,7 +478,6 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
29 * Find all the written-back checkpoint buffers in the given list and
32 - * Called with the journal locked.
33 * Called with j_list_lock held.
34 * Returns number of buffers reaped (for debug)
36 @@ -498,12 +497,12 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
38 next_jh = jh->b_cpnext;
39 ret = __try_to_free_cp_buf(jh);
54 * This function only frees up some memory
55 @@ -523,7 +522,6 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
57 * Find all the written-back checkpoint buffers in the journal and release them.
59 - * Called with the journal locked.
60 * Called with j_list_lock held.
61 * Returns number of buffers reaped (for debug)
63 @@ -531,7 +529,8 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
64 int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
66 transaction_t *transaction, *last_transaction, *next_transaction;
72 transaction = journal->j_checkpoint_transactions;
73 @@ -543,17 +542,21 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
75 transaction = next_transaction;
76 next_transaction = transaction->t_cpnext;
77 - ret += journal_clean_one_cp_list(transaction->
78 + ret = journal_clean_one_cp_list(transaction->
79 t_checkpoint_list, &released);
81 * This function only frees up some memory if possible so we
82 * dont have an obligation to finish processing. Bail out if
83 * preemption requested:
86 + if (need_resched()) {
96 * It is essential that we are as careful as in the case of
97 * t_checkpoint_list with removing the buffer from the list as
98 @@ -561,11 +564,12 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
100 ret += journal_clean_one_cp_list(transaction->
101 t_checkpoint_io_list, &released);
102 - if (need_resched())
104 + if (need_resched() || !ret)
106 } while (transaction != last_transaction);
117 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
118 the body of a message to majordomo@vger.kernel.org
119 More majordomo info at http://vger.kernel.org/majordomo-info.html