aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2015-07-22 12:40:26 +0200
committerAndreas Gruenbacher <agruenba@redhat.com>2017-03-07 16:11:30 +0100
commitb3a5d8874206989fa7681361d9ae6aa03d9fbfef (patch)
tree790bea4b23a4a0a3f76d4fc238f524d73ab892c5
parent74446d11163b7d8405d1fbb0eab0e4fbed3e0363 (diff)
downloadlinux-richacl-richacl-wip.tar.gz
nfs: Add support for the v4.1 dacl attributerichacl-wip
The dacl attribute includes Automatic Inheritance flags not supported by the acl attribute. it is only supported in NFS version 4.1 and higher. On systems where NFS version 4.0 is still the default, an additional mount option is needed: mount -t nfs4 -o vers=4.1 [...] Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
-rw-r--r--fs/nfs/nfs4proc.c1
-rw-r--r--fs/nfs/nfs4xdr.c52
-rw-r--r--include/linux/nfs_xdr.h1
3 files changed, 48 insertions, 6 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 907ac39862833..88bccb58cb93f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4884,6 +4884,7 @@ static int __nfs4_get_acl_uncached(struct inode *inode, struct richacl **acl)
struct nfs_server *server = NFS_SERVER(inode);
struct page *pages[DIV_ROUND_UP(NFS4ACL_SIZE_MAX, PAGE_SIZE) + 1] = {};
struct nfs_getaclargs args = {
+ .server = server,
.fh = NFS_FH(inode),
.acl_pages = pages,
.acl_len = ARRAY_SIZE(pages) * PAGE_SIZE,
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index d57d4bd9146df..6fec448040c23 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1670,9 +1670,16 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun
encode_nfs4_stateid(xdr, &zero_stateid);
/* Encode attribute bitmap. */
- p = reserve_space(xdr, 2*4);
- *p++ = cpu_to_be32(1);
- *p = cpu_to_be32(FATTR4_WORD0_ACL);
+ if (arg->server->attr_bitmask[1] & FATTR4_WORD1_DACL) {
+ p = reserve_space(xdr, 3*4);
+ *p++ = cpu_to_be32(2);
+ *p++ = 0;
+ *p = cpu_to_be32(FATTR4_WORD1_DACL);
+ } else {
+ p = reserve_space(xdr, 2*4);
+ *p++ = cpu_to_be32(1);
+ *p = cpu_to_be32(FATTR4_WORD0_ACL);
+ }
attrlen_offset = xdr->buf->len;
xdr_reserve_space(xdr, 4); /* to be backfilled later */
@@ -2527,7 +2534,10 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
encode_sequence(xdr, &args->seq_args, &hdr);
encode_putfh(xdr, args->fh, &hdr);
replen = hdr.replen + op_decode_hdr_maxsz;
- encode_getattr_two(xdr, FATTR4_WORD0_ACL, FATTR4_WORD1_MODE, &hdr);
+ if (args->server->attr_bitmask[1] & FATTR4_WORD1_DACL)
+ encode_getattr_two(xdr, 0, FATTR4_WORD1_MODE | FATTR4_WORD1_DACL, &hdr);
+ else
+ encode_getattr_two(xdr, FATTR4_WORD0_ACL, FATTR4_WORD1_MODE, &hdr);
xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
args->acl_pages, 0, args->acl_len);
@@ -5473,12 +5483,25 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
return -EIO;
- if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
+
+ if (bitmap[0] & FATTR4_WORD0_ACL) {
+ struct richace *ace;
+
+ if (bitmap[1] & FATTR4_WORD1_DACL)
+ return -EIO;
+
acl = decode_acl_entries(xdr, res->server);
if (IS_ERR(acl))
return PTR_ERR(acl);
+
+ status = -EIO;
+ richacl_for_each_entry(ace, acl) {
+ if (ace->e_flags & RICHACE_INHERITED_ACE)
+ goto out;
+ }
+
bitmap[0] &= ~FATTR4_WORD0_ACL;
- } else
+ } else if (!(bitmap[1] & FATTR4_WORD1_DACL))
return -EOPNOTSUPP;
status = -EIO;
@@ -5488,6 +5511,23 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
status = decode_attr_mode(xdr, bitmap, &res->mode);
if (status < 0)
goto out;
+
+ if (bitmap[1] & FATTR4_WORD1_DACL) {
+ unsigned int flags;
+ __be32 *p;
+
+ p = xdr_inline_decode(xdr, 4);
+ if (unlikely(!p))
+ return -EIO;
+ flags = be32_to_cpup(p);
+
+ acl = decode_acl_entries(xdr, res->server);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+
+ acl->a_flags = flags;
+ bitmap[1] &= ~FATTR4_WORD1_DACL;
+ }
status = 0;
out:
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 4eae491df774c..f37311d6ea64d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -743,6 +743,7 @@ struct nfs_setaclres {
struct nfs_getaclargs {
struct nfs4_sequence_args seq_args;
+ const struct nfs_server * server;
struct nfs_fh * fh;
size_t acl_len;
struct page ** acl_pages;