From 05fc0790b6c9c611129f2f712d00b6a8a364e8d2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Jun 2009 19:54:52 -0400 Subject: switch jfs to inode->i_acl Signed-off-by: Al Viro --- fs/jfs/acl.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'fs/jfs/acl.c') diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 06ca1b8d2054..5fcfc9857c11 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -31,7 +31,6 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) { struct posix_acl *acl; char *ea_name; - struct jfs_inode_info *ji = JFS_IP(inode); struct posix_acl **p_acl; int size; char *value = NULL; @@ -39,17 +38,17 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) switch(type) { case ACL_TYPE_ACCESS: ea_name = POSIX_ACL_XATTR_ACCESS; - p_acl = &ji->i_acl; + p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &ji->i_default_acl; + p_acl = &inode->i_default_acl; break; default: return ERR_PTR(-EINVAL); } - if (*p_acl != JFS_ACL_NOT_CACHED) + if (*p_acl != ACL_NOT_CACHED) return posix_acl_dup(*p_acl); size = __jfs_getxattr(inode, ea_name, NULL, 0); @@ -80,7 +79,6 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, struct posix_acl *acl) { char *ea_name; - struct jfs_inode_info *ji = JFS_IP(inode); struct posix_acl **p_acl; int rc; int size = 0; @@ -92,11 +90,11 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, switch(type) { case ACL_TYPE_ACCESS: ea_name = POSIX_ACL_XATTR_ACCESS; - p_acl = &ji->i_acl; + p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &ji->i_default_acl; + p_acl = &inode->i_default_acl; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; @@ -117,7 +115,7 @@ out: kfree(value); if (!rc) { - if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) + if (*p_acl && (*p_acl != ACL_NOT_CACHED)) posix_acl_release(*p_acl); *p_acl = posix_acl_dup(acl); } @@ -126,17 +124,15 @@ out: static int jfs_check_acl(struct inode *inode, int mask) { - struct jfs_inode_info *ji = JFS_IP(inode); - - if (ji->i_acl == JFS_ACL_NOT_CACHED) { + if (inode->i_acl == ACL_NOT_CACHED) { struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); if (IS_ERR(acl)) return PTR_ERR(acl); posix_acl_release(acl); } - if (ji->i_acl) - return posix_acl_permission(inode, ji->i_acl, mask); + if (inode->i_acl) + return posix_acl_permission(inode, inode->i_acl, mask); return -EAGAIN; } -- cgit v1.2.3 From 073aaa1b142461d91f83da66db1184d7c1b1edea Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 9 Jun 2009 12:11:54 -0400 Subject: helpers for acl caching + switch to those helpers: get_cached_acl(inode, type), set_cached_acl(inode, type, acl), forget_cached_acl(inode, type). ubifs/xattr.c needed includes reordered, the rest is a plain switchover. Signed-off-by: Al Viro --- fs/btrfs/acl.c | 44 +++++-------------------- fs/ext2/acl.c | 79 ++++++++++---------------------------------- fs/ext3/acl.c | 83 +++++++++++------------------------------------ fs/ext4/acl.c | 65 +++++-------------------------------- fs/jffs2/acl.c | 60 +++++++--------------------------- fs/jfs/acl.c | 32 ++++++++---------- fs/jfs/xattr.c | 10 ++---- fs/reiserfs/xattr_acl.c | 49 ++++++---------------------- fs/ubifs/xattr.c | 2 +- include/linux/posix_acl.h | 64 ++++++++++++++++++++++++++++++++++++ 10 files changed, 155 insertions(+), 333 deletions(-) (limited to 'fs/jfs/acl.c') diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 6db8a42a3e5e..f128427b995b 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -29,51 +29,28 @@ #ifdef CONFIG_FS_POSIX_ACL -static void btrfs_update_cached_acl(struct inode *inode, - struct posix_acl **p_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*p_acl && *p_acl != ACL_NOT_CACHED) - posix_acl_release(*p_acl); - *p_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) { int size; const char *name; char *value = NULL; - struct posix_acl *acl = NULL, **p_acl; + struct posix_acl *acl; + + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &inode->i_default_acl; break; default: - return ERR_PTR(-EINVAL); + BUG(); } - /* Handle the cached NULL acl case without locking */ - acl = ACCESS_ONCE(*p_acl); - if (!acl) - return acl; - - spin_lock(&inode->i_lock); - acl = *p_acl; - if (acl != ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); - - if (acl != ACL_NOT_CACHED) - return acl; - size = __btrfs_getxattr(inode, name, "", 0); if (size > 0) { value = kzalloc(size, GFP_NOFS); @@ -82,13 +59,13 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) size = __btrfs_getxattr(inode, name, value, size); if (size > 0) { acl = posix_acl_from_xattr(value, size); - btrfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); } kfree(value); } else if (size == -ENOENT || size == -ENODATA || size == 0) { /* FIXME, who returns -ENOENT? I think nobody */ acl = NULL; - btrfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); } else { acl = ERR_PTR(-EIO); } @@ -121,7 +98,6 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int ret, size = 0; const char *name; - struct posix_acl **p_acl; char *value = NULL; mode_t mode; @@ -141,13 +117,11 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) ret = 0; inode->i_mode = mode; name = POSIX_ACL_XATTR_ACCESS; - p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) return acl ? -EINVAL : 0; name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &inode->i_default_acl; break; default: return -EINVAL; @@ -172,7 +146,7 @@ out: kfree(value); if (!ret) - btrfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); return ret; } diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index d2ffddc12117..d636e1297cad 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -125,30 +125,6 @@ fail: return ERR_PTR(-EINVAL); } -static inline struct posix_acl * -ext2_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACL_NOT_CACHED; - - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - acl = posix_acl_dup(*i_acl); - spin_unlock(&inode->i_lock); - - return acl; -} - -static inline void -ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - /* * inode->i_mutex: don't care */ @@ -163,23 +139,19 @@ ext2_get_acl(struct inode *inode, int type) if (!test_opt(inode->i_sb, POSIX_ACL)) return NULL; - switch(type) { - case ACL_TYPE_ACCESS: - acl = ext2_iget_acl(inode, &inode->i_acl); - if (acl != ACL_NOT_CACHED) - return acl; - name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; - break; - - case ACL_TYPE_DEFAULT: - acl = ext2_iget_acl(inode, &inode->i_default_acl); - if (acl != ACL_NOT_CACHED) - return acl; - name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; - break; - - default: - return ERR_PTR(-EINVAL); + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + + switch (type) { + case ACL_TYPE_ACCESS: + name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; + break; + default: + BUG(); } retval = ext2_xattr_get(inode, name_index, "", NULL, 0); if (retval > 0) { @@ -196,17 +168,9 @@ ext2_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) { - switch(type) { - case ACL_TYPE_ACCESS: - ext2_iset_acl(inode, &inode->i_acl, acl); - break; + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext2_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } return acl; } @@ -261,17 +225,8 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) error = ext2_xattr_set(inode, name_index, "", value, size, 0); kfree(value); - if (!error) { - switch(type) { - case ACL_TYPE_ACCESS: - ext2_iset_acl(inode, &inode->i_acl, acl); - break; - - case ACL_TYPE_DEFAULT: - ext2_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } + if (!error) + set_cached_acl(inode, type, acl); return error; } diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index a9707689d9e1..e167bae37ef0 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -126,33 +126,6 @@ fail: return ERR_PTR(-EINVAL); } -static inline struct posix_acl * -ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACCESS_ONCE(*i_acl); - - if (acl) { - spin_lock(&inode->i_lock); - acl = *i_acl; - if (acl != ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); - } - - return acl; -} - -static inline void -ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - /* * Inode operation get_posix_acl(). * @@ -169,24 +142,21 @@ ext3_get_acl(struct inode *inode, int type) if (!test_opt(inode->i_sb, POSIX_ACL)) return NULL; - switch(type) { - case ACL_TYPE_ACCESS: - acl = ext3_iget_acl(inode, &inode->i_acl); - if (acl != ACL_NOT_CACHED) - return acl; - name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; - break; - - case ACL_TYPE_DEFAULT: - acl = ext3_iget_acl(inode, &inode->i_default_acl); - if (acl != ACL_NOT_CACHED) - return acl; - name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT; - break; - - default: - return ERR_PTR(-EINVAL); + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + + switch (type) { + case ACL_TYPE_ACCESS: + name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT; + break; + default: + BUG(); } + retval = ext3_xattr_get(inode, name_index, "", NULL, 0); if (retval > 0) { value = kmalloc(retval, GFP_NOFS); @@ -202,17 +172,9 @@ ext3_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) { - switch(type) { - case ACL_TYPE_ACCESS: - ext3_iset_acl(inode, &inode->i_acl, acl); - break; + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext3_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } return acl; } @@ -269,17 +231,10 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, value, size, 0); kfree(value); - if (!error) { - switch(type) { - case ACL_TYPE_ACCESS: - ext3_iset_acl(inode, &inode->i_acl, acl); - break; - case ACL_TYPE_DEFAULT: - ext3_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } + if (!error) + set_cached_acl(inode, type, acl); + return error; } diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 0084e3a19d86..f6d8967149ca 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -126,33 +126,6 @@ fail: return ERR_PTR(-EINVAL); } -static inline struct posix_acl * -ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACCESS_ONCE(*i_acl); - - if (acl) { - spin_lock(&inode->i_lock); - acl = *i_acl; - if (acl != ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); - } - - return acl; -} - -static inline void -ext4_iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - /* * Inode operation get_posix_acl(). * @@ -169,23 +142,19 @@ ext4_get_acl(struct inode *inode, int type) if (!test_opt(inode->i_sb, POSIX_ACL)) return NULL; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch (type) { case ACL_TYPE_ACCESS: - acl = ext4_iget_acl(inode, &inode->i_acl); - if (acl != ACL_NOT_CACHED) - return acl; name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; break; - case ACL_TYPE_DEFAULT: - acl = ext4_iget_acl(inode, &inode->i_default_acl); - if (acl != ACL_NOT_CACHED) - return acl; name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; break; - default: - return ERR_PTR(-EINVAL); + BUG(); } retval = ext4_xattr_get(inode, name_index, "", NULL, 0); if (retval > 0) { @@ -202,17 +171,9 @@ ext4_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) { - switch (type) { - case ACL_TYPE_ACCESS: - ext4_iset_acl(inode, &inode->i_acl, acl); - break; + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext4_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } return acl; } @@ -269,17 +230,9 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, value, size, 0); kfree(value); - if (!error) { - switch (type) { - case ACL_TYPE_ACCESS: - ext4_iset_acl(inode, &inode->i_acl, acl); - break; + if (!error) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext4_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } return error; } diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index ac16589ebbd1..edd2ad6416d8 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -156,47 +156,25 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size) return ERR_PTR(-EINVAL); } -static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACL_NOT_CACHED; - - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - acl = posix_acl_dup(*i_acl); - spin_unlock(&inode->i_lock); - return acl; -} - -static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) { struct posix_acl *acl; char *value = NULL; int rc, xprefix; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch (type) { case ACL_TYPE_ACCESS: - acl = jffs2_iget_acl(inode, &inode->i_acl); - if (acl != ACL_NOT_CACHED) - return acl; xprefix = JFFS2_XPREFIX_ACL_ACCESS; break; case ACL_TYPE_DEFAULT: - acl = jffs2_iget_acl(inode, &inode->i_default_acl); - if (acl != ACL_NOT_CACHED) - return acl; xprefix = JFFS2_XPREFIX_ACL_DEFAULT; break; default: - return ERR_PTR(-EINVAL); + BUG(); } rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0); if (rc > 0) { @@ -214,16 +192,8 @@ static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) } if (value) kfree(value); - if (!IS_ERR(acl)) { - switch (type) { - case ACL_TYPE_ACCESS: - jffs2_iset_acl(inode, &inode->i_acl, acl); - break; - case ACL_TYPE_DEFAULT: - jffs2_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); return acl; } @@ -283,16 +253,8 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) return -EINVAL; } rc = __jffs2_set_acl(inode, xprefix, acl); - if (!rc) { - switch(type) { - case ACL_TYPE_ACCESS: - jffs2_iset_acl(inode, &inode->i_acl, acl); - break; - case ACL_TYPE_DEFAULT: - jffs2_iset_acl(inode, &inode->i_default_acl, acl); - break; - } - } + if (!rc) + set_cached_acl(inode, type, acl); return rc; } @@ -336,7 +298,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) *i_mode &= ~current_umask(); } else { if (S_ISDIR(*i_mode)) - jffs2_iset_acl(inode, &inode->i_default_acl, acl); + set_cached_acl(inode, ACL_TYPE_DEFAULT, acl); clone = posix_acl_clone(acl, GFP_KERNEL); if (!clone) @@ -347,7 +309,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) return rc; } if (rc > 0) - jffs2_iset_acl(inode, &inode->i_acl, clone); + set_cached_acl(inode, ACL_TYPE_ACCESS, clone); posix_acl_release(clone); } diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 5fcfc9857c11..f272bf032e1e 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -31,26 +31,24 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) { struct posix_acl *acl; char *ea_name; - struct posix_acl **p_acl; int size; char *value = NULL; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch(type) { case ACL_TYPE_ACCESS: ea_name = POSIX_ACL_XATTR_ACCESS; - p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &inode->i_default_acl; break; default: return ERR_PTR(-EINVAL); } - if (*p_acl != ACL_NOT_CACHED) - return posix_acl_dup(*p_acl); - size = __jfs_getxattr(inode, ea_name, NULL, 0); if (size > 0) { @@ -61,17 +59,18 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) } if (size < 0) { - if (size == -ENODATA) { - *p_acl = NULL; + if (size == -ENODATA) acl = NULL; - } else + else acl = ERR_PTR(size); } else { acl = posix_acl_from_xattr(value, size); - if (!IS_ERR(acl)) - *p_acl = posix_acl_dup(acl); } kfree(value); + if (!IS_ERR(acl)) { + set_cached_acl(inode, type, acl); + posix_acl_release(acl); + } return acl; } @@ -79,7 +78,6 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, struct posix_acl *acl) { char *ea_name; - struct posix_acl **p_acl; int rc; int size = 0; char *value = NULL; @@ -90,11 +88,9 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, switch(type) { case ACL_TYPE_ACCESS: ea_name = POSIX_ACL_XATTR_ACCESS; - p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &inode->i_default_acl; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; @@ -114,11 +110,9 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, out: kfree(value); - if (!rc) { - if (*p_acl && (*p_acl != ACL_NOT_CACHED)) - posix_acl_release(*p_acl); - *p_acl = posix_acl_dup(acl); - } + if (!rc) + set_cached_acl(inode, type, acl); + return rc; } diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index f6e90e343593..fad364548bc9 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -727,10 +727,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name, /* * We're changing the ACL. Get rid of the cached one */ - acl =inode->i_acl; - if (acl != ACL_NOT_CACHED) - posix_acl_release(acl); - inode->i_acl = ACL_NOT_CACHED; + forget_cached_acl(inode, ACL_TYPE_ACCESS); return 0; } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) { @@ -746,10 +743,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name, /* * We're changing the default ACL. Get rid of the cached one */ - acl = inode->i_default_acl; - if (acl && (acl != ACL_NOT_CACHED)) - posix_acl_release(acl); - inode->i_default_acl = ACL_NOT_CACHED; + forget_cached_acl(inode, ACL_TYPE_DEFAULT); return 0; } diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index b6e473faa8b8..35d6e672a279 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -188,29 +188,6 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size) return ERR_PTR(-EINVAL); } -static inline void iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - -static inline struct posix_acl *iget_acl(struct inode *inode, - struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACL_NOT_CACHED; - - spin_lock(&inode->i_lock); - if (*i_acl != ACL_NOT_CACHED) - acl = posix_acl_dup(*i_acl); - spin_unlock(&inode->i_lock); - - return acl; -} - /* * Inode operation get_posix_acl(). * @@ -220,31 +197,29 @@ static inline struct posix_acl *iget_acl(struct inode *inode, struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) { char *name, *value; - struct posix_acl *acl, **p_acl; + struct posix_acl *acl; int size; int retval; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - p_acl = &inode->i_acl; break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &inode->i_default_acl; break; default: - return ERR_PTR(-EINVAL); + BUG(); } - acl = iget_acl(inode, p_acl); - if (acl != ACL_NOT_CACHED) - return acl; - size = reiserfs_xattr_get(inode, name, NULL, 0); if (size < 0) { if (size == -ENODATA || size == -ENOSYS) { - *p_acl = NULL; + set_cached_acl(inode, type, NULL); return NULL; } return ERR_PTR(size); @@ -259,14 +234,13 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) /* This shouldn't actually happen as it should have been caught above.. but just in case */ acl = NULL; - *p_acl = acl; } else if (retval < 0) { acl = ERR_PTR(retval); } else { acl = posix_acl_from_disk(value, retval); - if (!IS_ERR(acl)) - iset_acl(inode, p_acl, acl); } + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); kfree(value); return acl; @@ -284,7 +258,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, { char *name; void *value = NULL; - struct posix_acl **p_acl; size_t size = 0; int error; @@ -294,7 +267,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - p_acl = &inode->i_acl; if (acl) { mode_t mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); @@ -309,7 +281,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &inode->i_default_acl; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; @@ -342,7 +313,7 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, kfree(value); if (!error) - iset_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); return error; } diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index cfd31e229c89..adafcf556531 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -55,9 +55,9 @@ * ACL support is not implemented. */ +#include "ubifs.h" #include #include -#include "ubifs.h" /* * Limit the number of extended attributes per inode so that the total size diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 4bc241290c24..0cdba01b7756 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -83,4 +83,68 @@ extern int posix_acl_chmod_masq(struct posix_acl *, mode_t); extern struct posix_acl *get_posix_acl(struct inode *, int); extern int set_posix_acl(struct inode *, int, struct posix_acl *); +static inline struct posix_acl *get_cached_acl(struct inode *inode, int type) +{ + struct posix_acl **p, *acl; + switch (type) { + case ACL_TYPE_ACCESS: + p = &inode->i_acl; + break; + case ACL_TYPE_DEFAULT: + p = &inode->i_default_acl; + break; + default: + return ERR_PTR(-EINVAL); + } + acl = ACCESS_ONCE(*p); + if (acl) { + spin_lock(&inode->i_lock); + acl = *p; + if (acl != ACL_NOT_CACHED) + acl = posix_acl_dup(acl); + spin_unlock(&inode->i_lock); + } + return acl; +} + +static inline void set_cached_acl(struct inode *inode, + int type, + struct posix_acl *acl) +{ + struct posix_acl *old = NULL; + spin_lock(&inode->i_lock); + switch (type) { + case ACL_TYPE_ACCESS: + old = inode->i_acl; + inode->i_acl = posix_acl_dup(acl); + break; + case ACL_TYPE_DEFAULT: + old = inode->i_default_acl; + inode->i_default_acl = posix_acl_dup(acl); + break; + } + spin_unlock(&inode->i_lock); + if (old != ACL_NOT_CACHED) + posix_acl_release(old); +} + +static inline void forget_cached_acl(struct inode *inode, int type) +{ + struct posix_acl *old = NULL; + spin_lock(&inode->i_lock); + switch (type) { + case ACL_TYPE_ACCESS: + old = inode->i_acl; + inode->i_acl = ACL_NOT_CACHED; + break; + case ACL_TYPE_DEFAULT: + old = inode->i_default_acl; + inode->i_default_acl = ACL_NOT_CACHED; + break; + } + spin_unlock(&inode->i_lock); + if (old != ACL_NOT_CACHED) + posix_acl_release(old); +} + #endif /* __LINUX_POSIX_ACL_H */ -- cgit v1.2.3 From d5bb68adda7cc179e8efadeaa3a283cb470f13a6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 24 Jun 2009 17:02:42 -0400 Subject: another race fix in jfs_check_acl() Signed-off-by: Al Viro --- fs/jfs/acl.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'fs/jfs/acl.c') diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index f272bf032e1e..91fa3ad6e8c2 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -118,15 +118,16 @@ out: static int jfs_check_acl(struct inode *inode, int mask) { - if (inode->i_acl == ACL_NOT_CACHED) { - struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); - if (IS_ERR(acl)) - return PTR_ERR(acl); + struct posix_acl *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; } - if (inode->i_acl) - return posix_acl_permission(inode, inode->i_acl, mask); return -EAGAIN; } -- cgit v1.2.3 From 4a19fb11a90fdbbcb3bc02effa036230d035ca28 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Thu, 23 Jul 2009 11:26:05 +0200 Subject: jfs: Fix early release of acl in jfs_get_acl BugLink: http://bugs.launchpad.net/ubuntu/+bug/396780 Commit 073aaa1b142461d91f83da66db1184d7c1b1edea "helpers for acl caching + switch to those" introduced new helper functions for acl handling but seems to have introduced a regression for jfs as the acl is released before returning it to the caller, instead of leaving this for the caller to do. This causes the acl object to be used after freeing it, leading to kernel panics in completely different places. Thanks to Christophe Dumez for reporting and bisecting into this. Reported-by: Christophe Dumez Tested-by: Christophe Dumez Signed-off-by: Stefan Bader Acked-by: Andy Whitcroft Signed-off-by: Dave Kleikamp --- fs/jfs/acl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/jfs/acl.c') diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 91fa3ad6e8c2..a29c7c3e3fb8 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -67,10 +67,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) acl = posix_acl_from_xattr(value, size); } kfree(value); - if (!IS_ERR(acl)) { + if (!IS_ERR(acl)) set_cached_acl(inode, type, acl); - posix_acl_release(acl); - } return acl; } -- cgit v1.2.3