diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2010-05-16 22:00:00 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-05-16 22:00:00 -0400 |
commit | 12e9b892002d9af057655d35b44db8ee9243b0dc (patch) | |
tree | c5831b4bcf98eebdd39158d08dab97c198f5c683 /fs/ext4/inode.c | |
parent | 24676da469f50f433baa347845639662c561d1f6 (diff) |
ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
At several places we modify EXT4_I(inode)->i_flags without holding
i_mutex (ext4_do_update_inode, ...). These modifications are racy and
we can lose updates to i_flags. So convert handling of i_flags to use
bitops which are atomic.
https://bugzilla.kernel.org/show_bug.cgi?id=15792
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 3b687725758..c2b0724e8ad 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -931,7 +931,7 @@ static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, | |||
931 | int count = 0; | 931 | int count = 0; |
932 | ext4_fsblk_t first_block = 0; | 932 | ext4_fsblk_t first_block = 0; |
933 | 933 | ||
934 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); | 934 | J_ASSERT(!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))); |
935 | J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); | 935 | J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); |
936 | depth = ext4_block_to_path(inode, map->m_lblk, offsets, | 936 | depth = ext4_block_to_path(inode, map->m_lblk, offsets, |
937 | &blocks_to_boundary); | 937 | &blocks_to_boundary); |
@@ -1059,7 +1059,7 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode, | |||
1059 | */ | 1059 | */ |
1060 | static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock) | 1060 | static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock) |
1061 | { | 1061 | { |
1062 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | 1062 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
1063 | return ext4_ext_calc_metadata_amount(inode, lblock); | 1063 | return ext4_ext_calc_metadata_amount(inode, lblock); |
1064 | 1064 | ||
1065 | return ext4_indirect_calc_metadata_amount(inode, lblock); | 1065 | return ext4_indirect_calc_metadata_amount(inode, lblock); |
@@ -1236,7 +1236,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
1236 | * file system block. | 1236 | * file system block. |
1237 | */ | 1237 | */ |
1238 | down_read((&EXT4_I(inode)->i_data_sem)); | 1238 | down_read((&EXT4_I(inode)->i_data_sem)); |
1239 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 1239 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { |
1240 | retval = ext4_ext_map_blocks(handle, inode, map, 0); | 1240 | retval = ext4_ext_map_blocks(handle, inode, map, 0); |
1241 | } else { | 1241 | } else { |
1242 | retval = ext4_ind_map_blocks(handle, inode, map, 0); | 1242 | retval = ext4_ind_map_blocks(handle, inode, map, 0); |
@@ -1295,7 +1295,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
1295 | * We need to check for EXT4 here because migrate | 1295 | * We need to check for EXT4 here because migrate |
1296 | * could have changed the inode type in between | 1296 | * could have changed the inode type in between |
1297 | */ | 1297 | */ |
1298 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 1298 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { |
1299 | retval = ext4_ext_map_blocks(handle, inode, map, flags); | 1299 | retval = ext4_ext_map_blocks(handle, inode, map, flags); |
1300 | } else { | 1300 | } else { |
1301 | retval = ext4_ind_map_blocks(handle, inode, map, flags); | 1301 | retval = ext4_ind_map_blocks(handle, inode, map, flags); |
@@ -2325,7 +2325,7 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, | |||
2325 | goto flush_it; | 2325 | goto flush_it; |
2326 | 2326 | ||
2327 | /* check if thereserved journal credits might overflow */ | 2327 | /* check if thereserved journal credits might overflow */ |
2328 | if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) { | 2328 | if (!(ext4_test_inode_flag(mpd->inode, EXT4_INODE_EXTENTS))) { |
2329 | if (nrblocks >= EXT4_MAX_TRANS_DATA) { | 2329 | if (nrblocks >= EXT4_MAX_TRANS_DATA) { |
2330 | /* | 2330 | /* |
2331 | * With non-extent format we are limited by the journal | 2331 | * With non-extent format we are limited by the journal |
@@ -2779,7 +2779,7 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) | |||
2779 | * number of contiguous block. So we will limit | 2779 | * number of contiguous block. So we will limit |
2780 | * number of contiguous block to a sane value | 2780 | * number of contiguous block to a sane value |
2781 | */ | 2781 | */ |
2782 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) && | 2782 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) && |
2783 | (max_blocks > EXT4_MAX_TRANS_DATA)) | 2783 | (max_blocks > EXT4_MAX_TRANS_DATA)) |
2784 | max_blocks = EXT4_MAX_TRANS_DATA; | 2784 | max_blocks = EXT4_MAX_TRANS_DATA; |
2785 | 2785 | ||
@@ -3995,7 +3995,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, | |||
3995 | struct file *file = iocb->ki_filp; | 3995 | struct file *file = iocb->ki_filp; |
3996 | struct inode *inode = file->f_mapping->host; | 3996 | struct inode *inode = file->f_mapping->host; |
3997 | 3997 | ||
3998 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | 3998 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
3999 | return ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); | 3999 | return ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); |
4000 | 4000 | ||
4001 | return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); | 4001 | return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); |
@@ -4631,12 +4631,12 @@ void ext4_truncate(struct inode *inode) | |||
4631 | if (!ext4_can_truncate(inode)) | 4631 | if (!ext4_can_truncate(inode)) |
4632 | return; | 4632 | return; |
4633 | 4633 | ||
4634 | EXT4_I(inode)->i_flags &= ~EXT4_EOFBLOCKS_FL; | 4634 | ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS); |
4635 | 4635 | ||
4636 | if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) | 4636 | if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) |
4637 | ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); | 4637 | ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); |
4638 | 4638 | ||
4639 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 4639 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { |
4640 | ext4_ext_truncate(inode); | 4640 | ext4_ext_truncate(inode); |
4641 | return; | 4641 | return; |
4642 | } | 4642 | } |
@@ -5473,7 +5473,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
5473 | } | 5473 | } |
5474 | 5474 | ||
5475 | if (attr->ia_valid & ATTR_SIZE) { | 5475 | if (attr->ia_valid & ATTR_SIZE) { |
5476 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { | 5476 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { |
5477 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 5477 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
5478 | 5478 | ||
5479 | if (attr->ia_size > sbi->s_bitmap_maxbytes) { | 5479 | if (attr->ia_size > sbi->s_bitmap_maxbytes) { |
@@ -5486,7 +5486,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
5486 | if (S_ISREG(inode->i_mode) && | 5486 | if (S_ISREG(inode->i_mode) && |
5487 | attr->ia_valid & ATTR_SIZE && | 5487 | attr->ia_valid & ATTR_SIZE && |
5488 | (attr->ia_size < inode->i_size || | 5488 | (attr->ia_size < inode->i_size || |
5489 | (EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL))) { | 5489 | (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)))) { |
5490 | handle_t *handle; | 5490 | handle_t *handle; |
5491 | 5491 | ||
5492 | handle = ext4_journal_start(inode, 3); | 5492 | handle = ext4_journal_start(inode, 3); |
@@ -5518,7 +5518,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
5518 | } | 5518 | } |
5519 | } | 5519 | } |
5520 | /* ext4_truncate will clear the flag */ | 5520 | /* ext4_truncate will clear the flag */ |
5521 | if ((EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL)) | 5521 | if ((ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))) |
5522 | ext4_truncate(inode); | 5522 | ext4_truncate(inode); |
5523 | } | 5523 | } |
5524 | 5524 | ||
@@ -5594,7 +5594,7 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, | |||
5594 | 5594 | ||
5595 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) | 5595 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) |
5596 | { | 5596 | { |
5597 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) | 5597 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
5598 | return ext4_indirect_trans_blocks(inode, nrblocks, chunk); | 5598 | return ext4_indirect_trans_blocks(inode, nrblocks, chunk); |
5599 | return ext4_ext_index_trans_blocks(inode, nrblocks, chunk); | 5599 | return ext4_ext_index_trans_blocks(inode, nrblocks, chunk); |
5600 | } | 5600 | } |
@@ -5929,9 +5929,9 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) | |||
5929 | */ | 5929 | */ |
5930 | 5930 | ||
5931 | if (val) | 5931 | if (val) |
5932 | EXT4_I(inode)->i_flags |= EXT4_JOURNAL_DATA_FL; | 5932 | ext4_set_inode_flag(inode, EXT4_INODE_JOURNAL_DATA); |
5933 | else | 5933 | else |
5934 | EXT4_I(inode)->i_flags &= ~EXT4_JOURNAL_DATA_FL; | 5934 | ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA); |
5935 | ext4_set_aops(inode); | 5935 | ext4_set_aops(inode); |
5936 | 5936 | ||
5937 | jbd2_journal_unlock_updates(journal); | 5937 | jbd2_journal_unlock_updates(journal); |