]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sunrpc/xdr.c
Merge tag 'for-linus-2019-09-27' of git://git.kernel.dk/linux-block
[linux.git] / net / sunrpc / xdr.c
index 48c93b9e525ee3301718e1a5a17be0b92ace1e30..14ba9e72a20494d544657ce400880c13d8dddd3c 100644 (file)
@@ -560,7 +560,7 @@ EXPORT_SYMBOL_GPL(xdr_init_encode);
  * required at the end of encoding, or any other time when the xdr_buf
  * data might be read.
  */
-void xdr_commit_encode(struct xdr_stream *xdr)
+inline void xdr_commit_encode(struct xdr_stream *xdr)
 {
        int shift = xdr->scratch.iov_len;
        void *page;
@@ -1236,43 +1236,60 @@ xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj)
 }
 EXPORT_SYMBOL_GPL(xdr_encode_word);
 
-/* If the netobj starting offset bytes from the start of xdr_buf is contained
- * entirely in the head or the tail, set object to point to it; otherwise
- * try to find space for it at the end of the tail, copy it there, and
- * set obj to point to it. */
-int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset)
+/**
+ * xdr_buf_read_mic() - obtain the address of the GSS mic from xdr buf
+ * @buf: pointer to buffer containing a mic
+ * @mic: on success, returns the address of the mic
+ * @offset: the offset in buf where mic may be found
+ *
+ * This function may modify the xdr buf if the mic is found to be straddling
+ * a boundary between head, pages, and tail.  On success the mic can be read
+ * from the address returned.  There is no need to free the mic.
+ *
+ * Return: Success returns 0, otherwise an integer error.
+ */
+int xdr_buf_read_mic(struct xdr_buf *buf, struct xdr_netobj *mic, unsigned int offset)
 {
        struct xdr_buf subbuf;
+       unsigned int boundary;
 
-       if (xdr_decode_word(buf, offset, &obj->len))
+       if (xdr_decode_word(buf, offset, &mic->len))
                return -EFAULT;
-       if (xdr_buf_subsegment(buf, &subbuf, offset + 4, obj->len))
+       offset += 4;
+
+       /* Is the mic partially in the head? */
+       boundary = buf->head[0].iov_len;
+       if (offset < boundary && (offset + mic->len) > boundary)
+               xdr_shift_buf(buf, boundary - offset);
+
+       /* Is the mic partially in the pages? */
+       boundary += buf->page_len;
+       if (offset < boundary && (offset + mic->len) > boundary)
+               xdr_shrink_pagelen(buf, boundary - offset);
+
+       if (xdr_buf_subsegment(buf, &subbuf, offset, mic->len))
                return -EFAULT;
 
-       /* Is the obj contained entirely in the head? */
-       obj->data = subbuf.head[0].iov_base;
-       if (subbuf.head[0].iov_len == obj->len)
+       /* Is the mic contained entirely in the head? */
+       mic->data = subbuf.head[0].iov_base;
+       if (subbuf.head[0].iov_len == mic->len)
                return 0;
-       /* ..or is the obj contained entirely in the tail? */
-       obj->data = subbuf.tail[0].iov_base;
-       if (subbuf.tail[0].iov_len == obj->len)
+       /* ..or is the mic contained entirely in the tail? */
+       mic->data = subbuf.tail[0].iov_base;
+       if (subbuf.tail[0].iov_len == mic->len)
                return 0;
 
-       /* use end of tail as storage for obj:
-        * (We don't copy to the beginning because then we'd have
-        * to worry about doing a potentially overlapping copy.
-        * This assumes the object is at most half the length of the
-        * tail.) */
-       if (obj->len > buf->buflen - buf->len)
+       /* Find a contiguous area in @buf to hold all of @mic */
+       if (mic->len > buf->buflen - buf->len)
                return -ENOMEM;
        if (buf->tail[0].iov_len != 0)
-               obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len;
+               mic->data = buf->tail[0].iov_base + buf->tail[0].iov_len;
        else
-               obj->data = buf->head[0].iov_base + buf->head[0].iov_len;
-       __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len);
+               mic->data = buf->head[0].iov_base + buf->head[0].iov_len;
+       __read_bytes_from_xdr_buf(&subbuf, mic->data, mic->len);
        return 0;
 }
-EXPORT_SYMBOL_GPL(xdr_buf_read_netobj);
+EXPORT_SYMBOL_GPL(xdr_buf_read_mic);
 
 /* Returns 0 on success, or else a negative error code. */
 static int