diff options
author | Yunlei He <heyunlei@huawei.com> | 2017-09-06 22:40:54 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2017-09-07 23:57:20 -0400 |
commit | 27161f13e3c3241944846ac24942a85cceda0a2c (patch) | |
tree | bdd36b6171f9d48fd4a3c68c6f091697bb4cfaba | |
parent | 13ba41e346170e594b7ce582561b3efa5b85f18f (diff) |
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>
-rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
-rw-r--r-- | fs/f2fs/super.c | 1 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 6 |
3 files changed, 8 insertions, 0 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 91fb749686f2..c0803b1873b3 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -589,6 +589,7 @@ struct f2fs_inode_info { | |||
589 | struct extent_tree *extent_tree; /* cached extent_tree entry */ | 589 | struct extent_tree *extent_tree; /* cached extent_tree entry */ |
590 | struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */ | 590 | struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */ |
591 | struct rw_semaphore i_mmap_sem; | 591 | struct rw_semaphore i_mmap_sem; |
592 | struct rw_semaphore i_xattr_sem; /* avoid racing between reading and changing EAs */ | ||
592 | 593 | ||
593 | int i_extra_isize; /* size of extra space located in i_addr */ | 594 | int i_extra_isize; /* size of extra space located in i_addr */ |
594 | kprojid_t i_projid; /* id for project quota */ | 595 | kprojid_t i_projid; /* id for project quota */ |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 7730316c19c6..89f61eb3d167 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -630,6 +630,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) | |||
630 | init_rwsem(&fi->dio_rwsem[READ]); | 630 | init_rwsem(&fi->dio_rwsem[READ]); |
631 | init_rwsem(&fi->dio_rwsem[WRITE]); | 631 | init_rwsem(&fi->dio_rwsem[WRITE]); |
632 | init_rwsem(&fi->i_mmap_sem); | 632 | init_rwsem(&fi->i_mmap_sem); |
633 | init_rwsem(&fi->i_xattr_sem); | ||
633 | 634 | ||
634 | #ifdef CONFIG_QUOTA | 635 | #ifdef CONFIG_QUOTA |
635 | memset(&fi->i_dquot, 0, sizeof(fi->i_dquot)); | 636 | memset(&fi->i_dquot, 0, sizeof(fi->i_dquot)); |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index ef3a3721ea6b..7c65540148f8 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -473,8 +473,10 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, | |||
473 | if (len > F2FS_NAME_LEN) | 473 | if (len > F2FS_NAME_LEN) |
474 | return -ERANGE; | 474 | return -ERANGE; |
475 | 475 | ||
476 | down_read(&F2FS_I(inode)->i_xattr_sem); | ||
476 | error = lookup_all_xattrs(inode, ipage, index, len, name, | 477 | error = lookup_all_xattrs(inode, ipage, index, len, name, |
477 | &entry, &base_addr); | 478 | &entry, &base_addr); |
479 | up_read(&F2FS_I(inode)->i_xattr_sem); | ||
478 | if (error) | 480 | if (error) |
479 | return error; | 481 | return error; |
480 | 482 | ||
@@ -503,7 +505,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
503 | int error = 0; | 505 | int error = 0; |
504 | size_t rest = buffer_size; | 506 | size_t rest = buffer_size; |
505 | 507 | ||
508 | down_read(&F2FS_I(inode)->i_xattr_sem); | ||
506 | error = read_all_xattrs(inode, NULL, &base_addr); | 509 | error = read_all_xattrs(inode, NULL, &base_addr); |
510 | up_read(&F2FS_I(inode)->i_xattr_sem); | ||
507 | if (error) | 511 | if (error) |
508 | return error; | 512 | return error; |
509 | 513 | ||
@@ -686,7 +690,9 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, | |||
686 | f2fs_lock_op(sbi); | 690 | f2fs_lock_op(sbi); |
687 | /* protect xattr_ver */ | 691 | /* protect xattr_ver */ |
688 | down_write(&F2FS_I(inode)->i_sem); | 692 | down_write(&F2FS_I(inode)->i_sem); |
693 | down_write(&F2FS_I(inode)->i_xattr_sem); | ||
689 | err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags); | 694 | err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags); |
695 | up_write(&F2FS_I(inode)->i_xattr_sem); | ||
690 | up_write(&F2FS_I(inode)->i_sem); | 696 | up_write(&F2FS_I(inode)->i_sem); |
691 | f2fs_unlock_op(sbi); | 697 | f2fs_unlock_op(sbi); |
692 | 698 | ||