diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-01-31 14:25:19 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-02-03 17:12:37 -0500 |
commit | 789b663ae3d427ea9c50505339a13276e7228c9d (patch) | |
tree | b5e9bccd77fa11d0988def1ee440af17834ef186 /fs/posix_acl.c | |
parent | 8f493b9cfcd8941c6b27d6ce8e3b4a78c094b3c1 (diff) |
fs: get_acl() must be allowed to return EOPNOTSUPP
posix_acl_xattr_get requires get_acl() to return EOPNOTSUPP if the
filesystem cannot support acls. This is needed for NFS, which can't
know whether or not the server supports acls until it tries to get/set
one.
This patch converts posix_acl_chmod and posix_acl_create to deal with
EOPNOTSUPP return values from get_acl().
Reported-by: Russell King <linux@arm.linux.org.uk>
Link: http://lkml.kernel.org/r/20140130140834.GW15937@n2100.arm.linux.org.uk
Cc: Al Viro viro@zeniv.linux.org.uk>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/posix_acl.c')
-rw-r--r-- | fs/posix_acl.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 38bae5a0ea25..11c54fd51e16 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -521,8 +521,11 @@ posix_acl_chmod(struct inode *inode, umode_t mode) | |||
521 | return -EOPNOTSUPP; | 521 | return -EOPNOTSUPP; |
522 | 522 | ||
523 | acl = get_acl(inode, ACL_TYPE_ACCESS); | 523 | acl = get_acl(inode, ACL_TYPE_ACCESS); |
524 | if (IS_ERR_OR_NULL(acl)) | 524 | if (IS_ERR_OR_NULL(acl)) { |
525 | if (acl == ERR_PTR(-EOPNOTSUPP)) | ||
526 | return 0; | ||
525 | return PTR_ERR(acl); | 527 | return PTR_ERR(acl); |
528 | } | ||
526 | 529 | ||
527 | ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); | 530 | ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); |
528 | if (ret) | 531 | if (ret) |
@@ -544,14 +547,15 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
544 | goto no_acl; | 547 | goto no_acl; |
545 | 548 | ||
546 | p = get_acl(dir, ACL_TYPE_DEFAULT); | 549 | p = get_acl(dir, ACL_TYPE_DEFAULT); |
547 | if (IS_ERR(p)) | 550 | if (IS_ERR(p)) { |
551 | if (p == ERR_PTR(-EOPNOTSUPP)) | ||
552 | goto apply_umask; | ||
548 | return PTR_ERR(p); | 553 | return PTR_ERR(p); |
549 | |||
550 | if (!p) { | ||
551 | *mode &= ~current_umask(); | ||
552 | goto no_acl; | ||
553 | } | 554 | } |
554 | 555 | ||
556 | if (!p) | ||
557 | goto apply_umask; | ||
558 | |||
555 | *acl = posix_acl_clone(p, GFP_NOFS); | 559 | *acl = posix_acl_clone(p, GFP_NOFS); |
556 | if (!*acl) | 560 | if (!*acl) |
557 | return -ENOMEM; | 561 | return -ENOMEM; |
@@ -575,6 +579,8 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
575 | } | 579 | } |
576 | return 0; | 580 | return 0; |
577 | 581 | ||
582 | apply_umask: | ||
583 | *mode &= ~current_umask(); | ||
578 | no_acl: | 584 | no_acl: |
579 | *default_acl = NULL; | 585 | *default_acl = NULL; |
580 | *acl = NULL; | 586 | *acl = NULL; |