update and add new version of speedup-jbd2_journal_dirty_metadata
[ext4-patch-queue.git] / speedup-jbd2_journal_dirty_metadata
blob36d164ea029d3f440a51e6b676410c8b15ccce36
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
10 references.
12 Signed-off-by: Jan Kara <jack@suse.cz>
13 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
14 ---
15  fs/jbd2/transaction.c | 33 +++++++++++++++++++++++++++------
16  1 file changed, 27 insertions(+), 6 deletions(-)
18 diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
19 index a91f639af6c3..5887c880422b 100644
20 --- a/fs/jbd2/transaction.c
21 +++ b/fs/jbd2/transaction.c
22 @@ -1290,8 +1290,6 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
23         triggers->t_abort(triggers, jh2bh(jh));
24  }
28  /**
29   * int jbd2_journal_dirty_metadata() -  mark a buffer as containing dirty metadata
30   * @handle: transaction to add buffer to.
31 @@ -1325,12 +1323,36 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
32         WARN_ON(!transaction);
33         if (is_handle_aborted(handle))
34                 return -EROFS;
35 -       journal = transaction->t_journal;
36 -       jh = jbd2_journal_grab_journal_head(bh);
37 -       if (!jh) {
38 +       if (!buffer_jbd(bh)) {
39                 ret = -EUCLEAN;
40                 goto out;
41         }
42 +       /*
43 +        * We don't grab jh reference here since the buffer must be part
44 +        * of the running transaction.
45 +        */
46 +       jh = bh2jh(bh);
47 +       J_ASSERT_JH(jh, jh->b_transaction == transaction ||
48 +                       jh->b_next_transaction == transaction);
49 +       if (jh->b_modified == 1) {
50 +               /*
51 +                * If it's in our transaction it must be in BJ_Metadata list.
52 +                * The assertion is unreliable since we may see jh in
53 +                * inconsistent state unless we grab bh_state lock. But this
54 +                * is crutial to catch bugs so let's do a reliable check until
55 +                * the lockless handling is fully proven.
56 +                */
57 +               if (jh->b_transaction == transaction &&
58 +                   jh->b_jlist != BJ_Metadata) {
59 +                       jbd_lock_bh_state(bh);
60 +                       J_ASSERT_JH(jh, jh->b_transaction != transaction ||
61 +                                       jh->b_jlist == BJ_Metadata);
62 +                       jbd_unlock_bh_state(bh);
63 +               }
64 +               goto out;
65 +       }
67 +       journal = transaction->t_journal;
68         jbd_debug(5, "journal_head %p\n", jh);
69         JBUFFER_TRACE(jh, "entry");
71 @@ -1421,7 +1443,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
72         spin_unlock(&journal->j_list_lock);
73  out_unlock_bh:
74         jbd_unlock_bh_state(bh);
75 -       jbd2_journal_put_journal_head(jh);
76  out:
77         JBUFFER_TRACE(jh, "exit");
78         return ret;
79 -- 
80 2.1.4