Commit b8c06ad4 authored by Stefano Garzarella's avatar Stefano Garzarella Committed by Michael S. Tsirkin

vringh: implement vringh_kiov_advance()

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: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Link: https://lore.kernel.org/r/20210315163450.254396-6-sgarzare@redhat.comSigned-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 69c13c58
...@@ -75,6 +75,34 @@ static inline int __vringh_get_head(const struct vringh *vrh, ...@@ -75,6 +75,34 @@ static inline int __vringh_get_head(const struct vringh *vrh,
return head; 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. */ /* Copy some bytes to/from the iovec. Returns num copied. */
static inline ssize_t vringh_iov_xfer(struct vringh *vrh, static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
struct vringh_kiov *iov, struct vringh_kiov *iov,
...@@ -95,19 +123,8 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh, ...@@ -95,19 +123,8 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
done += partlen; done += partlen;
len -= partlen; len -= partlen;
ptr += 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) { vringh_kiov_advance(iov, partlen);
/* 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++;
}
} }
return done; return done;
} }
......
...@@ -199,6 +199,8 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov) ...@@ -199,6 +199,8 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
kiov->iov = NULL; kiov->iov = NULL;
} }
void vringh_kiov_advance(struct vringh_kiov *kiov, size_t len);
int vringh_getdesc_kern(struct vringh *vrh, int vringh_getdesc_kern(struct vringh *vrh,
struct vringh_kiov *riov, struct vringh_kiov *riov,
struct vringh_kiov *wiov, struct vringh_kiov *wiov,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment