static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
{
- int size, name_index;
+ int size;
+ const char *name;
char *value = NULL;
struct posix_acl *acl = NULL, **p_acl;
switch (type) {
case ACL_TYPE_ACCESS:
- name_index = BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS;
+ name = POSIX_ACL_XATTR_ACCESS;
p_acl = &BTRFS_I(inode)->i_acl;
break;
case ACL_TYPE_DEFAULT:
- name_index = BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+ name = POSIX_ACL_XATTR_DEFAULT;
p_acl = &BTRFS_I(inode)->i_default_acl;
break;
default:
return ERR_PTR(-EINVAL);
}
+ /* Handle the cached NULL acl case without locking */
+ acl = ACCESS_ONCE(*p_acl);
+ if (!acl)
+ return acl;
+
spin_lock(&inode->i_lock);
- if (*p_acl != BTRFS_ACL_NOT_CACHED)
- acl = posix_acl_dup(*p_acl);
+ acl = *p_acl;
+ if (acl != BTRFS_ACL_NOT_CACHED)
+ acl = posix_acl_dup(acl);
spin_unlock(&inode->i_lock);
- if (acl)
+ if (acl != BTRFS_ACL_NOT_CACHED)
return acl;
-
- size = btrfs_xattr_get(inode, name_index, "", NULL, 0);
+ size = __btrfs_getxattr(inode, name, "", 0);
if (size > 0) {
value = kzalloc(size, GFP_NOFS);
if (!value)
return ERR_PTR(-ENOMEM);
- size = btrfs_xattr_get(inode, name_index, "", value, size);
+ 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);
}
kfree(value);
- } else if (size == -ENOENT) {
+ } 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);
+ } else {
+ acl = ERR_PTR(-EIO);
}
return acl;
*/
static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
- int ret, name_index = 0, size = 0;
+ int ret, size = 0;
+ const char *name;
struct posix_acl **p_acl;
char *value = NULL;
mode_t mode;
return ret;
ret = 0;
inode->i_mode = mode;
- name_index = BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS;
+ name = POSIX_ACL_XATTR_ACCESS;
p_acl = &BTRFS_I(inode)->i_acl;
break;
case ACL_TYPE_DEFAULT:
if (!S_ISDIR(inode->i_mode))
return acl ? -EINVAL : 0;
- name_index = BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+ name = POSIX_ACL_XATTR_DEFAULT;
p_acl = &BTRFS_I(inode)->i_default_acl;
break;
default:
goto out;
}
- ret = btrfs_xattr_set(inode, name_index, "", value, size, 0);
+ ret = __btrfs_setxattr(inode, name, value, size, 0);
out:
- if (value)
- kfree(value);
+ kfree(value);
if (!ret)
btrfs_update_cached_acl(inode, p_acl, acl);
}
static int btrfs_xattr_acl_default_set(struct inode *inode, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags)
{
return btrfs_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
}
if (!acl)
- inode->i_mode &= ~current->fs->umask;
+ inode->i_mode &= ~current_umask();
}
if (IS_POSIXACL(dir) && acl) {
struct xattr_handler btrfs_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
- .list = btrfs_xattr_generic_list,
.get = btrfs_xattr_acl_default_get,
.set = btrfs_xattr_acl_default_set,
};
struct xattr_handler btrfs_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
- .list = btrfs_xattr_generic_list,
.get = btrfs_xattr_acl_access_get,
.set = btrfs_xattr_acl_access_set,
};