Commit db145db0 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

NFSv4: Add encoders/decoders for the NFSv4.1 dacl and sacl attributes



Add the ability to set or retrieve the acl using the NFSv4.1 'dacl' and
'sacl' attributes to the NFSv4 xdr encoders/decoders.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 7b8b44eb
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -5911,9 +5911,11 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
	struct page **pages;
	struct nfs_getaclargs args = {
		.fh = NFS_FH(inode),
		.acl_type = type,
		.acl_len = buflen,
	};
	struct nfs_getaclres res = {
		.acl_type = type,
		.acl_len = buflen,
	};
	struct rpc_message msg = {
@@ -6029,8 +6031,9 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
	struct page *pages[NFS4ACL_MAXPAGES];
	struct nfs_setaclargs arg = {
		.fh = NFS_FH(inode),
		.acl_pages	= pages,
		.acl_type = type,
		.acl_len = buflen,
		.acl_pages = pages,
	};
	struct nfs_setaclres res;
	struct rpc_message msg = {
+62 −33
Original line number Diff line number Diff line
@@ -1680,19 +1680,35 @@ encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
	encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr);
}

static void
encode_setacl(struct xdr_stream *xdr, const struct nfs_setaclargs *arg,
static void nfs4_acltype_to_bitmap(enum nfs4_acl_type type, __u32 bitmap[2])
{
	switch (type) {
	default:
		bitmap[0] = FATTR4_WORD0_ACL;
		bitmap[1] = 0;
		break;
	case NFS4ACL_DACL:
		bitmap[0] = 0;
		bitmap[1] = FATTR4_WORD1_DACL;
		break;
	case NFS4ACL_SACL:
		bitmap[0] = 0;
		bitmap[1] = FATTR4_WORD1_SACL;
	}
}

static void encode_setacl(struct xdr_stream *xdr,
			  const struct nfs_setaclargs *arg,
			  struct compound_hdr *hdr)
{
	__be32 *p;
	__u32 bitmap[2];

	nfs4_acltype_to_bitmap(arg->acl_type, bitmap);

	encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr);
	encode_nfs4_stateid(xdr, &zero_stateid);
	p = reserve_space(xdr, 2*4);
	*p++ = cpu_to_be32(1);
	*p = cpu_to_be32(FATTR4_WORD0_ACL);
	p = reserve_space(xdr, 4);
	*p = cpu_to_be32(arg->acl_len);
	xdr_encode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap));
	encode_uint32(xdr, arg->acl_len);
	xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len);
}

@@ -2587,11 +2603,11 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
	struct compound_hdr hdr = {
		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
	};
	const __u32 nfs4_acl_bitmap[1] = {
		[0] = FATTR4_WORD0_ACL,
	};
	__u32 nfs4_acl_bitmap[2];
	uint32_t replen;

	nfs4_acltype_to_bitmap(args->acl_type, nfs4_acl_bitmap);

	encode_compound_hdr(xdr, req, &hdr);
	encode_sequence(xdr, &args->seq_args, &hdr);
	encode_putfh(xdr, args->fh, &hdr);
@@ -5386,7 +5402,7 @@ decode_restorefh(struct xdr_stream *xdr)
}

static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
			 struct nfs_getaclres *res)
			 struct nfs_getaclres *res, enum nfs4_acl_type type)
{
	unsigned int savep;
	uint32_t attrlen,
@@ -5404,9 +5420,25 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
		goto out;

	switch (type) {
	default:
		if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
			return -EIO;
	if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
		if (!(bitmap[0] & FATTR4_WORD0_ACL))
			return -EOPNOTSUPP;
		break;
	case NFS4ACL_DACL:
		if (unlikely(bitmap[0] || bitmap[1] & (FATTR4_WORD1_DACL - 1U)))
			return -EIO;
		if (!(bitmap[1] & FATTR4_WORD1_DACL))
			return -EOPNOTSUPP;
		break;
	case NFS4ACL_SACL:
		if (unlikely(bitmap[0] || bitmap[1] & (FATTR4_WORD1_SACL - 1U)))
			return -EIO;
		if (!(bitmap[1] & FATTR4_WORD1_SACL))
			return -EOPNOTSUPP;
	}

	/* The bitmap (xdr len + bitmaps) and the attr xdr len words
	 * are stored with the acl data to handle the problem of
@@ -5421,9 +5453,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
		dprintk("NFS: acl reply: attrlen %u > page_len %zu\n",
			attrlen, xdr_stream_remaining(xdr));
	}
	} else
		status = -EOPNOTSUPP;

out:
	return status;
}
@@ -6486,7 +6515,7 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
	status = decode_putfh(xdr);
	if (status)
		goto out;
	status = decode_getacl(xdr, rqstp, res);
	status = decode_getacl(xdr, rqstp, res, res->acl_type);

out:
	return status;
+3 −0
Original line number Diff line number Diff line
@@ -810,6 +810,7 @@ enum nfs4_acl_type {
struct nfs_setaclargs {
	struct nfs4_sequence_args	seq_args;
	struct nfs_fh *			fh;
	enum nfs4_acl_type		acl_type;
	size_t				acl_len;
	struct page **			acl_pages;
};
@@ -821,6 +822,7 @@ struct nfs_setaclres {
struct nfs_getaclargs {
	struct nfs4_sequence_args 	seq_args;
	struct nfs_fh *			fh;
	enum nfs4_acl_type		acl_type;
	size_t				acl_len;
	struct page **			acl_pages;
};
@@ -829,6 +831,7 @@ struct nfs_getaclargs {
#define NFS4_ACL_TRUNC		0x0001	/* ACL was truncated */
struct nfs_getaclres {
	struct nfs4_sequence_res	seq_res;
	enum nfs4_acl_type		acl_type;
	size_t				acl_len;
	size_t				acl_data_offset;
	int				acl_flags;