vringh: implement vringh_kiov_advance()
authorStefano Garzarella <sgarzare@redhat.com>
Mon, 15 Mar 2021 16:34:41 +0000 (17:34 +0100)
committerMichael S. Tsirkin <mst@redhat.com>
Mon, 3 May 2021 08:55:53 +0000 (04:55 -0400)
In some cases, it may be useful to provide a way to skip a number
of bytes in a vringh_kiov.

Let's implement vringh_kiov_advance() for this purpose, reusing the
code from vringh_iov_xfer().
We replace that code calling the new vringh_kiov_advance().

Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Link: https://lore.kernel.org/r/20210315163450.254396-6-sgarzare@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/vhost/vringh.c
include/linux/vringh.h

index 2a88e08..4af8fa2 100644 (file)
@@ -75,6 +75,34 @@ static inline int __vringh_get_head(const struct vringh *vrh,
        return head;
 }
 
+/**
+ * vringh_kiov_advance - skip bytes from vring_kiov
+ * @iov: an iov passed to vringh_getdesc_*() (updated as we consume)
+ * @len: the maximum length to advance
+ */
+void vringh_kiov_advance(struct vringh_kiov *iov, size_t len)
+{
+       while (len && iov->i < iov->used) {
+               size_t partlen = min(iov->iov[iov->i].iov_len, len);
+
+               iov->consumed += partlen;
+               iov->iov[iov->i].iov_len -= partlen;
+               iov->iov[iov->i].iov_base += partlen;
+
+               if (!iov->iov[iov->i].iov_len) {
+                       /* Fix up old iov element then increment. */
+                       iov->iov[iov->i].iov_len = iov->consumed;
+                       iov->iov[iov->i].iov_base -= iov->consumed;
+
+                       iov->consumed = 0;
+                       iov->i++;
+               }
+
+               len -= partlen;
+       }
+}
+EXPORT_SYMBOL(vringh_kiov_advance);
+
 /* Copy some bytes to/from the iovec.  Returns num copied. */
 static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
                                      struct vringh_kiov *iov,
@@ -95,19 +123,8 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
                done += partlen;
                len -= partlen;
                ptr += partlen;
-               iov->consumed += partlen;
-               iov->iov[iov->i].iov_len -= partlen;
-               iov->iov[iov->i].iov_base += partlen;
 
-               if (!iov->iov[iov->i].iov_len) {
-                       /* Fix up old iov element then increment. */
-                       iov->iov[iov->i].iov_len = iov->consumed;
-                       iov->iov[iov->i].iov_base -= iov->consumed;
-
-                       
-                       iov->consumed = 0;
-                       iov->i++;
-               }
+               vringh_kiov_advance(iov, partlen);
        }
        return done;
 }
index 9c07786..755211e 100644 (file)
@@ -199,6 +199,8 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
        kiov->iov = NULL;
 }
 
+void vringh_kiov_advance(struct vringh_kiov *kiov, size_t len);
+
 int vringh_getdesc_kern(struct vringh *vrh,
                        struct vringh_kiov *riov,
                        struct vringh_kiov *wiov,