Commit 84e1b21d authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by J. Bruce Fields
Browse files

NFSD add ca_source_server<> to COPY



Decode the ca_source_server list that's sent but only use the
first one. Presence of non-zero list indicates an "inter" copy.

Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
parent af76fc6c
Loading
Loading
Loading
Loading
+64 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/utsname.h>
#include <linux/pagemap.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/addr.h>

#include "idmap.h"
#include "acl.h"
@@ -1744,10 +1745,47 @@ nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
	DECODE_TAIL;
}

static __be32 nfsd4_decode_nl4_server(struct nfsd4_compoundargs *argp,
				      struct nl4_server *ns)
{
	DECODE_HEAD;
	struct nfs42_netaddr *naddr;

	READ_BUF(4);
	ns->nl4_type = be32_to_cpup(p++);

	/* currently support for 1 inter-server source server */
	switch (ns->nl4_type) {
	case NL4_NETADDR:
		naddr = &ns->u.nl4_addr;

		READ_BUF(4);
		naddr->netid_len = be32_to_cpup(p++);
		if (naddr->netid_len > RPCBIND_MAXNETIDLEN)
			goto xdr_error;

		READ_BUF(naddr->netid_len + 4); /* 4 for uaddr len */
		COPYMEM(naddr->netid, naddr->netid_len);

		naddr->addr_len = be32_to_cpup(p++);
		if (naddr->addr_len > RPCBIND_MAXUADDRLEN)
			goto xdr_error;

		READ_BUF(naddr->addr_len);
		COPYMEM(naddr->addr, naddr->addr_len);
		break;
	default:
		goto xdr_error;
	}
	DECODE_TAIL;
}

static __be32
nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
{
	DECODE_HEAD;
	struct nl4_server *ns_dummy;
	int i, count;

	status = nfsd4_decode_stateid(argp, &copy->cp_src_stateid);
	if (status)
@@ -1762,7 +1800,32 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
	p = xdr_decode_hyper(p, &copy->cp_count);
	p++; /* ca_consecutive: we always do consecutive copies */
	copy->cp_synchronous = be32_to_cpup(p++);
	/* tmp = be32_to_cpup(p); Source server list not supported */

	count = be32_to_cpup(p++);

	copy->cp_intra = false;
	if (count == 0) { /* intra-server copy */
		copy->cp_intra = true;
		goto intra;
	}

	/* decode all the supplied server addresses but use first */
	status = nfsd4_decode_nl4_server(argp, &copy->cp_src);
	if (status)
		return status;

	ns_dummy = kmalloc(sizeof(struct nl4_server), GFP_KERNEL);
	if (ns_dummy == NULL)
		return nfserrno(-ENOMEM);
	for (i = 0; i < count - 1; i++) {
		status = nfsd4_decode_nl4_server(argp, ns_dummy);
		if (status) {
			kfree(ns_dummy);
			return status;
		}
	}
	kfree(ns_dummy);
intra:

	DECODE_TAIL;
}
+7 −5
Original line number Diff line number Diff line
@@ -523,6 +523,8 @@ struct nfsd4_copy {
	u64			cp_src_pos;
	u64			cp_dst_pos;
	u64			cp_count;
	struct nl4_server	cp_src;
	bool			cp_intra;

	/* both */
	bool		cp_synchronous;