[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[qemu-xen staging-4.14] xen/9pfs: yield when there isn't enough room on the ring



commit cb84d9d353d40dbcd02fd8ff2c83971ecac0e65b
Author:     Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
AuthorDate: Thu May 21 12:26:26 2020 -0700
Commit:     Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
CommitDate: Mon Aug 24 19:11:22 2020 -0500

    xen/9pfs: yield when there isn't enough room on the ring
    
    Instead of truncating replies, which is problematic, wait until the
    client reads more data and frees bytes on the reply ring.
    
    Do that by calling qemu_coroutine_yield(). The corresponding
    qemu_coroutine_enter_if_inactive() is called from xen_9pfs_bh upon
    receiving the next notification from the client.
    
    We need to be careful to avoid races in case xen_9pfs_bh and the
    coroutine are both active at the same time. In xen_9pfs_bh, wait until
    either the critical section is over (ring->co == NULL) or until the
    coroutine becomes inactive (qemu_coroutine_yield() was called) before
    continuing. Then, simply wake up the coroutine if it is inactive.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
    Reviewed-by: Christian Schoenebeck <qemu_oss@xxxxxxxxxxxxx>
    Message-Id: <20200521192627.15259-2-sstabellini@xxxxxxxxxx>
    Signed-off-by: Greg Kurz <groug@xxxxxxxx>
    (cherry picked from commit a4c4d462729466c4756bac8a0a8d77eb63b21ef7)
    Signed-off-by: Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
---
 hw/9pfs/xen-9p-backend.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index fc197f6c8a..3c84c86ab8 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -37,6 +37,7 @@ typedef struct Xen9pfsRing {
 
     struct iovec *sg;
     QEMUBH *bh;
+    Coroutine *co;
 
     /* local copies, so that we can read/write PDU data directly from
      * the ring */
@@ -198,16 +199,20 @@ static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu,
     g_free(ring->sg);
 
     ring->sg = g_new0(struct iovec, 2);
-    xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size);
+    ring->co = qemu_coroutine_self();
+    /* make sure other threads see ring->co changes before continuing */
+    smp_wmb();
 
+again:
+    xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size);
     buf_size = iov_size(ring->sg, num);
     if (buf_size  < size) {
-        xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d"
-                "needs %zu bytes, buffer has %zu\n", pdu->id, size,
-                buf_size);
-        xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
-        xen_9pfs_disconnect(&xen_9pfs->xendev);
+        qemu_coroutine_yield();
+        goto again;
     }
+    ring->co = NULL;
+    /* make sure other threads see ring->co changes before continuing */
+    smp_wmb();
 
     *piov = ring->sg;
     *pniov = num;
@@ -292,6 +297,20 @@ static int xen_9pfs_receive(Xen9pfsRing *ring)
 static void xen_9pfs_bh(void *opaque)
 {
     Xen9pfsRing *ring = opaque;
+    bool wait;
+
+again:
+    wait = ring->co != NULL && qemu_coroutine_entered(ring->co);
+    /* paired with the smb_wmb barriers in xen_9pfs_init_in_iov_from_pdu */
+    smp_rmb();
+    if (wait) {
+        cpu_relax();
+        goto again;
+    }
+
+    if (ring->co != NULL) {
+        qemu_coroutine_enter_if_inactive(ring->co);
+    }
     xen_9pfs_receive(ring);
 }
 
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#staging-4.14



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.