Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/xen/xen make xbdback actually MPSAFE and stop using...



details:   https://anonhg.NetBSD.org/src/rev/3ed09a7c5380
branches:  trunk
changeset: 1009441:3ed09a7c5380
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Thu Apr 23 09:16:21 2020 +0000

description:
make xbdback actually MPSAFE and stop using KERNEL_LOCK()

remove no longer necessary atomics, the counters are now always
updated with held mutex

diffstat:

 sys/arch/xen/xen/xbdback_xenbus.c |  130 +++++++++++++++++++++----------------
 1 files changed, 72 insertions(+), 58 deletions(-)

diffs (truncated from 359 to 300 lines):

diff -r e1b5d81fd908 -r 3ed09a7c5380 sys/arch/xen/xen/xbdback_xenbus.c
--- a/sys/arch/xen/xen/xbdback_xenbus.c Thu Apr 23 09:01:33 2020 +0000
+++ b/sys/arch/xen/xen/xbdback_xenbus.c Thu Apr 23 09:16:21 2020 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: xbdback_xenbus.c,v 1.89 2020/04/23 08:09:25 jdolecek Exp $      */
+/*      $NetBSD: xbdback_xenbus.c,v 1.90 2020/04/23 09:16:21 jdolecek Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,9 +26,8 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.89 2020/04/23 08:09:25 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.90 2020/04/23 09:16:21 jdolecek Exp $");
 
-#include <sys/atomic.h>
 #include <sys/buf.h>
 #include <sys/condvar.h>
 #include <sys/conf.h>
@@ -227,11 +226,11 @@
        struct timeval xbdi_lasterr_time;    /* error time tracking */
 };
 /* Manipulation of the above reference count. */
-#define xbdi_get(xbdip) atomic_inc_uint(&(xbdip)->xbdi_refcnt)
-#define xbdi_put(xbdip)                                      \
-do {                                                         \
-       if (atomic_dec_uint_nv(&(xbdip)->xbdi_refcnt) == 0)  \
-               xbdback_finish_disconnect(xbdip);             \
+#define xbdi_get(xbdip) (xbdip)->xbdi_refcnt++
+#define xbdi_put(xbdip)                                                \
+do {                                                           \
+       if (--((xbdip)->xbdi_refcnt) == 0)                      \
+               xbdback_finish_disconnect(xbdip);               \
 } while (/* CONSTCOND */ 0)
 
 static SLIST_HEAD(, xbdback_instance) xbdback_instances;
@@ -269,6 +268,8 @@
 
 static void xbdback_io_error(struct xbdback_io *, int);
 static void xbdback_iodone(struct buf *);
+static void xbdback_iodone_locked(struct xbdback_instance *,
+               struct xbdback_io *, struct buf *);
 static void xbdback_send_reply(struct xbdback_instance *, uint64_t , int , int);
 
 static void *xbdback_map_shm(struct xbdback_io *);
@@ -336,10 +337,6 @@
                return EFTYPE;
        }
 
-       /* XXXSMP unlocked search */
-       if (xbdif_lookup(domid, handle)) {
-               return EEXIST;
-       }
        xbdi = kmem_zalloc(sizeof(*xbdi), KM_SLEEP);
 
        xbdi->xbdi_domid = domid;
@@ -347,15 +344,21 @@
        snprintf(xbdi->xbdi_name, sizeof(xbdi->xbdi_name), "xbdb%di%d",
            xbdi->xbdi_domid, xbdi->xbdi_handle);
 
+       mutex_enter(&xbdback_lock);
+       if (xbdif_lookup(domid, handle)) {
+               mutex_exit(&xbdback_lock);
+               kmem_free(xbdi, sizeof(*xbdi));
+               return EEXIST;
+       }
+       SLIST_INSERT_HEAD(&xbdback_instances, xbdi, next);
+       mutex_exit(&xbdback_lock);
+
        /* initialize status and reference counter */
        xbdi->xbdi_status = DISCONNECTED;
        xbdi_get(xbdi);
 
        mutex_init(&xbdi->xbdi_lock, MUTEX_DEFAULT, IPL_BIO);
        cv_init(&xbdi->xbdi_cv, xbdi->xbdi_name);
