add patch return-EFSBADCRC-on-csum-error-in-ext4_find_entry
[ext4-patch-queue.git] / add-nombcache-mount-option
blobc6dcf82770d3defa64f99eb74d992c7801bcb0d6
1 ext4: add nombcache mount option
3 From: Tahsin Erdogan <tahsin@google.com>
5 The main purpose of mb cache is to achieve deduplication in
6 extended attributes. In use cases where opportunity for deduplication
7 is unlikely, it only adds overhead.
9 Add a mount option to explicitly turn off mb cache.
11 Suggested-by: Andreas Dilger <adilger@dilger.ca>
12 Signed-off-by: Tahsin Erdogan <tahsin@google.com>
13 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
14 ---
15 v2:
16  - updated definition of EXT4_MOUNT_NO_MBCACHE to be 0x00001
18  fs/ext4/ext4.h  |  1 +
19  fs/ext4/super.c | 34 +++++++++++++++++++++++-----------
20  fs/ext4/xattr.c | 52 +++++++++++++++++++++++++++++++++++-----------------
21  3 files changed, 59 insertions(+), 28 deletions(-)
23 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
24 index dc06287ddec8..7d66e1dade45 100644
25 --- a/fs/ext4/ext4.h
26 +++ b/fs/ext4/ext4.h
27 @@ -1114,6 +1114,7 @@ struct ext4_inode_info {
28  /*
29   * Mount flags set via mount options or defaults
30   */
31 +#define EXT4_MOUNT_NO_MBCACHE          0x00001 /* Do not use mbcache */
32  #define EXT4_MOUNT_GRPID               0x00004 /* Create files with directory's group */
33  #define EXT4_MOUNT_DEBUG               0x00008 /* Some debugging messages */
34  #define EXT4_MOUNT_ERRORS_CONT         0x00010 /* Continue on errors */
35 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
36 index 5ac76e8d4013..1fec35bd4084 100644
37 --- a/fs/ext4/super.c
38 +++ b/fs/ext4/super.c
39 @@ -1336,7 +1336,7 @@ enum {
40         Opt_inode_readahead_blks, Opt_journal_ioprio,
41         Opt_dioread_nolock, Opt_dioread_lock,
42         Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
43 -       Opt_max_dir_size_kb, Opt_nojournal_checksum,
44 +       Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
45  };
47  static const match_table_t tokens = {
48 @@ -1419,6 +1419,8 @@ static const match_table_t tokens = {
49         {Opt_noinit_itable, "noinit_itable"},
50         {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
51         {Opt_test_dummy_encryption, "test_dummy_encryption"},
52 +       {Opt_nombcache, "nombcache"},
53 +       {Opt_nombcache, "no_mbcache"},  /* for backward compatibility */
54         {Opt_removed, "check=none"},    /* mount option from ext2/3 */
55         {Opt_removed, "nocheck"},       /* mount option from ext2/3 */
56         {Opt_removed, "reservation"},   /* mount option from ext2/3 */
57 @@ -1626,6 +1628,7 @@ static const struct mount_opts {
58         {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
59         {Opt_max_dir_size_kb, 0, MOPT_GTE0},
60         {Opt_test_dummy_encryption, 0, MOPT_GTE0},
61 +       {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
62         {Opt_err, 0, 0}
63  };
65 @@ -4080,19 +4083,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
66         sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
68  no_journal:
69 -       sbi->s_ea_block_cache = ext4_xattr_create_cache();
70 -       if (!sbi->s_ea_block_cache) {
71 -               ext4_msg(sb, KERN_ERR, "Failed to create ea_block_cache");
72 -               goto failed_mount_wq;
73 -       }
75 -       if (ext4_has_feature_ea_inode(sb)) {
76 -               sbi->s_ea_inode_cache = ext4_xattr_create_cache();
77 -               if (!sbi->s_ea_inode_cache) {
78 +       if (!test_opt(sb, NO_MBCACHE)) {
79 +               sbi->s_ea_block_cache = ext4_xattr_create_cache();
80 +               if (!sbi->s_ea_block_cache) {
81                         ext4_msg(sb, KERN_ERR,
82 -                                "Failed to create ea_inode_cache");
83 +                                "Failed to create ea_block_cache");
84                         goto failed_mount_wq;
85                 }
87 +               if (ext4_has_feature_ea_inode(sb)) {
88 +                       sbi->s_ea_inode_cache = ext4_xattr_create_cache();
89 +                       if (!sbi->s_ea_inode_cache) {
90 +                               ext4_msg(sb, KERN_ERR,
91 +                                        "Failed to create ea_inode_cache");
92 +                               goto failed_mount_wq;
93 +                       }
94 +               }
95         }
97         if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) &&
98 @@ -4989,6 +4995,12 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
99                 }
100         }
102 +       if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_NO_MBCACHE) {
103 +               ext4_msg(sb, KERN_ERR, "can't enable nombcache during remount");
104 +               err = -EINVAL;
105 +               goto restore_opts;
106 +       }
108         if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX) {
109                 ext4_msg(sb, KERN_WARNING, "warning: refusing change of "
110                         "dax flag with busy inodes while remounting");
111 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
112 index 3f16dc979012..ce12c3fb7e59 100644
113 --- a/fs/ext4/xattr.c
114 +++ b/fs/ext4/xattr.c
115 @@ -976,10 +976,13 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
116                         set_nlink(ea_inode, 1);
117                         ext4_orphan_del(handle, ea_inode);
119 -                       hash = ext4_xattr_inode_get_hash(ea_inode);
120 -                       mb_cache_entry_create(ea_inode_cache, GFP_NOFS, hash,
121 -                                             ea_inode->i_ino,
122 -                                             true /* reusable */);
123 +                       if (ea_inode_cache) {
124 +                               hash = ext4_xattr_inode_get_hash(ea_inode);
125 +                               mb_cache_entry_create(ea_inode_cache,
126 +                                                     GFP_NOFS, hash,
127 +                                                     ea_inode->i_ino,
128 +                                                     true /* reusable */);
129 +                       }
130                 }
131         } else {
132                 WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld",
133 @@ -993,9 +996,11 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
134                         clear_nlink(ea_inode);
135                         ext4_orphan_add(handle, ea_inode);
137 -                       hash = ext4_xattr_inode_get_hash(ea_inode);
138 -                       mb_cache_entry_delete(ea_inode_cache, hash,
139 -                                             ea_inode->i_ino);
140 +                       if (ea_inode_cache) {
141 +                               hash = ext4_xattr_inode_get_hash(ea_inode);
142 +                               mb_cache_entry_delete(ea_inode_cache, hash,
143 +                                                     ea_inode->i_ino);
144 +                       }
145                 }
146         }
148 @@ -1179,7 +1184,9 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
149                  * This must happen under buffer lock for
150                  * ext4_xattr_block_set() to reliably detect freed block
151                  */
152 -               mb_cache_entry_delete(ea_block_cache, hash, bh->b_blocknr);
153 +               if (ea_block_cache)
154 +                       mb_cache_entry_delete(ea_block_cache, hash,
155 +                                             bh->b_blocknr);
156                 get_bh(bh);
157                 unlock_buffer(bh);
159 @@ -1199,11 +1206,13 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
160                 if (ref == EXT4_XATTR_REFCOUNT_MAX - 1) {
161                         struct mb_cache_entry *ce;
163 -                       ce = mb_cache_entry_get(ea_block_cache, hash,
164 -                                               bh->b_blocknr);
165 -                       if (ce) {
166 -                               ce->e_reusable = 1;
167 -                               mb_cache_entry_put(ea_block_cache, ce);
168 +                       if (ea_block_cache) {
169 +                               ce = mb_cache_entry_get(ea_block_cache, hash,
170 +                                                       bh->b_blocknr);
171 +                               if (ce) {
172 +                                       ce->e_reusable = 1;
173 +                                       mb_cache_entry_put(ea_block_cache, ce);
174 +                               }
175                         }
176                 }
178 @@ -1382,6 +1391,9 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
179         struct mb_cache *ea_inode_cache = EA_INODE_CACHE(inode);
180         void *ea_data;
182 +       if (!ea_inode_cache)
183 +               return NULL;
185         ce = mb_cache_entry_find_first(ea_inode_cache, hash);
186         if (!ce)
187                 return NULL;
188 @@ -1452,8 +1464,9 @@ static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode,
189                 return err;
190         }
192 -       mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash,
193 -                             ea_inode->i_ino, true /* reusable */);
194 +       if (EA_INODE_CACHE(inode))
195 +               mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash,
196 +                                     ea_inode->i_ino, true /* reusable */);
198         *ret_inode = ea_inode;
199         return 0;
200 @@ -1780,8 +1793,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
201                          * ext4_xattr_block_set() to reliably detect modified
202                          * block
203                          */
204 -                       mb_cache_entry_delete(ea_block_cache, hash,
205 -                                             bs->bh->b_blocknr);
206 +                       if (ea_block_cache)
207 +                               mb_cache_entry_delete(ea_block_cache, hash,
208 +                                                     bs->bh->b_blocknr);
209                         ea_bdebug(bs->bh, "modifying in-place");
210                         error = ext4_xattr_set_entry(i, s, handle, inode,
211                                                      true /* is_block */);
212 @@ -2870,6 +2884,8 @@ ext4_xattr_block_cache_insert(struct mb_cache *ea_block_cache,
213                        EXT4_XATTR_REFCOUNT_MAX;
214         int error;
216 +       if (!ea_block_cache)
217 +               return;
218         error = mb_cache_entry_create(ea_block_cache, GFP_NOFS, hash,
219                                       bh->b_blocknr, reusable);
220         if (error) {
221 @@ -2936,6 +2952,8 @@ ext4_xattr_block_cache_find(struct inode *inode,
222         struct mb_cache_entry *ce;
223         struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
225 +       if (!ea_block_cache)
226 +               return NULL;
227         if (!header->h_hash)
228                 return NULL;  /* never share */
229         ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
230 -- 
231 2.13.1.611.g7e3b11ae1-goog