aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/acl.c44
-rw-r--r--fs/ext2/acl.c79
-rw-r--r--fs/ext3/acl.c83
-rw-r--r--fs/ext4/acl.c65
-rw-r--r--fs/jffs2/acl.c60
-rw-r--r--fs/jfs/acl.c32
-rw-r--r--fs/jfs/xattr.c10
-rw-r--r--fs/reiserfs/xattr_acl.c49
-rw-r--r--fs/ubifs/xattr.c2
-rw-r--r--include/linux/posix_acl.h64
10 files changed, 155 insertions, 333 deletions
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 @@
29 29
30#ifdef CONFIG_FS_POSIX_ACL 30#ifdef CONFIG_FS_POSIX_ACL
31 31
32static 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 != ACL_NOT_CACHED)
38 posix_acl_release(*p_acl);
39 *p_acl = posix_acl_dup(acl);
40 spin_unlock(&inode->i_lock);
41}
42
43static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) 32static 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 = &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 = &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 != ACL_NOT_CACHED)
71 acl = posix_acl_dup(acl);
72 spin_unlock(&inode->i_lock);
73
74 if (acl != 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 = &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 = &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}
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:
125 return ERR_PTR(-EINVAL); 125 return ERR_PTR(-EINVAL);
126} 126}
127 127
128static inline struct posix_acl *
129ext2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
130{
131 struct posix_acl *acl = ACL_NOT_CACHED;
132
133 spin_lock(&inode->i_lock);
134 if (*i_acl != ACL_NOT_CACHED)
135 acl = posix_acl_dup(*i_acl);
136 spin_unlock(&inode->i_lock);
137
138 return acl;
139}
140
141static inline void
142ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl,
143 struct posix_acl *acl)
144{
145 spin_lock(&inode->i_lock);
146 if (*i_acl != ACL_NOT_CACHED)
147 posix_acl_release(*i_acl);
148 *i_acl = posix_acl_dup(acl);
149 spin_unlock(&inode->i_lock);
150}
151
152/* 128/*
153 * inode->i_mutex: don't care 129 * inode->i_mutex: don't care
154 */ 130 */
@@ -163,23 +139,19 @@ ext2_get_acl(struct inode *inode, int type)
163 if (!test_opt(inode->i_sb, POSIX_ACL)) 139 if (!test_opt(inode->i_sb, POSIX_ACL))
164 return NULL; 140 return NULL;
165 141
166 switch(type) { 142 acl = get_cached_acl(inode, type);
167 case ACL_TYPE_ACCESS: 143 if (acl != ACL_NOT_CACHED)
168 acl = ext2_iget_acl(inode, &inode->i_acl); 144 return acl;
169 if (acl != ACL_NOT_CACHED) 145
170 return acl; 146 switch (type) {
171 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; 147 case ACL_TYPE_ACCESS:
172 break; 148 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
173 149 break;
174 case ACL_TYPE_DEFAULT: 150 case ACL_TYPE_DEFAULT:
175 acl = ext2_iget_acl(inode, &inode->i_default_acl); 151 name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
176 if (acl != ACL_NOT_CACHED) 152 break;
177 return acl; 153 default:
178 name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; 154 BUG();
179 break;
180
181 default:
182 return ERR_PTR(-EINVAL);
183 } 155 }
184 retval = ext2_xattr_get(inode, name_index, "", NULL, 0); 156 retval = ext2_xattr_get(inode, name_index, "", NULL, 0);
185 if (retval > 0) { 157 if (retval > 0) {
@@ -196,17 +168,9 @@ ext2_get_acl(struct inode *inode, int type)
196 acl = ERR_PTR(retval); 168 acl = ERR_PTR(retval);
197 kfree(value); 169 kfree(value);
198 170
199 if (!IS_ERR(acl)) { 171 if (!IS_ERR(acl))
200 switch(type) { 172 set_cached_acl(inode, type, acl);
201 case ACL_TYPE_ACCESS:
202 ext2_iset_acl(inode, &inode->i_acl, acl);
203 break;
204 173
205 case ACL_TYPE_DEFAULT:
206 ext2_iset_acl(inode, &inode->i_default_acl, acl);
207 break;
208 }
209 }
210 return acl; 174 return acl;
211} 175}
212 176
@@ -261,17 +225,8 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
261 error = ext2_xattr_set(inode, name_index, "", value, size, 0); 225 error = ext2_xattr_set(inode, name_index, "", value, size, 0);
262 226
263 kfree(value); 227 kfree(value);
264 if (!error) { 228 if (!error)
265 switch(type) { 229 set_cached_acl(inode, type, acl);
266 case ACL_TYPE_ACCESS:
267 ext2_iset_acl(inode, &inode->i_acl, acl);
268 break;
269
270 case ACL_TYPE_DEFAULT:
271 ext2_iset_acl(inode, &inode->i_default_acl, acl);
272 break;
273 }
274 }
275 return error; 230 return error;
276} 231}
277 232
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:
126 return ERR_PTR(-EINVAL); 126 return ERR_PTR(-EINVAL);
127} 127}
128 128
129static inline struct posix_acl *
130ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl)
131{
132 struct posix_acl *acl = ACCESS_ONCE(*i_acl);
133
134 if (acl) {
135 spin_lock(&inode->i_lock);
136 acl = *i_acl;
137 if (acl != ACL_NOT_CACHED)
138 acl = posix_acl_dup(acl);
139 spin_unlock(&inode->i_lock);
140 }
141
142 return acl;
143}
144
145static inline void
146ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl,
147 struct posix_acl *acl)
148{
149 spin_lock(&inode->i_lock);
150 if (*i_acl != ACL_NOT_CACHED)
151 posix_acl_release(*i_acl);
152 *i_acl = posix_acl_dup(acl);
153 spin_unlock(&inode->i_lock);
154}
155
156/* 129/*
157 * Inode operation get_posix_acl(). 130 * Inode operation get_posix_acl().
158 * 131 *
@@ -169,24 +142,21 @@ ext3_get_acl(struct inode *inode, int type)
169 if (!test_opt(inode->i_sb, POSIX_ACL)) 142 if (!test_opt(inode->i_sb, POSIX_ACL))
170 return NULL; 143 return NULL;
171 144
172 switch(type) { 145 acl = get_cached_acl(inode, type);
173 case ACL_TYPE_ACCESS: 146 if (acl != ACL_NOT_CACHED)
174 acl = ext3_iget_acl(inode, &inode->i_acl); 147 return acl;
175 if (acl != ACL_NOT_CACHED) 148
176 return acl; 149 switch (type) {
177 name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; 150 case ACL_TYPE_ACCESS:
178 break; 151 name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
179 152 break;
180 case ACL_TYPE_DEFAULT: 153 case ACL_TYPE_DEFAULT:
181 acl = ext3_iget_acl(inode, &inode->i_default_acl); 154 name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
182 if (acl != ACL_NOT_CACHED) 155 break;
183 return acl; 156 default:
184 name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT; 157 BUG();
185 break;
186
187 default:
188 return ERR_PTR(-EINVAL);
189 } 158 }
159
190 retval = ext3_xattr_get(inode, name_index, "", NULL, 0); 160 retval = ext3_xattr_get(inode, name_index, "", NULL, 0);
191 if (retval > 0) { 161 if (retval > 0) {
192 value = kmalloc(retval, GFP_NOFS); 162 value = kmalloc(retval, GFP_NOFS);
@@ -202,17 +172,9 @@ ext3_get_acl(struct inode *inode, int type)
202 acl = ERR_PTR(retval); 172 acl = ERR_PTR(retval);
203 kfree(value); 173 kfree(value);
204 174
205 if (!IS_ERR(acl)) { 175 if (!IS_ERR(acl))
206 switch(type) { 176 set_cached_acl(inode, type, acl);
207 case ACL_TYPE_ACCESS:
208 ext3_iset_acl(inode, &inode->i_acl, acl);
209 break;
210 177
211 case ACL_TYPE_DEFAULT:
212 ext3_iset_acl(inode, &inode->i_default_acl, acl);
213 break;
214 }
215 }
216 return acl; 178 return acl;
217} 179}
218 180
@@ -269,17 +231,10 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
269 value, size, 0); 231 value, size, 0);
270 232
271 kfree(value); 233 kfree(value);
272 if (!error) {
273 switch(type) {
274 case ACL_TYPE_ACCESS:
275 ext3_iset_acl(inode, &inode->i_acl, acl);
276 break;
277 234
278 case ACL_TYPE_DEFAULT: 235 if (!error)
279 ext3_iset_acl(inode, &inode->i_default_acl, acl); 236 set_cached_acl(inode, type, acl);
280 break; 237
281 }
282 }
283 return error; 238 return error;
284} 239}
285 240
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:
126 return ERR_PTR(-EINVAL); 126 return ERR_PTR(-EINVAL);
127} 127}
128 128
129static inline struct posix_acl *
130ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl)
131{
132 struct posix_acl *acl = ACCESS_ONCE(*i_acl);
133
134 if (acl) {
135 spin_lock(&inode->i_lock);
136 acl = *i_acl;
137 if (acl != ACL_NOT_CACHED)
138 acl = posix_acl_dup(acl);
139 spin_unlock(&inode->i_lock);
140 }
141
142 return acl;
143}
144
145static inline void
146ext4_iset_acl(struct inode *inode, struct posix_acl **i_acl,
147 struct posix_acl *acl)
148{
149 spin_lock(&inode->i_lock);
150 if (*i_acl != ACL_NOT_CACHED)
151 posix_acl_release(*i_acl);
152 *i_acl = posix_acl_dup(acl);
153 spin_unlock(&inode->i_lock);
154}
155
156/* 129/*
157 * Inode operation get_posix_acl(). 130 * Inode operation get_posix_acl().
158 * 131 *
@@ -169,23 +142,19 @@ ext4_get_acl(struct inode *inode, int type)
169 if (!test_opt(inode->i_sb, POSIX_ACL)) 142 if (!test_opt(inode->i_sb, POSIX_ACL))
170 return NULL; 143 return NULL;
171 144
145 acl = get_cached_acl(inode, type);
146 if (acl != ACL_NOT_CACHED)
147 return acl;
148
172 switch (type) { 149 switch (type) {
173 case ACL_TYPE_ACCESS: 150 case ACL_TYPE_ACCESS:
174 acl = ext4_iget_acl(inode, &inode->i_acl);
175 if (acl != ACL_NOT_CACHED)
176 return acl;
177 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 151 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
178 break; 152 break;
179
180 case ACL_TYPE_DEFAULT: 153 case ACL_TYPE_DEFAULT:
181 acl = ext4_iget_acl(inode, &inode->i_default_acl);
182 if (acl != ACL_NOT_CACHED)
183 return acl;
184 name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; 154 name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
185 break; 155 break;
186
187 default: 156 default:
188 return ERR_PTR(-EINVAL); 157 BUG();
189 } 158 }
190 retval = ext4_xattr_get(inode, name_index, "", NULL, 0); 159 retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
191 if (retval > 0) { 160 if (retval > 0) {
@@ -202,17 +171,9 @@ ext4_get_acl(struct inode *inode, int type)
202 acl = ERR_PTR(retval); 171 acl = ERR_PTR(retval);
203 kfree(value); 172 kfree(value);
204 173
205 if (!IS_ERR(acl)) { 174 if (!IS_ERR(acl))
206 switch (type) { 175 set_cached_acl(inode, type, acl);
207 case ACL_TYPE_ACCESS:
208 ext4_iset_acl(inode, &inode->i_acl, acl);
209 break;
210 176
211 case ACL_TYPE_DEFAULT:
212 ext4_iset_acl(inode, &inode->i_default_acl, acl);
213 break;
214 }
215 }
216 return acl; 177 return acl;
217} 178}
218 179
@@ -269,17 +230,9 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
269 value, size, 0); 230 value, size, 0);
270 231
271 kfree(value); 232 kfree(value);
272 if (!error) { 233 if (!error)
273 switch (type) { 234 set_cached_acl(inode, type, acl);
274 case ACL_TYPE_ACCESS:
275 ext4_iset_acl(inode, &inode->i_acl, acl);
276 break;
277 235
278 case ACL_TYPE_DEFAULT:
279 ext4_iset_acl(inode, &inode->i_default_acl, acl);
280 break;
281 }
282 }
283 return error; 236 return error;
284} 237}
285 238
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)
156 return ERR_PTR(-EINVAL); 156 return ERR_PTR(-EINVAL);
157} 157}
158 158
159static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
160{
161 struct posix_acl *acl = ACL_NOT_CACHED;
162
163 spin_lock(&inode->i_lock);
164 if (*i_acl != ACL_NOT_CACHED)
165 acl = posix_acl_dup(*i_acl);
166 spin_unlock(&inode->i_lock);
167 return acl;
168}
169
170static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl)
171{
172 spin_lock(&inode->i_lock);
173 if (*i_acl != ACL_NOT_CACHED)
174 posix_acl_release(*i_acl);
175 *i_acl = posix_acl_dup(acl);
176 spin_unlock(&inode->i_lock);
177}
178
179static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) 159static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
180{ 160{
181 struct posix_acl *acl; 161 struct posix_acl *acl;
182 char *value = NULL; 162 char *value = NULL;
183 int rc, xprefix; 163 int rc, xprefix;
184 164
165 acl = get_cached_acl(inode, type);
166 if (acl != ACL_NOT_CACHED)
167 return acl;
168
185 switch (type) { 169 switch (type) {
186 case ACL_TYPE_ACCESS: 170 case ACL_TYPE_ACCESS:
187 acl = jffs2_iget_acl(inode, &inode->i_acl);
188 if (acl != ACL_NOT_CACHED)
189 return acl;
190 xprefix = JFFS2_XPREFIX_ACL_ACCESS; 171 xprefix = JFFS2_XPREFIX_ACL_ACCESS;
191 break; 172 break;
192 case ACL_TYPE_DEFAULT: 173 case ACL_TYPE_DEFAULT:
193 acl = jffs2_iget_acl(inode, &inode->i_default_acl);
194 if (acl != ACL_NOT_CACHED)
195 return acl;
196 xprefix = JFFS2_XPREFIX_ACL_DEFAULT; 174 xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
197 break; 175 break;
198 default: 176 default:
199 return ERR_PTR(-EINVAL); 177 BUG();
200 } 178 }
201 rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0); 179 rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0);
202 if (rc > 0) { 180 if (rc > 0) {
@@ -214,16 +192,8 @@ static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
214 } 192 }
215 if (value) 193 if (value)
216 kfree(value); 194 kfree(value);
217 if (!IS_ERR(acl)) { 195 if (!IS_ERR(acl))
218 switch (type) { 196 set_cached_acl(inode, type, acl);
219 case ACL_TYPE_ACCESS:
220 jffs2_iset_acl(inode, &inode->i_acl, acl);
221 break;
222 case ACL_TYPE_DEFAULT:
223 jffs2_iset_acl(inode, &inode->i_default_acl, acl);
224 break;
225 }
226 }
227 return acl; 197 return acl;
228} 198}
229 199
@@ -283,16 +253,8 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
283 return -EINVAL; 253 return -EINVAL;
284 } 254 }
285 rc = __jffs2_set_acl(inode, xprefix, acl); 255 rc = __jffs2_set_acl(inode, xprefix, acl);
286 if (!rc) { 256 if (!rc)
287 switch(type) { 257 set_cached_acl(inode, type, acl);
288 case ACL_TYPE_ACCESS:
289 jffs2_iset_acl(inode, &inode->i_acl, acl);
290 break;
291 case ACL_TYPE_DEFAULT:
292 jffs2_iset_acl(inode, &inode->i_default_acl, acl);
293 break;
294 }
295 }
296 return rc; 258 return rc;
297} 259}
298 260
@@ -336,7 +298,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
336 *i_mode &= ~current_umask(); 298 *i_mode &= ~current_umask();
337 } else { 299 } else {
338 if (S_ISDIR(*i_mode)) 300 if (S_ISDIR(*i_mode))
339 jffs2_iset_acl(inode, &inode->i_default_acl, acl); 301 set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
340 302
341 clone = posix_acl_clone(acl, GFP_KERNEL); 303 clone = posix_acl_clone(acl, GFP_KERNEL);
342 if (!clone) 304 if (!clone)
@@ -347,7 +309,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
347 return rc; 309 return rc;
348 } 310 }
349 if (rc > 0) 311 if (rc > 0)
350 jffs2_iset_acl(inode, &inode->i_acl, clone); 312 set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
351 313
352 posix_acl_release(clone); 314 posix_acl_release(clone);
353 } 315 }
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)
31{ 31{
32 struct posix_acl *acl; 32 struct posix_acl *acl;
33 char *ea_name; 33 char *ea_name;
34 struct posix_acl **p_acl;
35 int size; 34 int size;
36 char *value = NULL; 35 char *value = NULL;
37 36
37 acl = get_cached_acl(inode, type);
38 if (acl != ACL_NOT_CACHED)
39 return acl;
40
38 switch(type) { 41 switch(type) {
39 case ACL_TYPE_ACCESS: 42 case ACL_TYPE_ACCESS:
40 ea_name = POSIX_ACL_XATTR_ACCESS; 43 ea_name = POSIX_ACL_XATTR_ACCESS;
41 p_acl = &inode->i_acl;
42 break; 44 break;
43 case ACL_TYPE_DEFAULT: 45 case ACL_TYPE_DEFAULT:
44 ea_name = POSIX_ACL_XATTR_DEFAULT; 46 ea_name = POSIX_ACL_XATTR_DEFAULT;
45 p_acl = &inode->i_default_acl;
46 break; 47 break;
47 default: 48 default:
48 return ERR_PTR(-EINVAL); 49 return ERR_PTR(-EINVAL);
49 } 50 }
50 51
51 if (*p_acl != ACL_NOT_CACHED)
52 return posix_acl_dup(*p_acl);
53
54 size = __jfs_getxattr(inode, ea_name, NULL, 0); 52 size = __jfs_getxattr(inode, ea_name, NULL, 0);
55 53
56 if (size > 0) { 54 if (size > 0) {
@@ -61,17 +59,18 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
61 } 59 }
62 60
63 if (size < 0) { 61 if (size < 0) {
64 if (size == -ENODATA) { 62 if (size == -ENODATA)
65 *p_acl = NULL;
66 acl = NULL; 63 acl = NULL;
67 } else 64 else
68 acl = ERR_PTR(size); 65 acl = ERR_PTR(size);
69 } else { 66 } else {
70 acl = posix_acl_from_xattr(value, size); 67 acl = posix_acl_from_xattr(value, size);
71 if (!IS_ERR(acl))
72 *p_acl = posix_acl_dup(acl);
73 } 68 }
74 kfree(value); 69 kfree(value);
70 if (!IS_ERR(acl)) {
71 set_cached_acl(inode, type, acl);
72 posix_acl_release(acl);
73 }
75 return acl; 74 return acl;
76} 75}
77 76
@@ -79,7 +78,6 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
79 struct posix_acl *acl) 78 struct posix_acl *acl)
80{ 79{
81 char *ea_name; 80 char *ea_name;
82 struct posix_acl **p_acl;
83 int rc; 81 int rc;
84 int size = 0; 82 int size = 0;
85 char *value = NULL; 83 char *value = NULL;
@@ -90,11 +88,9 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
90 switch(type) { 88 switch(type) {
91 case ACL_TYPE_ACCESS: 89 case ACL_TYPE_ACCESS:
92 ea_name = POSIX_ACL_XATTR_ACCESS; 90 ea_name = POSIX_ACL_XATTR_ACCESS;
93 p_acl = &inode->i_acl;
94 break; 91 break;
95 case ACL_TYPE_DEFAULT: 92 case ACL_TYPE_DEFAULT:
96 ea_name = POSIX_ACL_XATTR_DEFAULT; 93 ea_name = POSIX_ACL_XATTR_DEFAULT;
97 p_acl = &inode->i_default_acl;
98 if (!S_ISDIR(inode->i_mode)) 94 if (!S_ISDIR(inode->i_mode))
99 return acl ? -EACCES : 0; 95 return acl ? -EACCES : 0;
100 break; 96 break;
@@ -114,11 +110,9 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
114out: 110out:
115 kfree(value); 111 kfree(value);
116 112
117 if (!rc) { 113 if (!rc)
118 if (*p_acl && (*p_acl != ACL_NOT_CACHED)) 114 set_cached_acl(inode, type, acl);
119 posix_acl_release(*p_acl); 115
120 *p_acl = posix_acl_dup(acl);
121 }
122 return rc; 116 return rc;
123} 117}
124 118
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,
727 /* 727 /*
728 * We're changing the ACL. Get rid of the cached one 728 * We're changing the ACL. Get rid of the cached one
729 */ 729 */
730 acl =inode->i_acl; 730 forget_cached_acl(inode, ACL_TYPE_ACCESS);
731 if (acl != ACL_NOT_CACHED)
732 posix_acl_release(acl);
733 inode->i_acl = ACL_NOT_CACHED;
734 731
735 return 0; 732 return 0;
736 } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) { 733 } 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,
746 /* 743 /*
747 * We're changing the default ACL. Get rid of the cached one 744 * We're changing the default ACL. Get rid of the cached one
748 */ 745 */
749 acl = inode->i_default_acl; 746 forget_cached_acl(inode, ACL_TYPE_DEFAULT);
750 if (acl && (acl != ACL_NOT_CACHED))
751 posix_acl_release(acl);
752 inode->i_default_acl = ACL_NOT_CACHED;
753 747
754 return 0; 748 return 0;
755 } 749 }
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)
188 return ERR_PTR(-EINVAL); 188 return ERR_PTR(-EINVAL);
189} 189}
190 190
191static inline void iset_acl(struct inode *inode, struct posix_acl **i_acl,
192 struct posix_acl *acl)
193{
194 spin_lock(&inode->i_lock);
195 if (*i_acl != ACL_NOT_CACHED)
196 posix_acl_release(*i_acl);
197 *i_acl = posix_acl_dup(acl);
198 spin_unlock(&inode->i_lock);
199}
200
201static inline struct posix_acl *iget_acl(struct inode *inode,
202 struct posix_acl **i_acl)
203{
204 struct posix_acl *acl = ACL_NOT_CACHED;
205
206 spin_lock(&inode->i_lock);
207 if (*i_acl != ACL_NOT_CACHED)
208 acl = posix_acl_dup(*i_acl);
209 spin_unlock(&inode->i_lock);
210
211 return acl;
212}
213
214/* 191/*
215 * Inode operation get_posix_acl(). 192 * Inode operation get_posix_acl().
216 * 193 *
@@ -220,31 +197,29 @@ static inline struct posix_acl *iget_acl(struct inode *inode,
220struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) 197struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
221{ 198{
222 char *name, *value; 199 char *name, *value;
223 struct posix_acl *acl, **p_acl; 200 struct posix_acl *acl;
224 int size; 201 int size;
225 int retval; 202 int retval;
226 203
204 acl = get_cached_acl(inode, type);
205 if (acl != ACL_NOT_CACHED)
206 return acl;
207
227 switch (type) { 208 switch (type) {
228 case ACL_TYPE_ACCESS: 209 case ACL_TYPE_ACCESS:
229 name = POSIX_ACL_XATTR_ACCESS; 210 name = POSIX_ACL_XATTR_ACCESS;
230 p_acl = &inode->i_acl;
231 break; 211 break;
232 case ACL_TYPE_DEFAULT: 212 case ACL_TYPE_DEFAULT:
233 name = POSIX_ACL_XATTR_DEFAULT; 213 name = POSIX_ACL_XATTR_DEFAULT;
234 p_acl = &inode->i_default_acl;
235 break; 214 break;
236 default: 215 default:
237 return ERR_PTR(-EINVAL); 216 BUG();
238 } 217 }
239 218
240 acl = iget_acl(inode, p_acl);
241 if (acl != ACL_NOT_CACHED)
242 return acl;
243
244 size = reiserfs_xattr_get(inode, name, NULL, 0); 219 size = reiserfs_xattr_get(inode, name, NULL, 0);
245 if (size < 0) { 220 if (size < 0) {
246 if (size == -ENODATA || size == -ENOSYS) { 221 if (size == -ENODATA || size == -ENOSYS) {
247 *p_acl = NULL; 222 set_cached_acl(inode, type, NULL);
248 return NULL; 223 return NULL;
249 } 224 }
250 return ERR_PTR(size); 225 return ERR_PTR(size);
@@ -259,14 +234,13 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
259 /* This shouldn't actually happen as it should have 234 /* This shouldn't actually happen as it should have
260 been caught above.. but just in case */ 235 been caught above.. but just in case */
261 acl = NULL; 236 acl = NULL;
262 *p_acl = acl;
263 } else if (retval < 0) { 237 } else if (retval < 0) {
264 acl = ERR_PTR(retval); 238 acl = ERR_PTR(retval);
265 } else { 239 } else {
266 acl = posix_acl_from_disk(value, retval); 240 acl = posix_acl_from_disk(value, retval);
267 if (!IS_ERR(acl))
268 iset_acl(inode, p_acl, acl);
269 } 241 }
242 if (!IS_ERR(acl))
243 set_cached_acl(inode, type, acl);
270 244
271 kfree(value); 245 kfree(value);
272 return acl; 246 return acl;
@@ -284,7 +258,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
284{ 258{
285 char *name; 259 char *name;
286 void *value = NULL; 260 void *value = NULL;
287 struct posix_acl **p_acl;
288 size_t size = 0; 261 size_t size = 0;
289 int error; 262 int error;
290 263
@@ -294,7 +267,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
294 switch (type) { 267 switch (type) {
295 case ACL_TYPE_ACCESS: 268 case ACL_TYPE_ACCESS:
296 name = POSIX_ACL_XATTR_ACCESS; 269 name = POSIX_ACL_XATTR_ACCESS;
297 p_acl = &inode->i_acl;
298 if (acl) { 270 if (acl) {
299 mode_t mode = inode->i_mode; 271 mode_t mode = inode->i_mode;
300 error = posix_acl_equiv_mode(acl, &mode); 272 error = posix_acl_equiv_mode(acl, &mode);
@@ -309,7 +281,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
309 break; 281 break;
310 case ACL_TYPE_DEFAULT: 282 case ACL_TYPE_DEFAULT:
311 name = POSIX_ACL_XATTR_DEFAULT; 283 name = POSIX_ACL_XATTR_DEFAULT;
312 p_acl = &inode->i_default_acl;
313 if (!S_ISDIR(inode->i_mode)) 284 if (!S_ISDIR(inode->i_mode))
314 return acl ? -EACCES : 0; 285 return acl ? -EACCES : 0;
315 break; 286 break;
@@ -342,7 +313,7 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
342 kfree(value); 313 kfree(value);
343 314
344 if (!error) 315 if (!error)
345 iset_acl(inode, p_acl, acl); 316 set_cached_acl(inode, type, acl);
346 317
347 return error; 318 return error;
348} 319}
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 @@
55 * ACL support is not implemented. 55 * ACL support is not implemented.
56 */ 56 */
57 57
58#include "ubifs.h"
58#include <linux/xattr.h> 59#include <linux/xattr.h>
59#include <linux/posix_acl_xattr.h> 60#include <linux/posix_acl_xattr.h>
60#include "ubifs.h"
61 61
62/* 62/*
63 * Limit the number of extended attributes per inode so that the total size 63 * 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);
83extern struct posix_acl *get_posix_acl(struct inode *, int); 83extern struct posix_acl *get_posix_acl(struct inode *, int);
84extern int set_posix_acl(struct inode *, int, struct posix_acl *); 84extern int set_posix_acl(struct inode *, int, struct posix_acl *);
85 85
86static inline struct posix_acl *get_cached_acl(struct inode *inode, int type)
87{
88 struct posix_acl **p, *acl;
89 switch (type) {
90 case ACL_TYPE_ACCESS:
91 p = &inode->i_acl;
92 break;
93 case ACL_TYPE_DEFAULT:
94 p = &inode->i_default_acl;
95 break;
96 default:
97 return ERR_PTR(-EINVAL);
98 }
99 acl = ACCESS_ONCE(*p);
100 if (acl) {
101 spin_lock(&inode->i_lock);
102 acl = *p;
103 if (acl != ACL_NOT_CACHED)
104 acl = posix_acl_dup(acl);
105 spin_unlock(&inode->i_lock);
106 }
107 return acl;
108}
109
110static inline void set_cached_acl(struct inode *inode,
111 int type,
112 struct posix_acl *acl)
113{
114 struct posix_acl *old = NULL;
115 spin_lock(&inode->i_lock);
116 switch (type) {
117 case ACL_TYPE_ACCESS:
118 old = inode->i_acl;
119 inode->i_acl = posix_acl_dup(acl);
120 break;
121 case ACL_TYPE_DEFAULT:
122 old = inode->i_default_acl;
123 inode->i_default_acl = posix_acl_dup(acl);
124 break;
125 }
126 spin_unlock(&inode->i_lock);
127 if (old != ACL_NOT_CACHED)
128 posix_acl_release(old);
129}
130
131static inline void forget_cached_acl(struct inode *inode, int type)
132{
133 struct posix_acl *old = NULL;
134 spin_lock(&inode->i_lock);
135 switch (type) {
136 case ACL_TYPE_ACCESS:
137 old = inode->i_acl;
138 inode->i_acl = ACL_NOT_CACHED;
139 break;
140 case ACL_TYPE_DEFAULT:
141 old = inode->i_default_acl;
142 inode->i_default_acl = ACL_NOT_CACHED;
143 break;
144 }
145 spin_unlock(&inode->i_lock);
146 if (old != ACL_NOT_CACHED)
147 posix_acl_release(old);
148}
149
86#endif /* __LINUX_POSIX_ACL_H */ 150#endif /* __LINUX_POSIX_ACL_H */