summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/acl.c18
-rw-r--r--fs/btrfs/inode.c4
2 files changed, 15 insertions, 7 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 7fdd184a528d..cbba000dccbe 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -60,15 +60,20 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
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_getxattr(inode, name, "", 0);
if (size > 0) {
value = kzalloc(size, GFP_NOFS);
@@ -80,9 +85,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
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;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 98bd5069d54a..dc812ec551f6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3047,8 +3047,8 @@ static noinline void init_btrfs_i(struct inode *inode)
{
struct btrfs_inode *bi = BTRFS_I(inode);
- bi->i_acl = NULL;
- bi->i_default_acl = NULL;
+ bi->i_acl = BTRFS_ACL_NOT_CACHED;
+ bi->i_default_acl = BTRFS_ACL_NOT_CACHED;
bi->generation = 0;
bi->sequence = 0;