diff options
Diffstat (limited to 'fs/ocfs2/acl.c')
-rw-r--r-- | fs/ocfs2/acl.c | 169 |
1 files changed, 98 insertions, 71 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index fbeaec762103..e13fc9e8fcdc 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/string.h> | 25 | #include <linux/string.h> |
25 | 26 | ||
26 | #define MLOG_MASK_PREFIX ML_INODE | 27 | #define MLOG_MASK_PREFIX ML_INODE |
@@ -30,6 +31,8 @@ | |||
30 | #include "alloc.h" | 31 | #include "alloc.h" |
31 | #include "dlmglue.h" | 32 | #include "dlmglue.h" |
32 | #include "file.h" | 33 | #include "file.h" |
34 | #include "inode.h" | ||
35 | #include "journal.h" | ||
33 | #include "ocfs2_fs.h" | 36 | #include "ocfs2_fs.h" |
34 | 37 | ||
35 | #include "xattr.h" | 38 | #include "xattr.h" |
@@ -98,15 +101,11 @@ static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode, | |||
98 | int type, | 101 | int type, |
99 | struct buffer_head *di_bh) | 102 | struct buffer_head *di_bh) |
100 | { | 103 | { |
101 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
102 | int name_index; | 104 | int name_index; |
103 | char *value = NULL; | 105 | char *value = NULL; |
104 | struct posix_acl *acl; | 106 | struct posix_acl *acl; |
105 | int retval; | 107 | int retval; |
106 | 108 | ||
107 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) | ||
108 | return NULL; | ||
109 | |||
110 | switch (type) { | 109 | switch (type) { |
111 | case ACL_TYPE_ACCESS: | 110 | case ACL_TYPE_ACCESS: |
112 | name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; | 111 | name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; |
@@ -170,6 +169,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type) | |||
170 | } | 169 | } |
171 | 170 | ||
172 | /* | 171 | /* |
172 | * Helper function to set i_mode in memory and disk. Some call paths | ||
173 | * will not have di_bh or a journal handle to pass, in which case it | ||
174 | * will create it's own. | ||
175 | */ | ||
176 | static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, | ||
177 | handle_t *handle, umode_t new_mode) | ||
178 | { | ||
179 | int ret, commit_handle = 0; | ||
180 | struct ocfs2_dinode *di; | ||
181 | |||
182 | if (di_bh == NULL) { | ||
183 | ret = ocfs2_read_inode_block(inode, &di_bh); | ||
184 | if (ret) { | ||
185 | mlog_errno(ret); | ||
186 | goto out; | ||
187 | } | ||
188 | } else | ||
189 | get_bh(di_bh); | ||
190 | |||
191 | if (handle == NULL) { | ||
192 | handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), | ||
193 | OCFS2_INODE_UPDATE_CREDITS); | ||
194 | if (IS_ERR(handle)) { | ||
195 | ret = PTR_ERR(handle); | ||
196 | mlog_errno(ret); | ||
197 | goto out_brelse; | ||
198 | } | ||
199 | |||
200 | commit_handle = 1; | ||
201 | } | ||
202 | |||
203 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
204 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, | ||
205 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
206 | if (ret) { | ||
207 | mlog_errno(ret); | ||
208 | goto out_commit; | ||
209 | } | ||
210 | |||
211 | inode->i_mode = new_mode; | ||
212 | di->i_mode = cpu_to_le16(inode->i_mode); | ||
213 | |||
214 | ocfs2_journal_dirty(handle, di_bh); | ||
215 | |||
216 | out_commit: | ||
217 | if (commit_handle) | ||
218 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
219 | out_brelse: | ||
220 | brelse(di_bh); | ||
221 | out: | ||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | /* | ||
173 | * Set the access or default ACL of an inode. | 226 | * Set the access or default ACL of an inode. |
174 | */ | 227 | */ |
175 | static int ocfs2_set_acl(handle_t *handle, | 228 | static int ocfs2_set_acl(handle_t *handle, |
@@ -197,9 +250,14 @@ static int ocfs2_set_acl(handle_t *handle, | |||
197 | if (ret < 0) | 250 | if (ret < 0) |
198 | return ret; | 251 | return ret; |
199 | else { | 252 | else { |
200 | inode->i_mode = mode; | ||
201 | if (ret == 0) | 253 | if (ret == 0) |
202 | acl = NULL; | 254 | acl = NULL; |
255 | |||
256 | ret = ocfs2_acl_set_mode(inode, di_bh, | ||
257 | handle, mode); | ||
258 | if (ret) | ||
259 | return ret; | ||
260 | |||
203 | } | 261 | } |
204 | } | 262 | } |
205 | break; | 263 | break; |
@@ -287,6 +345,7 @@ int ocfs2_init_acl(handle_t *handle, | |||
287 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 345 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
288 | struct posix_acl *acl = NULL; | 346 | struct posix_acl *acl = NULL; |
289 | int ret = 0; | 347 | int ret = 0; |
348 | mode_t mode; | ||
290 | 349 | ||
291 | if (!S_ISLNK(inode->i_mode)) { | 350 | if (!S_ISLNK(inode->i_mode)) { |
292 | if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { | 351 | if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { |
@@ -295,12 +354,17 @@ int ocfs2_init_acl(handle_t *handle, | |||
295 | if (IS_ERR(acl)) | 354 | if (IS_ERR(acl)) |
296 | return PTR_ERR(acl); | 355 | return PTR_ERR(acl); |
297 | } | 356 | } |
298 | if (!acl) | 357 | if (!acl) { |
299 | inode->i_mode &= ~current_umask(); | 358 | mode = inode->i_mode & ~current_umask(); |
359 | ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); | ||
360 | if (ret) { | ||
361 | mlog_errno(ret); | ||
362 | goto cleanup; | ||
363 | } | ||
364 | } | ||
300 | } | 365 | } |
301 | if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { | 366 | if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { |
302 | struct posix_acl *clone; | 367 | struct posix_acl *clone; |
303 | mode_t mode; | ||
304 | 368 | ||
305 | if (S_ISDIR(inode->i_mode)) { | 369 | if (S_ISDIR(inode->i_mode)) { |
306 | ret = ocfs2_set_acl(handle, inode, di_bh, | 370 | ret = ocfs2_set_acl(handle, inode, di_bh, |
@@ -317,7 +381,7 @@ int ocfs2_init_acl(handle_t *handle, | |||
317 | mode = inode->i_mode; | 381 | mode = inode->i_mode; |
318 | ret = posix_acl_create_masq(clone, &mode); | 382 | ret = posix_acl_create_masq(clone, &mode); |
319 | if (ret >= 0) { | 383 | if (ret >= 0) { |
320 | inode->i_mode = mode; | 384 | ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); |
321 | if (ret > 0) { | 385 | if (ret > 0) { |
322 | ret = ocfs2_set_acl(handle, inode, | 386 | ret = ocfs2_set_acl(handle, inode, |
323 | di_bh, ACL_TYPE_ACCESS, | 387 | di_bh, ACL_TYPE_ACCESS, |
@@ -331,13 +395,14 @@ cleanup: | |||
331 | return ret; | 395 | return ret; |
332 | } | 396 | } |
333 | 397 | ||
334 | static size_t ocfs2_xattr_list_acl_access(struct inode *inode, | 398 | static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry, |
335 | char *list, | 399 | char *list, |
336 | size_t list_len, | 400 | size_t list_len, |
337 | const char *name, | 401 | const char *name, |
338 | size_t name_len) | 402 | size_t name_len, |
403 | int type) | ||
339 | { | 404 | { |
340 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 405 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); |
341 | const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); | 406 | const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); |
342 | 407 | ||
343 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) | 408 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) |
@@ -348,13 +413,14 @@ static size_t ocfs2_xattr_list_acl_access(struct inode *inode, | |||
348 | return size; | 413 | return size; |
349 | } | 414 | } |
350 | 415 | ||
351 | static size_t ocfs2_xattr_list_acl_default(struct inode *inode, | 416 | static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry, |
352 | char *list, | 417 | char *list, |
353 | size_t list_len, | 418 | size_t list_len, |
354 | const char *name, | 419 | const char *name, |
355 | size_t name_len) | 420 | size_t name_len, |
421 | int type) | ||
356 | { | 422 | { |
357 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 423 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); |
358 | const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); | 424 | const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); |
359 | 425 | ||
360 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) | 426 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) |
@@ -365,19 +431,19 @@ static size_t ocfs2_xattr_list_acl_default(struct inode *inode, | |||
365 | return size; | 431 | return size; |
366 | } | 432 | } |
367 | 433 | ||
368 | static int ocfs2_xattr_get_acl(struct inode *inode, | 434 | static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name, |
369 | int type, | 435 | void *buffer, size_t size, int type) |
370 | void *buffer, | ||
371 | size_t size) | ||
372 | { | 436 | { |
373 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 437 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); |
374 | struct posix_acl *acl; | 438 | struct posix_acl *acl; |
375 | int ret; | 439 | int ret; |
376 | 440 | ||
441 | if (strcmp(name, "") != 0) | ||
442 | return -EINVAL; | ||
377 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) | 443 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) |
378 | return -EOPNOTSUPP; | 444 | return -EOPNOTSUPP; |
379 | 445 | ||
380 | acl = ocfs2_get_acl(inode, type); | 446 | acl = ocfs2_get_acl(dentry->d_inode, type); |
381 | if (IS_ERR(acl)) | 447 | if (IS_ERR(acl)) |
382 | return PTR_ERR(acl); | 448 | return PTR_ERR(acl); |
383 | if (acl == NULL) | 449 | if (acl == NULL) |
@@ -388,35 +454,16 @@ static int ocfs2_xattr_get_acl(struct inode *inode, | |||
388 | return ret; | 454 | return ret; |
389 | } | 455 | } |
390 | 456 | ||
391 | static int ocfs2_xattr_get_acl_access(struct inode *inode, | 457 | static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name, |
392 | const char *name, | 458 | const void *value, size_t size, int flags, int type) |
393 | void *buffer, | ||
394 | size_t size) | ||
395 | { | ||
396 | if (strcmp(name, "") != 0) | ||
397 | return -EINVAL; | ||
398 | return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); | ||
399 | } | ||
400 | |||
401 | static int ocfs2_xattr_get_acl_default(struct inode *inode, | ||
402 | const char *name, | ||
403 | void *buffer, | ||
404 | size_t size) | ||
405 | { | ||
406 | if (strcmp(name, "") != 0) | ||
407 | return -EINVAL; | ||
408 | return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); | ||
409 | } | ||
410 | |||
411 | static int ocfs2_xattr_set_acl(struct inode *inode, | ||
412 | int type, | ||
413 | const void *value, | ||
414 | size_t size) | ||
415 | { | 459 | { |
460 | struct inode *inode = dentry->d_inode; | ||
416 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 461 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
417 | struct posix_acl *acl; | 462 | struct posix_acl *acl; |
418 | int ret = 0; | 463 | int ret = 0; |
419 | 464 | ||
465 | if (strcmp(name, "") != 0) | ||
466 | return -EINVAL; | ||
420 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) | 467 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) |
421 | return -EOPNOTSUPP; | 468 | return -EOPNOTSUPP; |
422 | 469 | ||
@@ -442,38 +489,18 @@ cleanup: | |||
442 | return ret; | 489 | return ret; |
443 | } | 490 | } |
444 | 491 | ||
445 | static int ocfs2_xattr_set_acl_access(struct inode *inode, | ||
446 | const char *name, | ||
447 | const void *value, | ||
448 | size_t size, | ||
449 | int flags) | ||
450 | { | ||
451 | if (strcmp(name, "") != 0) | ||
452 | return -EINVAL; | ||
453 | return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); | ||
454 | } | ||
455 | |||
456 | static int ocfs2_xattr_set_acl_default(struct inode *inode, | ||
457 | const char *name, | ||
458 | const void *value, | ||
459 | size_t size, | ||
460 | int flags) | ||
461 | { | ||
462 | if (strcmp(name, "") != 0) | ||
463 | return -EINVAL; | ||
464 | return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); | ||
465 | } | ||
466 | |||
467 | struct xattr_handler ocfs2_xattr_acl_access_handler = { | 492 | struct xattr_handler ocfs2_xattr_acl_access_handler = { |
468 | .prefix = POSIX_ACL_XATTR_ACCESS, | 493 | .prefix = POSIX_ACL_XATTR_ACCESS, |
494 | .flags = ACL_TYPE_ACCESS, | ||
469 | .list = ocfs2_xattr_list_acl_access, | 495 | .list = ocfs2_xattr_list_acl_access, |
470 | .get = ocfs2_xattr_get_acl_access, | 496 | .get = ocfs2_xattr_get_acl, |
471 | .set = ocfs2_xattr_set_acl_access, | 497 | .set = ocfs2_xattr_set_acl, |
472 | }; | 498 | }; |
473 | 499 | ||
474 | struct xattr_handler ocfs2_xattr_acl_default_handler = { | 500 | struct xattr_handler ocfs2_xattr_acl_default_handler = { |
475 | .prefix = POSIX_ACL_XATTR_DEFAULT, | 501 | .prefix = POSIX_ACL_XATTR_DEFAULT, |
502 | .flags = ACL_TYPE_DEFAULT, | ||
476 | .list = ocfs2_xattr_list_acl_default, | 503 | .list = ocfs2_xattr_list_acl_default, |
477 | .get = ocfs2_xattr_get_acl_default, | 504 | .get = ocfs2_xattr_get_acl, |
478 | .set = ocfs2_xattr_set_acl_default, | 505 | .set = ocfs2_xattr_set_acl, |
479 | }; | 506 | }; |