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: Andy Adamson <andros@netapp.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
This commit is contained in:
Olga Kornievskaia 2019-09-13 14:00:57 -04:00 committed by J. Bruce Fields
parent af76fc6c15
commit 84e1b21d5e
2 changed files with 71 additions and 6 deletions

View File

@ -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;
}

View File

@ -518,11 +518,13 @@ struct nfsd42_write_res {
struct nfsd4_copy {
/* request */
stateid_t cp_src_stateid;
stateid_t cp_dst_stateid;
u64 cp_src_pos;
u64 cp_dst_pos;
u64 cp_count;
stateid_t cp_src_stateid;
stateid_t cp_dst_stateid;
u64 cp_src_pos;
u64 cp_dst_pos;
u64 cp_count;
struct nl4_server cp_src;
bool cp_intra;
/* both */
bool cp_synchronous;