aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2010-01-24 14:34:07 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-01-24 14:34:07 -0500
commit19f5fb7ad679bb361222c7916086435020c37cce (patch)
tree9e301163075c4faaf340cf50afd51855c76acd8c /fs/ext4/inode.c
parentd2eecb03936878ec574ade5532fa83df7d75dde7 (diff)
ext4: Use bitops to read/modify EXT4_I(inode)->i_state
At several places we modify EXT4_I(inode)->i_state without holding i_mutex (ext4_release_file, ext4_bmap, ext4_journalled_writepage, ext4_do_update_inode, ...). These modifications are racy and we can lose updates to i_state. So convert handling of i_state to use bitops which are atomic. Cc: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1a3d7b232cd7..3e530119d7f0 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1307,7 +1307,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
1307 * i_data's format changing. Force the migrate 1307 * i_data's format changing. Force the migrate
1308 * to fail by clearing migrate flags 1308 * to fail by clearing migrate flags
1309 */ 1309 */
1310 EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE; 1310 ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
1311 } 1311 }
1312 1312
1313 /* 1313 /*
@@ -1794,7 +1794,7 @@ static int ext4_journalled_write_end(struct file *file,
1794 new_i_size = pos + copied; 1794 new_i_size = pos + copied;
1795 if (new_i_size > inode->i_size) 1795 if (new_i_size > inode->i_size)
1796 i_size_write(inode, pos+copied); 1796 i_size_write(inode, pos+copied);
1797 EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; 1797 ext4_set_inode_state(inode, EXT4_STATE_JDATA);
1798 if (new_i_size > EXT4_I(inode)->i_disksize) { 1798 if (new_i_size > EXT4_I(inode)->i_disksize) {
1799 ext4_update_i_disksize(inode, new_i_size); 1799 ext4_update_i_disksize(inode, new_i_size);
1800 ret2 = ext4_mark_inode_dirty(handle, inode); 1800 ret2 = ext4_mark_inode_dirty(handle, inode);
@@ -2632,7 +2632,7 @@ static int __ext4_journalled_writepage(struct page *page,
2632 ret = err; 2632 ret = err;
2633 2633
2634 walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one); 2634 walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
2635 EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; 2635 ext4_set_inode_state(inode, EXT4_STATE_JDATA);
2636out: 2636out:
2637 return ret; 2637 return ret;
2638} 2638}
@@ -3303,7 +3303,8 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
3303 filemap_write_and_wait(mapping); 3303 filemap_write_and_wait(mapping);
3304 } 3304 }
3305 3305
3306 if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) { 3306 if (EXT4_JOURNAL(inode) &&
3307 ext4_test_inode_state(inode, EXT4_STATE_JDATA)) {
3307 /* 3308 /*
3308 * This is a REALLY heavyweight approach, but the use of 3309 * This is a REALLY heavyweight approach, but the use of
3309 * bmap on dirty files is expected to be extremely rare: 3310 * bmap on dirty files is expected to be extremely rare:
@@ -3322,7 +3323,7 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
3322 * everything they get. 3323 * everything they get.
3323 */ 3324 */
3324 3325
3325 EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA; 3326 ext4_clear_inode_state(inode, EXT4_STATE_JDATA);
3326 journal = EXT4_JOURNAL(inode); 3327 journal = EXT4_JOURNAL(inode);
3327 jbd2_journal_lock_updates(journal); 3328 jbd2_journal_lock_updates(journal);
3328 err = jbd2_journal_flush(journal); 3329 err = jbd2_journal_flush(journal);
@@ -3790,8 +3791,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
3790 if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) { 3791 if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
3791 ext4_free_io_end(iocb->private); 3792 ext4_free_io_end(iocb->private);
3792 iocb->private = NULL; 3793 iocb->private = NULL;
3793 } else if (ret > 0 && (EXT4_I(inode)->i_state & 3794 } else if (ret > 0 && ext4_test_inode_state(inode,
3794 EXT4_STATE_DIO_UNWRITTEN)) { 3795 EXT4_STATE_DIO_UNWRITTEN)) {
3795 int err; 3796 int err;
3796 /* 3797 /*
3797 * for non AIO case, since the IO is already 3798 * for non AIO case, since the IO is already
@@ -3801,7 +3802,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
3801 offset, ret); 3802 offset, ret);
3802 if (err < 0) 3803 if (err < 0)
3803 ret = err; 3804 ret = err;
3804 EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN; 3805 ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
3805 } 3806 }
3806 return ret; 3807 return ret;
3807 } 3808 }
@@ -4457,7 +4458,7 @@ void ext4_truncate(struct inode *inode)
4457 return; 4458 return;
4458 4459
4459 if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) 4460 if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
4460 ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE; 4461 ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
4461 4462
4462 if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { 4463 if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
4463 ext4_ext_truncate(inode); 4464 ext4_ext_truncate(inode);
@@ -4743,7 +4744,7 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
4743{ 4744{
4744 /* We have all inode data except xattrs in memory here. */ 4745 /* We have all inode data except xattrs in memory here. */
4745 return __ext4_get_inode_loc(inode, iloc, 4746 return __ext4_get_inode_loc(inode, iloc,
4746 !(EXT4_I(inode)->i_state & EXT4_STATE_XATTR)); 4747 !ext4_test_inode_state(inode, EXT4_STATE_XATTR));
4747} 4748}
4748 4749
4749void ext4_set_inode_flags(struct inode *inode) 4750void ext4_set_inode_flags(struct inode *inode)
@@ -4837,7 +4838,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
4837 } 4838 }
4838 inode->i_nlink = le16_to_cpu(raw_inode->i_links_count); 4839 inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
4839 4840
4840 ei->i_state = 0; 4841 ei->i_state_flags = 0;
4841 ei->i_dir_start_lookup = 0; 4842 ei->i_dir_start_lookup = 0;
4842 ei->i_dtime = le32_to_cpu(raw_inode->i_dtime); 4843 ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
4843 /* We now have enough fields to check if the inode was active or not. 4844 /* We now have enough fields to check if the inode was active or not.
@@ -4920,7 +4921,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
4920 EXT4_GOOD_OLD_INODE_SIZE + 4921 EXT4_GOOD_OLD_INODE_SIZE +
4921 ei->i_extra_isize; 4922 ei->i_extra_isize;
4922 if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) 4923 if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
4923 ei->i_state |= EXT4_STATE_XATTR; 4924 ext4_set_inode_state(inode, EXT4_STATE_XATTR);
4924 } 4925 }
4925 } else 4926 } else
4926 ei->i_extra_isize = 0; 4927 ei->i_extra_isize = 0;
@@ -5060,7 +5061,7 @@ static int ext4_do_update_inode(handle_t *handle,
5060 5061
5061 /* For fields not not tracking in the in-memory inode, 5062 /* For fields not not tracking in the in-memory inode,
5062 * initialise them to zero for new inodes. */ 5063 * initialise them to zero for new inodes. */
5063 if (ei->i_state & EXT4_STATE_NEW) 5064 if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
5064 memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size); 5065 memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
5065 5066
5066 ext4_get_inode_flags(ei); 5067 ext4_get_inode_flags(ei);
@@ -5156,7 +5157,7 @@ static int ext4_do_update_inode(handle_t *handle,
5156 rc = ext4_handle_dirty_metadata(handle, inode, bh); 5157 rc = ext4_handle_dirty_metadata(handle, inode, bh);
5157 if (!err) 5158 if (!err)
5158 err = rc; 5159 err = rc;
5159 ei->i_state &= ~EXT4_STATE_NEW; 5160 ext4_clear_inode_state(inode, EXT4_STATE_NEW);
5160 5161
5161 ext4_update_inode_fsync_trans(handle, inode, 0); 5162 ext4_update_inode_fsync_trans(handle, inode, 0);
5162out_brelse: 5163out_brelse:
@@ -5580,8 +5581,8 @@ static int ext4_expand_extra_isize(struct inode *inode,
5580 entry = IFIRST(header); 5581 entry = IFIRST(header);
5581 5582
5582 /* No extended attributes present */ 5583 /* No extended attributes present */
5583 if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR) || 5584 if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
5584 header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { 5585 header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
5585 memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, 5586 memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
5586 new_extra_isize); 5587 new_extra_isize);
5587 EXT4_I(inode)->i_extra_isize = new_extra_isize; 5588 EXT4_I(inode)->i_extra_isize = new_extra_isize;
@@ -5625,7 +5626,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
5625 err = ext4_reserve_inode_write(handle, inode, &iloc); 5626 err = ext4_reserve_inode_write(handle, inode, &iloc);
5626 if (ext4_handle_valid(handle) && 5627 if (ext4_handle_valid(handle) &&
5627 EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize && 5628 EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
5628 !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) { 5629 !ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
5629 /* 5630 /*
5630 * We need extra buffer credits since we may write into EA block 5631 * We need extra buffer credits since we may write into EA block
5631 * with this same handle. If journal_extend fails, then it will 5632 * with this same handle. If journal_extend fails, then it will
@@ -5639,7 +5640,8 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
5639 sbi->s_want_extra_isize, 5640 sbi->s_want_extra_isize,
5640 iloc, handle); 5641 iloc, handle);
5641 if (ret) { 5642 if (ret) {
5642 EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND; 5643 ext4_set_inode_state(inode,
5644 EXT4_STATE_NO_EXPAND);
5643 if (mnt_count != 5645 if (mnt_count !=
5644 le16_to_cpu(sbi->s_es->s_mnt_count)) { 5646 le16_to_cpu(sbi->s_es->s_mnt_count)) {
5645 ext4_warning(inode->i_sb, __func__, 5647 ext4_warning(inode->i_sb, __func__,