summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-25 21:53:15 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-25 21:53:15 +0200
commit0003230e8200699860f0b10af524dc47bf8aecad (patch)
tree8addb0c889b32111d6973c46cd3d0a5b5c17606c /fs
parentMerge branch 'next/deletion' of git+ssh://master.kernel.org/pub/scm/linux/ker... (diff)
parentfs: take the ACL checks to common code (diff)
downloadlinux-0003230e8200699860f0b10af524dc47bf8aecad.tar.xz
linux-0003230e8200699860f0b10af524dc47bf8aecad.zip
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: fs: take the ACL checks to common code bury posix_acl_..._masq() variants kill boilerplates around posix_acl_create_masq() generic_acl: no need to clone acl just to push it to set_cached_acl() kill boilerplate around posix_acl_chmod_masq() reiserfs: cache negative ACLs for v1 stat format xfs: cache negative ACLs if there is no attribute fork 9p: do no return 0 from ->check_acl without actually checking vfs: move ACL cache lookup into generic code CIFS: Fix oops while mounting with prefixpath xfs: Fix wrong return value of xfs_file_aio_write fix devtmpfs race caam: don't pass bogus S_IFCHR to debugfs_create_...() get rid of create_proc_entry() abuses - proc_mkdir() is there for purpose asus-wmi: ->is_visible() can't return negative fix jffs2 ACLs on big-endian with 16bit mode_t 9p: close ACL leaks ocfs2_init_acl(): fix a leak VFS : mount lock scalability for internal mounts
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/acl.c68
-rw-r--r--fs/9p/acl.h10
-rw-r--r--fs/9p/vfs_inode_dotl.c13
-rw-r--r--fs/anon_inodes.c2
-rw-r--r--fs/btrfs/acl.c63
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/inode.c10
-rw-r--r--fs/cifs/dir.c2
-rw-r--r--fs/ext2/acl.c63
-rw-r--r--fs/ext2/acl.h4
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext2/namei.c4
-rw-r--r--fs/ext3/acl.c94
-rw-r--r--fs/ext3/acl.h4
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/namei.c4
-rw-r--r--fs/ext4/acl.c95
-rw-r--r--fs/ext4/acl.h4
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/namei.c4
-rw-r--r--fs/generic_acl.c62
-rw-r--r--fs/gfs2/acl.c75
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/gfs2/inode.c6
-rw-r--r--fs/hugetlbfs/inode.c1
-rw-r--r--fs/jffs2/acl.c49
-rw-r--r--fs/jffs2/acl.h6
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/fs.c2
-rw-r--r--fs/jffs2/os-linux.h2
-rw-r--r--fs/jffs2/symlink.c2
-rw-r--r--fs/jfs/acl.c75
-rw-r--r--fs/jfs/file.c2
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/namei.c54
-rw-r--r--fs/namespace.c21
-rw-r--r--fs/nfs/nfs3acl.c10
-rw-r--r--fs/ocfs2/acl.c77
-rw-r--r--fs/ocfs2/acl.h2
-rw-r--r--fs/ocfs2/file.c4
-rw-r--r--fs/ocfs2/namei.c2
-rw-r--r--fs/pipe.c2
-rw-r--r--fs/posix_acl.c48
-rw-r--r--fs/reiserfs/file.c2
-rw-r--r--fs/reiserfs/inode.c5
-rw-r--r--fs/reiserfs/namei.c6
-rw-r--r--fs/reiserfs/xattr.c27
-rw-r--r--fs/reiserfs/xattr_acl.c71
-rw-r--r--fs/xfs/linux-2.6/xfs_acl.c80
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c14
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.h2
-rw-r--r--fs/xfs/xfs_acl.h2
55 files changed, 438 insertions, 742 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index e98f56d3787d..814be079c185 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -96,14 +96,11 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
return acl;
}
-int v9fs_check_acl(struct inode *inode, int mask)
+struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type)
{
struct posix_acl *acl;
struct v9fs_session_info *v9ses;
- if (mask & MAY_NOT_BLOCK)
- return -ECHILD;
-
v9ses = v9fs_inode2v9ses(inode);
if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) ||
((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {
@@ -111,18 +108,10 @@ int v9fs_check_acl(struct inode *inode, int mask)
* On access = client and acl = on mode get the acl
* values from the server
*/
- return 0;
+ return NULL;
}
- acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
+ return v9fs_get_cached_acl(inode, type);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- int error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
- return -EAGAIN;
}
static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)
@@ -165,32 +154,32 @@ err_free_out:
int v9fs_acl_chmod(struct dentry *dentry)
{
int retval = 0;
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
struct inode *inode = dentry->d_inode;
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
if (acl) {
- clone = posix_acl_clone(acl, GFP_KERNEL);
+ retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (retval)
+ return retval;
+ retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, acl);
posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- retval = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!retval)
- retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, clone);
- posix_acl_release(clone);
}
return retval;
}
int v9fs_set_create_acl(struct dentry *dentry,
- struct posix_acl *dpacl, struct posix_acl *pacl)
+ struct posix_acl **dpacl, struct posix_acl **pacl)
{
- v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl);
- v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl);
- posix_acl_release(dpacl);
- posix_acl_release(pacl);
+ if (dentry) {
+ v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, *dpacl);
+ v9fs_set_acl(dentry, ACL_TYPE_ACCESS, *pacl);
+ }
+ posix_acl_release(*dpacl);
+ posix_acl_release(*pacl);
+ *dpacl = *pacl = NULL;
return 0;
}
@@ -209,29 +198,18 @@ int v9fs_acl_mode(struct inode *dir, mode_t *modep,
mode &= ~current_umask();
}
if (acl) {
- struct posix_acl *clone;
-
if (S_ISDIR(mode))
- *dpacl = acl;
- clone = posix_acl_clone(acl, GFP_NOFS);
- retval = -ENOMEM;
- if (!clone)
- goto cleanup;
-
- retval = posix_acl_create_masq(clone, &mode);
- if (retval < 0) {
- posix_acl_release(clone);
- goto cleanup;
- }
+ *dpacl = posix_acl_dup(acl);
+ retval = posix_acl_create(&acl, GFP_NOFS, &mode);
+ if (retval < 0)
+ return retval;
if (retval > 0)
- *pacl = clone;
+ *pacl = acl;
+ else
+ posix_acl_release(acl);
}
*modep = mode;
return 0;
-cleanup:
- posix_acl_release(acl);
- return retval;
-
}
static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
diff --git a/fs/9p/acl.h b/fs/9p/acl.h
index 59e18c2e8c7e..ddb7ae19d971 100644
--- a/fs/9p/acl.h
+++ b/fs/9p/acl.h
@@ -16,14 +16,14 @@
#ifdef CONFIG_9P_FS_POSIX_ACL
extern int v9fs_get_acl(struct inode *, struct p9_fid *);
-extern int v9fs_check_acl(struct inode *inode, int mask);
+extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type);
extern int v9fs_acl_chmod(struct dentry *);
extern int v9fs_set_create_acl(struct dentry *,
- struct posix_acl *, struct posix_acl *);
+ struct posix_acl **, struct posix_acl **);
extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl);
#else
-#define v9fs_check_acl NULL
+#define v9fs_iop_get_acl NULL
static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
{
return 0;
@@ -33,8 +33,8 @@ static inline int v9fs_acl_chmod(struct dentry *dentry)
return 0;
}
static inline int v9fs_set_create_acl(struct dentry *dentry,
- struct posix_acl *dpacl,
- struct posix_acl *pacl)
+ struct posix_acl **dpacl,
+ struct posix_acl **pacl)
{
return 0;
}
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 276f4a69ecd4..9a26dce5a99f 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -287,7 +287,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
goto error;
/* Now set the ACL based on the default value */
- v9fs_set_create_acl(dentry, dacl, pacl);
+ v9fs_set_create_acl(dentry, &dacl, &pacl);
v9inode = V9FS_I(inode);
mutex_lock(&v9inode->v_mutex);
@@ -328,6 +328,7 @@ error:
err_clunk_old_fid:
if (ofid)
p9_client_clunk(ofid);
+ v9fs_set_create_acl(NULL, &dacl, &pacl);
return err;
}
@@ -421,12 +422,13 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
d_instantiate(dentry, inode);
}
/* Now set the ACL based on the default value */
- v9fs_set_create_acl(dentry, dacl, pacl);
+ v9fs_set_create_acl(dentry, &dacl, &pacl);
inc_nlink(dir);
v9fs_invalidate_inode_attr(dir);
error:
if (fid)
p9_client_clunk(fid);
+ v9fs_set_create_acl(NULL, &dacl, &pacl);
return err;
}
@@ -826,10 +828,11 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
d_instantiate(dentry, inode);
}
/* Now set the ACL based on the default value */
- v9fs_set_create_acl(dentry, dacl, pacl);
+ v9fs_set_create_acl(dentry, &dacl, &pacl);
error:
if (fid)
p9_client_clunk(fid);
+ v9fs_set_create_acl(NULL, &dacl, &pacl);
return err;
}
@@ -914,7 +917,7 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = v9fs_listxattr,
- .check_acl = v9fs_check_acl,
+ .get_acl = v9fs_iop_get_acl,
};
const struct inode_operations v9fs_file_inode_operations_dotl = {
@@ -924,7 +927,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = v9fs_listxattr,
- .check_acl = v9fs_check_acl,
+ .get_acl = v9fs_iop_get_acl,
};
const struct inode_operations v9fs_symlink_inode_operations_dotl = {
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index c5567cb78432..4d433d34736f 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -233,7 +233,7 @@ static int __init anon_inode_init(void)
return 0;
err_mntput:
- mntput(anon_inode_mnt);
+ kern_unmount(anon_inode_mnt);
err_unregister_filesystem:
unregister_filesystem(&anon_inode_fs_type);
err_exit:
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 9f62ab2a7282..65a735d8f6e4 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -30,7 +30,7 @@
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
-static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
+struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
{
int size;
const char *name;
@@ -195,27 +195,6 @@ out:
return ret;
}
-int btrfs_check_acl(struct inode *inode, int mask)
-{
- int error = -EAGAIN;
-
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- error = -ECHILD;
- } else {
- struct posix_acl *acl;
- acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- }
- }
-
- return error;
-}
-
/*
* btrfs_init_acl is already generally called under fs_mutex, so the locking
* stuff has been fixed to work with that. If the locking stuff changes, we
@@ -243,8 +222,7 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
}
if (IS_POSIXACL(dir) && acl) {
- struct posix_acl *clone;
- mode_t mode;
+ mode_t mode = inode->i_mode;
if (S_ISDIR(inode->i_mode)) {
ret = btrfs_set_acl(trans, inode, acl,
@@ -252,22 +230,15 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
if (ret)
goto failed;
}
- clone = posix_acl_clone(acl, GFP_NOFS);
- ret = -ENOMEM;
- if (!clone)
- goto failed;
+ ret = posix_acl_create(&acl, GFP_NOFS, &mode);
+ if (ret < 0)
+ return ret;
- mode = inode->i_mode;
- ret = posix_acl_create_masq(clone, &mode);
- if (ret >= 0) {
- inode->i_mode = mode;
- if (ret > 0) {
- /* we need an acl */
- ret = btrfs_set_acl(trans, inode, clone,
- ACL_TYPE_ACCESS);
- }
+ inode->i_mode = mode;
+ if (ret > 0) {
+ /* we need an acl */
+ ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
}
- posix_acl_release(clone);
}
failed:
posix_acl_release(acl);
@@ -277,7 +248,7 @@ failed:
int btrfs_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int ret = 0;
if (S_ISLNK(inode->i_mode))
@@ -290,17 +261,11 @@ int btrfs_acl_chmod(struct inode *inode)
if (IS_ERR_OR_NULL(acl))
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
+ ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (ret)
+ return ret;
+ ret = btrfs_set_acl(NULL, inode, acl, ACL_TYPE_ACCESS);
posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
-
- ret = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!ret)
- ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
-
- posix_acl_release(clone);
-
return ret;
}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 82be74efbb26..fe9287b06496 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2645,9 +2645,9 @@ do { \
/* acl.c */
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
-int btrfs_check_acl(struct inode *inode, int mask);
+struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
#else
-#define btrfs_check_acl NULL
+#define btrfs_get_acl NULL
#endif
int btrfs_init_acl(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 2548a04a0230..e91b097e7252 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7351,12 +7351,12 @@ static const struct inode_operations btrfs_dir_inode_operations = {
.listxattr = btrfs_listxattr,
.removexattr = btrfs_removexattr,
.permission = btrfs_permission,
- .check_acl = btrfs_check_acl,
+ .get_acl = btrfs_get_acl,
};
static const struct inode_operations btrfs_dir_ro_inode_operations = {
.lookup = btrfs_lookup,
.permission = btrfs_permission,
- .check_acl = btrfs_check_acl,
+ .get_acl = btrfs_get_acl,
};
static const struct file_operations btrfs_dir_file_operations = {
@@ -7425,7 +7425,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
.removexattr = btrfs_removexattr,
.permission = btrfs_permission,
.fiemap = btrfs_fiemap,
- .check_acl = btrfs_check_acl,
+ .get_acl = btrfs_get_acl,
};
static const struct inode_operations btrfs_special_inode_operations = {
.getattr = btrfs_getattr,
@@ -7435,7 +7435,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
.getxattr = btrfs_getxattr,
.listxattr = btrfs_listxattr,
.removexattr = btrfs_removexattr,
- .check_acl = btrfs_check_acl,
+ .get_acl = btrfs_get_acl,
};
static const struct inode_operations btrfs_symlink_inode_operations = {
.readlink = generic_readlink,
@@ -7447,7 +7447,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
.getxattr = btrfs_getxattr,
.listxattr = btrfs_listxattr,
.removexattr = btrfs_removexattr,
- .check_acl = btrfs_check_acl,
+ .get_acl = btrfs_get_acl,
};
const struct dentry_operations btrfs_dentry_operations = {
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 14d602f178c2..499f27fc8576 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -641,7 +641,7 @@ lookup_out:
static int
cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
{
- if (nd->flags & LOOKUP_RCU)
+ if (nd && (nd->flags & LOOKUP_RCU))
return -ECHILD;
if (direntry->d_inode) {
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index bfe651f9ae16..52c053763942 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -128,7 +128,7 @@ fail:
/*
* inode->i_mutex: don't care
*/
-static struct posix_acl *
+struct posix_acl *
ext2_get_acl(struct inode *inode, int type)
{
int name_index;
@@ -231,29 +231,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return error;
}
-int
-ext2_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl;
-
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- return -ECHILD;
- return -EAGAIN;
- }
-
- acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- int error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
-}
-
/*
* Initialize the ACLs of a new inode. Called from ext2_new_inode.
*
@@ -276,29 +253,20 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
inode->i_mode &= ~current_umask();
}
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
- struct posix_acl *clone;
- mode_t mode;
-
+ mode_t mode = inode->i_mode;
if (S_ISDIR(inode->i_mode)) {
error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
if (error)
goto cleanup;
}
- clone = posix_acl_clone(acl, GFP_KERNEL);
- error = -ENOMEM;
- if (!clone)
- goto cleanup;
- mode = inode->i_mode;
- error = posix_acl_create_masq(clone, &mode);
- if (error >= 0) {
- inode->i_mode = mode;
- if (error > 0) {
- /* This is an extended ACL */
- error = ext2_set_acl(inode,
- ACL_TYPE_ACCESS, clone);
- }
+ error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+ if (error < 0)
+ return error;
+ inode->i_mode = mode;
+ if (error > 0) {
+ /* This is an extended ACL */
+ error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
}
- posix_acl_release(clone);
}
cleanup:
posix_acl_release(acl);
@@ -322,7 +290,7 @@ cleanup:
int
ext2_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int error;
if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -332,14 +300,11 @@ ext2_acl_chmod(struct inode *inode)
acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
+ error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (error)
+ return error;
+ error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- error = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!error)
- error = ext2_set_acl(inode, ACL_TYPE_ACCESS, clone);
- posix_acl_release(clone);
return error;
}
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 3ff6cbb9ac44..5c0a6a4fb052 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -54,13 +54,13 @@ static inline int ext2_acl_count(size_t size)
#ifdef CONFIG_EXT2_FS_POSIX_ACL
/* acl.c */
-extern int ext2_check_acl (struct inode *, int);
+extern struct posix_acl *ext2_get_acl(struct inode *inode, int type);
extern int ext2_acl_chmod (struct inode *);
extern int ext2_init_acl (struct inode *, struct inode *);
#else
#include <linux/sched.h>
-#define ext2_check_acl NULL
+#define ext2_get_acl NULL
#define ext2_get_acl NULL
#define ext2_set_acl NULL
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 82e06321de35..a5b3a5db3120 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -102,6 +102,6 @@ const struct inode_operations ext2_file_inode_operations = {
.removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
- .check_acl = ext2_check_acl,
+ .get_acl = ext2_get_acl,
.fiemap = ext2_fiemap,
};
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index d60b7099e2db..761fde807fc9 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -408,7 +408,7 @@ const struct inode_operations ext2_dir_inode_operations = {
.removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
- .check_acl = ext2_check_acl,
+ .get_acl = ext2_get_acl,
};
const struct inode_operations ext2_special_inode_operations = {
@@ -419,5 +419,5 @@ const struct inode_operations ext2_special_inode_operations = {
.removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
- .check_acl = ext2_check_acl,
+ .get_acl = ext2_get_acl,
};
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index edfeb293d4cb..6c29bf0df04a 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -131,7 +131,7 @@ fail:
*
* inode->i_mutex: don't care
*/
-static struct posix_acl *
+struct posix_acl *
ext3_get_acl(struct inode *inode, int type)
{
int name_index;
@@ -239,29 +239,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
return error;
}
-int
-ext3_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl;
-
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- return -ECHILD;
- return -EAGAIN;
- }
-
- acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- int error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
-}
-
/*
* Initialize the ACLs of a new inode. Called from ext3_new_inode.
*
@@ -284,8 +261,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
inode->i_mode &= ~current_umask();
}
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
- struct posix_acl *clone;
- mode_t mode;
+ mode_t mode = inode->i_mode;
if (S_ISDIR(inode->i_mode)) {
error = ext3_set_acl(handle, inode,
@@ -293,22 +269,15 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
if (error)
goto cleanup;
}
- clone = posix_acl_clone(acl, GFP_NOFS);
- error = -ENOMEM;
- if (!clone)
- goto cleanup;
-
- mode = inode->i_mode;
- error = posix_acl_create_masq(clone, &mode);
- if (error >= 0) {
- inode->i_mode = mode;
- if (error > 0) {
- /* This is an extended ACL */
- error = ext3_set_acl(handle, inode,
- ACL_TYPE_ACCESS, clone);
- }
+ error = posix_acl_create(&acl, GFP_NOFS, &mode);
+ if (error < 0)
+ return error;
+
+ inode->i_mode = mode;
+ if (error > 0) {
+ /* This is an extended ACL */
+ error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
}
- posix_acl_release(clone);
}
cleanup:
posix_acl_release(acl);
@@ -332,7 +301,9 @@ cleanup:
int
ext3_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
+ handle_t *handle;
+ int retries = 0;
int error;
if (S_ISLNK(inode->i_mode))
@@ -342,31 +313,24 @@ ext3_acl_chmod(struct inode *inode)
acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
- posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- error = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!error) {
- handle_t *handle;
- int retries = 0;
-
- retry:
- handle = ext3_journal_start(inode,
- EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
- if (IS_ERR(handle)) {
- error = PTR_ERR(handle);
- ext3_std_error(inode->i_sb, error);
- goto out;
- }
- error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
- ext3_journal_stop(handle);
- if (error == -ENOSPC &&
- ext3_should_retry_alloc(inode->i_sb, &retries))
- goto retry;
+ error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (error)
+ return error;
+retry:
+ handle = ext3_journal_start(inode,
+ EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
+ if (IS_ERR(handle)) {
+ error = PTR_ERR(handle);
+ ext3_std_error(inode->i_sb, error);
+ goto out;
}
+ error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
+ ext3_journal_stop(handle);
+ if (error == -ENOSPC &&
+ ext3_should_retry_alloc(inode->i_sb, &retries))
+ goto retry;
out:
- posix_acl_release(clone);
+ posix_acl_release(acl);
return error;
}
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 597334626de9..dbc921e458c5 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -54,13 +54,13 @@ static inline int ext3_acl_count(size_t size)
#ifdef CONFIG_EXT3_FS_POSIX_ACL
/* acl.c */
-extern int ext3_check_acl (struct inode *, int);
+extern struct posix_acl *ext3_get_acl(struct inode *inode, int type);
extern int ext3_acl_chmod (struct inode *);
extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
#else /* CONFIG_EXT3_FS_POSIX_ACL */
#include <linux/sched.h>
-#define ext3_check_acl NULL
+#define ext3_get_acl NULL
static inline int
ext3_acl_chmod(struct inode *inode)
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index f55df0e61cbd..2be5b99097f1 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -79,7 +79,7 @@ const struct inode_operations ext3_file_inode_operations = {
.listxattr = ext3_listxattr,
.removexattr = generic_removexattr,
#endif
- .check_acl = ext3_check_acl,
+ .get_acl = ext3_get_acl,
.fiemap = ext3_fiemap,
};
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index c095cf5640c7..3b57230a17bb 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2529,7 +2529,7 @@ const struct inode_operations ext3_dir_inode_operations = {
.listxattr = ext3_listxattr,
.removexattr = generic_removexattr,
#endif
- .check_acl = ext3_check_acl,
+ .get_acl = ext3_get_acl,
};
const struct inode_operations ext3_special_inode_operations = {
@@ -2540,5 +2540,5 @@ const struct inode_operations ext3_special_inode_operations = {
.listxattr = ext3_listxattr,
.removexattr = generic_removexattr,
#endif
- .check_acl = ext3_check_acl,
+ .get_acl = ext3_get_acl,
};
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 60d900fcc3db..dca2d1ded931 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -131,7 +131,7 @@ fail:
*
* inode->i_mutex: don't care
*/
-static struct posix_acl *
+struct posix_acl *
ext4_get_acl(struct inode *inode, int type)
{
int name_index;
@@ -237,29 +237,6 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
return error;
}
-int
-ext4_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl;
-
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- return -ECHILD;
- return -EAGAIN;
- }
-
- acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- int error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
-}
-
/*
* Initialize the ACLs of a new inode. Called from ext4_new_inode.
*
@@ -282,8 +259,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
inode->i_mode &= ~current_umask();
}
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
- struct posix_acl *clone;
- mode_t mode;
+ mode_t mode = inode->i_mode;
if (S_ISDIR(inode->i_mode)) {
error = ext4_set_acl(handle, inode,
@@ -291,22 +267,15 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
if (error)
goto cleanup;
}
- clone = posix_acl_clone(acl, GFP_NOFS);
- error = -ENOMEM;
- if (!clone)
- goto cleanup;
-
- mode = inode->i_mode;
- error = posix_acl_create_masq(clone, &mode);
- if (error >= 0) {
- inode->i_mode = mode;
- if (error > 0) {
- /* This is an extended ACL */
- error = ext4_set_acl(handle, inode,
- ACL_TYPE_ACCESS, clone);
- }
+ error = posix_acl_create(&acl, GFP_NOFS, &mode);
+ if (error < 0)
+ return error;
+
+ inode->i_mode = mode;
+ if (error > 0) {
+ /* This is an extended ACL */
+ error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
}
- posix_acl_release(clone);
}
cleanup:
posix_acl_release(acl);
@@ -330,9 +299,12 @@ cleanup:
int
ext4_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
+ handle_t *handle;
+ int retries = 0;
int error;
+
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -340,31 +312,24 @@ ext4_acl_chmod(struct inode *inode)
acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
- posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- error = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!error) {
- handle_t *handle;
- int retries = 0;
-
- retry:
- handle = ext4_journal_start(inode,
- EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
- if (IS_ERR(handle)) {
- error = PTR_ERR(handle);
- ext4_std_error(inode->i_sb, error);
- goto out;
- }
- error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
- ext4_journal_stop(handle);
- if (error == -ENOSPC &&
- ext4_should_retry_alloc(inode->i_sb, &retries))
- goto retry;
+ error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (error)
+ return error;
+retry:
+ handle = ext4_journal_start(inode,
+ EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+ if (IS_ERR(handle)) {
+ error = PTR_ERR(handle);
+ ext4_std_error(inode->i_sb, error);
+ goto out;
}
+ error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
+ ext4_journal_stop(handle);
+ if (error == -ENOSPC &&
+ ext4_should_retry_alloc(inode->i_sb, &retries))
+ goto retry;
out:
- posix_acl_release(clone);
+ posix_acl_release(acl);
return error;
}
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
index 9d843d5deac4..18cb39ed7c7b 100644
--- a/fs/ext4/acl.h
+++ b/fs/ext4/acl.h
@@ -54,13 +54,13 @@ static inline int ext4_acl_count(size_t size)
#ifdef CONFIG_EXT4_FS_POSIX_ACL
/* acl.c */
-extern int ext4_check_acl(struct inode *, int);
+struct posix_acl *ext4_get_acl(struct inode *inode, int type);
extern int ext4_acl_chmod(struct inode *);
extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
#else /* CONFIG_EXT4_FS_POSIX_ACL */
#include <linux/sched.h>
-#define ext4_check_acl NULL
+#define ext4_get_acl NULL
static inline int
ext4_acl_chmod(struct inode *inode)
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index ce766f974b1d..e4095e988eba 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -301,7 +301,7 @@ const struct inode_operations ext4_file_inode_operations = {
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
#endif
- .check_acl = ext4_check_acl,
+ .get_acl = ext4_get_acl,
.fiemap = ext4_fiemap,
};
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 707d605bf769..8c9babac43dc 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2590,7 +2590,7 @@ const struct inode_operations ext4_dir_inode_operations = {
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
#endif
- .check_acl = ext4_check_acl,
+ .get_acl = ext4_get_acl,
.fiemap = ext4_fiemap,
};
@@ -2602,5 +2602,5 @@ const struct inode_operations ext4_special_inode_operations = {
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
#endif
- .check_acl = ext4_check_acl,
+ .get_acl = ext4_get_acl,
};
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 70e90b4974ce..d5e33a077a67 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -132,31 +132,17 @@ generic_acl_init(struct inode *inode, struct inode *dir)
if (!S_ISLNK(inode->i_mode))
acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
if (acl) {
- struct posix_acl *clone;
-
- if (S_ISDIR(inode->i_mode)) {
- clone = posix_acl_clone(acl, GFP_KERNEL);
- error = -ENOMEM;
- if (!clone)
- goto cleanup;
- set_cached_acl(inode, ACL_TYPE_DEFAULT, clone);
- posix_acl_release(clone);
- }
- clone = posix_acl_clone(acl, GFP_KERNEL);
- error = -ENOMEM;
- if (!clone)
- goto cleanup;
- error = posix_acl_create_masq(clone, &mode);
- if (error >= 0) {
- inode->i_mode = mode;
- if (error > 0)
- set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
- }
- posix_acl_release(clone);
+ if (S_ISDIR(inode->i_mode))
+ set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
+ error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+ if (error < 0)
+ return error;
+ inode->i_mode = mode;
+ if (error > 0)
+ set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
}
error = 0;
-cleanup:
posix_acl_release(acl);
return error;
}
@@ -170,44 +156,22 @@ cleanup:
int
generic_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int error = 0;
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
if (acl) {
- clone = posix_acl_clone(acl, GFP_KERNEL);
+ error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (error)
+ return error;
+ set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- error = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!error)
- set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
- posix_acl_release(clone);
}
return error;
}
-int
-generic_check_acl(struct inode *inode, int mask)
-{
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- return -ECHILD;
- } else {
- struct posix_acl *acl;
-
- acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
- if (acl) {
- int error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
- }
- return -EAGAIN;
-}
-
const struct xattr_handler generic_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 8ef1079f1665..884c9af0542f 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -67,36 +67,9 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
return acl;
}
-/**
- * gfs2_check_acl - Check an ACL to see if we're allowed to do something
- * @inode: the file we want to do something to
- * @mask: what we want to do
- *
- * Returns: errno
- */
-
-int gfs2_check_acl(struct inode *inode, int mask)
+struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
{
- struct posix_acl *acl;
- int error;
-
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- return -ECHILD;
- return -EAGAIN;
- }
-
- acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
-
- if (acl) {
- error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
+ return gfs2_acl_get(GFS2_I(inode), type);
}
static int gfs2_set_mode(struct inode *inode, mode_t mode)
@@ -143,7 +116,7 @@ out:
int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
mode_t mode = inode->i_mode;
int error = 0;
@@ -168,16 +141,10 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
goto out;
}
- clone = posix_acl_clone(acl, GFP_NOFS);
- error = -ENOMEM;
- if (!clone)
- goto out;
- posix_acl_release(acl);
- acl = clone;
-
- error = posix_acl_create_masq(acl, &mode);
+ error = posix_acl_create(&acl, GFP_NOFS, &mode);
if (error < 0)
- goto out;
+ return error;
+
if (error == 0)
goto munge;
@@ -193,7 +160,7 @@ out:
int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
char *data;
unsigned int len;
int error;
@@ -204,25 +171,19 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
if (!acl)
return gfs2_setattr_simple(ip, attr);
- clone = posix_acl_clone(acl, GFP_NOFS);
+ error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode);
+ if (error)
+ return error;
+
+ len = posix_acl_to_xattr(acl, NULL, 0);
+ data = kmalloc(len, GFP_NOFS);
error = -ENOMEM;
- if (!clone)
+ if (data == NULL)
goto out;
- posix_acl_release(acl);
- acl = clone;
-
- error = posix_acl_chmod_masq(acl, attr->ia_mode);
- if (!error) {
- len = posix_acl_to_xattr(acl, NULL, 0);
- data = kmalloc(len, GFP_NOFS);
- error = -ENOMEM;
- if (data == NULL)
- goto out;
- posix_acl_to_xattr(acl, data, len);
- error = gfs2_xattr_acl_chmod(ip, attr, data);
- kfree(data);
- set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
- }
+ posix_acl_to_xattr(acl, data, len);
+ error = gfs2_xattr_acl_chmod(ip, attr, data);
+ kfree(data);
+ set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
out:
posix_acl_release(acl);
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index b522b0cb39ea..0da38dc7efec 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -16,7 +16,7 @@
#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default"
#define GFS2_ACL_MAX_ENTRIES 25
-extern int gfs2_check_acl(struct inode *inode, int mask);
+extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode);
extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
extern const struct xattr_handler gfs2_xattr_system_handler;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 0fb51a96eff0..900cf986aadc 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1846,7 +1846,7 @@ const struct inode_operations gfs2_file_iops = {
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
.fiemap = gfs2_fiemap,
- .check_acl = gfs2_check_acl,
+ .get_acl = gfs2_get_acl,
};
const struct inode_operations gfs2_dir_iops = {
@@ -1867,7 +1867,7 @@ const struct inode_operations gfs2_dir_iops = {
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
.fiemap = gfs2_fiemap,
- .check_acl = gfs2_check_acl,
+ .get_acl = gfs2_get_acl,
};
const struct inode_operations gfs2_symlink_iops = {
@@ -1882,6 +1882,6 @@ const struct inode_operations gfs2_symlink_iops = {
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
.fiemap = gfs2_fiemap,
- .check_acl = gfs2_check_acl,
+ .get_acl = gfs2_get_acl,
};
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7aafeb8fa300..0b686cec9976 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1030,6 +1030,7 @@ static int __init init_hugetlbfs_fs(void)
static void __exit exit_hugetlbfs_fs(void)
{
kmem_cache_destroy(hugetlbfs_inode_cachep);
+ kern_unmount(hugetlbfs_vfsmount);
unregister_filesystem(&hugetlbfs_fs_type);
bdi_destroy(&hugetlbfs_backing_dev_info);
}
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 3675b3cdee89..27c511a1cf05 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -156,7 +156,7 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
return ERR_PTR(-EINVAL);
}
-static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
+struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
{
struct posix_acl *acl;
char *value = NULL;
@@ -259,30 +259,11 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return rc;
}
-int jffs2_check_acl(struct inode *inode, int mask)
+int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, mode_t *i_mode)
{
struct posix_acl *acl;
int rc;
- if (mask & MAY_NOT_BLOCK)
- return -ECHILD;
-
- acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- rc = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return rc;
- }
- return -EAGAIN;
-}
-
-int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
-{
- struct posix_acl *acl, *clone;
- int rc;
-
cache_no_acl(inode);
if (S_ISLNK(*i_mode))
@@ -298,18 +279,13 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
if (S_ISDIR(*i_mode))
set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
- if (!clone)
- return -ENOMEM;
- rc = posix_acl_create_masq(clone, (mode_t *)i_mode);
- if (rc < 0) {
- posix_acl_release(clone);
+ rc = posix_acl_create(&acl, GFP_KERNEL, i_mode);
+ if (rc < 0)
return rc;
- }
if (rc > 0)
- set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
+ set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
- posix_acl_release(clone);
+ posix_acl_release(acl);
}
return 0;
}
@@ -335,7 +311,7 @@ int jffs2_init_acl_post(struct inode *inode)
int jffs2_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int rc;
if (S_ISLNK(inode->i_mode))
@@ -343,14 +319,11 @@ int jffs2_acl_chmod(struct inode *inode)
acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
+ rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (rc)
+ return rc;
+ rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, acl);
posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- rc = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!rc)
- rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
- posix_acl_release(clone);
return rc;
}
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 5e42de8d9541..b3421c78d9f8 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -26,9 +26,9 @@ struct jffs2_acl_header {
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
-extern int jffs2_check_acl(struct inode *, int);
+struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
extern int jffs2_acl_chmod(struct inode *);
-extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
+extern int jffs2_init_acl_pre(struct inode *, struct inode *, mode_t *);
extern int jffs2_init_acl_post(struct inode *);
extern const struct xattr_handler jffs2_acl_access_xattr_handler;
@@ -36,7 +36,7 @@ extern const struct xattr_handler jffs2_acl_default_xattr_handler;
#else
-#define jffs2_check_acl (NULL)
+#define jffs2_get_acl (NULL)
#define jffs2_acl_chmod(inode) (0)
#define jffs2_init_acl_pre(dir_i,inode,mode) (0)
#define jffs2_init_acl_post(inode) (0)
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 5f243cd63afc..9659b7c00468 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -56,7 +56,7 @@ const struct inode_operations jffs2_dir_inode_operations =
.rmdir = jffs2_rmdir,
.mknod = jffs2_mknod,
.rename = jffs2_rename,
- .check_acl = jffs2_check_acl,
+ .get_acl = jffs2_get_acl,
.setattr = jffs2_setattr,
.setxattr = jffs2_setxattr,
.getxattr = jffs2_getxattr,
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 3989f7e09f7f..61e6723535b9 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -63,7 +63,7 @@ const struct file_operations jffs2_file_operations =
const struct inode_operations jffs2_file_inode_operations =
{
- .check_acl = jffs2_check_acl,
+ .get_acl = jffs2_get_acl,
.setattr = jffs2_setattr,
.setxattr = jffs2_setxattr,
.getxattr = jffs2_getxattr,
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 46ad619b6124..eeead33d8ef0 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -406,7 +406,7 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
fill in the raw_inode while you're at it. */
-struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri)
+struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode, struct jffs2_raw_inode *ri)
{
struct inode *inode;
struct super_block *sb = dir_i->i_sb;
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 9c252835e8e5..526979c607b6 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -173,7 +173,7 @@ int jffs2_do_setattr (struct inode *, struct iattr *);
struct inode *jffs2_iget(struct super_block *, unsigned long);
void jffs2_evict_inode (struct inode *);
void jffs2_dirty_inode(struct inode *inode, int flags);
-struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
+struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode,
struct jffs2_raw_inode *ri);
int jffs2_statfs (struct dentry *, struct kstatfs *);
int jffs2_remount_fs (struct super_block *, int *, char *);
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index b955626071c2..e3035afb1814 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -20,7 +20,7 @@ const struct inode_operations jffs2_symlink_inode_operations =
{
.readlink = generic_readlink,
.follow_link = jffs2_follow_link,
- .check_acl = jffs2_check_acl,
+ .get_acl = jffs2_get_acl,
.setattr = jffs2_setattr,
.setxattr = jffs2_setxattr,
.getxattr = jffs2_getxattr,
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8a0a0666d5a6..b3a32caf2b45 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -27,7 +27,7 @@
#include "jfs_xattr.h"
#include "jfs_acl.h"
-static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
+struct posix_acl *jfs_get_acl(struct inode *inode, int type)
{
struct posix_acl *acl;
char *ea_name;
@@ -114,30 +114,9 @@ out:
return rc;
}
-int jfs_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl;
-
- if (mask & MAY_NOT_BLOCK)
- return -ECHILD;
-
- acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- int error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
-}
-
int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
{
struct posix_acl *acl = NULL;
- struct posix_acl *clone;
- mode_t mode;
int rc = 0;
if (S_ISLNK(inode->i_mode))
@@ -148,25 +127,18 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
return PTR_ERR(acl);
if (acl) {
+ mode_t mode = inode->i_mode;
if (S_ISDIR(inode->i_mode)) {
rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
if (rc)
goto cleanup;
}
- clone = posix_acl_clone(acl, GFP_KERNEL);
- if (!clone) {
- rc = -ENOMEM;
- goto cleanup;
- }
- mode = inode->i_mode;
- rc = posix_acl_create_masq(clone, &mode);
- if (rc >= 0) {
- inode->i_mode = mode;
- if (rc > 0)
- rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS,
- clone);
- }
- posix_acl_release(clone);
+ rc = posix_acl_create(&acl, GFP_KERNEL, &mode);
+ if (rc < 0)
+ goto cleanup; /* posix_acl_release(NULL) is no-op */
+ inode->i_mode = mode;
+ if (rc > 0)
+ rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
cleanup:
posix_acl_release(acl);
} else
@@ -180,8 +152,9 @@ cleanup:
int jfs_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int rc;
+ tid_t tid;
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
@@ -190,22 +163,18 @@ int jfs_acl_chmod(struct inode *inode)
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
- posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
-
- rc = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!rc) {
- tid_t tid = txBegin(inode->i_sb, 0);
- mutex_lock(&JFS_IP(inode)->commit_mutex);
- rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone);
- if (!rc)
- rc = txCommit(tid, 1, &inode, 0);
- txEnd(tid);
- mutex_unlock(&JFS_IP(inode)->commit_mutex);
- }
+ rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (rc)
+ return rc;
- posix_acl_release(clone);
+ tid = txBegin(inode->i_sb, 0);
+ mutex_lock(&JFS_IP(inode)->commit_mutex);
+ rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
+ if (!rc)
+ rc = txCommit(tid, 1, &inode, 0);
+ txEnd(tid);
+ mutex_unlock(&JFS_IP(inode)->commit_mutex);
+
+ posix_acl_release(acl);
return rc;
}
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index 7527855b5cc6..844f9460cb11 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -140,7 +140,7 @@ const struct inode_operations jfs_file_inode_operations = {
.removexattr = jfs_removexattr,
.setattr = jfs_setattr,
#ifdef CONFIG_JFS_POSIX_ACL
- .check_acl = jfs_check_acl,
+ .get_acl = jfs_get_acl,
#endif
};
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index 54e07559878d..ad84fe50ca9e 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -20,7 +20,7 @@
#ifdef CONFIG_JFS_POSIX_ACL
-int jfs_check_acl(struct inode *, int);
+struct posix_acl *jfs_get_acl(struct inode *inode, int type);
int jfs_init_acl(tid_t, struct inode *, struct inode *);
int jfs_acl_chmod(struct inode *inode);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 03787ef6a118..29b1f1a21142 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1537,7 +1537,7 @@ const struct inode_operations jfs_dir_inode_operations = {
.removexattr = jfs_removexattr,
.setattr = jfs_setattr,
#ifdef CONFIG_JFS_POSIX_ACL
- .check_acl = jfs_check_acl,
+ .get_acl = jfs_get_acl,
#endif
};
diff --git a/fs/namei.c b/fs/namei.c
index b7fad009bbf6..ec2e5656b444 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -32,6 +32,7 @@
#include <linux/fcntl.h>
#include <linux/device_cgroup.h>
#include <linux/fs_struct.h>
+#include <linux/posix_acl.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -173,12 +174,60 @@ void putname(const char *name)
EXPORT_SYMBOL(putname);
#endif
+static int check_acl(struct inode *inode, int mask)
+{
+ struct posix_acl *acl;
+
+ /*
+ * Under RCU walk, we cannot even do a "get_cached_acl()",
+ * because that involves locking and getting a refcount on
+ * a cached ACL.
+ *
+ * So the only case we handle during RCU walking is the
+ * case of a cached "no ACL at all", which needs no locks
+ * or refcounts.
+ */
+ if (mask & MAY_NOT_BLOCK) {
+ if (negative_cached_acl(inode, ACL_TYPE_ACCESS))
+ return -EAGAIN;
+ return -ECHILD;
+ }
+
+ acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
+
+ /*
+ * A filesystem can force a ACL callback by just never filling the
+ * ACL cache. But normally you'd fill the cache either at inode
+ * instantiation time, or on the first ->get_acl call.
+ *
+ * If the filesystem doesn't have a get_acl() function at all, we'll
+ * just create the negative cache entry.
+ */
+ if (acl == ACL_NOT_CACHED) {
+ if (inode->i_op->get_acl) {
+ acl = inode->i_op->get_acl(inode, ACL_TYPE_ACCESS);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ } else {
+ set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);
+ return -EAGAIN;
+ }
+ }
+
+ if (acl) {
+ int error = posix_acl_permission(inode, acl, mask);
+ posix_acl_release(acl);
+ return error;
+ }
+
+ return -EAGAIN;
+}
+
/*
* This does basic POSIX ACL permission checking
*/
static int acl_permission_check(struct inode *inode, int mask)
{
- int (*check_acl)(struct inode *inode, int mask);
unsigned int mode = inode->i_mode;
mask &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_NOT_BLOCK;
@@ -189,8 +238,7 @@ static int acl_permission_check(struct inode *inode, int mask)
if (current_fsuid() == inode->i_uid)
mode >>= 6;
else {
- check_acl = inode->i_op->check_acl;
- if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
+ if (IS_POSIXACL(inode) && (mode & S_IRWXG)) {
int error = check_acl(inode, mask);
if (error != -EAGAIN)
return error;
diff --git a/fs/namespace.c b/fs/namespace.c
index cda50fe9250a..22bfe8273c68 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2721,6 +2721,25 @@ EXPORT_SYMBOL(put_mnt_ns);
struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
{
- return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+ struct vfsmount *mnt;
+ mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+ if (!IS_ERR(mnt)) {
+ /*
+ * it is a longterm mount, don't release mnt until
+ * we unmount before file sys is unregistered
+ */
+ mnt_make_longterm(mnt);
+ }
+ return mnt;
}
EXPORT_SYMBOL_GPL(kern_mount_data);
+
+void kern_unmount(struct vfsmount *mnt)
+{
+ /* release long term mount so mount point can be released */
+ if (!IS_ERR_OR_NULL(mnt)) {
+ mnt_make_shortterm(mnt);
+ mntput(mnt);
+ }
+}
+EXPORT_SYMBOL(kern_unmount);
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 274342771655..e49e73107e62 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -427,16 +427,12 @@ int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
}
if (!dfacl)
return 0;
- acl = posix_acl_clone(dfacl, GFP_KERNEL);
- error = -ENOMEM;
- if (!acl)
- goto out_release_dfacl;
- error = posix_acl_create_masq(acl, &mode);
+ acl = posix_acl_dup(dfacl);
+ error = posix_acl_create(&acl, GFP_KERNEL, &mode);
if (error < 0)
- goto out_release_acl;
+ goto out_release_dfacl;
error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
dfacl : NULL);
-out_release_acl:
posix_acl_release(acl);
out_release_dfacl:
posix_acl_release(dfacl);
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 1cee970eb55a..783c58d9daf1 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -290,47 +290,32 @@ static int ocfs2_set_acl(handle_t *handle,
return ret;
}
-int ocfs2_check_acl(struct inode *inode, int mask)
+struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
{
struct ocfs2_super *osb;
struct buffer_head *di_bh = NULL;
struct posix_acl *acl;
int ret = -EAGAIN;
- if (mask & MAY_NOT_BLOCK)
- return -ECHILD;
-
osb = OCFS2_SB(inode->i_sb);
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
- return ret;
+ return NULL;
ret = ocfs2_read_inode_block(inode, &di_bh);
- if (ret < 0) {
- mlog_errno(ret);
- return ret;
- }
+ if (ret < 0)
+ return ERR_PTR(ret);
- acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh);
+ acl = ocfs2_get_acl_nolock(inode, type, di_bh);
brelse(di_bh);
- if (IS_ERR(acl)) {
- mlog_errno(PTR_ERR(acl));
- return PTR_ERR(acl);
- }
- if (acl) {
- ret = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return ret;
- }
-
- return -EAGAIN;
+ return acl;
}
int ocfs2_acl_chmod(struct inode *inode)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int ret;
if (S_ISLNK(inode->i_mode))
@@ -342,15 +327,12 @@ int ocfs2_acl_chmod(struct inode *inode)
acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
+ ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (ret)
+ return ret;
+ ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
+ acl, NULL, NULL);
posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- ret = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!ret)
- ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
- clone, NULL, NULL);
- posix_acl_release(clone);
return ret;
}
@@ -388,8 +370,6 @@ int ocfs2_init_acl(handle_t *handle,
}
}
if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
- struct posix_acl *clone;
-
if (S_ISDIR(inode->i_mode)) {
ret = ocfs2_set_acl(handle, inode, di_bh,
ACL_TYPE_DEFAULT, acl,
@@ -397,27 +377,22 @@ int ocfs2_init_acl(handle_t *handle,
if (ret)
goto cleanup;
}
- clone = posix_acl_clone(acl, GFP_NOFS);
- ret = -ENOMEM;
- if (!clone)
- goto cleanup;
-
mode = inode->i_mode;
- ret = posix_acl_create_masq(clone, &mode);
- if (ret >= 0) {
- ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
- if (ret2) {
- mlog_errno(ret2);
- ret = ret2;
- goto cleanup;
- }
- if (ret > 0) {
- ret = ocfs2_set_acl(handle, inode,
- di_bh, ACL_TYPE_ACCESS,
- clone, meta_ac, data_ac);
- }
+ ret = posix_acl_create(&acl, GFP_NOFS, &mode);
+ if (ret < 0)
+ return ret;
+
+ ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+ if (ret2) {
+ mlog_errno(ret2);
+ ret = ret2;
+ goto cleanup;
+ }
+ if (ret > 0) {
+ ret = ocfs2_set_acl(handle, inode,
+ di_bh, ACL_TYPE_ACCESS,
+ acl, meta_ac, data_ac);
}
- posix_acl_release(clone);
}
cleanup:
posix_acl_release(acl);
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index 5c5d31f05853..071fbd380f2f 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -26,7 +26,7 @@ struct ocfs2_acl_entry {
__le32 e_id;
};
-extern int ocfs2_check_acl(struct inode *, int);
+struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type);
extern int ocfs2_acl_chmod(struct inode *);
extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
struct buffer_head *, struct buffer_head *,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 0fc2bd34039d..de4ea1af041b 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2600,14 +2600,14 @@ const struct inode_operations ocfs2_file_iops = {
.listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
- .check_acl = ocfs2_check_acl,
+ .get_acl = ocfs2_iop_get_acl,
};
const struct inode_operations ocfs2_special_file_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
.permission = ocfs2_permission,
- .check_acl = ocfs2_check_acl,
+ .get_acl = ocfs2_iop_get_acl,
};
/*
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 33889dc52dd7..53aa41ed7bf3 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2498,5 +2498,5 @@ const struct inode_operations ocfs2_dir_iops = {
.listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
- .check_acl = ocfs2_check_acl,
+ .get_acl = ocfs2_iop_get_acl,
};
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7db50de..1b7f9af67ccf 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1291,8 +1291,8 @@ static int __init init_pipe_fs(void)
static void __exit exit_pipe_fs(void)
{
+ kern_unmount(pipe_mnt);
unregister_filesystem(&pipe_fs_type);
- mntput(pipe_mnt);
}
fs_initcall(init_pipe_fs);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index b1cf6bf4b41d..a6227d219e93 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -24,13 +24,9 @@
EXPORT_SYMBOL(posix_acl_init);
EXPORT_SYMBOL(posix_acl_alloc);
-EXPORT_SYMBOL(posix_acl_clone);
EXPORT_SYMBOL(posix_acl_valid);
EXPORT_SYMBOL(posix_acl_equiv_mode);
EXPORT_SYMBOL(posix_acl_from_mode);
-EXPORT_SYMBOL(posix_acl_create_masq);
-EXPORT_SYMBOL(posix_acl_chmod_masq);
-EXPORT_SYMBOL(posix_acl_permission);
/*
* Init a fresh posix_acl
@@ -59,7 +55,7 @@ posix_acl_alloc(int count, gfp_t flags)
/*
* Clone an ACL.
*/
-struct posix_acl *
+static struct posix_acl *
posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
{
struct posix_acl *clone = NULL;
@@ -283,8 +279,7 @@ check_perm:
* system calls. All permissions that are not granted by the acl are removed.
* The permissions in the acl are changed to reflect the mode_p parameter.
*/
-int
-posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
+static int posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
{
struct posix_acl_entry *pa, *pe;
struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
@@ -341,8 +336,7 @@ posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
/*
* Modify the ACL for the chmod syscall.
*/
-int
-posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
+static int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
{
struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
struct posix_acl_entry *pa, *pe;
@@ -386,3 +380,39 @@ posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
return 0;
}
+
+int
+posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p)
+{
+ struct posix_acl *clone = posix_acl_clone(*acl, gfp);
+ int err = -ENOMEM;
+ if (clone) {
+ err = posix_acl_create_masq(clone, mode_p);
+ if (err < 0) {
+ posix_acl_release(clone);
+ clone = NULL;
+ }
+ }
+ posix_acl_release(*acl);
+ *acl = clone;
+ return err;
+}
+EXPORT_SYMBOL(posix_acl_create);
+
+int
+posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, mode_t mode)
+{
+ struct posix_acl *clone = posix_acl_clone(*acl, gfp);
+ int err = -ENOMEM;
+ if (clone) {
+ err = posix_acl_chmod_masq(clone, mode);
+ if (err) {
+ posix_acl_release(clone);
+ clone = NULL;
+ }
+ }
+ posix_acl_release(*acl);
+ *acl = clone;
+ return err;
+}
+EXPORT_SYMBOL(posix_acl_chmod);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index c7156dc39ce7..ace635053a36 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -319,5 +319,5 @@ const struct inode_operations reiserfs_file_inode_operations = {
.listxattr = reiserfs_listxattr,
.removexattr = reiserfs_removexattr,
.permission = reiserfs_permission,
- .check_acl = reiserfs_check_acl,
+ .get_acl = reiserfs_get_acl,
};
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2922b90ceac1..9b0d4b78b4fb 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1475,6 +1475,11 @@ void reiserfs_read_locked_inode(struct inode *inode,
reiserfs_check_path(&path_to_sd); /* init inode should be relsing */
+ /*
+ * Stat data v1 doesn't support ACLs.
+ */
+ if (get_inode_sd_version(inode) == STAT_DATA_V1)
+ cache_no_acl(inode);
}
/**
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 551f1b79dbc4..ef392324bbf1 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1529,7 +1529,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
.listxattr = reiserfs_listxattr,
.removexattr = reiserfs_removexattr,
.permission = reiserfs_permission,
- .check_acl = reiserfs_check_acl,
+ .get_acl = reiserfs_get_acl,
};
/*
@@ -1546,7 +1546,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
.listxattr = reiserfs_listxattr,
.removexattr = reiserfs_removexattr,
.permission = reiserfs_permission,
- .check_acl = reiserfs_check_acl,
+ .get_acl = reiserfs_get_acl,
};
@@ -1560,5 +1560,5 @@ const struct inode_operations reiserfs_special_inode_operations = {
.listxattr = reiserfs_listxattr,
.removexattr = reiserfs_removexattr,
.permission = reiserfs_permission,
- .check_acl = reiserfs_check_acl,
+ .get_acl = reiserfs_get_acl,
};
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 6938d8c68d6e..6bc346c160e7 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -867,33 +867,6 @@ out:
return err;
}
-int reiserfs_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl;
- int error = -EAGAIN; /* do regular unix permission checks by default */
-
- /*
- * Stat data v1 doesn't support ACLs.
- */
- if (get_inode_sd_version(inode) == STAT_DATA_V1)
- return -EAGAIN;
-
- if (mask & MAY_NOT_BLOCK)
- return -ECHILD;
-
- acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-
- if (acl) {
- if (!IS_ERR(acl)) {
- error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- } else if (PTR_ERR(acl) != -ENODATA)
- error = PTR_ERR(acl);
- }
-
- return error;
-}
-
static int create_privroot(struct dentry *dentry)
{
int err;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 3dc38f1206fc..7362cf4c946a 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -354,9 +354,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
return PTR_ERR(acl);
if (acl) {
- struct posix_acl *acl_copy;
mode_t mode = inode->i_mode;
- int need_acl;
/* Copy the default ACL to the default ACL of a new directory */
if (S_ISDIR(inode->i_mode)) {
@@ -368,29 +366,15 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
/* Now we reconcile the new ACL and the mode,
potentially modifying both */
- acl_copy = posix_acl_clone(acl, GFP_NOFS);
- if (!acl_copy) {
- err = -ENOMEM;
- goto cleanup;
- }
+ err = posix_acl_create(&acl, GFP_NOFS, &mode);
+ if (err < 0)
+ return err;
- need_acl = posix_acl_create_masq(acl_copy, &mode);
- if (need_acl >= 0) {
- if (mode != inode->i_mode) {
- inode->i_mode = mode;
- }
+ inode->i_mode = mode;
- /* If we need an ACL.. */
- if (need_acl > 0) {
- err = reiserfs_set_acl(th, inode,
- ACL_TYPE_ACCESS,
- acl_copy);
- if (err)
- goto cleanup_copy;
- }
- }
- cleanup_copy:
- posix_acl_release(acl_copy);
+ /* If we need an ACL.. */
+ if (err > 0)
+ err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
cleanup:
posix_acl_release(acl);
} else {
@@ -445,7 +429,10 @@ int reiserfs_cache_default_acl(struct inode *inode)
int reiserfs_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct reiserfs_transaction_handle th;
+ struct posix_acl *acl;
+ size_t size;
+ int depth;
int error;
if (S_ISLNK(inode->i_mode))
@@ -463,30 +450,22 @@ int reiserfs_acl_chmod(struct inode *inode)
return 0;
if (IS_ERR(acl))
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_NOFS);
- posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
- error = posix_acl_chmod_masq(clone, inode->i_mode);
+ error = posix_acl_chmod(&acl, GFP_NOFS, inode->i_mode);
+ if (error)
+ return error;
+
+ size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count));
+ depth = reiserfs_write_lock_once(inode->i_sb);
+ error = journal_begin(&th, inode->i_sb, size * 2);
if (!error) {
- struct reiserfs_transaction_handle th;
- size_t size = reiserfs_xattr_nblocks(inode,
- reiserfs_acl_size(clone->a_count));
- int depth;
-
- depth = reiserfs_write_lock_once(inode->i_sb);
- error = journal_begin(&th, inode->i_sb, size * 2);
- if (!error) {
- int error2;
- error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
- clone);
- error2 = journal_end(&th, inode->i_sb, size * 2);
- if (error2)
- error = error2;
- }
- reiserfs_write_unlock_once(inode->i_sb, depth);
+ int error2;
+ error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl);
+ error2 = journal_end(&th, inode->i_sb, size * 2);
+ if (error2)
+ error = error2;
}
- posix_acl_release(clone);
+ reiserfs_write_unlock_once(inode->i_sb, depth);
+ posix_acl_release(acl);
return error;
}
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c
index cac48fe22ad5..44ce51656804 100644
--- a/fs/xfs/linux-2.6/xfs_acl.c
+++ b/fs/xfs/linux-2.6/xfs_acl.c
@@ -114,6 +114,8 @@ xfs_get_acl(struct inode *inode, int type)
if (acl != ACL_NOT_CACHED)
return acl;
+ trace_xfs_get_acl(ip);
+
switch (type) {
case ACL_TYPE_ACCESS:
ea_name = SGI_ACL_FILE;
@@ -218,40 +220,6 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return error;
}
-int
-xfs_check_acl(struct inode *inode, int mask)
-{
- struct xfs_inode *ip;
- struct posix_acl *acl;
- int error = -EAGAIN;
-
- ip = XFS_I(inode);
- trace_xfs_check_acl(ip);
-
- /*
- * If there is no attribute fork no ACL exists on this inode and
- * we can skip the whole exercise.
- */
- if (!XFS_IFORK_Q(ip))
- return -EAGAIN;
-
- if (mask & MAY_NOT_BLOCK) {
- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
- return -ECHILD;
- return -EAGAIN;
- }
-
- acl = xfs_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl) {
- error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- }
-
- return error;
-}
-
static int
xfs_set_mode(struct inode *inode, mode_t mode)
{
@@ -297,29 +265,23 @@ posix_acl_default_exists(struct inode *inode)
* No need for i_mutex because the inode is not yet exposed to the VFS.
*/
int
-xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl)
+xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
{
- struct posix_acl *clone;
- mode_t mode;
+ mode_t mode = inode->i_mode;
int error = 0, inherit = 0;
if (S_ISDIR(inode->i_mode)) {
- error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl);
+ error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
if (error)
- return error;
+ goto out;
}
- clone = posix_acl_clone(default_acl, GFP_KERNEL);
- if (!clone)
- return -ENOMEM;
-
- mode = inode->i_mode;
- error = posix_acl_create_masq(clone, &mode);
+ error = posix_acl_create(&acl, GFP_KERNEL, &mode);
if (error < 0)
- goto out_release_clone;
+ return error;
/*
- * If posix_acl_create_masq returns a positive value we need to
+ * If posix_acl_create returns a positive value we need to
* inherit a permission that can't be represented using the Unix
* mode bits and we actually need to set an ACL.
*/
@@ -328,20 +290,20 @@ xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl)
error = xfs_set_mode(inode, mode);
if (error)
- goto out_release_clone;
+ goto out;
if (inherit)
- error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+ error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
- out_release_clone:
- posix_acl_release(clone);
+out:
+ posix_acl_release(acl);
return error;
}
int
xfs_acl_chmod(struct inode *inode)
{
- struct posix_acl *acl, *clone;
+ struct posix_acl *acl;
int error;
if (S_ISLNK(inode->i_mode))
@@ -351,16 +313,12 @@ xfs_acl_chmod(struct inode *inode)
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
- clone = posix_acl_clone(acl, GFP_KERNEL);
- posix_acl_release(acl);
- if (!clone)
- return -ENOMEM;
-
- error = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!error)
- error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+ error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+ if (error)
+ return error;
- posix_acl_release(clone);
+ error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+ posix_acl_release(acl);
return error;
}
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index cca00f49e092..825390e1c138 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -881,11 +881,14 @@ xfs_file_aio_write(
/* Handle various SYNC-type writes */
if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
loff_t end = pos + ret - 1;
+ int error;
xfs_rw_iunlock(ip, iolock);
- ret = -xfs_file_fsync(file, pos, end,
+ error = xfs_file_fsync(file, pos, end,
(file->f_flags & __O_SYNC) ? 0 : 1);
xfs_rw_ilock(ip, iolock);
+ if (error)
+ ret = error;
}
out_unlock:
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 501e4f630548..6544c3236bc8 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -202,9 +202,9 @@ xfs_vn_mknod(
if (default_acl) {
error = -xfs_inherit_acl(inode, default_acl);
+ default_acl = NULL;
if (unlikely(error))
goto out_cleanup_inode;
- posix_acl_release(default_acl);
}
@@ -1022,7 +1022,7 @@ xfs_vn_fiemap(
}
static const struct inode_operations xfs_inode_operations = {
- .check_acl = xfs_check_acl,
+ .get_acl = xfs_get_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
@@ -1048,7 +1048,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
.rmdir = xfs_vn_unlink,
.mknod = xfs_vn_mknod,
.rename = xfs_vn_rename,
- .check_acl = xfs_check_acl,
+ .get_acl = xfs_get_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
@@ -1073,7 +1073,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
.rmdir = xfs_vn_unlink,
.mknod = xfs_vn_mknod,
.rename = xfs_vn_rename,
- .check_acl = xfs_check_acl,
+ .get_acl = xfs_get_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
@@ -1086,7 +1086,7 @@ static const struct inode_operations xfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = xfs_vn_follow_link,
.put_link = xfs_vn_put_link,
- .check_acl = xfs_check_acl,
+ .get_acl = xfs_get_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
@@ -1194,6 +1194,10 @@ xfs_setup_inode(
break;
}
+ /* if there is no attribute fork no ACL can exist on this inode */
+ if (!XFS_IFORK_Q(ip))
+ cache_no_acl(inode);
+
xfs_iflags_clear(ip, XFS_INEW);
barrier();
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index fda0708ef2ea..690fc7a7bd72 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -571,7 +571,7 @@ DEFINE_INODE_EVENT(xfs_alloc_file_space);
DEFINE_INODE_EVENT(xfs_free_file_space);
DEFINE_INODE_EVENT(xfs_readdir);
#ifdef CONFIG_XFS_POSIX_ACL
-DEFINE_INODE_EVENT(xfs_check_acl);
+DEFINE_INODE_EVENT(xfs_get_acl);
#endif
DEFINE_INODE_EVENT(xfs_vm_bmap);
DEFINE_INODE_EVENT(xfs_file_ioctl);
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 0135e2a669d7..2c656ef49473 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -42,7 +42,6 @@ struct xfs_acl {
#define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1)
#ifdef CONFIG_XFS_POSIX_ACL
-extern int xfs_check_acl(struct inode *inode, int mask);
extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl);
extern int xfs_acl_chmod(struct inode *inode);
@@ -52,7 +51,6 @@ extern int posix_acl_default_exists(struct inode *inode);
extern const struct xattr_handler xfs_xattr_acl_access_handler;
extern const struct xattr_handler xfs_xattr_acl_default_handler;
#else
-# define xfs_check_acl NULL
# define xfs_get_acl(inode, type) NULL
# define xfs_inherit_acl(inode, default_acl) 0
# define xfs_acl_chmod(inode) 0