In commit bce8d1120707 ("f2fs: avoid deadlock on init_inode_metadata"), we copied posix_acl codes from posix_acl.c, and reorganize them to avoid deadlock described as below: - f2fs_mknod - __f2fs_add_link - f2fs_add_inline_entry - get_node_page get parent's inode page - init_inode_metadata - f2fs_init_acl - posix_acl_create - get_acl - f2fs_get_acl - f2fs_getxattr - read_all_xattrs - get_node_page get parent's inode page again
For now, we reorganized init_inode_metadata, and f2fs_init_acl will no longer called after parent's inode page is grabbed. So this patch reverts all changes in commit bce8d1120707 ("f2fs: avoid deadlock on init_inode_metadata"). Signed-off-by: Chao Yu <chao2...@samsung.com> --- fs/f2fs/acl.c | 140 ++---------------------------------------------- fs/f2fs/acl.h | 5 +- fs/f2fs/crypto_key.c | 2 +- fs/f2fs/crypto_policy.c | 6 +-- fs/f2fs/dir.c | 8 +-- fs/f2fs/xattr.c | 6 +-- fs/f2fs/xattr.h | 6 +-- 7 files changed, 20 insertions(+), 153 deletions(-) diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index c8f25f7..af83577 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -162,8 +162,7 @@ fail: return ERR_PTR(-EINVAL); } -static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, - struct page *dpage) +struct posix_acl *f2fs_get_acl(struct inode *inode, int type) { int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; void *value = NULL; @@ -173,13 +172,12 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, if (type == ACL_TYPE_ACCESS) name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; - retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage); + retval = f2fs_getxattr(inode, name_index, "", NULL, 0); if (retval > 0) { value = kmalloc(retval, GFP_F2FS_ZERO); if (!value) return ERR_PTR(-ENOMEM); - retval = f2fs_getxattr(inode, name_index, "", value, - retval, dpage); + retval = f2fs_getxattr(inode, name_index, "", value, retval); } if (retval > 0) @@ -196,11 +194,6 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, return acl; } -struct posix_acl *f2fs_get_acl(struct inode *inode, int type) -{ - return __f2fs_get_acl(inode, type, NULL); -} - static int __f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl, struct page *ipage) { @@ -256,135 +249,12 @@ int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type) return __f2fs_set_acl(inode, type, acl, NULL); } -/* - * Most part of f2fs_acl_clone, f2fs_acl_create_masq, f2fs_acl_create - * are copied from posix_acl.c - */ -static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, - gfp_t flags) -{ - struct posix_acl *clone = NULL; - - if (acl) { - int size = sizeof(struct posix_acl) + acl->a_count * - sizeof(struct posix_acl_entry); - clone = kmemdup(acl, size, flags); - if (clone) - atomic_set(&clone->a_refcount, 1); - } - return clone; -} - -static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) -{ - struct posix_acl_entry *pa, *pe; - struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; - umode_t mode = *mode_p; - int not_equiv = 0; - - /* assert(atomic_read(acl->a_refcount) == 1); */ - - FOREACH_ACL_ENTRY(pa, acl, pe) { - switch(pa->e_tag) { - case ACL_USER_OBJ: - pa->e_perm &= (mode >> 6) | ~S_IRWXO; - mode &= (pa->e_perm << 6) | ~S_IRWXU; - break; - - case ACL_USER: - case ACL_GROUP: - not_equiv = 1; - break; - - case ACL_GROUP_OBJ: - group_obj = pa; - break; - - case ACL_OTHER: - pa->e_perm &= mode | ~S_IRWXO; - mode &= pa->e_perm | ~S_IRWXO; - break; - - case ACL_MASK: - mask_obj = pa; - not_equiv = 1; - break; - - default: - return -EIO; - } - } - - if (mask_obj) { - mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO; - mode &= (mask_obj->e_perm << 3) | ~S_IRWXG; - } else { - if (!group_obj) - return -EIO; - group_obj->e_perm &= (mode >> 3) | ~S_IRWXO; - mode &= (group_obj->e_perm << 3) | ~S_IRWXG; - } - - *mode_p = (*mode_p & ~S_IRWXUGO) | mode; - return not_equiv; -} - -static int f2fs_acl_create(struct inode *dir, umode_t *mode, - struct posix_acl **default_acl, struct posix_acl **acl, - struct page *dpage) -{ - struct posix_acl *p; - struct posix_acl *clone; - int ret; - - *acl = NULL; - *default_acl = NULL; - - if (S_ISLNK(*mode) || !IS_POSIXACL(dir)) - return 0; - - p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage); - if (!p || p == ERR_PTR(-EOPNOTSUPP)) { - *mode &= ~current_umask(); - return 0; - } - if (IS_ERR(p)) - return PTR_ERR(p); - - clone = f2fs_acl_clone(p, GFP_NOFS); - if (!clone) - goto no_mem; - - ret = f2fs_acl_create_masq(clone, mode); - if (ret < 0) - goto no_mem_clone; - - if (ret == 0) - posix_acl_release(clone); - else - *acl = clone; - - if (!S_ISDIR(*mode)) - posix_acl_release(p); - else - *default_acl = p; - - return 0; - -no_mem_clone: - posix_acl_release(clone); -no_mem: - posix_acl_release(p); - return -ENOMEM; -} - -int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage, - struct page *dpage) +int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage) { struct posix_acl *default_acl = NULL, *acl = NULL; int error = 0; - error = f2fs_acl_create(dir, &inode->i_mode, &default_acl, &acl, dpage); + error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); if (error) return error; diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h index 997ca8e..0504394 100644 --- a/fs/f2fs/acl.h +++ b/fs/f2fs/acl.h @@ -38,15 +38,14 @@ struct f2fs_acl_header { extern struct posix_acl *f2fs_get_acl(struct inode *, int); extern int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type); -extern int f2fs_init_acl(struct inode *, struct inode *, struct page *, - struct page *); +extern int f2fs_init_acl(struct inode *, struct inode *, struct page *); #else #define f2fs_check_acl NULL #define f2fs_get_acl NULL #define f2fs_set_acl NULL static inline int f2fs_init_acl(struct inode *inode, struct inode *dir, - struct page *ipage, struct page *dpage) + struct page *ipage) { return 0; } diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c index 9f77de2..c994c9e 100644 --- a/fs/f2fs/crypto_key.c +++ b/fs/f2fs/crypto_key.c @@ -144,7 +144,7 @@ retry: res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, - &ctx, sizeof(ctx), NULL); + &ctx, sizeof(ctx)); if (res < 0) return res; else if (res != sizeof(ctx)) diff --git a/fs/f2fs/crypto_policy.c b/fs/f2fs/crypto_policy.c index d4a96af..6d243fc 100644 --- a/fs/f2fs/crypto_policy.c +++ b/fs/f2fs/crypto_policy.c @@ -21,7 +21,7 @@ static int f2fs_inode_has_encryption_context(struct inode *inode) { int res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, - F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, NULL, 0, NULL); + F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, NULL, 0); return (res > 0); } @@ -35,7 +35,7 @@ static int f2fs_is_encryption_context_consistent_with_policy( struct f2fs_encryption_context ctx; int res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, - sizeof(ctx), NULL); + sizeof(ctx)); if (res != sizeof(ctx)) return 0; @@ -120,7 +120,7 @@ int f2fs_get_policy(struct inode *inode, struct f2fs_encryption_policy *policy) res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, - &ctx, sizeof(ctx), NULL); + &ctx, sizeof(ctx)); if (res != sizeof(ctx)) return -ENODATA; if (ctx.format != F2FS_ENCRYPTION_CONTEXT_FORMAT_V1) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 0ad9a1c..f0c099e 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -382,7 +382,7 @@ static int make_empty_dir(struct inode *inode, } int init_inode_metadata(struct inode *inode, struct inode *dir, - const struct qstr *name, struct page *dpage) + const struct qstr *name) { struct page *page; int err; @@ -400,7 +400,7 @@ int init_inode_metadata(struct inode *inode, struct inode *dir, goto error; } - err = f2fs_init_acl(inode, dir, page, dpage); + err = f2fs_init_acl(inode, dir, page); if (err) goto put_error; @@ -554,7 +554,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, if (inode) { down_write(&F2FS_I(inode)->i_sem); - err = init_inode_metadata(inode, dir, &new_name, NULL); + err = init_inode_metadata(inode, dir, &new_name); up_write(&F2FS_I(inode)->i_sem); if (err) goto free_filename; @@ -666,7 +666,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir) int err; down_write(&F2FS_I(inode)->i_sem); - err = init_inode_metadata(inode, dir, NULL, NULL); + err = init_inode_metadata(inode, dir, NULL); up_write(&F2FS_I(inode)->i_sem); if (err) return err; diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 4de2286..944d2a0 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -83,7 +83,7 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name, } if (strcmp(name, "") == 0) return -EINVAL; - return f2fs_getxattr(d_inode(dentry), type, name, buffer, size, NULL); + return f2fs_getxattr(d_inode(dentry), type, name, buffer, size); } static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, @@ -400,7 +400,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, } int f2fs_getxattr(struct inode *inode, int index, const char *name, - void *buffer, size_t buffer_size, struct page *ipage) + void *buffer, size_t buffer_size) { struct f2fs_xattr_entry *entry; void *base_addr; @@ -414,7 +414,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, if (len > F2FS_NAME_LEN) return -ERANGE; - base_addr = read_all_xattrs(inode, ipage); + base_addr = read_all_xattrs(inode, NULL); if (!base_addr) return -ENOMEM; diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 71a7100..288b869 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -119,8 +119,7 @@ extern const struct xattr_handler *f2fs_xattr_handlers[]; extern int f2fs_setxattr(struct inode *, int, const char *, const void *, size_t, struct page *, int); -extern int f2fs_getxattr(struct inode *, int, const char *, void *, - size_t, struct page *); +extern int f2fs_getxattr(struct inode *, int, const char *, void *, size_t); extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t); #else @@ -131,8 +130,7 @@ static inline int f2fs_setxattr(struct inode *inode, int index, return -EOPNOTSUPP; } static inline int f2fs_getxattr(struct inode *inode, int index, - const char *name, void *buffer, - size_t buffer_size, struct page *dpage) + const char *name, void *buffer, size_t buffer_size) { return -EOPNOTSUPP; } -- 2.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/