-       mutex_enter(&xbdback_lock);
-       SLIST_INSERT_HEAD(&xbdback_instances, xbdi, next);
-       mutex_exit(&xbdback_lock);
 
        xbusd->xbusd_u.b.b_cookie = xbdi;       
        xbusd->xbusd_u.b.b_detach = xbdback_xenbus_destroy;
@@ -852,7 +855,7 @@
 
        xbdi->xbdi_status = DISCONNECTED;
 
-       cv_signal(&xbdi->xbdi_cv);
+       cv_broadcast(&xbdi->xbdi_cv);
 }
 
 static bool
@@ -861,14 +864,14 @@
        struct xbdback_instance *xbdi;
        bool found = false;
 
-       mutex_enter(&xbdback_lock);
+       KASSERT(mutex_owned(&xbdback_lock));
+
        SLIST_FOREACH(xbdi, &xbdback_instances, next) {
                if (xbdi->xbdi_domid == dom && xbdi->xbdi_handle == handle) {
                        found = true;
                        break;
                }
        }
-       mutex_exit(&xbdback_lock);
 
        return found;
 }
@@ -881,7 +884,9 @@
        XENPRINTF(("xbdback_evthandler domain %d: cont %p\n",
            xbdi->xbdi_domid, xbdi->xbdi_cont));
 
+       mutex_enter(&xbdi->xbdi_lock);
        xbdback_wakeup_thread(xbdi);
+       mutex_exit(&xbdi->xbdi_lock);
 
        return 1;
 }
