diff options
Diffstat (limited to 'fs/btrfs/acl.c')
-rw-r--r-- | fs/btrfs/acl.c | 44 |
1 files changed, 9 insertions, 35 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 603972576f0f..f128427b995b 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -29,51 +29,28 @@ | |||
29 | 29 | ||
30 | #ifdef CONFIG_FS_POSIX_ACL | 30 | #ifdef CONFIG_FS_POSIX_ACL |
31 | 31 | ||
32 | static void btrfs_update_cached_acl(struct inode *inode, | ||
33 | struct posix_acl **p_acl, | ||
34 | struct posix_acl *acl) | ||
35 | { | ||
36 | spin_lock(&inode->i_lock); | ||
37 | if (*p_acl && *p_acl != BTRFS_ACL_NOT_CACHED) | ||
38 | posix_acl_release(*p_acl); | ||
39 | *p_acl = posix_acl_dup(acl); | ||
40 | spin_unlock(&inode->i_lock); | ||
41 | } | ||
42 | |||
43 | static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) | 32 | static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) |
44 | { | 33 | { |
45 | int size; | 34 | int size; |
46 | const char *name; | 35 | const char *name; |
47 | char *value = NULL; | 36 | char *value = NULL; |
48 | struct posix_acl *acl = NULL, **p_acl; | 37 | struct posix_acl *acl; |
38 | |||
39 | acl = get_cached_acl(inode, type); | ||
40 | if (acl != ACL_NOT_CACHED) | ||
41 | return acl; | ||
49 | 42 | ||
50 | switch (type) { | 43 | switch (type) { |
51 | case ACL_TYPE_ACCESS: | 44 | case ACL_TYPE_ACCESS: |
52 | name = POSIX_ACL_XATTR_ACCESS; | 45 | name = POSIX_ACL_XATTR_ACCESS; |
53 | p_acl = &BTRFS_I(inode)->i_acl; | ||
54 | break; | 46 | break; |
55 | case ACL_TYPE_DEFAULT: | 47 | case ACL_TYPE_DEFAULT: |
56 | name = POSIX_ACL_XATTR_DEFAULT; | 48 | name = POSIX_ACL_XATTR_DEFAULT; |
57 | p_acl = &BTRFS_I(inode)->i_default_acl; | ||
58 | break; | 49 | break; |
59 | default: | 50 | default: |
60 | return ERR_PTR(-EINVAL); | 51 | BUG(); |
61 | } | 52 | } |
62 | 53 | ||
63 | /* Handle the cached NULL acl case without locking */ | ||
64 | acl = ACCESS_ONCE(*p_acl); | ||
65 | if (!acl) | ||
66 | return acl; | ||
67 | |||
68 | spin_lock(&inode->i_lock); | ||
69 | acl = *p_acl; | ||
70 | if (acl != BTRFS_ACL_NOT_CACHED) | ||
71 | acl = posix_acl_dup(acl); | ||
72 | spin_unlock(&inode->i_lock); | ||
73 | |||
74 | if (acl != BTRFS_ACL_NOT_CACHED) | ||
75 | return acl; | ||
76 | |||
77 | size = __btrfs_getxattr(inode, name, "", 0); | 54 | size = __btrfs_getxattr(inode, name, "", 0); |
78 | if (size > 0) { | 55 | if (size > 0) { |
79 | value = kzalloc(size, GFP_NOFS); | 56 | value = kzalloc(size, GFP_NOFS); |
@@ -82,13 +59,13 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) | |||
82 | size = __btrfs_getxattr(inode, name, value, size); | 59 | size = __btrfs_getxattr(inode, name, value, size); |
83 | if (size > 0) { | 60 | if (size > 0) { |
84 | acl = posix_acl_from_xattr(value, size); | 61 | acl = posix_acl_from_xattr(value, size); |
85 | btrfs_update_cached_acl(inode, p_acl, acl); | 62 | set_cached_acl(inode, type, acl); |
86 | } | 63 | } |
87 | kfree(value); | 64 | kfree(value); |
88 | } else if (size == -ENOENT || size == -ENODATA || size == 0) { | 65 | } else if (size == -ENOENT || size == -ENODATA || size == 0) { |
89 | /* FIXME, who returns -ENOENT? I think nobody */ | 66 | /* FIXME, who returns -ENOENT? I think nobody */ |
90 | acl = NULL; | 67 | acl = NULL; |
91 | btrfs_update_cached_acl(inode, p_acl, acl); | 68 | set_cached_acl(inode, type, acl); |
92 | } else { | 69 | } else { |
93 | acl = ERR_PTR(-EIO); | 70 | acl = ERR_PTR(-EIO); |
94 | } | 71 | } |
@@ -121,7 +98,6 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
121 | { | 98 | { |
122 | int ret, size = 0; | 99 | int ret, size = 0; |
123 | const char *name; | 100 | const char *name; |
124 | struct posix_acl **p_acl; | ||
125 | char *value = NULL; | 101 | char *value = NULL; |
126 | mode_t mode; | 102 | mode_t mode; |
127 | 103 | ||
@@ -141,13 +117,11 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
141 | ret = 0; | 117 | ret = 0; |
142 | inode->i_mode = mode; | 118 | inode->i_mode = mode; |
143 | name = POSIX_ACL_XATTR_ACCESS; | 119 | name = POSIX_ACL_XATTR_ACCESS; |
144 | p_acl = &BTRFS_I(inode)->i_acl; | ||
145 | break; | 120 | break; |
146 | case ACL_TYPE_DEFAULT: | 121 | case ACL_TYPE_DEFAULT: |
147 | if (!S_ISDIR(inode->i_mode)) | 122 | if (!S_ISDIR(inode->i_mode)) |
148 | return acl ? -EINVAL : 0; | 123 | return acl ? -EINVAL : 0; |
149 | name = POSIX_ACL_XATTR_DEFAULT; | 124 | name = POSIX_ACL_XATTR_DEFAULT; |
150 | p_acl = &BTRFS_I(inode)->i_default_acl; | ||
151 | break; | 125 | break; |
152 | default: | 126 | default: |
153 | return -EINVAL; | 127 | return -EINVAL; |
@@ -172,7 +146,7 @@ out: | |||
172 | kfree(value); | 146 | kfree(value); |
173 | 147 | ||
174 | if (!ret) | 148 | if (!ret) |
175 | btrfs_update_cached_acl(inode, p_acl, acl); | 149 | set_cached_acl(inode, type, acl); |
176 | 150 | ||
177 | return ret; | 151 | return ret; |
178 | } | 152 | } |