diff options
author | Theodore Ts'o <tytso@mit.edu> | 2008-11-05 00:09:22 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-11-05 00:09:22 -0500 |
commit | 1a0d3786dd57dbd74f340322054c3d618b999dcf (patch) | |
tree | b10b3ed6cb60ee34a4e8140e60da2ecc34b52f32 | |
parent | 498e5f24158da7bf8fa48074a70e370e22844492 (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.c | 22 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 2 | ||||
-rw-r--r-- | include/linux/jbd2.h | 10 |
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 | |||
254 | static void | 252 | static 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 | */ |
279 | static int __process_buffer(journal_t *journal, struct journal_head *jh, | 277 | static 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 | */ |