Currently, journal descriptor blocks were not accounted in transaction->t_outstanding_credits and we were just leaving some slack space in the journal for them (in jbd2_log_space_left() and jbd2_space_needed()). This is making proper accounting (and reservation we want to add) of descriptor blocks difficult so switch to accounting descriptor blocks in transaction->t_outstanding_credits and just reserve the same amount of credits in t_outstanding credits for journal descriptor blocks when creating transaction.
Unified · Split
| @@ -560,8 +560,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) · 559 unmodified lines | |||
| 560 | stats.run.rs_logging = jiffies; | 560 | stats.run.rs_logging = jiffies; |
| 561 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, | 561 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, |
| 562 | stats.run.rs_logging); | 562 | stats.run.rs_logging); |
| 563 | stats.run.rs_blocks = | 563 | stats.run.rs_blocks = commit_transaction->t_nr_buffers; |
| 564 | atomic_read(&commit_transaction->t_outstanding_credits); | ||
| 565 | stats.run.rs_blocks_logged = 0; | 564 | stats.run.rs_blocks_logged = 0; |
| 566 | 565 | ||
| 567 | J_ASSERT(commit_transaction->t_nr_buffers <= | 566 | J_ASSERT(commit_transaction->t_nr_buffers <= |
| @@ -889,6 +888,9 @@ start_journal_io: · 321 unmodified lines | |||
| 889 | if (err) | 888 | if (err) |
| 890 | jbd2_journal_abort(journal, err); | 889 | jbd2_journal_abort(journal, err); |
| 891 | 890 | ||
| 891 | WARN_ON_ONCE( | ||
| 892 | atomic_read(&commit_transaction->t_outstanding_credits) < 0); | ||
| 893 | |||
| 892 | /* | 894 | /* |
| 893 | * Now disk caches for filesystem device are flushed so we are safe to | 895 | * Now disk caches for filesystem device are flushed so we are safe to |
| 894 | * erase checkpointed transactions from the log by updating journal | 896 | * erase checkpointed transactions from the log by updating journal |
| @@ -840,6 +840,7 @@ jbd2_journal_get_descriptor_buffer(transaction_t *transaction, int type) · 839 unmodified lines | |||
| 840 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); | 840 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); |
| 841 | if (!bh) | 841 | if (!bh) |
| 842 | return NULL; | 842 | return NULL; |
| 843 | atomic_dec(&transaction->t_outstanding_credits); | ||
| 843 | lock_buffer(bh); | 844 | lock_buffer(bh); |
| 844 | memset(bh->b_data, 0, journal->j_blocksize); | 845 | memset(bh->b_data, 0, journal->j_blocksize); |
| 845 | header = (journal_header_t *)bh->b_data; | 846 | header = (journal_header_t *)bh->b_data; |
| @@ -62,6 +62,17 @@ void jbd2_journal_free_transaction(transaction_t *transaction) · 61 unmodified lines | |||
| 62 | kmem_cache_free(transaction_cache, transaction); | 62 | kmem_cache_free(transaction_cache, transaction); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /* | ||
| 66 | * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for | ||
| 67 | * transaction descriptor blocks. | ||
| 68 | */ | ||
| 69 | #define JBD2_CONTROL_BLOCKS_SHIFT 5 | ||
| 70 | |||
| 71 | static int jbd2_descriptor_blocks_per_trans(journal_t *journal) | ||
| 72 | { | ||
| 73 | return journal->j_max_transaction_buffers >> JBD2_CONTROL_BLOCKS_SHIFT; | ||
| 74 | } | ||
| 75 | |||
| 65 | /* | 76 | /* |
| 66 | * jbd2_get_transaction: obtain a new transaction_t object. | 77 | * jbd2_get_transaction: obtain a new transaction_t object. |
| 67 | * | 78 | * |
| @@ -88,6 +99,7 @@ static void jbd2_get_transaction(journal_t *journal, · 20 unmodified lines | |||
| 88 | spin_lock_init(&transaction->t_handle_lock); | 99 | spin_lock_init(&transaction->t_handle_lock); |
| 89 | atomic_set(&transaction->t_updates, 0); | 100 | atomic_set(&transaction->t_updates, 0); |
| 90 | atomic_set(&transaction->t_outstanding_credits, | 101 | atomic_set(&transaction->t_outstanding_credits, |
| 102 | jbd2_descriptor_blocks_per_trans(journal) + | ||
| 91 | atomic_read(&journal->j_reserved_credits)); | 103 | atomic_read(&journal->j_reserved_credits)); |
| 92 | atomic_set(&transaction->t_handle_count, 0); | 104 | atomic_set(&transaction->t_handle_count, 0); |
| 93 | INIT_LIST_HEAD(&transaction->t_inode_list); | 105 | INIT_LIST_HEAD(&transaction->t_inode_list); |
| @@ -634,14 +646,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) · 540 unmodified lines | |||
| 634 | goto unlock; | 646 | goto unlock; |
| 635 | } | 647 | } |
| 636 | 648 | ||
| 637 | if (wanted + (wanted >> JBD2_CONTROL_BLOCKS_SHIFT) > | ||
| 638 | jbd2_log_space_left(journal)) { | ||
| 639 | jbd_debug(3, "denied handle %p %d blocks: " | ||
| 640 | "insufficient log space\n", handle, nblocks); | ||
| 641 | atomic_sub(nblocks, &transaction->t_outstanding_credits); | ||
| 642 | goto unlock; | ||
| 643 | } | ||
| 644 | |||
| 645 | trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev, | 649 | trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev, |
| 646 | transaction->t_tid, | 650 | transaction->t_tid, |
| 647 | handle->h_type, handle->h_line_no, | 651 | handle->h_type, handle->h_line_no, |
| @@ -681,8 +681,10 @@ struct transaction_s · 680 unmodified lines | |||
| 681 | atomic_t t_updates; | 681 | atomic_t t_updates; |
| 682 | 682 | ||
| 683 | /* | 683 | /* |
| 684 | * Number of buffers reserved for use by all handles in this transaction | 684 | * Number of blocks reserved for this transaction in the journal. |
| 685 | * handle but not yet modified. [none] | 685 | * This is including all credits reserved when starting transaction |
| 686 | * handles as well as all journal descriptor blocks needed for this | ||
| 687 | * transaction. [none] | ||
| 686 | */ | 688 | */ |
| 687 | atomic_t t_outstanding_credits; | 689 | atomic_t t_outstanding_credits; |
| 688 | 690 | ||
| @@ -1560,20 +1562,13 @@ static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) · 871 unmodified lines | |||
| 1560 | return journal->j_chksum_driver != NULL; | 1562 | return journal->j_chksum_driver != NULL; |
| 1561 | } | 1563 | } |
| 1562 | 1564 | ||
| 1563 | /* | ||
| 1564 | * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for | ||
| 1565 | * transaction control blocks. | ||
| 1566 | */ | ||
| 1567 | #define JBD2_CONTROL_BLOCKS_SHIFT 5 | ||
| 1568 | |||
| 1569 | /* | 1565 | /* |
| 1570 | * Return the minimum number of blocks which must be free in the journal | 1566 | * Return the minimum number of blocks which must be free in the journal |
| 1571 | * before a new transaction may be started. Must be called under j_state_lock. | 1567 | * before a new transaction may be started. Must be called under j_state_lock. |
| 1572 | */ | 1568 | */ |
| 1573 | static inline int jbd2_space_needed(journal_t *journal) | 1569 | static inline int jbd2_space_needed(journal_t *journal) |
| 1574 | { | 1570 | { |
| 1575 | int nblocks = journal->j_max_transaction_buffers; | 1571 | return journal->j_max_transaction_buffers; |
| 1576 | return nblocks + (nblocks >> JBD2_CONTROL_BLOCKS_SHIFT); | ||
| 1577 | } | 1572 | } |
| 1578 | 1573 | ||
| 1579 | /* | 1574 | /* |
| @@ -1585,11 +1580,8 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal) · 5 unmodified lines | |||
| 1585 | long free = journal->j_free - 32; | 1580 | long free = journal->j_free - 32; |
| 1586 | 1581 | ||
| 1587 | if (journal->j_committing_transaction) { | 1582 | if (journal->j_committing_transaction) { |
| 1588 | unsigned long committing = atomic_read(&journal-> | 1583 | free -= atomic_read(&journal-> |
| 1589 | j_committing_transaction->t_outstanding_credits); | 1584 | j_committing_transaction->t_outstanding_credits); |
| 1590 | |||
| 1591 | /* Transaction + control blocks */ | ||
| 1592 | free -= committing + (committing >> JBD2_CONTROL_BLOCKS_SHIFT); | ||
| 1593 | } | 1585 | } |
| 1594 | return max_t(long, free, 0); | 1586 | return max_t(long, free, 0); |
| 1595 | } | 1587 | } |