diff mbox

[v5,39/39] nfs: Add support for the v4.1 dacl attribute

Message ID 1437570209-29832-40-git-send-email-andreas.gruenbacher@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andreas Grünbacher July 22, 2015, 1:03 p.m. UTC
From: Andreas Gruenbacher <agruenba@redhat.com>

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 minorversion=1 [...]

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/nfs/nfs4proc.c       |  2 +-
 fs/nfs/nfs4xdr.c        | 55 ++++++++++++++++++++++++++++++++++++++++++-------
 include/linux/nfs_xdr.h |  2 +-
 3 files changed, 50 insertions(+), 9 deletions(-)

Comments

Schumaker, Anna July 22, 2015, 3:57 p.m. UTC | #1
Hi Andreas,

On 07/22/2015 09:03 AM, Andreas Gruenbacher wrote:
> From: Andreas Gruenbacher <agruenba@redhat.com>
> 
> 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 minorversion=1 [...]

Discussions around deprecating or removing the minorversion= argument have come up recently.  The preferred way of mounting NFS v4.1 these days is with: "-o vers=4.1".  Can you update your patch description so we don't confuse people? :)

Thanks,
Anna

> 
> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
> ---
>  fs/nfs/nfs4proc.c       |  2 +-
>  fs/nfs/nfs4xdr.c        | 55 ++++++++++++++++++++++++++++++++++++++++++-------
>  include/linux/nfs_xdr.h |  2 +-
>  3 files changed, 50 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 5ba49c3..39f5548 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -4469,7 +4469,7 @@ static struct richacl *__nfs4_get_acl_uncached(struct inode *inode)
>  	struct nfs_server *server = NFS_SERVER(inode);
>  	struct page *pages[DIV_ROUND_UP(NFS4ACL_SIZE_MAX, PAGE_SIZE)] = {};
>  	struct nfs_getaclargs args = {
> -		.fh = NFS_FH(inode),
> +		.inode = inode,
>  		.acl_pages = pages,
>  		.acl_len = ARRAY_SIZE(pages) * PAGE_SIZE,
>  	};
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 85270df..06f5759 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -1649,9 +1649,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 */
> @@ -2486,9 +2493,12 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
>  
>  	encode_compound_hdr(xdr, req, &hdr);
>  	encode_sequence(xdr, &args->seq_args, &hdr);
> -	encode_putfh(xdr, args->fh, &hdr);
> +	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
>  	replen = hdr.replen + op_decode_hdr_maxsz + 1;
> -	encode_getattr_two(xdr, FATTR4_WORD0_ACL, FATTR4_WORD1_MODE, &hdr);
> +	if (NFS_SERVER(args->inode)->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);
> @@ -5376,14 +5386,28 @@ 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);
>  		status = PTR_ERR(acl);
>  		if (IS_ERR(acl))
>  			goto out;
> +
> +		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)) {
>  		status = -EOPNOTSUPP;
> +		goto out;
> +	}
>  
>  	status = -EIO;
>  	if (unlikely(bitmap[0]))
> @@ -5391,6 +5415,23 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
>  
>  	if ((status = decode_attr_mode(xdr, bitmap, &res->mode)) < 0)
>  		goto out;
> +	if (bitmap[1] & FATTR4_WORD1_DACL) {
> +		unsigned int flags;
> +		__be32 *p;
> +
> +		p = xdr_inline_decode(xdr, 4);
> +                status = -EIO;
> +                if (unlikely(!p))
> +                        goto out;
> +                flags = be32_to_cpup(p);
> +
> +		acl = decode_acl_entries(xdr, res->server);
> +		status = PTR_ERR(acl);
> +		if (IS_ERR(acl))
> +			goto out;
> +		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 f1c8f93..abe0b66 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -695,7 +695,7 @@ struct nfs_setaclres {
>  
>  struct nfs_getaclargs {
>  	struct nfs4_sequence_args 	seq_args;
> -	struct nfs_fh *			fh;
> +	struct inode *			inode;
>  	size_t				acl_len;
>  	struct page **			acl_pages;
>  };
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andreas Grünbacher July 22, 2015, 4:08 p.m. UTC | #2
Hi Anna,

2015-07-22 17:57 GMT+02:00 Anna Schumaker <Anna.Schumaker@netapp.com>:
> Discussions around deprecating or removing the minorversion= argument have come up recently.
> The preferred way of mounting NFS v4.1 these days is with: "-o vers=4.1".  Can you update your
> patch description so we don't confuse people? :)

sure, that was easy :)

Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5ba49c3..39f5548 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4469,7 +4469,7 @@  static struct richacl *__nfs4_get_acl_uncached(struct inode *inode)
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct page *pages[DIV_ROUND_UP(NFS4ACL_SIZE_MAX, PAGE_SIZE)] = {};
 	struct nfs_getaclargs args = {
-		.fh = NFS_FH(inode),
+		.inode = inode,
 		.acl_pages = pages,
 		.acl_len = ARRAY_SIZE(pages) * PAGE_SIZE,
 	};
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 85270df..06f5759 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1649,9 +1649,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 */
@@ -2486,9 +2493,12 @@  static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
 
 	encode_compound_hdr(xdr, req, &hdr);
 	encode_sequence(xdr, &args->seq_args, &hdr);
-	encode_putfh(xdr, args->fh, &hdr);
+	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
 	replen = hdr.replen + op_decode_hdr_maxsz + 1;
-	encode_getattr_two(xdr, FATTR4_WORD0_ACL, FATTR4_WORD1_MODE, &hdr);
+	if (NFS_SERVER(args->inode)->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);
@@ -5376,14 +5386,28 @@  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);
 		status = PTR_ERR(acl);
 		if (IS_ERR(acl))
 			goto out;
+
+		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)) {
 		status = -EOPNOTSUPP;
+		goto out;
+	}
 
 	status = -EIO;
 	if (unlikely(bitmap[0]))
@@ -5391,6 +5415,23 @@  static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
 
 	if ((status = decode_attr_mode(xdr, bitmap, &res->mode)) < 0)
 		goto out;
+	if (bitmap[1] & FATTR4_WORD1_DACL) {
+		unsigned int flags;
+		__be32 *p;
+
+		p = xdr_inline_decode(xdr, 4);
+                status = -EIO;
+                if (unlikely(!p))
+                        goto out;
+                flags = be32_to_cpup(p);
+
+		acl = decode_acl_entries(xdr, res->server);
+		status = PTR_ERR(acl);
+		if (IS_ERR(acl))
+			goto out;
+		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 f1c8f93..abe0b66 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -695,7 +695,7 @@  struct nfs_setaclres {
 
 struct nfs_getaclargs {
 	struct nfs4_sequence_args 	seq_args;
-	struct nfs_fh *			fh;
+	struct inode *			inode;
 	size_t				acl_len;
 	struct page **			acl_pages;
 };