add patch dont-check-quota-format-when-there-are-no-quota-files
[ext4-patch-queue.git] / avoid-pointless-scanning-of-checkpoint-lists
blob05812eddcb4130c48cede8554271282119b831fb
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>
20 ---
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
30   * release them.
31   *
32 - * Called with the journal locked.
33   * Called with j_list_lock held.
34   * Returns number of buffers reaped (for debug)
35   */
36 @@ -498,12 +497,12 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
37                 jh = next_jh;
38                 next_jh = jh->b_cpnext;
39                 ret = __try_to_free_cp_buf(jh);
40 -               if (ret) {
41 -                       freed++;
42 -                       if (ret == 2) {
43 -                               *released = 1;
44 -                               return freed;
45 -                       }
46 +               if (!ret)
47 +                       return freed;
48 +               freed++;
49 +               if (ret == 2) {
50 +                       *released = 1;
51 +                       return freed;
52                 }
53                 /*
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)
56   *
57   * Find all the written-back checkpoint buffers in the journal and release them.
58   *
59 - * Called with the journal locked.
60   * Called with j_list_lock held.
61   * Returns number of buffers reaped (for debug)
62   */
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)
65  {
66         transaction_t *transaction, *last_transaction, *next_transaction;
67 -       int ret = 0;
68 +       int ret;
69 +       int freed = 0;
70         int released;
72         transaction = journal->j_checkpoint_transactions;
73 @@ -543,17 +542,21 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
74         do {
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);
80                 /*
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:
84                  */
85 -               if (need_resched())
86 +               if (need_resched()) {
87 +                       freed += ret;
88                         goto out;
89 -               if (released)
90 +               }
91 +               if (released) {
92 +                       freed += ret;
93                         continue;
94 +               }
95                 /*
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)
99                  */
100                 ret += journal_clean_one_cp_list(transaction->
101                                 t_checkpoint_io_list, &released);
102 -               if (need_resched())
103 +               freed += ret;
104 +               if (need_resched() || !ret)
105                         goto out;
106         } while (transaction != last_transaction);
107  out:
108 -       return ret;
109 +       return freed;
112  /*
113 -- 
114 1.8.1.4
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