]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.32.17/0013-ext4-Use-bitops-to-read-modify-EXT4_I-inode-i_state.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.17 / 0013-ext4-Use-bitops-to-read-modify-EXT4_I-inode-i_state.patch
CommitLineData
7d777456
GKH
1From f7ae767b11e7ac054c5f8de55e5a83ec7c60c6a0 Mon Sep 17 00:00:00 2001
2From: Theodore Ts'o <tytso@mit.edu>
3Date: Sun, 30 May 2010 22:49:27 -0400
4Subject: ext4: Use bitops to read/modify EXT4_I(inode)->i_state
5
6commit 19f5fb7ad679bb361222c7916086435020c37cce upstream (as of v2.6.33-git11)
7
8At several places we modify EXT4_I(inode)->i_state without holding
9i_mutex (ext4_release_file, ext4_bmap, ext4_journalled_writepage,
10ext4_do_update_inode, ...). These modifications are racy and we can
11lose updates to i_state. So convert handling of i_state to use bitops
12which are atomic.
13
14Cc: Jan Kara <jack@suse.cz>
15Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
16Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
17---
18 fs/ext4/ext4.h | 41 +++++++++++++++++++++++++++++------------
19 fs/ext4/extents.c | 8 ++++----
20 fs/ext4/file.c | 4 ++--
21 fs/ext4/ialloc.c | 3 ++-
22 fs/ext4/inode.c | 38 ++++++++++++++++++++------------------
23 fs/ext4/migrate.c | 6 +++---
24 fs/ext4/xattr.c | 22 +++++++++++-----------
25 7 files changed, 71 insertions(+), 51 deletions(-)
26
27--- a/fs/ext4/ext4.h
28+++ b/fs/ext4/ext4.h
29@@ -313,17 +313,6 @@ static inline __u32 ext4_mask_flags(umod
30 return flags & EXT4_OTHER_FLMASK;
31 }
32
33-/*
34- * Inode dynamic state flags
35- */
36-#define EXT4_STATE_JDATA 0x00000001 /* journaled data exists */
37-#define EXT4_STATE_NEW 0x00000002 /* inode is newly created */
38-#define EXT4_STATE_XATTR 0x00000004 /* has in-inode xattrs */
39-#define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */
40-#define EXT4_STATE_DA_ALLOC_CLOSE 0x00000010 /* Alloc DA blks on close */
41-#define EXT4_STATE_EXT_MIGRATE 0x00000020 /* Inode is migrating */
42-#define EXT4_STATE_DIO_UNWRITTEN 0x00000040 /* need convert on dio done*/
43-
44 /* Used to pass group descriptor data when online resize is done */
45 struct ext4_new_group_input {
46 __u32 group; /* Group number for this data */
47@@ -624,7 +613,7 @@ struct ext4_inode_info {
48 * near to their parent directory's inode.
49 */
50 ext4_group_t i_block_group;
51- __u32 i_state; /* Dynamic state flags for ext4 */
52+ unsigned long i_state_flags; /* Dynamic state flags */
53
54 ext4_lblk_t i_dir_start_lookup;
55 #ifdef CONFIG_EXT4_FS_XATTR
56@@ -1044,6 +1033,34 @@ static inline int ext4_valid_inum(struct
57 (ino >= EXT4_FIRST_INO(sb) &&
58 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
59 }
60+
61+/*
62+ * Inode dynamic state flags
63+ */
64+enum {
65+ EXT4_STATE_JDATA, /* journaled data exists */
66+ EXT4_STATE_NEW, /* inode is newly created */
67+ EXT4_STATE_XATTR, /* has in-inode xattrs */
68+ EXT4_STATE_NO_EXPAND, /* No space for expansion */
69+ EXT4_STATE_DA_ALLOC_CLOSE, /* Alloc DA blks on close */
70+ EXT4_STATE_EXT_MIGRATE, /* Inode is migrating */
71+ EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/
72+};
73+
74+static inline int ext4_test_inode_state(struct inode *inode, int bit)
75+{
76+ return test_bit(bit, &EXT4_I(inode)->i_state_flags);
77+}
78+
79+static inline void ext4_set_inode_state(struct inode *inode, int bit)
80+{
81+ set_bit(bit, &EXT4_I(inode)->i_state_flags);
82+}
83+
84+static inline void ext4_clear_inode_state(struct inode *inode, int bit)
85+{
86+ clear_bit(bit, &EXT4_I(inode)->i_state_flags);
87+}
88 #else
89 /* Assume that user mode programs are passing in an ext4fs superblock, not
90 * a kernel struct super_block. This will allow us to call the feature-test
91--- a/fs/ext4/extents.c
92+++ b/fs/ext4/extents.c
93@@ -3082,7 +3082,7 @@ ext4_ext_handle_uninitialized_extents(ha
94 if (io)
95 io->flag = DIO_AIO_UNWRITTEN;
96 else
97- EXT4_I(inode)->i_state |= EXT4_STATE_DIO_UNWRITTEN;
98+ ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
99 goto out;
100 }
101 /* async DIO end_io complete, convert the filled extent to written */
102@@ -3368,8 +3368,8 @@ int ext4_ext_get_blocks(handle_t *handle
103 if (io)
104 io->flag = DIO_AIO_UNWRITTEN;
105 else
106- EXT4_I(inode)->i_state |=
107- EXT4_STATE_DIO_UNWRITTEN;;
108+ ext4_set_inode_state(inode,
109+ EXT4_STATE_DIO_UNWRITTEN);
110 }
111 }
112 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
113@@ -3745,7 +3745,7 @@ static int ext4_xattr_fiemap(struct inod
114 int error = 0;
115
116 /* in-inode? */
117- if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
118+ if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
119 struct ext4_iloc iloc;
120 int offset; /* offset of xattr in inode */
121
122--- a/fs/ext4/file.c
123+++ b/fs/ext4/file.c
124@@ -35,9 +35,9 @@
125 */
126 static int ext4_release_file(struct inode *inode, struct file *filp)
127 {
128- if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
129+ if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) {
130 ext4_alloc_da_blocks(inode);
131- EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
132+ ext4_clear_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
133 }
134 /* if we are the last writer on the inode, drop the block reservation */
135 if ((filp->f_mode & FMODE_WRITE) &&
136--- a/fs/ext4/ialloc.c
137+++ b/fs/ext4/ialloc.c
138@@ -1029,7 +1029,8 @@ got:
139 inode->i_generation = sbi->s_next_generation++;
140 spin_unlock(&sbi->s_next_gen_lock);
141
142- ei->i_state = EXT4_STATE_NEW;
143+ ei->i_state_flags = 0;
144+ ext4_set_inode_state(inode, EXT4_STATE_NEW);
145
146 ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
147
148--- a/fs/ext4/inode.c
149+++ b/fs/ext4/inode.c
150@@ -1348,7 +1348,7 @@ int ext4_get_blocks(handle_t *handle, st
151 * i_data's format changing. Force the migrate
152 * to fail by clearing migrate flags
153 */
154- EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
155+ ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
156 }
157
158 /*
159@@ -1835,7 +1835,7 @@ static int ext4_journalled_write_end(str
160 new_i_size = pos + copied;
161 if (new_i_size > inode->i_size)
162 i_size_write(inode, pos+copied);
163- EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
164+ ext4_set_inode_state(inode, EXT4_STATE_JDATA);
165 if (new_i_size > EXT4_I(inode)->i_disksize) {
166 ext4_update_i_disksize(inode, new_i_size);
167 ret2 = ext4_mark_inode_dirty(handle, inode);
168@@ -2673,7 +2673,7 @@ static int __ext4_journalled_writepage(s
169 ret = err;
170
171 walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
172- EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
173+ ext4_set_inode_state(inode, EXT4_STATE_JDATA);
174 out:
175 return ret;
176 }
177@@ -3344,7 +3344,8 @@ static sector_t ext4_bmap(struct address
178 filemap_write_and_wait(mapping);
179 }
180
181- if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) {
182+ if (EXT4_JOURNAL(inode) &&
183+ ext4_test_inode_state(inode, EXT4_STATE_JDATA)) {
184 /*
185 * This is a REALLY heavyweight approach, but the use of
186 * bmap on dirty files is expected to be extremely rare:
187@@ -3363,7 +3364,7 @@ static sector_t ext4_bmap(struct address
188 * everything they get.
189 */
190
191- EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA;
192+ ext4_clear_inode_state(inode, EXT4_STATE_JDATA);
193 journal = EXT4_JOURNAL(inode);
194 jbd2_journal_lock_updates(journal);
195 err = jbd2_journal_flush(journal);
196@@ -3831,8 +3832,8 @@ static ssize_t ext4_ext_direct_IO(int rw
197 if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
198 ext4_free_io_end(iocb->private);
199 iocb->private = NULL;
200- } else if (ret > 0 && (EXT4_I(inode)->i_state &
201- EXT4_STATE_DIO_UNWRITTEN)) {
202+ } else if (ret > 0 && ext4_test_inode_state(inode,
203+ EXT4_STATE_DIO_UNWRITTEN)) {
204 int err;
205 /*
206 * for non AIO case, since the IO is already
207@@ -3842,7 +3843,7 @@ static ssize_t ext4_ext_direct_IO(int rw
208 offset, ret);
209 if (err < 0)
210 ret = err;
211- EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN;
212+ ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
213 }
214 return ret;
215 }
216@@ -4490,7 +4491,7 @@ void ext4_truncate(struct inode *inode)
217 return;
218
219 if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
220- ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
221+ ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
222
223 if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
224 ext4_ext_truncate(inode);
225@@ -4776,7 +4777,7 @@ int ext4_get_inode_loc(struct inode *ino
226 {
227 /* We have all inode data except xattrs in memory here. */
228 return __ext4_get_inode_loc(inode, iloc,
229- !(EXT4_I(inode)->i_state & EXT4_STATE_XATTR));
230+ !ext4_test_inode_state(inode, EXT4_STATE_XATTR));
231 }
232
233 void ext4_set_inode_flags(struct inode *inode)
234@@ -4870,7 +4871,7 @@ struct inode *ext4_iget(struct super_blo
235 }
236 inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
237
238- ei->i_state = 0;
239+ ei->i_state_flags = 0;
240 ei->i_dir_start_lookup = 0;
241 ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
242 /* We now have enough fields to check if the inode was active or not.
243@@ -4953,7 +4954,7 @@ struct inode *ext4_iget(struct super_blo
244 EXT4_GOOD_OLD_INODE_SIZE +
245 ei->i_extra_isize;
246 if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
247- ei->i_state |= EXT4_STATE_XATTR;
248+ ext4_set_inode_state(inode, EXT4_STATE_XATTR);
249 }
250 } else
251 ei->i_extra_isize = 0;
252@@ -5093,7 +5094,7 @@ static int ext4_do_update_inode(handle_t
253
254 /* For fields not not tracking in the in-memory inode,
255 * initialise them to zero for new inodes. */
256- if (ei->i_state & EXT4_STATE_NEW)
257+ if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
258 memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
259
260 ext4_get_inode_flags(ei);
261@@ -5189,7 +5190,7 @@ static int ext4_do_update_inode(handle_t
262 rc = ext4_handle_dirty_metadata(handle, inode, bh);
263 if (!err)
264 err = rc;
265- ei->i_state &= ~EXT4_STATE_NEW;
266+ ext4_clear_inode_state(inode, EXT4_STATE_NEW);
267
268 ext4_update_inode_fsync_trans(handle, inode, 0);
269 out_brelse:
270@@ -5613,8 +5614,8 @@ static int ext4_expand_extra_isize(struc
271 entry = IFIRST(header);
272
273 /* No extended attributes present */
274- if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR) ||
275- header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
276+ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
277+ header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
278 memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
279 new_extra_isize);
280 EXT4_I(inode)->i_extra_isize = new_extra_isize;
281@@ -5658,7 +5659,7 @@ int ext4_mark_inode_dirty(handle_t *hand
282 err = ext4_reserve_inode_write(handle, inode, &iloc);
283 if (ext4_handle_valid(handle) &&
284 EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
285- !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) {
286+ !ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
287 /*
288 * We need extra buffer credits since we may write into EA block
289 * with this same handle. If journal_extend fails, then it will
290@@ -5672,7 +5673,8 @@ int ext4_mark_inode_dirty(handle_t *hand
291 sbi->s_want_extra_isize,
292 iloc, handle);
293 if (ret) {
294- EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
295+ ext4_set_inode_state(inode,
296+ EXT4_STATE_NO_EXPAND);
297 if (mnt_count !=
298 le16_to_cpu(sbi->s_es->s_mnt_count)) {
299 ext4_warning(inode->i_sb, __func__,
300--- a/fs/ext4/migrate.c
301+++ b/fs/ext4/migrate.c
302@@ -357,12 +357,12 @@ static int ext4_ext_swap_inode_data(hand
303 * happened after we started the migrate. We need to
304 * fail the migrate
305 */
306- if (!(EXT4_I(inode)->i_state & EXT4_STATE_EXT_MIGRATE)) {
307+ if (!ext4_test_inode_state(inode, EXT4_STATE_EXT_MIGRATE)) {
308 retval = -EAGAIN;
309 up_write(&EXT4_I(inode)->i_data_sem);
310 goto err_out;
311 } else
312- EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
313+ ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
314 /*
315 * We have the extent map build with the tmp inode.
316 * Now copy the i_data across
317@@ -524,7 +524,7 @@ int ext4_ext_migrate(struct inode *inode
318 * allocation.
319 */
320 down_read((&EXT4_I(inode)->i_data_sem));
321- EXT4_I(inode)->i_state |= EXT4_STATE_EXT_MIGRATE;
322+ ext4_set_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
323 up_read((&EXT4_I(inode)->i_data_sem));
324
325 handle = ext4_journal_start(inode, 1);
326--- a/fs/ext4/xattr.c
327+++ b/fs/ext4/xattr.c
328@@ -267,7 +267,7 @@ ext4_xattr_ibody_get(struct inode *inode
329 void *end;
330 int error;
331
332- if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
333+ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
334 return -ENODATA;
335 error = ext4_get_inode_loc(inode, &iloc);
336 if (error)
337@@ -393,7 +393,7 @@ ext4_xattr_ibody_list(struct inode *inod
338 void *end;
339 int error;
340
341- if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
342+ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
343 return 0;
344 error = ext4_get_inode_loc(inode, &iloc);
345 if (error)
346@@ -903,7 +903,7 @@ ext4_xattr_ibody_find(struct inode *inod
347 is->s.base = is->s.first = IFIRST(header);
348 is->s.here = is->s.first;
349 is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
350- if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
351+ if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
352 error = ext4_xattr_check_names(IFIRST(header), is->s.end);
353 if (error)
354 return error;
355@@ -935,10 +935,10 @@ ext4_xattr_ibody_set(handle_t *handle, s
356 header = IHDR(inode, ext4_raw_inode(&is->iloc));
357 if (!IS_LAST_ENTRY(s->first)) {
358 header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
359- EXT4_I(inode)->i_state |= EXT4_STATE_XATTR;
360+ ext4_set_inode_state(inode, EXT4_STATE_XATTR);
361 } else {
362 header->h_magic = cpu_to_le32(0);
363- EXT4_I(inode)->i_state &= ~EXT4_STATE_XATTR;
364+ ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
365 }
366 return 0;
367 }
368@@ -981,8 +981,8 @@ ext4_xattr_set_handle(handle_t *handle,
369 if (strlen(name) > 255)
370 return -ERANGE;
371 down_write(&EXT4_I(inode)->xattr_sem);
372- no_expand = EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND;
373- EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
374+ no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
375+ ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
376
377 error = ext4_get_inode_loc(inode, &is.iloc);
378 if (error)
379@@ -992,10 +992,10 @@ ext4_xattr_set_handle(handle_t *handle,
380 if (error)
381 goto cleanup;
382
383- if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) {
384+ if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) {
385 struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
386 memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
387- EXT4_I(inode)->i_state &= ~EXT4_STATE_NEW;
388+ ext4_clear_inode_state(inode, EXT4_STATE_NEW);
389 }
390
391 error = ext4_xattr_ibody_find(inode, &i, &is);
392@@ -1047,7 +1047,7 @@ ext4_xattr_set_handle(handle_t *handle,
393 ext4_xattr_update_super_block(handle, inode->i_sb);
394 inode->i_ctime = ext4_current_time(inode);
395 if (!value)
396- EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
397+ ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
398 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
399 /*
400 * The bh is consumed by ext4_mark_iloc_dirty, even with
401@@ -1062,7 +1062,7 @@ cleanup:
402 brelse(is.iloc.bh);
403 brelse(bs.bh);
404 if (no_expand == 0)
405- EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
406+ ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
407 up_write(&EXT4_I(inode)->xattr_sem);
408 return error;
409 }