Add cc: stable to revert-remove-block_device_ejected
[ext4-patch-queue.git] / speedup-jbd2_journal_dirty_metadata
blob943e517472986cbc4c82289846df85883cbb7c17
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 [ 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>
18 ---
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));
32  }
36  /**
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))
42                 return -EROFS;
43 -       journal = transaction->t_journal;
44 -       jh = jbd2_journal_grab_journal_head(bh);
45 -       if (!jh) {
46 +       if (!buffer_jbd(bh)) {
47                 ret = -EUCLEAN;
48                 goto out;
49         }
50 +       /*
51 +        * We don't grab jh reference here since the buffer must be part
52 +        * of the running transaction.
53 +        */
54 +       jh = bh2jh(bh);
55 +       /*
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.
60 +        */
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);
67 +       }
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);
76 +               }
77 +               goto out;
78 +       }
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);
86  out_unlock_bh:
87         jbd_unlock_bh_state(bh);
88 -       jbd2_journal_put_journal_head(jh);
89  out:
90         JBUFFER_TRACE(jh, "exit");
91         return ret;
92 -- 
93 2.1.4