Commit 21d316a7 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Clean up nfsd4_encode_copy_notify()



Replace open-coded encoding logic with the use of conventional XDR
utility functions.

Note that if we replace the cpn_sec and cpn_nsec fields with a
single struct timespec64 field, the encoder can use
nfsd4_encode_nfstime4(), as that is the data type specified by the
XDR spec.

NFS4ERR_INVAL seems inappropriate if the encoder doesn't support
encoding the response. Instead use NFS4ERR_SERVERFAULT, since this
condition is a software bug on the server.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 02e0297f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1939,8 +1939,8 @@ nfsd4_copy_notify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	if (status)
		return status;

	cn->cpn_sec = nn->nfsd4_lease;
	cn->cpn_nsec = 0;
	cn->cpn_lease_time.tv_sec = nn->nfsd4_lease;
	cn->cpn_lease_time.tv_nsec = 0;

	status = nfserrno(-ENOMEM);
	cps = nfs4_alloc_init_cpntf_state(nn, stid);
+41 −65
Original line number Diff line number Diff line
@@ -2575,6 +2575,19 @@ nfsd4_encode_change_info4(struct xdr_stream *xdr, const struct nfsd4_change_info
	return nfsd4_encode_changeid4(xdr, c->after_change);
}

static __be32 nfsd4_encode_netaddr4(struct xdr_stream *xdr,
				    const struct nfs42_netaddr *addr)
{
	__be32 status;

	/* na_r_netid */
	status = nfsd4_encode_opaque(xdr, addr->netid, addr->netid_len);
	if (status != nfs_ok)
		return status;
	/* na_r_addr */
	return nfsd4_encode_opaque(xdr, addr->addr, addr->addr_len);
}

/* Encode as an array of strings the string given with components
 * separated @sep, escaped with esc_enter and esc_exit.
 */
@@ -5132,43 +5145,42 @@ nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
}

static __be32
nfsd42_encode_nl4_server(struct nfsd4_compoundres *resp, struct nl4_server *ns)
nfsd4_encode_netloc4(struct xdr_stream *xdr, const struct nl4_server *ns)
{
	struct xdr_stream *xdr = resp->xdr;
	struct nfs42_netaddr *addr;
	__be32 *p;

	p = xdr_reserve_space(xdr, 4);
	*p++ = cpu_to_be32(ns->nl4_type);
	__be32 status;

	if (xdr_stream_encode_u32(xdr, ns->nl4_type) != XDR_UNIT)
		return nfserr_resource;
	switch (ns->nl4_type) {
	case NL4_NETADDR:
		addr = &ns->u.nl4_addr;

		/* netid_len, netid, uaddr_len, uaddr (port included
		 * in RPCBIND_MAXUADDRLEN)
		 */
		p = xdr_reserve_space(xdr,
			4 /* netid len */ +
			(XDR_QUADLEN(addr->netid_len) * 4) +
			4 /* uaddr len */ +
			(XDR_QUADLEN(addr->addr_len) * 4));
		if (!p)
			return nfserr_resource;

		*p++ = cpu_to_be32(addr->netid_len);
		p = xdr_encode_opaque_fixed(p, addr->netid,
					    addr->netid_len);
		*p++ = cpu_to_be32(addr->addr_len);
		p = xdr_encode_opaque_fixed(p, addr->addr,
					addr->addr_len);
		/* nl_addr */
		status = nfsd4_encode_netaddr4(xdr, &ns->u.nl4_addr);
		break;
	default:
		WARN_ON_ONCE(ns->nl4_type != NL4_NETADDR);
		return nfserr_inval;
		status = nfserr_serverfault;
	}
	return status;
}

	return 0;
static __be32
nfsd4_encode_copy_notify(struct nfsd4_compoundres *resp, __be32 nfserr,
			 union nfsd4_op_u *u)
{
	struct nfsd4_copy_notify *cn = &u->copy_notify;
	struct xdr_stream *xdr = resp->xdr;

	/* cnr_lease_time */
	nfserr = nfsd4_encode_nfstime4(xdr, &cn->cpn_lease_time);
	if (nfserr)
		return nfserr;
	/* cnr_stateid */
	nfserr = nfsd4_encode_stateid4(xdr, &cn->cpn_cnr_stateid);
	if (nfserr)
		return nfserr;
	/* cnr_source_server<> */
	if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT)
		return nfserr_resource;
	return nfsd4_encode_netloc4(xdr, cn->cpn_src);
}

static __be32
@@ -5261,42 +5273,6 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
	return nfserr;
}

static __be32
nfsd4_encode_copy_notify(struct nfsd4_compoundres *resp, __be32 nfserr,
			 union nfsd4_op_u *u)
{
	struct nfsd4_copy_notify *cn = &u->copy_notify;
	struct xdr_stream *xdr = resp->xdr;
	__be32 *p;

	if (nfserr)
		return nfserr;

	/* 8 sec, 4 nsec */
	p = xdr_reserve_space(xdr, 12);
	if (!p)
		return nfserr_resource;

	/* cnr_lease_time */
	p = xdr_encode_hyper(p, cn->cpn_sec);
	*p++ = cpu_to_be32(cn->cpn_nsec);

	/* cnr_stateid */
	nfserr = nfsd4_encode_stateid4(xdr, &cn->cpn_cnr_stateid);
	if (nfserr)
		return nfserr;

	/* cnr_src.nl_nsvr */
	p = xdr_reserve_space(xdr, 4);
	if (!p)
		return nfserr_resource;

	*p++ = cpu_to_be32(1);

	nfserr = nfsd42_encode_nl4_server(resp, cn->cpn_src);
	return nfserr;
}

static __be32
nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr,
		  union nfsd4_op_u *u)
+1 −2
Original line number Diff line number Diff line
@@ -745,8 +745,7 @@ struct nfsd4_copy_notify {

	/* response */
	stateid_t		cpn_cnr_stateid;
	u64			cpn_sec;
	u32			cpn_nsec;
	struct timespec64	cpn_lease_time;
	struct nl4_server	*cpn_src;
};