diff options
Diffstat (limited to 'fs/btrfs/acl.c')
-rw-r--r-- | fs/btrfs/acl.c | 18 |
1 files changed, 13 insertions, 5 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) | |||
60 | return ERR_PTR(-EINVAL); | 60 | return ERR_PTR(-EINVAL); |
61 | } | 61 | } |
62 | 62 | ||
63 | /* Handle the cached NULL acl case without locking */ | ||
64 | acl = ACCESS_ONCE(*p_acl); | ||
65 | if (!acl) | ||
66 | return acl; | ||
67 | |||
63 | spin_lock(&inode->i_lock); | 68 | spin_lock(&inode->i_lock); |
64 | if (*p_acl != BTRFS_ACL_NOT_CACHED) | 69 | acl = *p_acl; |
65 | acl = posix_acl_dup(*p_acl); | 70 | if (acl != BTRFS_ACL_NOT_CACHED) |
71 | acl = posix_acl_dup(acl); | ||
66 | spin_unlock(&inode->i_lock); | 72 | spin_unlock(&inode->i_lock); |
67 | 73 | ||
68 | if (acl) | 74 | if (acl != BTRFS_ACL_NOT_CACHED) |
69 | return acl; | 75 | return acl; |
70 | 76 | ||
71 | |||
72 | size = __btrfs_getxattr(inode, name, "", 0); | 77 | size = __btrfs_getxattr(inode, name, "", 0); |
73 | if (size > 0) { | 78 | if (size > 0) { |
74 | value = kzalloc(size, GFP_NOFS); | 79 | value = kzalloc(size, GFP_NOFS); |
@@ -80,9 +85,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) | |||
80 | btrfs_update_cached_acl(inode, p_acl, acl); | 85 | btrfs_update_cached_acl(inode, p_acl, acl); |
81 | } | 86 | } |
82 | kfree(value); | 87 | kfree(value); |
83 | } else if (size == -ENOENT) { | 88 | } else if (size == -ENOENT || size == -ENODATA || size == 0) { |
89 | /* FIXME, who returns -ENOENT? I think nobody */ | ||
84 | acl = NULL; | 90 | acl = NULL; |
85 | btrfs_update_cached_acl(inode, p_acl, acl); | 91 | btrfs_update_cached_acl(inode, p_acl, acl); |
92 | } else { | ||
93 | acl = ERR_PTR(-EIO); | ||
86 | } | 94 | } |
87 | 95 | ||
88 | return acl; | 96 | return acl; |