1 ext4: akpm's locking hack to fix locking delays
3 This is a port of the following patch from Andrew Morton to ext4:
5 http://lkml.org/lkml/2008/10/3/22
7 This fixes a major contention problem in do_get_write_access() when a
8 buffer is modified in both the current and committing transaction.
10 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
11 Cc: akpm@linux-foundation.org
12 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
13 index 4880cc3..b1cdd8d 100644
16 @@ -540,6 +540,7 @@ do { \
17 #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */
18 #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */
19 #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */
20 +#define EXT4_MOUNT_AKPM_LOCK_HACK 0x20000000 /* akpm lock hack */
22 /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
23 #ifndef _LINUX_EXT2_FS_H
24 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
25 index 9b2b2bc..faebc2e 100644
28 @@ -693,6 +693,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
29 seq_puts(seq, ",journal_async_commit");
30 if (test_opt(sb, NOBH))
31 seq_puts(seq, ",nobh");
32 + if (test_opt(sb, AKPM_LOCK_HACK))
33 + seq_puts(seq, ",akpm_lock_hack");
34 if (!test_opt(sb, EXTENTS))
35 seq_puts(seq, ",noextents");
36 if (test_opt(sb, I_VERSION))
37 @@ -856,7 +858,7 @@ enum {
38 Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
39 Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
40 Opt_stripe, Opt_delalloc, Opt_nodelalloc,
41 - Opt_inode_readahead_blks
42 + Opt_inode_readahead_blks, Opt_akpm_lock_hack,
45 static const match_table_t tokens = {
46 @@ -916,6 +918,7 @@ static const match_table_t tokens = {
47 {Opt_delalloc, "delalloc"},
48 {Opt_nodelalloc, "nodelalloc"},
49 {Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
50 + {Opt_akpm_lock_hack, "akpm_lock_hack"},
54 @@ -1328,6 +1331,9 @@ set_qf_format:
56 sbi->s_inode_readahead_blks = option;
58 + case Opt_akpm_lock_hack:
59 + set_opt(sbi->s_mount_opt, AKPM_LOCK_HACK);
63 "EXT4-fs: Unrecognized mount option \"%s\" "
64 @@ -2489,6 +2495,10 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
65 journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR;
67 journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR;
68 + if (test_opt(sb, AKPM_LOCK_HACK))
69 + journal->j_flags |= JBD2_LOCK_HACK;
71 + journal->j_flags &= ~JBD2_LOCK_HACK;
72 spin_unlock(&journal->j_state_lock);
75 diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
76 index 648624c..e48c225 100644
77 --- a/fs/jbd2/transaction.c
78 +++ b/fs/jbd2/transaction.c
79 @@ -547,6 +547,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
81 char *frozen_buffer = NULL;
85 if (is_handle_aborted(handle))
87 @@ -562,7 +563,13 @@ repeat:
89 /* @@@ Need to check for errors here at some point. */
92 + if (journal->j_flags & JBD2_LOCK_HACK) {
93 + if (trylock_buffer(bh))
94 + locked = 1; /* lolz */
99 jbd_lock_bh_state(bh);
101 /* We now hold the buffer lock so it is safe to query the buffer
102 @@ -601,7 +608,8 @@ repeat:
103 jbd_unexpected_dirty_buffer(jh);
111 if (is_handle_aborted(handle)) {
112 diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
113 index 09458eb..6131c3c 100644
114 --- a/include/linux/jbd2.h
115 +++ b/include/linux/jbd2.h
116 @@ -979,6 +979,7 @@ struct journal_s
117 #define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file
118 * data write error in ordered
120 +#define JBD2_LOCK_HACK 0x080 /* akpm's locking hack */
123 * Function declarations for the journaling transaction and buffer