diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-06-01 10:24:30 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-06-02 09:13:16 -0400 |
commit | d631abdac9d541d282a1461b5aeae70aa3866e9f (patch) | |
tree | ccfc16753097b9efe76f35569d23aa5da9ef2a6c /fs | |
parent | f6238a72092c7be20565509643b70276853e8f2b (diff) |
f2fs: fix recursive lock by f2fs_setxattr
This patch should resolve the following recursive lock.
[<ffffffff8135a9c3>] call_rwsem_down_write_failed+0x13/0x20
[<ffffffffa01749dc>] f2fs_setxattr+0x5c/0xa0 [f2fs]
[<ffffffffa0174c99>] __f2fs_set_acl+0x1b9/0x340 [f2fs]
[<ffffffffa017515a>] f2fs_init_acl+0x4a/0xcb [f2fs]
[<ffffffffa0159abe>] __f2fs_add_link+0x26e/0x780 [f2fs]
[<ffffffffa015d4d8>] f2fs_mkdir+0xb8/0x150 [f2fs]
[<ffffffff811cebd7>] vfs_mkdir+0xb7/0x160
[<ffffffff811cf89b>] SyS_mkdir+0xab/0xe0
[<ffffffff817244bf>] tracesys+0xe1/0xe6
[<ffffffffffffffff>] 0xffffffffffffffff
The call path indicates:
- f2fs_add_link
: down_write(&fi->i_sem);
- init_inode_metadata
- f2fs_init_acl
- __f2fs_set_acl
- f2fs_setxattr
: down_write(&fi->i_sem);
Here we should not call f2fs_setxattr, but __f2fs_setxattr.
But __f2fs_setxattr is a static function in xattr.c, so that I found the other
generic approach to use f2fs_setxattr.
In f2fs_setxattr, the page pointer is only given from init_inode_metadata.
So, this patch adds this condition to avoid this in f2fs_setxattr.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/f2fs/xattr.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 1f546b4b6b61..8bea941ee309 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -156,10 +156,6 @@ static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name, | |||
156 | } | 156 | } |
157 | 157 | ||
158 | #ifdef CONFIG_F2FS_FS_SECURITY | 158 | #ifdef CONFIG_F2FS_FS_SECURITY |
159 | static int __f2fs_setxattr(struct inode *inode, int index, | ||
160 | const char *name, const void *value, size_t size, | ||
161 | struct page *ipage, int); | ||
162 | |||
163 | static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, | 159 | static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, |
164 | void *page) | 160 | void *page) |
165 | { | 161 | { |
@@ -167,7 +163,7 @@ static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, | |||
167 | int err = 0; | 163 | int err = 0; |
168 | 164 | ||
169 | for (xattr = xattr_array; xattr->name != NULL; xattr++) { | 165 | for (xattr = xattr_array; xattr->name != NULL; xattr++) { |
170 | err = __f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, | 166 | err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, |
171 | xattr->name, xattr->value, | 167 | xattr->name, xattr->value, |
172 | xattr->value_len, (struct page *)page, 0); | 168 | xattr->value_len, (struct page *)page, 0); |
173 | if (err < 0) | 169 | if (err < 0) |
@@ -603,6 +599,10 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, | |||
603 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 599 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
604 | int err; | 600 | int err; |
605 | 601 | ||
602 | /* this case is only from init_inode_metadata */ | ||
603 | if (ipage) | ||
604 | return __f2fs_setxattr(inode, index, name, value, | ||
605 | size, ipage, flags); | ||
606 | f2fs_balance_fs(sbi); | 606 | f2fs_balance_fs(sbi); |
607 | 607 | ||
608 | f2fs_lock_op(sbi); | 608 | f2fs_lock_op(sbi); |