NFSD: Clean up nfsd4_encode_copy_notify()
authorChuck Lever <chuck.lever@oracle.com>
Mon, 9 Oct 2023 18:30:16 +0000 (14:30 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 16 Oct 2023 16:44:37 +0000 (12:44 -0400)
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: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4xdr.c
fs/nfsd/xdr4.h

index f288039545e3f3d43bd25f0b06ce0b7517ddc7cc..35987b98d773423d0752d92d264ff2a32e98374a 100644 (file)
@@ -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);
index ce894aba19ceeb3be43e2501f5522ef04db63ba7..c72240c3f4db4a6cc1fcd6d0577b460e03b603ab 100644 (file)
@@ -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 @@ out:
        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)
index f97977bbd6fb954d791d706f681556b13c829ce1..80e859dc84d8329c0d806b3c8fa37266d7a6ca18 100644 (file)
@@ -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;
 };