aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-09-18 00:42:16 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-09-18 00:42:16 -0400
commitcc97f1a7c7eed970e674b84be0e68f479c80228d (patch)
tree43d4358c0792994358968b8d1dc2ebef654ba396 /fs
parent844749764b416ee2c4ba2da328c04eaad7388242 (diff)
jbd2: avoid pointless scanning of checkpoint lists
Yuanhan has reported that when he is running fsync(2) heavy workload creating new files over ramdisk, significant amount of time is spent in __jbd2_journal_clean_checkpoint_list() trying to clean old transactions (but they cannot be cleaned up because flusher hasn't yet checkpointed those buffers). The workload can be generated by: fs_mark -d /fs/ram0/1 -D 2 -N 2560 -n 1000000 -L 1 -S 1 -s 4096 Reduce the amount of scanning by stopping to scan the transaction list once we find a transaction that cannot be checkpointed. Note that this way of cleaning is still enough to keep freeing space in the journal after fully checkpointed transactions. Reported-and-tested-by: Yuanhan Liu <yuanhan.liu@linux.intel.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/jbd2/checkpoint.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 1fbf59938cc0..3ab4c5ee12ce 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -420,7 +420,6 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
420 * Find all the written-back checkpoint buffers in the given list and 420 * Find all the written-back checkpoint buffers in the given list and
421 * release them. 421 * release them.
422 * 422 *
423 * Called with the journal locked.
424 * Called with j_list_lock held. 423 * Called with j_list_lock held.
425 * Returns number of buffers reaped (for debug) 424 * Returns number of buffers reaped (for debug)
426 */ 425 */
@@ -440,12 +439,12 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
440 jh = next_jh; 439 jh = next_jh;
441 next_jh = jh->b_cpnext; 440 next_jh = jh->b_cpnext;
442 ret = __try_to_free_cp_buf(jh); 441 ret = __try_to_free_cp_buf(jh);
443 if (ret) { 442 if (!ret)
444 freed++; 443 return freed;
445 if (ret == 2) { 444 freed++;
446 *released = 1; 445 if (ret == 2) {
447 return freed; 446 *released = 1;
448 } 447 return freed;
449 } 448 }
450 /* 449 /*
451 * This function only frees up some memory 450 * This function only frees up some memory
@@ -465,7 +464,6 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
465 * 464 *
466 * Find all the written-back checkpoint buffers in the journal and release them. 465 * Find all the written-back checkpoint buffers in the journal and release them.
467 * 466 *
468 * Called with the journal locked.
469 * Called with j_list_lock held. 467 * Called with j_list_lock held.
470 * Returns number of buffers reaped (for debug) 468 * Returns number of buffers reaped (for debug)
471 */ 469 */
@@ -473,7 +471,8 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
473int __jbd2_journal_clean_checkpoint_list(journal_t *journal) 471int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
474{ 472{
475 transaction_t *transaction, *last_transaction, *next_transaction; 473 transaction_t *transaction, *last_transaction, *next_transaction;
476 int ret = 0; 474 int ret;
475 int freed = 0;
477 int released; 476 int released;
478 477
479 transaction = journal->j_checkpoint_transactions; 478 transaction = journal->j_checkpoint_transactions;
@@ -485,17 +484,21 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
485 do { 484 do {
486 transaction = next_transaction; 485 transaction = next_transaction;
487 next_transaction = transaction->t_cpnext; 486 next_transaction = transaction->t_cpnext;
488 ret += journal_clean_one_cp_list(transaction-> 487 ret = journal_clean_one_cp_list(transaction->
489 t_checkpoint_list, &released); 488 t_checkpoint_list, &released);
490 /* 489 /*
491 * This function only frees up some memory if possible so we 490 * This function only frees up some memory if possible so we
492 * dont have an obligation to finish processing. Bail out if 491 * dont have an obligation to finish processing. Bail out if
493 * preemption requested: 492 * preemption requested:
494 */ 493 */
495 if (need_resched()) 494 if (need_resched()) {
495 freed += ret;
496 goto out; 496 goto out;
497 if (released) 497 }
498 if (released) {
499 freed += ret;
498 continue; 500 continue;
501 }
499 /* 502 /*
500 * It is essential that we are as careful as in the case of 503 * It is essential that we are as careful as in the case of
501 * t_checkpoint_list with removing the buffer from the list as 504 * t_checkpoint_list with removing the buffer from the list as
@@ -503,11 +506,12 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
503 */ 506 */
504 ret += journal_clean_one_cp_list(transaction-> 507 ret += journal_clean_one_cp_list(transaction->
505 t_checkpoint_io_list, &released); 508 t_checkpoint_io_list, &released);
506 if (need_resched()) 509 freed += ret;
510 if (need_resched() || !ret)
507 goto out; 511 goto out;
508 } while (transaction != last_transaction); 512 } while (transaction != last_transaction);
509out: 513out:
510 return ret; 514 return freed;
511} 515}
512 516
513/* 517/*