Source-Changes-HG archive

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

[src/netbsd-9]: src/sys/dev Pull up following revision(s) (requested by riast...



details:   https://anonhg.NetBSD.org/src/rev/36ad91e383c3
branches:  netbsd-9
changeset: 963767:36ad91e383c3
user:      martin <martin%NetBSD.org@localhost>
date:      Mon Apr 06 14:57:42 2020 +0000

description:
Pull up following revision(s) (requested by riastradh in ticket #823):

        sys/dev/cgdvar.h: revision 1.19
        sys/dev/cgd.c: revision 1.122
        sys/dev/cgd.c: revision 1.123
        sys/dev/cgd.c: revision 1.124

Defer crypto operations to a workqueue and make it utilize all CPUs.

Make device mpsafe.

Some code cleanup.

Don't wait for data buffer.

cgd: switch from malloc(9) to kmem(9)
XXX might be worthwhile to use pool_cache(9) in the write path

diffstat:

 sys/dev/cgd.c    |  716 ++++++++++++++++++++++++++++++++++++++++--------------
 sys/dev/cgdvar.h |   32 ++-
 2 files changed, 552 insertions(+), 196 deletions(-)

diffs (truncated from 1306 to 300 lines):

diff -r 3c42352794d5 -r 36ad91e383c3 sys/dev/cgd.c
--- a/sys/dev/cgd.c     Mon Apr 06 14:53:33 2020 +0000
+++ b/sys/dev/cgd.c     Mon Apr 06 14:57:42 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cgd.c,v 1.116.10.2 2020/03/21 15:52:09 martin Exp $ */
+/* $NetBSD: cgd.c,v 1.116.10.3 2020/04/06 14:57:42 martin Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.116.10.2 2020/03/21 15:52:09 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.116.10.3 2020/04/06 14:57:42 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -39,7 +39,7 @@
 #include <sys/errno.h>
 #include <sys/buf.h>
 #include <sys/bufq.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/module.h>
 #include <sys/pool.h>
 #include <sys/ioctl.h>
@@ -51,6 +51,8 @@
 #include <sys/vnode.h>
 #include <sys/conf.h>
 #include <sys/syslog.h>
+#include <sys/workqueue.h>
+#include <sys/cpu.h>
 
 #include <dev/dkvar.h>
 #include <dev/cgdvar.h>
@@ -90,7 +92,7 @@
        .d_dump = cgddump,
        .d_psize = cgdsize,
        .d_discard = nodiscard,
-       .d_flag = D_DISK
+       .d_flag = D_DISK | D_MPSAFE
 };
 
 const struct cdevsw cgd_cdevsw = {
@@ -105,7 +107,7 @@
        .d_mmap = nommap,
        .d_kqfilter = nokqfilter,
        .d_discard = nodiscard,
-       .d_flag = D_DISK
+       .d_flag = D_DISK | D_MPSAFE
 };
 
 /*
@@ -207,12 +209,20 @@
 static void cgd_attach(device_t, device_t, void *);
 static int cgd_detach(device_t, int);
 static struct cgd_softc        *cgd_spawn(int);
+static struct cgd_worker *cgd_create_one_worker(void);
+static void cgd_destroy_one_worker(struct cgd_worker *);
+static struct cgd_worker *cgd_create_worker(void);
+static void cgd_destroy_worker(struct cgd_worker *);
 static int cgd_destroy(device_t);
 
 /* Internal Functions */
 
 static int     cgd_diskstart(device_t, struct buf *);
+static void    cgd_diskstart2(struct cgd_softc *, struct cgd_xfer *);
 static void    cgdiodone(struct buf *);
+static void    cgd_iodone2(struct cgd_softc *, struct cgd_xfer *);
+static void    cgd_enqueue(struct cgd_softc *, struct cgd_xfer *);
+static void    cgd_process(struct work *, void *);
 static int     cgd_dumpblocks(device_t, void *, daddr_t, int);
 
 static int     cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
@@ -272,25 +282,49 @@
 
 /* Global variables */
 
+static kmutex_t cgd_spawning_mtx;
+static kcondvar_t cgd_spawning_cv;
+static bool cgd_spawning;
+static struct cgd_worker *cgd_worker;
+static u_int cgd_refcnt;       /* number of users of cgd_worker */
+
 /* Utility Functions */
 
 #define CGDUNIT(x)             DISKUNIT(x)
-#define GETCGD_SOFTC(_cs, x)   if (!((_cs) = getcgd_softc(x))) return ENXIO
 
 /* The code */
 
+static int
+cgd_lock(bool intr)
+{
+       int error = 0;
+
+       mutex_enter(&cgd_spawning_mtx);
+       while (cgd_spawning) {
+               if (intr)
+                       error = cv_wait_sig(&cgd_spawning_cv, &cgd_spawning_mtx);
+               else
+                       cv_wait(&cgd_spawning_cv, &cgd_spawning_mtx);
+       }
+       if (error == 0)
+               cgd_spawning = true;
+       mutex_exit(&cgd_spawning_mtx);
+       return error;
+}
+
+static void
+cgd_unlock(void)
+{
+       mutex_enter(&cgd_spawning_mtx);
+       cgd_spawning = false;
+       cv_broadcast(&cgd_spawning_cv);
+       mutex_exit(&cgd_spawning_mtx);
+}
+
 static struct cgd_softc *
 getcgd_softc(dev_t dev)
 {
-       int     unit = CGDUNIT(dev);
-       struct cgd_softc *sc;
-
-       DPRINTF_FOLLOW(("getcgd_softc(0x%"PRIx64"): unit = %d\n", dev, unit));
-
-       sc = device_lookup_private(&cgd_cd, unit);
-       if (sc == NULL)
-               sc = cgd_spawn(unit);
-       return sc;
+       return device_lookup_private(&cgd_cd, CGDUNIT(dev));
 }
 
 static int
@@ -306,6 +340,7 @@
        struct cgd_softc *sc = device_private(self);
 
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
+       cv_init(&sc->sc_cv, "cgdcv");
        dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
        disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
 
@@ -331,6 +366,7 @@
                return ret;
 
        disk_destroy(&dksc->sc_dkdev);
+       cv_destroy(&sc->sc_cv);
        mutex_destroy(&sc->sc_lock);
 
        return 0;
@@ -339,89 +375,224 @@
 void
 cgdattach(int num)
 {
+#ifndef _MODULE
        int error;
 
+       mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
+       cv_init(&cgd_spawning_cv, "cgspwn");
+
        error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
        if (error != 0)
                aprint_error("%s: unable to register cfattach\n",
                    cgd_cd.cd_name);
+#endif
 }
 
 static struct cgd_softc *
 cgd_spawn(int unit)
 {
        cfdata_t cf;
+       struct cgd_worker *cw;
+       struct cgd_softc *sc;
 
-       cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
+       cf = kmem_alloc(sizeof(*cf), KM_SLEEP);
        cf->cf_name = cgd_cd.cd_name;
        cf->cf_atname = cgd_cd.cd_name;
        cf->cf_unit = unit;
        cf->cf_fstate = FSTATE_STAR;
 
-       return device_private(config_attach_pseudo(cf));
+       cw = cgd_create_one_worker();
+       if (cw == NULL) {
+               kmem_free(cf, sizeof(*cf));
+               return NULL;
+       }
+
+       sc = device_private(config_attach_pseudo(cf));
+       if (sc == NULL) {
+               cgd_destroy_one_worker(cw);
+               return NULL;
+       }
+
+       sc->sc_worker = cw;
+
+       return sc;
 }
 
 static int
 cgd_destroy(device_t dev)
 {
+       struct cgd_softc *sc = device_private(dev);
+       struct cgd_worker *cw = sc->sc_worker;
+       cfdata_t cf;
        int error;
-       cfdata_t cf;
 
        cf = device_cfdata(dev);
        error = config_detach(dev, DETACH_QUIET);
        if (error)
                return error;
-       free(cf, M_DEVBUF);
+
+       cgd_destroy_one_worker(cw);
+
+       kmem_free(cf, sizeof(*cf));
        return 0;
 }
 
+static void
+cgd_busy(struct cgd_softc *sc)
+{
+
+       mutex_enter(&sc->sc_lock);
+       while (sc->sc_busy)
+               cv_wait(&sc->sc_cv, &sc->sc_lock);
+       sc->sc_busy = true;
+       mutex_exit(&sc->sc_lock);
+}
+
+static void
+cgd_unbusy(struct cgd_softc *sc)
+{
+
+       mutex_enter(&sc->sc_lock);
+       sc->sc_busy = false;
+       cv_broadcast(&sc->sc_cv);
+       mutex_exit(&sc->sc_lock);
+}
+
+static struct cgd_worker *
+cgd_create_one_worker(void)
+{
+       KASSERT(cgd_spawning);
+
+       if (cgd_refcnt++ == 0) {
+               KASSERT(cgd_worker == NULL);
+               cgd_worker = cgd_create_worker();
+       }
+
+       KASSERT(cgd_worker != NULL);
+       return cgd_worker;
+}
+
+static void
+cgd_destroy_one_worker(struct cgd_worker *cw)
+{
+       KASSERT(cgd_spawning);
+       KASSERT(cw == cgd_worker);
+
+       if (--cgd_refcnt == 0) {
+               cgd_destroy_worker(cgd_worker);
+               cgd_worker = NULL;
+       }
+}
+
+static struct cgd_worker *
+cgd_create_worker(void)
+{
+       struct cgd_worker *cw;
+       struct workqueue *wq;
+       struct pool *cp;
+       int error;
+
+       cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP);
+       cp = kmem_alloc(sizeof(struct pool), KM_SLEEP);
+
+       error = workqueue_create(&wq, "cgd", cgd_process, NULL,
+                                PRI_BIO, IPL_BIO, WQ_MPSAFE | WQ_PERCPU);
+       if (error) {
+               kmem_free(cp, sizeof(struct pool));
+               kmem_free(cw, sizeof(struct cgd_worker));
+               return NULL;
+       }
+
+       cw->cw_cpool = cp;
+       cw->cw_wq = wq;
+       pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0,
+           0, 0, "cgdcpl", NULL, IPL_BIO);
+
+       mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO);
+       
+       return cw;
+}
+
+static void
+cgd_destroy_worker(struct cgd_worker *cw)
+{



Home | Main Index | Thread Index | Old Index