SUNRPC: Add xdr_pad_size() helper
authorChuck Lever <chuck.lever@oracle.com>
Mon, 2 Mar 2020 20:01:08 +0000 (15:01 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 16 Mar 2020 16:04:31 +0000 (12:04 -0400)
Introduce a helper function to compute the XDR pad size of a
variable-length XDR object.

Clean up: Replace open-coded calculation of XDR pad sizes.
I'm sure I haven't found every instance of this calculation.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/linux/sunrpc/xdr.h
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c

index b41f3497799551ab4a5902b7791f38fdc63123fb..83cd9f15c52626b6acc403f9c29ac6d229a1545b 100644 (file)
@@ -300,6 +300,21 @@ xdr_align_size(size_t n)
        return (n + mask) & ~mask;
 }
 
+/**
+ * xdr_pad_size - Calculate size of an object's pad
+ * @n: Size of an object being XDR encoded (in bytes)
+ *
+ * This implementation avoids the need for conditional
+ * branches or modulo division.
+ *
+ * Return value:
+ *   Size (in bytes) of the needed XDR pad
+ */
+static inline size_t xdr_pad_size(size_t n)
+{
+       return xdr_align_size(n) - n;
+}
+
 /**
  * xdr_stream_encode_u32 - Encode a 32-bit integer
  * @xdr: pointer to xdr_stream
index 24ca861815b1d3ffde8c02b3a4ac1f7844d60a03..ee060d57d216598d4cd97b7fbd20d4964ad7ddf3 100644 (file)
@@ -1877,7 +1877,7 @@ static int gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        else
                iov = snd_buf->head;
        p = iov->iov_base + iov->iov_len;
-       pad = 3 - ((snd_buf->len - offset - 1) & 3);
+       pad = xdr_pad_size(snd_buf->len - offset);
        memset(p, 0, pad);
        iov->iov_len += pad;
        snd_buf->len += pad;
index 65b67b2573021d5685e97a7d3ab4e131cd10b88a..fcf74621f008db65bf57bdd27f738eaaffde97c0 100644 (file)
@@ -961,7 +961,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
        /* XXX: This is very inefficient.  It would be better to either do
         * this while we encrypt, or maybe in the receive code, if we can peak
         * ahead and work out the service and mechanism there. */
-       offset = buf->head[0].iov_len % 4;
+       offset = xdr_pad_size(buf->head[0].iov_len);
        if (offset) {
                buf->buflen = RPCSVC_MAXPAYLOAD;
                xdr_shift_buf(buf, offset);
@@ -1680,7 +1680,8 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
                goto out;
        integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base;
        integ_len = resbuf->len - integ_offset;
-       BUG_ON(integ_len % 4);
+       if (integ_len & 3)
+               goto out;
        *p++ = htonl(integ_len);
        *p++ = htonl(gc->gc_seq);
        if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) {
index 354c5619176a349b9525a04df37f323c75c20b0c..4add875277f8af84a81c0a611702417148558cfa 100644 (file)
@@ -322,11 +322,6 @@ int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr)
        return ret;
 }
 
-static u32 xdr_padsize(u32 len)
-{
-       return (len & 3) ? (4 - (len & 3)) : 0;
-}
-
 /* Returns length of transport header, in bytes.
  */
 static unsigned int svc_rdma_reply_hdr_len(__be32 *rdma_resp)
@@ -595,7 +590,7 @@ static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma,
        if (wr_lst) {
                u32 xdrpad;
 
-               xdrpad = xdr_padsize(xdr->page_len);
+               xdrpad = xdr_pad_size(xdr->page_len);
                if (taillen && xdrpad) {
                        tailbase += xdrpad;
                        taillen -= xdrpad;
@@ -670,7 +665,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        if (wr_lst) {
                base = xdr->tail[0].iov_base;
                len = xdr->tail[0].iov_len;
-               xdr_pad = xdr_padsize(xdr->page_len);
+               xdr_pad = xdr_pad_size(xdr->page_len);
 
                if (len && xdr_pad) {
                        base += xdr_pad;