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 | 560 | stats.run.rs_logging = jiffies; |
| 561 | 561 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, |
| 562 | 562 | stats.run.rs_logging); |
| 563 | − stats.run.rs_blocks = | |
| 564 | − atomic_read(&commit_transaction->t_outstanding_credits); | |
| 563 | + stats.run.rs_blocks = commit_transaction->t_nr_buffers; | |
| 565 | 564 | stats.run.rs_blocks_logged = 0; |
| 566 | 565 | |
| 567 | 566 | J_ASSERT(commit_transaction->t_nr_buffers <= |
| @@ -889,6 +888,9 @@ start_journal_io: · 321 unmodified lines | ||
| 889 | 888 | if (err) |
| 890 | 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 | 895 | * Now disk caches for filesystem device are flushed so we are safe to |
| 894 | 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 | 840 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); |
| 841 | 841 | if (!bh) |
| 842 | 842 | return NULL; |
| 843 | + atomic_dec(&transaction->t_outstanding_credits); | |
| 843 | 844 | lock_buffer(bh); |
| 844 | 845 | memset(bh->b_data, 0, journal->j_blocksize); |
| 845 | 846 | header = (journal_header_t *)bh->b_data; |
| @@ -62,6 +62,17 @@ void jbd2_journal_free_transaction(transaction_t *transaction) · 61 unmodified lines | ||
| 62 | 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 | 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 | 99 | spin_lock_init(&transaction->t_handle_lock); |
| 89 | 100 | atomic_set(&transaction->t_updates, 0); |
| 90 | 101 | atomic_set(&transaction->t_outstanding_credits, |
| 102 | + jbd2_descriptor_blocks_per_trans(journal) + | |
| 91 | 103 | atomic_read(&journal->j_reserved_credits)); |
| 92 | 104 | atomic_set(&transaction->t_handle_count, 0); |
| 93 | 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 | 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 | 649 | trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev, |
| 646 | 650 | transaction->t_tid, |
| 647 | 651 | handle->h_type, handle->h_line_no, |
| @@ -681,8 +681,10 @@ struct transaction_s · 680 unmodified lines | ||
| 681 | 681 | atomic_t t_updates; |
| 682 | 682 | |
| 683 | 683 | /* |
| 684 | − * Number of buffers reserved for use by all handles in this transaction | |
| 685 | − * handle but not yet modified. [none] | |
| 684 | + * Number of blocks reserved for this transaction in the journal. | |
| 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 | 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 | 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 | 1566 | * Return the minimum number of blocks which must be free in the journal |
| 1571 | 1567 | * before a new transaction may be started. Must be called under j_state_lock. |
| 1572 | 1568 | */ |
| 1573 | 1569 | static inline int jbd2_space_needed(journal_t *journal) |
| 1574 | 1570 | { |
| 1575 | − int nblocks = journal->j_max_transaction_buffers; | |
| 1576 | − return nblocks + (nblocks >> JBD2_CONTROL_BLOCKS_SHIFT); | |
| 1571 | + return journal->j_max_transaction_buffers; | |
| 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 | 1580 | long free = journal->j_free - 32; |
| 1586 | 1581 | |
| 1587 | 1582 | if (journal->j_committing_transaction) { |
| 1588 | − unsigned long committing = atomic_read(&journal-> | |
| 1589 | − j_committing_transaction->t_outstanding_credits); | |
| 1590 | − | |
| 1591 | − /* Transaction + control blocks */ | |
| 1592 | − free -= committing + (committing >> JBD2_CONTROL_BLOCKS_SHIFT); | |
| 1583 | + free -= atomic_read(&journal-> | |
| 1584 | + j_committing_transaction->t_outstanding_credits); | |
| 1593 | 1585 | } |
| 1594 | 1586 | return max_t(long, free, 0); |
| 1595 | 1587 | } |