diff mbox

[for-2.7,3/4] virtio: add virtqueue_rewind()

Message ID 1471015978-1123-4-git-send-email-stefanha@redhat.com
State New
Headers show

Commit Message

Stefan Hajnoczi Aug. 12, 2016, 3:32 p.m. UTC
virtqueue_discard() requires a VirtQueueElement but virtio-balloon does
not migrate its in-use element.  Introduce a new function that is
similar to virtqueue_discard() but doesn't require a VirtQueueElement.

This will allow virtio-balloon to access element again after migration
with the usual proviso that the guest may have modified the vring since
last time.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/virtio/virtio.c         | 22 ++++++++++++++++++++++
 include/hw/virtio/virtio.h |  1 +
 2 files changed, 23 insertions(+)

Comments

Cornelia Huck Aug. 15, 2016, 8:36 a.m. UTC | #1
On Fri, 12 Aug 2016 16:32:57 +0100
Stefan Hajnoczi <stefanha@redhat.com> wrote:

> virtqueue_discard() requires a VirtQueueElement but virtio-balloon does
> not migrate its in-use element.  Introduce a new function that is
> similar to virtqueue_discard() but doesn't require a VirtQueueElement.
> 
> This will allow virtio-balloon to access element again after migration
> with the usual proviso that the guest may have modified the vring since
> last time.
> 
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  hw/virtio/virtio.c         | 22 ++++++++++++++++++++++
>  include/hw/virtio/virtio.h |  1 +
>  2 files changed, 23 insertions(+)
> 
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 00158b6..22727ba 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -272,6 +272,28 @@ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
>      virtqueue_unmap_sg(vq, elem, len);
>  }
> 
> +/* virtqueue_rewind:
> + * @vq: The #VirtQueue
> + * @num: Number of elements to push back
> + *
> + * Pretend that elements weren't popped from the virtqueue.  The next
> + * virtqueue_pop() will refetch the oldest element.
> + *
> + * Use virtqueue_discard() instead if you have a VirtQueueElement.
> + *
> + * Returns: true on success, false if @num is greater than the number of in use
> + * elements.

Does it make sense at all to rewind multiple elements at once? Or does
it make more sense for the caller to rewind one-by-one until they know
that there are no more elements that could be refetched?

> + */
> +bool virtqueue_rewind(VirtQueue *vq, unsigned int num)
> +{
> +    if (num > vq->inuse) {
> +        return false;
> +    }
> +    vq->last_avail_idx -= num;
> +    vq->inuse -= num;
> +    return true;
> +}
> +
>  void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
>                      unsigned int len, unsigned int idx)
>  {
Stefan Hajnoczi Aug. 15, 2016, 12:34 p.m. UTC | #2
On Mon, Aug 15, 2016 at 10:36:25AM +0200, Cornelia Huck wrote:
> On Fri, 12 Aug 2016 16:32:57 +0100
> Stefan Hajnoczi <stefanha@redhat.com> wrote:
> 
> > virtqueue_discard() requires a VirtQueueElement but virtio-balloon does
> > not migrate its in-use element.  Introduce a new function that is
> > similar to virtqueue_discard() but doesn't require a VirtQueueElement.
> > 
> > This will allow virtio-balloon to access element again after migration
> > with the usual proviso that the guest may have modified the vring since
> > last time.
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  hw/virtio/virtio.c         | 22 ++++++++++++++++++++++
> >  include/hw/virtio/virtio.h |  1 +
> >  2 files changed, 23 insertions(+)
> > 
> > diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> > index 00158b6..22727ba 100644
> > --- a/hw/virtio/virtio.c
> > +++ b/hw/virtio/virtio.c
> > @@ -272,6 +272,28 @@ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
> >      virtqueue_unmap_sg(vq, elem, len);
> >  }
> > 
> > +/* virtqueue_rewind:
> > + * @vq: The #VirtQueue
> > + * @num: Number of elements to push back
> > + *
> > + * Pretend that elements weren't popped from the virtqueue.  The next
> > + * virtqueue_pop() will refetch the oldest element.
> > + *
> > + * Use virtqueue_discard() instead if you have a VirtQueueElement.
> > + *
> > + * Returns: true on success, false if @num is greater than the number of in use
> > + * elements.
> 
> Does it make sense at all to rewind multiple elements at once? Or does
> it make more sense for the caller to rewind one-by-one until they know
> that there are no more elements that could be refetched?

I think Ladi's virtio-balloon stats fix using the vmchange callback is
preferrable.  I'll drop this and the next patch.

Stefan
diff mbox

Patch

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 00158b6..22727ba 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -272,6 +272,28 @@  void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
     virtqueue_unmap_sg(vq, elem, len);
 }
 
+/* virtqueue_rewind:
+ * @vq: The #VirtQueue
+ * @num: Number of elements to push back
+ *
+ * Pretend that elements weren't popped from the virtqueue.  The next
+ * virtqueue_pop() will refetch the oldest element.
+ *
+ * Use virtqueue_discard() instead if you have a VirtQueueElement.
+ *
+ * Returns: true on success, false if @num is greater than the number of in use
+ * elements.
+ */
+bool virtqueue_rewind(VirtQueue *vq, unsigned int num)
+{
+    if (num > vq->inuse) {
+        return false;
+    }
+    vq->last_avail_idx -= num;
+    vq->inuse -= num;
+    return true;
+}
+
 void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                     unsigned int len, unsigned int idx)
 {
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index d2490c1..f05559d 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -154,6 +154,7 @@  void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
 void virtqueue_flush(VirtQueue *vq, unsigned int count);
 void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
                        unsigned int len);
+bool virtqueue_rewind(VirtQueue *vq, unsigned int num);
 void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                     unsigned int len, unsigned int idx);