aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/xattr.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/xattr.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/xattr.c')
-rw-r--r--fs/ext4/xattr.c22
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}