1 jbd2: Remove a large array of bh's from the stack of the checkpoint routine
3 jbd2_log_do_checkpoint()n is one of the kernel's largest stack users.
4 Move the array of buffer head's from the stack of jbd2_log_do_checkpoint()
5 to the in-core journal structure.
7 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
8 diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
9 index 02f9db1..6b7e06d 100644
10 --- a/fs/jbd2/checkpoint.c
11 +++ b/fs/jbd2/checkpoint.c
12 @@ -243,16 +243,14 @@ restart:
19 -__flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
20 +__flush_batch(journal_t *journal, int *batch_count)
24 - ll_rw_block(SWRITE, *batch_count, bhs);
25 + ll_rw_block(SWRITE, *batch_count, journal->j_chkpt_bhs);
26 for (i = 0; i < *batch_count; i++) {
27 - struct buffer_head *bh = bhs[i];
28 + struct buffer_head *bh = journal->j_chkpt_bhs[i];
29 clear_buffer_jwrite(bh);
30 BUFFER_TRACE(bh, "brelse");
32 @@ -271,8 +269,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
33 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
35 static int __process_buffer(journal_t *journal, struct journal_head *jh,
36 - struct buffer_head **bhs, int *batch_count,
37 - transaction_t *transaction)
38 + int *batch_count, transaction_t *transaction)
40 struct buffer_head *bh = jh2bh(jh);
42 @@ -319,14 +316,14 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
44 J_ASSERT_BH(bh, !buffer_jwrite(bh));
45 set_buffer_jwrite(bh);
46 - bhs[*batch_count] = bh;
47 + journal->j_chkpt_bhs[*batch_count] = bh;
48 __buffer_relink_io(jh);
49 jbd_unlock_bh_state(bh);
50 transaction->t_chp_stats.cs_written++;
52 - if (*batch_count == NR_BATCH) {
53 + if (*batch_count == JBD2_NR_BATCH) {
54 spin_unlock(&journal->j_list_lock);
55 - __flush_batch(journal, bhs, batch_count);
56 + __flush_batch(journal, batch_count);
60 @@ -382,7 +379,6 @@ restart:
61 if (journal->j_checkpoint_transactions == transaction &&
62 transaction->t_tid == this_tid) {
64 - struct buffer_head *bhs[NR_BATCH];
65 struct journal_head *jh;
68 @@ -396,7 +392,7 @@ restart:
72 - retry = __process_buffer(journal, jh, bhs, &batch_count,
73 + retry = __process_buffer(journal, jh, &batch_count,
75 if (retry < 0 && !result)
77 @@ -413,7 +409,7 @@ restart:
78 spin_unlock(&journal->j_list_lock);
81 - __flush_batch(journal, bhs, &batch_count);
82 + __flush_batch(journal, &batch_count);
86 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
87 index e70d657..d91310b 100644
88 --- a/fs/jbd2/journal.c
89 +++ b/fs/jbd2/journal.c
90 @@ -1472,7 +1472,9 @@ int jbd2_journal_destroy(journal_t *journal)
91 spin_lock(&journal->j_list_lock);
92 while (journal->j_checkpoint_transactions != NULL) {
93 spin_unlock(&journal->j_list_lock);
94 + mutex_lock(&journal->j_checkpoint_mutex);
95 jbd2_log_do_checkpoint(journal);
96 + mutex_unlock(&journal->j_checkpoint_mutex);
97 spin_lock(&journal->j_list_lock);
100 diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
101 index b8b8744..e9dbaa6 100644
102 --- a/include/linux/jbd2.h
103 +++ b/include/linux/jbd2.h
104 @@ -686,6 +686,8 @@ jbd2_time_diff(unsigned long start, unsigned long end)
105 return end + (MAX_JIFFY_OFFSET - start);
108 +#define JBD2_NR_BATCH 64
111 * struct journal_s - The journal_s type is the concrete type associated with
113 @@ -830,6 +832,14 @@ struct journal_s
114 struct mutex j_checkpoint_mutex;
117 + * List of buffer heads used by the checkpoint routine. This
118 + * was moved from jbd2_log_do_checkpoint() to reduce stack
119 + * usage. Access to this array is controlled by the
120 + * j_checkpoint_mutex. [j_checkpoint_mutex]
122 + struct buffer_head *j_chkpt_bhs[JBD2_NR_BATCH];
125 * Journal head: identifies the first unused block in the journal.