virtio: Introduce virtqueue_drop_all procedure
Add procedure for fast drop of queued packets, acting like pop and push without mapping the buffers into memory. Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
aa94d52142
commit
54e17709ac
|
@ -783,6 +783,44 @@ err_undo_map:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* virtqueue_drop_all:
|
||||
* @vq: The #VirtQueue
|
||||
* Drops all queued buffers and indicates them to the guest
|
||||
* as if they are done. Useful when buffers can not be
|
||||
* processed but must be returned to the guest.
|
||||
*/
|
||||
unsigned int virtqueue_drop_all(VirtQueue *vq)
|
||||
{
|
||||
unsigned int dropped = 0;
|
||||
VirtQueueElement elem = {};
|
||||
VirtIODevice *vdev = vq->vdev;
|
||||
bool fEventIdx = virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
|
||||
|
||||
if (unlikely(vdev->broken)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!virtio_queue_empty(vq) && vq->inuse < vq->vring.num) {
|
||||
/* works similar to virtqueue_pop but does not map buffers
|
||||
* and does not allocate any memory */
|
||||
smp_rmb();
|
||||
if (!virtqueue_get_head(vq, vq->last_avail_idx, &elem.index)) {
|
||||
break;
|
||||
}
|
||||
vq->inuse++;
|
||||
vq->last_avail_idx++;
|
||||
if (fEventIdx) {
|
||||
vring_set_avail_event(vq, vq->last_avail_idx);
|
||||
}
|
||||
/* immediately push the element, nothing to unmap
|
||||
* as both in_num and out_num are set to 0 */
|
||||
virtqueue_push(vq, &elem, 0);
|
||||
dropped++;
|
||||
}
|
||||
|
||||
return dropped;
|
||||
}
|
||||
|
||||
/* Reading and writing a structure directly to QEMUFile is *awful*, but
|
||||
* it is what QEMU has always done by mistake. We can change it sooner
|
||||
* or later by bumping the version number of the affected vm states.
|
||||
|
|
|
@ -173,6 +173,7 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
|||
|
||||
void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem);
|
||||
void *virtqueue_pop(VirtQueue *vq, size_t sz);
|
||||
unsigned int virtqueue_drop_all(VirtQueue *vq);
|
||||
void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz);
|
||||
void qemu_put_virtqueue_element(QEMUFile *f, VirtQueueElement *elem);
|
||||
int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
|
||||
|
|
Loading…
Reference in a new issue