Add patch SR-ext4-resize-mark-new-group-EXT_BG_INODE_ZEROED.patch
[ext4-patch-queue/an.git] / akpm-jbd2-locking-fix
blob7ba3408de44e6997e3131f336cd616b456b43ae7
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
14 --- a/fs/ext4/ext4.h
15 +++ b/fs/ext4/ext4.h
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
26 --- a/fs/ext4/super.c
27 +++ b/fs/ext4/super.c
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,
43  };
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"},
51         {Opt_err, NULL},
52  };
54 @@ -1328,6 +1331,9 @@ set_qf_format:
55                                 return 0;
56                         sbi->s_inode_readahead_blks = option;
57                         break;
58 +               case Opt_akpm_lock_hack:
59 +                       set_opt(sbi->s_mount_opt, AKPM_LOCK_HACK);
60 +                       break;
61                 default:
62                         printk(KERN_ERR
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;
66         else
67                 journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR;
68 +       if (test_opt(sb, AKPM_LOCK_HACK))
69 +               journal->j_flags |= JBD2_LOCK_HACK;
70 +       else
71 +               journal->j_flags &= ~JBD2_LOCK_HACK;
72         spin_unlock(&journal->j_state_lock);
73  }
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,
80         int error;
81         char *frozen_buffer = NULL;
82         int need_copy = 0;
83 +       int locked = 0;
85         if (is_handle_aborted(handle))
86                 return -EROFS;
87 @@ -562,7 +563,13 @@ repeat:
89         /* @@@ Need to check for errors here at some point. */
91 -       lock_buffer(bh);
92 +       if (journal->j_flags & JBD2_LOCK_HACK) {
93 +               if (trylock_buffer(bh))
94 +                       locked = 1;     /* lolz */
95 +       } else {
96 +               lock_buffer(bh);
97 +               locked = 1;
98 +       }
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);
104         }
106 -       unlock_buffer(bh);
107 +       if (locked)
108 +               unlock_buffer(bh);
110         error = -EROFS;
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
119                                                  * mode */
120 +#define JBD2_LOCK_HACK 0x080   /* akpm's locking hack */
122  /*
123   * Function declarations for the journaling transaction and buffer