diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-01-24 14:34:07 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-01-24 14:34:07 -0500 |
commit | 19f5fb7ad679bb361222c7916086435020c37cce (patch) | |
tree | 9e301163075c4faaf340cf50afd51855c76acd8c /fs/ext4/xattr.c | |
parent | d2eecb03936878ec574ade5532fa83df7d75dde7 (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/xattr.c')
-rw-r--r-- | fs/ext4/xattr.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index f3a2f7ed45aa..c619a7ea670d 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -267,7 +267,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, | |||
267 | void *end; | 267 | void *end; |
268 | int error; | 268 | int error; |
269 | 269 | ||
270 | if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR)) | 270 | if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) |
271 | return -ENODATA; | 271 | return -ENODATA; |
272 | error = ext4_get_inode_loc(inode, &iloc); | 272 | error = ext4_get_inode_loc(inode, &iloc); |
273 | if (error) | 273 | if (error) |
@@ -396,7 +396,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
396 | void *end; | 396 | void *end; |
397 | int error; | 397 | int error; |
398 | 398 | ||
399 | if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR)) | 399 | if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) |
400 | return 0; | 400 | return 0; |
401 | error = ext4_get_inode_loc(inode, &iloc); | 401 | error = ext4_get_inode_loc(inode, &iloc); |
402 | if (error) | 402 | if (error) |
@@ -908,7 +908,7 @@ ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, | |||
908 | is->s.base = is->s.first = IFIRST(header); | 908 | is->s.base = is->s.first = IFIRST(header); |
909 | is->s.here = is->s.first; | 909 | is->s.here = is->s.first; |
910 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 910 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
911 | if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) { | 911 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { |
912 | error = ext4_xattr_check_names(IFIRST(header), is->s.end); | 912 | error = ext4_xattr_check_names(IFIRST(header), is->s.end); |
913 | if (error) | 913 | if (error) |
914 | return error; | 914 | return error; |
@@ -940,10 +940,10 @@ ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, | |||
940 | header = IHDR(inode, ext4_raw_inode(&is->iloc)); | 940 | header = IHDR(inode, ext4_raw_inode(&is->iloc)); |
941 | if (!IS_LAST_ENTRY(s->first)) { | 941 | if (!IS_LAST_ENTRY(s->first)) { |
942 | header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); | 942 | header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); |
943 | EXT4_I(inode)->i_state |= EXT4_STATE_XATTR; | 943 | ext4_set_inode_state(inode, EXT4_STATE_XATTR); |
944 | } else { | 944 | } else { |
945 | header->h_magic = cpu_to_le32(0); | 945 | header->h_magic = cpu_to_le32(0); |
946 | EXT4_I(inode)->i_state &= ~EXT4_STATE_XATTR; | 946 | ext4_clear_inode_state(inode, EXT4_STATE_XATTR); |
947 | } | 947 | } |
948 | return 0; | 948 | return 0; |
949 | } | 949 | } |
@@ -986,8 +986,8 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
986 | if (strlen(name) > 255) | 986 | if (strlen(name) > 255) |
987 | return -ERANGE; | 987 | return -ERANGE; |
988 | down_write(&EXT4_I(inode)->xattr_sem); | 988 | down_write(&EXT4_I(inode)->xattr_sem); |
989 | no_expand = EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND; | 989 | no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); |
990 | EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND; | 990 | ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); |
991 | 991 | ||
992 | error = ext4_get_inode_loc(inode, &is.iloc); | 992 | error = ext4_get_inode_loc(inode, &is.iloc); |
993 | if (error) | 993 | if (error) |
@@ -997,10 +997,10 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
997 | if (error) | 997 | if (error) |
998 | goto cleanup; | 998 | goto cleanup; |
999 | 999 | ||
1000 | if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) { | 1000 | if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) { |
1001 | struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc); | 1001 | struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc); |
1002 | memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size); | 1002 | memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size); |
1003 | EXT4_I(inode)->i_state &= ~EXT4_STATE_NEW; | 1003 | ext4_clear_inode_state(inode, EXT4_STATE_NEW); |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | error = ext4_xattr_ibody_find(inode, &i, &is); | 1006 | error = ext4_xattr_ibody_find(inode, &i, &is); |
@@ -1052,7 +1052,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
1052 | ext4_xattr_update_super_block(handle, inode->i_sb); | 1052 | ext4_xattr_update_super_block(handle, inode->i_sb); |
1053 | inode->i_ctime = ext4_current_time(inode); | 1053 | inode->i_ctime = ext4_current_time(inode); |
1054 | if (!value) | 1054 | if (!value) |
1055 | EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND; | 1055 | ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); |
1056 | error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); | 1056 | error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); |
1057 | /* | 1057 | /* |
1058 | * The bh is consumed by ext4_mark_iloc_dirty, even with | 1058 | * The bh is consumed by ext4_mark_iloc_dirty, even with |
@@ -1067,7 +1067,7 @@ cleanup: | |||
1067 | brelse(is.iloc.bh); | 1067 | brelse(is.iloc.bh); |
1068 | brelse(bs.bh); | 1068 | brelse(bs.bh); |
1069 | if (no_expand == 0) | 1069 | if (no_expand == 0) |
1070 | EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND; | 1070 | ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); |
1071 | up_write(&EXT4_I(inode)->xattr_sem); | 1071 | up_write(&EXT4_I(inode)->xattr_sem); |
1072 | return error; | 1072 | return error; |
1073 | } | 1073 | } |