aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2008-11-05 00:09:22 -0500
committerTheodore Ts'o <tytso@mit.edu>2008-11-05 00:09:22 -0500
commit1a0d3786dd57dbd74f340322054c3d618b999dcf (patch)
treeb10b3ed6cb60ee34a4e8140e60da2ecc34b52f32
parent498e5f24158da7bf8fa48074a70e370e22844492 (diff)
jbd2: Remove a large array of bh's from the stack of the checkpoint routine
jbd2_log_do_checkpoint()n is one of the kernel's largest stack users. Move the array of buffer head's from the stack of jbd2_log_do_checkpoint() to the in-core journal structure. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/jbd2/checkpoint.c22
-rw-r--r--fs/jbd2/journal.c2
-rw-r--r--include/linux/jbd2.h10
3 files changed, 21 insertions, 13 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 9497718fe920..adc08ec875ed 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -249,16 +249,14 @@ restart:
249 return ret; 249 return ret;
250} 250}
251 251
252#define NR_BATCH 64
253
254static void 252static void
255__flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) 253__flush_batch(journal_t *journal, int *batch_count)
256{ 254{
257 int i; 255 int i;
258 256
259 ll_rw_block(SWRITE, *batch_count, bhs); 257 ll_rw_block(SWRITE, *batch_count, journal->j_chkpt_bhs);
260 for (i = 0; i < *batch_count; i++) { 258 for (i = 0; i < *batch_count; i++) {
261 struct buffer_head *bh = bhs[i]; 259 struct buffer_head *bh = journal->j_chkpt_bhs[i];
262 clear_buffer_jwrite(bh); 260 clear_buffer_jwrite(bh);
263 BUFFER_TRACE(bh, "brelse"); 261 BUFFER_TRACE(bh, "brelse");
264 __brelse(bh); 262 __brelse(bh);
@@ -277,8 +275,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
277 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it 275 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
278 */ 276 */
279static int __process_buffer(journal_t *journal, struct journal_head *jh, 277static int __process_buffer(journal_t *journal, struct journal_head *jh,
280 struct buffer_head **bhs, int *batch_count, 278 int *batch_count, transaction_t *transaction)
281 transaction_t *transaction)
282{ 279{
283 struct buffer_head *bh = jh2bh(jh); 280 struct buffer_head *bh = jh2bh(jh);
284 int ret = 0; 281 int ret = 0;
@@ -325,14 +322,14 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
325 get_bh(bh); 322 get_bh(bh);
326 J_ASSERT_BH(bh, !buffer_jwrite(bh)); 323 J_ASSERT_BH(bh, !buffer_jwrite(bh));
327 set_buffer_jwrite(bh); 324 set_buffer_jwrite(bh);
328 bhs[*batch_count] = bh; 325 journal->j_chkpt_bhs[*batch_count] = bh;
329 __buffer_relink_io(jh); 326 __buffer_relink_io(jh);
330 jbd_unlock_bh_state(bh); 327 jbd_unlock_bh_state(bh);
331 transaction->t_chp_stats.cs_written++; 328 transaction->t_chp_stats.cs_written++;
332 (*batch_count)++; 329 (*batch_count)++;
333 if (*batch_count == NR_BATCH) { 330 if (*batch_count == JBD2_NR_BATCH) {
334 spin_unlock(&journal->j_list_lock); 331 spin_unlock(&journal->j_list_lock);
335 __flush_batch(journal, bhs, batch_count); 332 __flush_batch(journal, batch_count);
336 ret = 1; 333 ret = 1;
337 } 334 }
338 } 335 }
@@ -388,7 +385,6 @@ restart:
388 if (journal->j_checkpoint_transactions == transaction && 385 if (journal->j_checkpoint_transactions == transaction &&
389 transaction->t_tid == this_tid) { 386 transaction->t_tid == this_tid) {
390 int batch_count = 0; 387 int batch_count = 0;
391 struct buffer_head *bhs[NR_BATCH];
392 struct journal_head *jh; 388 struct journal_head *jh;
393 int retry = 0, err; 389 int retry = 0, err;
394 390
@@ -402,7 +398,7 @@ restart:
402 retry = 1; 398 retry = 1;
403 break; 399 break;
404 } 400 }
405 retry = __process_buffer(journal, jh, bhs, &batch_count, 401 retry = __process_buffer(journal, jh, &batch_count,
406 transaction); 402 transaction);
407 if (retry < 0 && !result) 403 if (retry < 0 && !result)
408 result = retry; 404 result = retry;
@@ -419,7 +415,7 @@ restart:
419 spin_unlock(&journal->j_list_lock); 415 spin_unlock(&journal->j_list_lock);
420 retry = 1; 416 retry = 1;
421 } 417 }
422 __flush_batch(journal, bhs, &batch_count); 418 __flush_batch(journal, &batch_count);
423 } 419 }
424 420
425 if (retry) { 421 if (retry) {
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index fd1d7557a098..34ef98057202 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1477,7 +1477,9 @@ int jbd2_journal_destroy(journal_t *journal)
1477 spin_lock(&journal->j_list_lock); 1477 spin_lock(&journal->j_list_lock);
1478 while (journal->j_checkpoint_transactions != NULL) { 1478 while (journal->j_checkpoint_transactions != NULL) {
1479 spin_unlock(&journal->j_list_lock); 1479 spin_unlock(&journal->j_list_lock);
1480 mutex_lock(&journal->j_checkpoint_mutex);
1480 jbd2_log_do_checkpoint(journal); 1481 jbd2_log_do_checkpoint(journal);
1482 mutex_unlock(&journal->j_checkpoint_mutex);
1481 spin_lock(&journal->j_list_lock); 1483 spin_lock(&journal->j_list_lock);
1482 } 1484 }
1483 1485
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index a3cd647ea1bc..004c9a8d63ed 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -687,6 +687,8 @@ jbd2_time_diff(unsigned long start, unsigned long end)
687 return end + (MAX_JIFFY_OFFSET - start); 687 return end + (MAX_JIFFY_OFFSET - start);
688} 688}
689 689
690#define JBD2_NR_BATCH 64
691
690/** 692/**
691 * struct journal_s - The journal_s type is the concrete type associated with 693 * struct journal_s - The journal_s type is the concrete type associated with
692 * journal_t. 694 * journal_t.
@@ -831,6 +833,14 @@ struct journal_s
831 struct mutex j_checkpoint_mutex; 833 struct mutex j_checkpoint_mutex;
832 834
833 /* 835 /*
836 * List of buffer heads used by the checkpoint routine. This
837 * was moved from jbd2_log_do_checkpoint() to reduce stack
838 * usage. Access to this array is controlled by the
839 * j_checkpoint_mutex. [j_checkpoint_mutex]
840 */
841 struct buffer_head *j_chkpt_bhs[JBD2_NR_BATCH];
842
843 /*
834 * Journal head: identifies the first unused block in the journal. 844 * Journal head: identifies the first unused block in the journal.
835 * [j_state_lock] 845 * [j_state_lock]
836 */ 846 */