1 jbd2: speedup jbd2_journal_dirty_metadata()
3 From: Jan Kara <jack@suse.cz>
5 It is often the case that we mark buffer as having dirty metadata when
6 the buffer is already in that state (frequent for bitmaps, inode table
7 blocks, superblock). Thus it is unnecessary to contend on grabbing
8 journal head reference and bh_state lock. Avoid that by checking whether
9 any modification to the buffer is needed before grabbing any locks or
12 [ Note: this is a fixed version of commit 2143c1965a761, which was
13 reverted in ebeaa8ddb3663b5 due to a false positive triggering of an
14 assertion check. -- Ted ]
16 Signed-off-by: Jan Kara <jack@suse.cz>
17 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
19 fs/jbd2/transaction.c | 38 ++++++++++++++++++++++++++++++++------
20 1 file changed, 32 insertions(+), 6 deletions(-)
22 Ted, this is the speedup patch with fixed assertion. It survived several
23 hours of beating with xfstests generic/269. Ming Lei, can you verify this
24 patch passes testing on your machine as well? Thanks!
26 diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
27 index f3d06174b051..546ce0e76605 100644
28 --- a/fs/jbd2/transaction.c
29 +++ b/fs/jbd2/transaction.c
30 @@ -1280,8 +1280,6 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
31 triggers->t_abort(triggers, jh2bh(jh));
37 * int jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata
38 * @handle: transaction to add buffer to.
39 @@ -1314,12 +1312,41 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
41 if (is_handle_aborted(handle))
43 - journal = transaction->t_journal;
44 - jh = jbd2_journal_grab_journal_head(bh);
46 + if (!buffer_jbd(bh)) {
51 + * We don't grab jh reference here since the buffer must be part
52 + * of the running transaction.
56 + * This and the following assertions are unreliable since we may see jh
57 + * in inconsistent state unless we grab bh_state lock. But this is
58 + * crucial to catch bugs so let's do a reliable check until the
59 + * lockless handling is fully proven.
61 + if (jh->b_transaction != transaction &&
62 + jh->b_next_transaction != transaction) {
63 + jbd_lock_bh_state(bh);
64 + J_ASSERT_JH(jh, jh->b_transaction == transaction ||
65 + jh->b_next_transaction == transaction);
66 + jbd_unlock_bh_state(bh);
68 + if (jh->b_modified == 1) {
69 + /* If it's in our transaction it must be in BJ_Metadata list. */
70 + if (jh->b_transaction == transaction &&
71 + jh->b_jlist != BJ_Metadata) {
72 + jbd_lock_bh_state(bh);
73 + J_ASSERT_JH(jh, jh->b_transaction != transaction ||
74 + jh->b_jlist == BJ_Metadata);
75 + jbd_unlock_bh_state(bh);
80 + journal = transaction->t_journal;
81 jbd_debug(5, "journal_head %p\n", jh);
82 JBUFFER_TRACE(jh, "entry");
84 @@ -1410,7 +1437,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
85 spin_unlock(&journal->j_list_lock);
87 jbd_unlock_bh_state(bh);
88 - jbd2_journal_put_journal_head(jh);
90 JBUFFER_TRACE(jh, "exit");