OSDN Git Service

NFSD add ca_source_server<> to COPY
authorOlga Kornievskaia <olga.kornievskaia@gmail.com>
Fri, 13 Sep 2019 18:00:57 +0000 (14:00 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 9 Dec 2019 16:42:14 +0000 (11:42 -0500)
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>
fs/nfsd/nfs4xdr.c
fs/nfsd/xdr4.h

index d2dc4c0..a1d8394 100644 (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;
 }
index f4737d6..e815a9c 100644 (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;