@@ -895,16 +900,14 @@
 {
        struct xbdback_instance *xbdi = arg;
 
+       mutex_enter(&xbdi->xbdi_lock);
        for (;;) {
-               mutex_enter(&xbdi->xbdi_lock);
                switch (xbdi->xbdi_status) {
                case WAITING:
                        cv_wait(&xbdi->xbdi_cv, &xbdi->xbdi_lock);
-                       mutex_exit(&xbdi->xbdi_lock);
                        break;
                case RUN:
                        xbdi->xbdi_status = WAITING; /* reset state */
-                       mutex_exit(&xbdi->xbdi_lock);
 
                        if (xbdi->xbdi_cont == NULL) {
                                xbdi->xbdi_cont = xbdback_co_main;
@@ -916,22 +919,24 @@
                        if (xbdi->xbdi_pendingreqs > 0) {
                                /* there are pending I/Os. Wait for them. */
                                cv_wait(&xbdi->xbdi_cv, &xbdi->xbdi_lock);
-                               mutex_exit(&xbdi->xbdi_lock);
-                               break;
+                               continue;
                        }
                        
                        /* All I/Os should have been processed by now,
                         * xbdi_refcnt should drop to 0 */
                        xbdi_put(xbdi);
                        KASSERT(xbdi->xbdi_refcnt == 0);
-                       mutex_exit(&xbdi->xbdi_lock);
-                       kthread_exit(0);
-                       break;
+                       goto out;
+                       /* NOTREACHED */
                default:
                        panic("%s: invalid state %d",
                            xbdi->xbdi_name, xbdi->xbdi_status);
                }
        }
+out:
+       mutex_exit(&xbdi->xbdi_lock);
+
+       kthread_exit(0);
 }
 
 static void *
@@ -1042,30 +1047,19 @@
  * we want to disconnect, leave continuation now.
  */
 static void *
-xbdback_co_main_incr(struct xbdback_instance *xbdi, void *obj)
+xbdback_co_main_incr(struct xbdback_instance *xbdi, void *obj __unused)
 {
-       (void)obj;
+       KASSERT(mutex_owned(&xbdi->xbdi_lock));
+
        blkif_back_ring_t *ring = &xbdi->xbdi_ring.ring_n;
 
        ring->req_cons++;
 
-       /*
-        * Do not bother with locking here when checking for xbdi_status: if
-        * we get a transient state, we will get the right value at
-        * the next increment.
-        */
        if (xbdi->xbdi_status == DISCONNECTING)
                xbdi->xbdi_cont = NULL;
        else
                xbdi->xbdi_cont = xbdback_co_main_loop;
 
-       /*
-        * Each time the thread processes a full ring of requests, give
-        * a chance to other threads to process I/Os too
-        */
-       if ((ring->req_cons % BLKIF_RING_SIZE) == 0)
-               yield();
-
        return xbdi;
 }
 
@@ -1250,8 +1244,10 @@
        size_t bcount;
        blkif_request_t *req;
 
+       KASSERT(mutex_owned(&xbdi->xbdi_lock));
+
        xbdi_get(xbdi);
-       atomic_inc_uint(&xbdi->xbdi_pendingreqs);
+       xbdi->xbdi_pendingreqs++;
        
        req = &xbdi->xbdi_xen_req;
        xbd_io = obj;
@@ -1331,8 +1327,12 @@
 static void
 xbdback_io_error(struct xbdback_io *xbd_io, int error)
 {
-       xbd_io->xio_buf.b_error = error;
-       xbdback_iodone(&xbd_io->xio_buf);
+       KASSERT(mutex_owned(&xbd_io->xio_xbdi->xbdi_lock));
+
+       struct buf *bp = &xbd_io->xio_buf;
+
+       bp->b_error = error;
+       xbdback_iodone_locked(xbd_io->xio_xbdi, xbd_io, bp);
 }
 
 /*
@@ -1350,8 +1350,11 @@
                int error;
                int force = 1;
 
+               KASSERT(mutex_owned(&xbdi->xbdi_lock));
+               mutex_exit(&xbdi->xbdi_lock);
                error = VOP_IOCTL(xbdi->xbdi_vp, DIOCCACHESYNC, &force, FWRITE,
                    kauth_cred_get());
+               mutex_enter(&xbdi->xbdi_lock);
                if (error) {
                        aprint_error("xbdback %s: DIOCCACHESYNC returned %d\n",
                            xbdi->xbdi_xbusd->xbusd_path, error);
@@ -1392,24 +1395,36 @@
 /*
  * Called from softint(9) context when an I/O is done: for each request, send
  * back the associated reply to the domain.
- *
- * This gets reused by xbdback_io_error to report errors from other sources.
  */
 static void
 xbdback_iodone(struct buf *bp)
 {
        struct xbdback_io *xbd_io;
        struct xbdback_instance *xbdi;
-       int status;
-
-       KERNEL_LOCK(1, NULL);           /* XXXSMP */
 
        xbd_io = bp->b_private;
+       KASSERT(bp == &xbd_io->xio_buf);
        xbdi = xbd_io->xio_xbdi;
 
+       mutex_enter(&xbdi->xbdi_lock);
+       xbdback_iodone_locked(xbdi, xbd_io, bp);
+       mutex_exit(&xbdi->xbdi_lock);
+}
+
+/*
+ * This gets reused by xbdback_io_error to report errors from other sources.
+ */
+static void
+xbdback_iodone_locked(struct xbdback_instance *xbdi, struct xbdback_io *xbd_io,
+    struct buf *bp)
+{
+       int status;
+
        XENPRINTF(("xbdback_io domain %d: iodone ptr 0x%lx\n",
                   xbdi->xbdi_domid, (long)xbd_io));
 
+       KASSERT(mutex_owned(&xbdi->xbdi_lock));
+
        KASSERT(bp->b_error != 0 || xbd_io->xio_xv != NULL);
        if (xbd_io->xio_xv != NULL)
                xbdback_unmap_shm(xbd_io);
@@ -1424,12 +1439,12 @@
        xbdback_send_reply(xbdi, xbd_io->xio_id, xbd_io->xio_operation, status);
 
        xbdi_put(xbdi);
-       atomic_dec_uint(&xbdi->xbdi_pendingreqs);
+       KASSERT(xbdi->xbdi_pendingreqs > 0);
+       xbdi->xbdi_pendingreqs--;
        buf_destroy(&xbd_io->xio_buf);
        xbdback_io_put(xbdi, xbd_io);
 
        xbdback_wakeup_thread(xbdi);
-       KERNEL_UNLOCK_ONE(NULL);        /* XXXSMP */
 }
 
 /*
@@ -1438,13 +1453,12 @@
 static void
 xbdback_wakeup_thread(struct xbdback_instance *xbdi)
 {



Home | Main Index | Thread Index | Old Index