@@ -219,7 +219,7 @@ static int peek_head_len(struct vhost_virtqueue *vq, struct sock *sk)
/* This is a multi-buffer version of vhost_get_desc, that works if
* vq has read descriptors only.
* @vq - the relevant virtqueue
- * @datalen - data length we'll be reading
+ * @datalen - data length we'll be reading. must be > 0
* @iovcount - returned count of io vectors we fill
* @log - vhost log
* @log_num - log offset
@@ -236,9 +236,10 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
int seg = 0;
int headcount = 0;
unsigned d;
+ size_t len;
int r, nlogs = 0;
- while (datalen > 0) {
+ for (;;) {
if (unlikely(headcount >= VHOST_NET_MAX_SG)) {
r = -ENOBUFS;
goto err;
@@ -260,16 +261,20 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
nlogs += *log_num;
log += *log_num;
}
+ len = iov_length(vq->iov + seg, in);
+ seg += in;
heads[headcount].id = d;
- heads[headcount].len = iov_length(vq->iov + seg, in);
- datalen -= heads[headcount].len;
+ if (datalen <= len)
+ break;
+ heads[headcount].len = len;
++headcount;
- seg += in;
+ datalen -= len;
}
+ heads[headcount].len = datalen;
*iovcount = seg;
if (unlikely(log))
*log_num = nlogs;
- return headcount;
+ return headcount + 1;
err:
vhost_discard_desc(vq, headcount);
return r;