Skip to content

Commit 27161f1

Browse files
Yunlei HeJaegeuk Kim
authored andcommitted
f2fs: avoid race in between read xattr & write xattr
Thread A: Thread B: -f2fs_getxattr -lookup_all_xattrs -xnid = F2FS_I(inode)->i_xattr_nid; -f2fs_setxattr -__f2fs_setxattr -write_all_xattrs -truncate_xattr_node ... ... -write_checkpoint ... ... -alloc_nid <- nid reuse -get_node_page -f2fs_bug_on <- nid != node_footer->nid It's need a rw_sem to avoid the race Signed-off-by: Yunlei He <heyunlei@huawei.com> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 13ba41e commit 27161f1

File tree

3 files changed

+8
-0
lines changed

3 files changed

+8
-0
lines changed

fs/f2fs/f2fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ struct f2fs_inode_info {
589589
struct extent_tree *extent_tree; /* cached extent_tree entry */
590590
struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
591591
struct rw_semaphore i_mmap_sem;
592+
struct rw_semaphore i_xattr_sem; /* avoid racing between reading and changing EAs */
592593

593594
int i_extra_isize; /* size of extra space located in i_addr */
594595
kprojid_t i_projid; /* id for project quota */

fs/f2fs/super.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
630630
init_rwsem(&fi->dio_rwsem[READ]);
631631
init_rwsem(&fi->dio_rwsem[WRITE]);
632632
init_rwsem(&fi->i_mmap_sem);
633+
init_rwsem(&fi->i_xattr_sem);
633634

634635
#ifdef CONFIG_QUOTA
635636
memset(&fi->i_dquot, 0, sizeof(fi->i_dquot));

fs/f2fs/xattr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,10 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name,
473473
if (len > F2FS_NAME_LEN)
474474
return -ERANGE;
475475

476+
down_read(&F2FS_I(inode)->i_xattr_sem);
476477
error = lookup_all_xattrs(inode, ipage, index, len, name,
477478
&entry, &base_addr);
479+
up_read(&F2FS_I(inode)->i_xattr_sem);
478480
if (error)
479481
return error;
480482

@@ -503,7 +505,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
503505
int error = 0;
504506
size_t rest = buffer_size;
505507

508+
down_read(&F2FS_I(inode)->i_xattr_sem);
506509
error = read_all_xattrs(inode, NULL, &base_addr);
510+
up_read(&F2FS_I(inode)->i_xattr_sem);
507511
if (error)
508512
return error;
509513

@@ -686,7 +690,9 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name,
686690
f2fs_lock_op(sbi);
687691
/* protect xattr_ver */
688692
down_write(&F2FS_I(inode)->i_sem);
693+
down_write(&F2FS_I(inode)->i_xattr_sem);
689694
err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags);
695+
up_write(&F2FS_I(inode)->i_xattr_sem);
690696
up_write(&F2FS_I(inode)->i_sem);
691697
f2fs_unlock_op(sbi);
692698

0 commit comments

Comments
 (0)