aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-06-01 10:24:30 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2014-06-02 09:13:16 -0400
commitd631abdac9d541d282a1461b5aeae70aa3866e9f (patch)
treeccfc16753097b9efe76f35569d23aa5da9ef2a6c /fs
parentf6238a72092c7be20565509643b70276853e8f2b (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.c10
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
159static int __f2fs_setxattr(struct inode *inode, int index,
160 const char *name, const void *value, size_t size,
161 struct page *ipage, int);
162
163static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, 159static 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);