diff mbox series

[17/30] virtiofsd: Add main virtio loop

Message ID 20191021105832.36574-18-dgilbert@redhat.com
State New
Headers show
Series virtiofs daemon (base) | expand

Commit Message

Dr. David Alan Gilbert Oct. 21, 2019, 10:58 a.m. UTC
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Processes incoming requests on the vhost-user fd.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 contrib/virtiofsd/fuse_virtio.c | 42 ++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

Comments

Marc-André Lureau Oct. 21, 2019, 2:51 p.m. UTC | #1
On Mon, Oct 21, 2019 at 1:26 PM Dr. David Alan Gilbert (git)
<dgilbert@redhat.com> wrote:
>
> From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
>
> Processes incoming requests on the vhost-user fd.

Is there a reason to avoid using glib & its main loop?

>
> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
>  contrib/virtiofsd/fuse_virtio.c | 42 ++++++++++++++++++++++++++++++---
>  1 file changed, 39 insertions(+), 3 deletions(-)
>
> diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virtio.c
> index 22f71d260f..9c58f11634 100644
> --- a/contrib/virtiofsd/fuse_virtio.c
> +++ b/contrib/virtiofsd/fuse_virtio.c
> @@ -11,12 +11,14 @@
>   * See the file COPYING.LIB
>   */
>
> +#include "fuse_virtio.h"
>  #include "fuse_i.h"
>  #include "fuse_kernel.h"
>  #include "fuse_misc.h"
>  #include "fuse_opt.h"
> -#include "fuse_virtio.h"
>
> +#include <assert.h>
> +#include <errno.h>
>  #include <stdint.h>
>  #include <stdio.h>
>  #include <stdlib.h>
> @@ -80,15 +82,49 @@ static const VuDevIface fv_iface = {
>      .queue_is_processed_in_order = fv_queue_order,
>  };
>
> +/*
> + * Main loop; this mostly deals with events on the vhost-user
> + * socket itself, and not actual fuse data.
> + */
>  int virtio_loop(struct fuse_session *se)
>  {
>      fuse_log(FUSE_LOG_INFO, "%s: Entry\n", __func__);
>
> -    while (1) {
> -        /* TODO: Add stuffing */
> +    while (!fuse_session_exited(se)) {
> +        struct pollfd pf[1];
> +        pf[0].fd = se->vu_socketfd;
> +        pf[0].events = POLLIN;
> +        pf[0].revents = 0;
> +
> +        fuse_log(FUSE_LOG_DEBUG, "%s: Waiting for VU event\n", __func__);
> +        int poll_res = ppoll(pf, 1, NULL, NULL);
> +
> +        if (poll_res == -1) {
> +            if (errno == EINTR) {
> +                fuse_log(FUSE_LOG_INFO, "%s: ppoll interrupted, going around\n",
> +                         __func__);
> +                continue;
> +            }
> +            fuse_log(FUSE_LOG_ERR, "virtio_loop ppoll: %m\n");
> +            break;
> +        }
> +        assert(poll_res == 1);
> +        if (pf[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
> +            fuse_log(FUSE_LOG_ERR, "%s: Unexpected poll revents %x\n", __func__,
> +                     pf[0].revents);
> +            break;
> +        }
> +        assert(pf[0].revents & POLLIN);
> +        fuse_log(FUSE_LOG_DEBUG, "%s: Got VU event\n", __func__);
> +        if (!vu_dispatch(&se->virtio_dev->dev)) {
> +            fuse_log(FUSE_LOG_ERR, "%s: vu_dispatch failed\n", __func__);
> +            break;
> +        }
>      }
>
>      fuse_log(FUSE_LOG_INFO, "%s: Exit\n", __func__);
> +
> +    return 0;
>  }
>
>  int virtio_session_mount(struct fuse_session *se)
> --
> 2.23.0
>
>
Dr. David Alan Gilbert Oct. 22, 2019, 11:07 a.m. UTC | #2
* Marc-André Lureau (marcandre.lureau@gmail.com) wrote:
> On Mon, Oct 21, 2019 at 1:26 PM Dr. David Alan Gilbert (git)
> <dgilbert@redhat.com> wrote:
> >
> > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> >
> > Processes incoming requests on the vhost-user fd.
> 
> Is there a reason to avoid using glib & its main loop?

Not particularly;  would it actually work out any easier?
Is there an easy way to get the glib loop to check something like
the fuse_session_exited at each iteration.

I probably didn't originally because I wasn't sure if this code
was going back into libfuse or staying here; and libfuse doesn't
use glib.

Dave

> >
> > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> > ---
> >  contrib/virtiofsd/fuse_virtio.c | 42 ++++++++++++++++++++++++++++++---
> >  1 file changed, 39 insertions(+), 3 deletions(-)
> >
> > diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virtio.c
> > index 22f71d260f..9c58f11634 100644
> > --- a/contrib/virtiofsd/fuse_virtio.c
> > +++ b/contrib/virtiofsd/fuse_virtio.c
> > @@ -11,12 +11,14 @@
> >   * See the file COPYING.LIB
> >   */
> >
> > +#include "fuse_virtio.h"
> >  #include "fuse_i.h"
> >  #include "fuse_kernel.h"
> >  #include "fuse_misc.h"
> >  #include "fuse_opt.h"
> > -#include "fuse_virtio.h"
> >
> > +#include <assert.h>
> > +#include <errno.h>
> >  #include <stdint.h>
> >  #include <stdio.h>
> >  #include <stdlib.h>
> > @@ -80,15 +82,49 @@ static const VuDevIface fv_iface = {
> >      .queue_is_processed_in_order = fv_queue_order,
> >  };
> >
> > +/*
> > + * Main loop; this mostly deals with events on the vhost-user
> > + * socket itself, and not actual fuse data.
> > + */
> >  int virtio_loop(struct fuse_session *se)
> >  {
> >      fuse_log(FUSE_LOG_INFO, "%s: Entry\n", __func__);
> >
> > -    while (1) {
> > -        /* TODO: Add stuffing */
> > +    while (!fuse_session_exited(se)) {
> > +        struct pollfd pf[1];
> > +        pf[0].fd = se->vu_socketfd;
> > +        pf[0].events = POLLIN;
> > +        pf[0].revents = 0;
> > +
> > +        fuse_log(FUSE_LOG_DEBUG, "%s: Waiting for VU event\n", __func__);
> > +        int poll_res = ppoll(pf, 1, NULL, NULL);
> > +
> > +        if (poll_res == -1) {
> > +            if (errno == EINTR) {
> > +                fuse_log(FUSE_LOG_INFO, "%s: ppoll interrupted, going around\n",
> > +                         __func__);
> > +                continue;
> > +            }
> > +            fuse_log(FUSE_LOG_ERR, "virtio_loop ppoll: %m\n");
> > +            break;
> > +        }
> > +        assert(poll_res == 1);
> > +        if (pf[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
> > +            fuse_log(FUSE_LOG_ERR, "%s: Unexpected poll revents %x\n", __func__,
> > +                     pf[0].revents);
> > +            break;
> > +        }
> > +        assert(pf[0].revents & POLLIN);
> > +        fuse_log(FUSE_LOG_DEBUG, "%s: Got VU event\n", __func__);
> > +        if (!vu_dispatch(&se->virtio_dev->dev)) {
> > +            fuse_log(FUSE_LOG_ERR, "%s: vu_dispatch failed\n", __func__);
> > +            break;
> > +        }
> >      }
> >
> >      fuse_log(FUSE_LOG_INFO, "%s: Exit\n", __func__);
> > +
> > +    return 0;
> >  }
> >
> >  int virtio_session_mount(struct fuse_session *se)
> > --
> > 2.23.0
> >
> >
> 
> 
> -- 
> Marc-André Lureau
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
Stefan Hajnoczi Nov. 14, 2019, 2:13 p.m. UTC | #3
On Tue, Oct 22, 2019 at 12:07:25PM +0100, Dr. David Alan Gilbert wrote:
> * Marc-André Lureau (marcandre.lureau@gmail.com) wrote:
> > On Mon, Oct 21, 2019 at 1:26 PM Dr. David Alan Gilbert (git)
> > <dgilbert@redhat.com> wrote:
> > >
> > > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> > >
> > > Processes incoming requests on the vhost-user fd.
> > 
> > Is there a reason to avoid using glib & its main loop?
> 
> Not particularly;  would it actually work out any easier?
> Is there an easy way to get the glib loop to check something like
> the fuse_session_exited at each iteration.
> 
> I probably didn't originally because I wasn't sure if this code
> was going back into libfuse or staying here; and libfuse doesn't
> use glib.

I tried to convert this to glib a few months ago, but stopped because
libvhost-user-glib.c is difficult to use from multiple threads.  If I
remember correctly we'd need to change it quite a bit to make
multi-threaded vhost-user device backends possible and I gave up.

Stefan
diff mbox series

Patch

diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virtio.c
index 22f71d260f..9c58f11634 100644
--- a/contrib/virtiofsd/fuse_virtio.c
+++ b/contrib/virtiofsd/fuse_virtio.c
@@ -11,12 +11,14 @@ 
  * See the file COPYING.LIB
  */
 
+#include "fuse_virtio.h"
 #include "fuse_i.h"
 #include "fuse_kernel.h"
 #include "fuse_misc.h"
 #include "fuse_opt.h"
-#include "fuse_virtio.h"
 
+#include <assert.h>
+#include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -80,15 +82,49 @@  static const VuDevIface fv_iface = {
     .queue_is_processed_in_order = fv_queue_order,
 };
 
+/*
+ * Main loop; this mostly deals with events on the vhost-user
+ * socket itself, and not actual fuse data.
+ */
 int virtio_loop(struct fuse_session *se)
 {
     fuse_log(FUSE_LOG_INFO, "%s: Entry\n", __func__);
 
-    while (1) {
-        /* TODO: Add stuffing */
+    while (!fuse_session_exited(se)) {
+        struct pollfd pf[1];
+        pf[0].fd = se->vu_socketfd;
+        pf[0].events = POLLIN;
+        pf[0].revents = 0;
+
+        fuse_log(FUSE_LOG_DEBUG, "%s: Waiting for VU event\n", __func__);
+        int poll_res = ppoll(pf, 1, NULL, NULL);
+
+        if (poll_res == -1) {
+            if (errno == EINTR) {
+                fuse_log(FUSE_LOG_INFO, "%s: ppoll interrupted, going around\n",
+                         __func__);
+                continue;
+            }
+            fuse_log(FUSE_LOG_ERR, "virtio_loop ppoll: %m\n");
+            break;
+        }
+        assert(poll_res == 1);
+        if (pf[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
+            fuse_log(FUSE_LOG_ERR, "%s: Unexpected poll revents %x\n", __func__,
+                     pf[0].revents);
+            break;
+        }
+        assert(pf[0].revents & POLLIN);
+        fuse_log(FUSE_LOG_DEBUG, "%s: Got VU event\n", __func__);
+        if (!vu_dispatch(&se->virtio_dev->dev)) {
+            fuse_log(FUSE_LOG_ERR, "%s: vu_dispatch failed\n", __func__);
+            break;
+        }
     }
 
     fuse_log(FUSE_LOG_INFO, "%s: Exit\n", __func__);
+
+    return 0;
 }
 
 int virtio_session_mount(struct fuse_session *se)