aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/acl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:48 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 23:58:21 -0500
commit702e5bc68ad2c02f1b12b53ef7093074af9d2441 (patch)
treeb88af8aafb7f8e166da41824cbffb99adf16f042 /fs/ocfs2/acl.c
parentf2963d4551e7f500025d687586a25a09ea28941e (diff)
ocfs2: use generic posix ACL infrastructure
This contains some major refactoring for the create path so that inodes are created with the right mode to start with instead of fixing it up later. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ocfs2/acl.c')
-rw-r--r--fs/ocfs2/acl.c234
1 files changed, 6 insertions, 228 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index c0f9d2fe134f..555f4cddefe3 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -160,36 +160,6 @@ static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode,
160 return acl; 160 return acl;
161} 161}
162 162
163
164/*
165 * Get posix acl.
166 */
167static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
168{
169 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
170 struct buffer_head *di_bh = NULL;
171 struct posix_acl *acl;
172 int ret;
173
174 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
175 return NULL;
176
177 ret = ocfs2_inode_lock(inode, &di_bh, 0);
178 if (ret < 0) {
179 mlog_errno(ret);
180 acl = ERR_PTR(ret);
181 return acl;
182 }
183
184 acl = ocfs2_get_acl_nolock(inode, type, di_bh);
185
186 ocfs2_inode_unlock(inode, 0);
187
188 brelse(di_bh);
189
190 return acl;
191}
192
193/* 163/*
194 * Helper function to set i_mode in memory and disk. Some call paths 164 * Helper function to set i_mode in memory and disk. Some call paths
195 * will not have di_bh or a journal handle to pass, in which case it 165 * will not have di_bh or a journal handle to pass, in which case it
@@ -250,7 +220,7 @@ out:
250/* 220/*
251 * Set the access or default ACL of an inode. 221 * Set the access or default ACL of an inode.
252 */ 222 */
253static int ocfs2_set_acl(handle_t *handle, 223int ocfs2_set_acl(handle_t *handle,
254 struct inode *inode, 224 struct inode *inode,
255 struct buffer_head *di_bh, 225 struct buffer_head *di_bh,
256 int type, 226 int type,
@@ -313,6 +283,11 @@ static int ocfs2_set_acl(handle_t *handle,
313 return ret; 283 return ret;
314} 284}
315 285
286int ocfs2_iop_set_acl(struct inode *inode, struct posix_acl *acl, int type)
287{
288 return ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
289}
290
316struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type) 291struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
317{ 292{
318 struct ocfs2_super *osb; 293 struct ocfs2_super *osb;
@@ -334,200 +309,3 @@ struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
334 309
335 return acl; 310 return acl;
336} 311}
337
338int ocfs2_acl_chmod(struct inode *inode)
339{
340 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
341 struct posix_acl *acl;
342 int ret;
343
344 if (S_ISLNK(inode->i_mode))
345 return -EOPNOTSUPP;
346
347 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
348 return 0;
349
350 acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
351 if (IS_ERR(acl) || !acl)
352 return PTR_ERR(acl);
353 ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
354 if (ret)
355 return ret;
356 ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
357 acl, NULL, NULL);
358 posix_acl_release(acl);
359 return ret;
360}
361
362/*
363 * Initialize the ACLs of a new inode. If parent directory has default ACL,
364 * then clone to new inode. Called from ocfs2_mknod.
365 */
366int ocfs2_init_acl(handle_t *handle,
367 struct inode *inode,
368 struct inode *dir,
369 struct buffer_head *di_bh,
370 struct buffer_head *dir_bh,
371 struct ocfs2_alloc_context *meta_ac,
372 struct ocfs2_alloc_context *data_ac)
373{
374 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
375 struct posix_acl *acl = NULL;
376 int ret = 0, ret2;
377 umode_t mode;
378
379 if (!S_ISLNK(inode->i_mode)) {
380 if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
381 acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
382 dir_bh);
383 if (IS_ERR(acl))
384 return PTR_ERR(acl);
385 }
386 if (!acl) {
387 mode = inode->i_mode & ~current_umask();
388 ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
389 if (ret) {
390 mlog_errno(ret);
391 goto cleanup;
392 }
393 }
394 }
395 if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
396 if (S_ISDIR(inode->i_mode)) {
397 ret = ocfs2_set_acl(handle, inode, di_bh,
398 ACL_TYPE_DEFAULT, acl,
399 meta_ac, data_ac);
400 if (ret)
401 goto cleanup;
402 }
403 mode = inode->i_mode;
404 ret = __posix_acl_create(&acl, GFP_NOFS, &mode);
405 if (ret < 0)
406 return ret;
407
408 ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
409 if (ret2) {
410 mlog_errno(ret2);
411 ret = ret2;
412 goto cleanup;
413 }
414 if (ret > 0) {
415 ret = ocfs2_set_acl(handle, inode,
416 di_bh, ACL_TYPE_ACCESS,
417 acl, meta_ac, data_ac);
418 }
419 }
420cleanup:
421 posix_acl_release(acl);
422 return ret;
423}
424
425static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry,
426 char *list,
427 size_t list_len,
428 const char *name,
429 size_t name_len,
430 int type)
431{
432 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
433 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
434
435 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
436 return 0;
437
438 if (list && size <= list_len)
439 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
440 return size;
441}
442
443static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry,
444 char *list,
445 size_t list_len,
446 const char *name,
447 size_t name_len,
448 int type)
449{
450 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
451 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
452
453 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
454 return 0;
455
456 if (list && size <= list_len)
457 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
458 return size;
459}
460
461static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name,
462 void *buffer, size_t size, int type)
463{
464 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
465 struct posix_acl *acl;
466 int ret;
467
468 if (strcmp(name, "") != 0)
469 return -EINVAL;
470 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
471 return -EOPNOTSUPP;
472
473 acl = ocfs2_get_acl(dentry->d_inode, type);
474 if (IS_ERR(acl))
475 return PTR_ERR(acl);
476 if (acl == NULL)
477 return -ENODATA;
478 ret = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
479 posix_acl_release(acl);
480
481 return ret;
482}
483
484static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name,
485 const void *value, size_t size, int flags, int type)
486{
487 struct inode *inode = dentry->d_inode;
488 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
489 struct posix_acl *acl;
490 int ret = 0;
491
492 if (strcmp(name, "") != 0)
493 return -EINVAL;
494 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
495 return -EOPNOTSUPP;
496
497 if (!inode_owner_or_capable(inode))
498 return -EPERM;
499
500 if (value) {
501 acl = posix_acl_from_xattr(&init_user_ns, value, size);
502 if (IS_ERR(acl))
503 return PTR_ERR(acl);
504 else if (acl) {
505 ret = posix_acl_valid(acl);
506 if (ret)
507 goto cleanup;
508 }
509 } else
510 acl = NULL;
511
512 ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
513
514cleanup:
515 posix_acl_release(acl);
516 return ret;
517}
518
519const struct xattr_handler ocfs2_xattr_acl_access_handler = {
520 .prefix = POSIX_ACL_XATTR_ACCESS,
521 .flags = ACL_TYPE_ACCESS,
522 .list = ocfs2_xattr_list_acl_access,
523 .get = ocfs2_xattr_get_acl,
524 .set = ocfs2_xattr_set_acl,
525};
526
527const struct xattr_handler ocfs2_xattr_acl_default_handler = {
528 .prefix = POSIX_ACL_XATTR_DEFAULT,
529 .flags = ACL_TYPE_DEFAULT,
530 .list = ocfs2_xattr_list_acl_default,
531 .get = ocfs2_xattr_get_acl,
532 .set = ocfs2_xattr_set_acl,
533};