? sys/dev/sdmmc/cscope.out Index: sys/dev/dksubr.c =================================================================== RCS file: /cvsroot/src/sys/dev/dksubr.c,v retrieving revision 1.63 diff -u -p -w -b -r1.63 dksubr.c --- sys/dev/dksubr.c 9 May 2015 13:07:20 -0000 1.63 +++ sys/dev/dksubr.c 6 Jun 2015 16:55:43 -0000 @@ -74,6 +74,28 @@ static int dk_subr_modcmd(modcmd_t, void static void dk_makedisklabel(struct dk_softc *); +static inline void +dk_lock(struct dk_softc *dksc) +{ + if (dksc->sc_iolock) + mutex_enter(dksc->sc_iolock); +} + +static inline void +dk_unlock(struct dk_softc *dksc) +{ + if (dksc->sc_iolock) + mutex_exit(dksc->sc_iolock); +} + +static inline void +dk_assertlock(struct dk_softc *dksc) +{ + if (dksc->sc_iolock) { + KASSERT(mutex_owned(dksc->sc_iolock)); + } +} + void dk_init(struct dk_softc *dksc, device_t dev, int dtype) { @@ -89,16 +111,20 @@ dk_init(struct dk_softc *dksc, device_t void dk_attach(struct dk_softc *dksc) { + dk_lock(dksc); dksc->sc_flags |= DKF_INITED; #ifdef DIAGNOSTIC dksc->sc_flags |= DKF_WARNLABEL | DKF_LABELSANITY; #endif + dk_unlock(dksc); } void dk_detach(struct dk_softc *dksc) { + dk_lock(dksc); dksc->sc_flags &= ~DKF_INITED; + dk_unlock(dksc); } /* ARGSUSED */ @@ -207,7 +233,7 @@ void dk_strategy(struct dk_softc *dksc, struct buf *bp) { const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver; - int s, part; + int part; int wlabel; daddr_t blkno; struct disklabel *lp; @@ -218,7 +244,11 @@ dk_strategy(struct dk_softc *dksc, struc DPRINTF_FOLLOW(("dk_strategy(%s, %p, %p)\n", dksc->sc_xname, dksc, bp)); + dk_lock(dksc); + + /* Synchronize with init/uninit. */ if (!(dksc->sc_flags & DKF_INITED)) { + dk_unlock(dksc); DPRINTF_FOLLOW(("dk_strategy: not inited\n")); bp->b_error = ENXIO; biodone(bp); @@ -239,6 +269,8 @@ dk_strategy(struct dk_softc *dksc, struc * not be negative. */ if ((bp->b_bcount % secsize) != 0 || bp->b_blkno < 0) { + dk_unlock(dksc); + bp->b_error = EINVAL; biodone(bp); return; @@ -246,6 +278,8 @@ dk_strategy(struct dk_softc *dksc, struc /* If there is nothing to do, then we are done */ if (bp->b_bcount == 0) { + dk_unlock(dksc); + biodone(bp); return; } @@ -253,11 +287,13 @@ dk_strategy(struct dk_softc *dksc, struc wlabel = dksc->sc_flags & (DKF_WLABEL|DKF_LABELLING); if (part == RAW_PART) { if (bounds_check_with_mediasize(bp, DEV_BSIZE, numsecs) <= 0) { + dk_unlock(dksc); biodone(bp); return; } } else { if (bounds_check_with_label(&dksc->sc_dkdev, bp, wlabel) <= 0) { + dk_unlock(dksc); biodone(bp); return; } @@ -272,10 +308,10 @@ dk_strategy(struct dk_softc *dksc, struc * Start the unit by calling the start routine * provided by the individual driver. */ - s = splbio(); + dk_assertlock(dksc); bufq_put(dksc->sc_bufq, bp); dkd->d_diskstart(dksc->sc_dev); - splx(s); + return; } @@ -284,6 +320,8 @@ dk_done(struct dk_softc *dksc, struct bu { struct disk *dk = &dksc->sc_dkdev; + dk_assertlock(dksc); + if (bp->b_error != 0) { diskerr(bp, dksc->sc_xname, "error", LOG_PRINTF, 0, dk->dk_label); @@ -294,7 +332,9 @@ dk_done(struct dk_softc *dksc, struct bu #ifdef notyet rnd_add_uint(&dksc->sc_rnd_source, bp->b_rawblkno); #endif + dk_unlock(dksc); biodone(bp); + dk_lock(dksc); } int @@ -352,12 +392,15 @@ dk_ioctl(struct dk_softc *dksc, dev_t de case ODIOCWDINFO: #endif case DIOCWLABEL: + case DIOCKLABEL: case DIOCAWEDGE: case DIOCDWEDGE: + case DIOCSSTRATEGY: if ((flag & FWRITE) == 0) return EBADF; } + dk_lock(dksc); /* ensure that the pseudo-disk is initialized for these */ switch (cmd) { case DIOCGDINFO: @@ -378,14 +421,16 @@ dk_ioctl(struct dk_softc *dksc, dev_t de case ODIOCWDINFO: case ODIOCGDEFLABEL: #endif - if ((dksc->sc_flags & DKF_INITED) == 0) + if ((dksc->sc_flags & DKF_INITED) == 0) { + dk_unlock(dksc); return ENXIO; } + } error = disk_ioctl(dk, dev, cmd, data, flag, l); if (error != EPASSTHROUGH) - return error; - else + goto done; + error = 0; switch (cmd) { @@ -425,8 +470,6 @@ dk_ioctl(struct dk_softc *dksc, dev_t de break; case DIOCKLABEL: - if ((flag & FWRITE) == 0) - return (EBADF); if (*(int *)data != 0) dksc->sc_flags |= DKF_KLABEL; else @@ -456,12 +499,11 @@ dk_ioctl(struct dk_softc *dksc, dev_t de case DIOCGSTRATEGY: { struct disk_strategy *dks = (void *)data; - int s; - s = splbio(); + dk_lock(dksc); strlcpy(dks->dks_name, bufq_getstrategyname(dksc->sc_bufq), sizeof(dks->dks_name)); - splx(s); + dk_unlock(dksc); dks->dks_paramlen = 0; return 0; @@ -472,11 +514,7 @@ dk_ioctl(struct dk_softc *dksc, dev_t de struct disk_strategy *dks = (void *)data; struct bufq_state *new; struct bufq_state *old; - int s; - if ((flag & FWRITE) == 0) { - return EBADF; - } if (dks->dks_param != NULL) { return EINVAL; } @@ -486,11 +524,12 @@ dk_ioctl(struct dk_softc *dksc, dev_t de if (error) { return error; } - s = splbio(); + dk_lock(dksc); old = dksc->sc_bufq; bufq_move(new, old); dksc->sc_bufq = new; - splx(s); + dk_unlock(dksc); + bufq_free(old); return 0; @@ -499,7 +538,8 @@ dk_ioctl(struct dk_softc *dksc, dev_t de default: error = ENOTTY; } - +done: + dk_unlock(dksc); return error; } Index: sys/dev/dkvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/dkvar.h,v retrieving revision 1.20 diff -u -p -w -b -r1.20 dkvar.h --- sys/dev/dkvar.h 2 May 2015 08:00:08 -0000 1.20 +++ sys/dev/dkvar.h 6 Jun 2015 16:55:44 -0000 @@ -31,7 +31,8 @@ struct pathbuf; /* from namei.h */ -/* literally this is not a softc, but is intended to be included in +/* + * literally this is not a softc, but is intended to be included in * the pseudo-disk's softc and passed to calls in dksubr.c. It * should include the common elements of the pseudo-disk's softc. * All elements that are included here should describe the external @@ -44,6 +45,7 @@ struct dk_softc { #define DK_XNAME_SIZE 8 char sc_xname[DK_XNAME_SIZE]; /* external name */ struct disk sc_dkdev; /* generic disk info */ + kmutex_t *sc_iolock; /* protects buffer queue */ struct bufq_state *sc_bufq; /* buffer queue */ int sc_dtype; /* disk type */ }; Index: sys/dev/ld.c =================================================================== RCS file: /cvsroot/src/sys/dev/ld.c,v retrieving revision 1.83 diff -u -p -w -b -r1.83 ld.c --- sys/dev/ld.c 2 May 2015 08:00:08 -0000 1.83 +++ sys/dev/ld.c 6 Jun 2015 16:55:44 -0000 @@ -30,7 +30,7 @@ */ /* - * Disk driver for use by RAID controllers. + * Disk driver for use by RAID controllers and SD/MMC devices. */ #include @@ -60,6 +60,16 @@ __KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.83 #include +/* + * Logical Disk driver. + * + * Notes on concurrency: + * + * => sc_mutex serializes access to ld_softc members, and to sc_bufq and disk + * stats of dk_softc if non-NULL. This is a temporary measure while + * all users of ld(4) are updated. + */ + static void ldminphys(struct buf *bp); static bool ld_suspend(device_t, const pmf_qual_t *); static bool ld_shutdown(device_t, int); @@ -90,7 +100,7 @@ const struct bdevsw ld_bdevsw = { .d_dump = lddump, .d_psize = ldsize, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; const struct cdevsw ld_cdevsw = { @@ -105,7 +115,7 @@ const struct cdevsw ld_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; static struct dkdriver lddkdriver = { @@ -125,14 +135,17 @@ ldattach(struct ld_softc *sc) device_t self = sc->sc_dv; struct dk_softc *dksc = &sc->sc_dksc; - mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); - if ((sc->sc_flags & LDF_ENABLED) == 0) { return; } +// cv_init(&sc->sc_stop, "lddstop"); +// cv_init(&sc->sc_work, "ldwork"); /* Initialise dk and disk structure. */ dk_init(dksc, self, DKTYPE_LD); + /* Could be NULL until all backends are converted */ + dksc->sc_iolock = sc->sc_mutex; + disk_init(&dksc->sc_dkdev, dksc->sc_xname, &lddkdriver); /* Attach the device into the rnd source list. */ @@ -168,11 +181,10 @@ ldattach(struct ld_softc *sc) int ldadjqparam(struct ld_softc *sc, int xmax) { - int s; - s = splbio(); + mutex_enter(sc->sc_mutex); sc->sc_maxqueuecnt = xmax; - splx(s); + mutex_exit(sc->sc_mutex); return (0); } @@ -181,57 +193,60 @@ int ldbegindetach(struct ld_softc *sc, int flags) { struct dk_softc *dksc = &sc->sc_dksc; - int s, rv = 0; + int rv = 0; if ((sc->sc_flags & LDF_ENABLED) == 0) - return (0); + return 0; rv = disk_begindetach(&dksc->sc_dkdev, ld_lastclose, dksc->sc_dev, flags); if (rv != 0) return rv; - s = splbio(); + mutex_enter(sc->sc_mutex); sc->sc_maxqueuecnt = 0; dk_detach(dksc); while (sc->sc_queuecnt > 0) { sc->sc_flags |= LDF_DRAIN; - rv = tsleep(&sc->sc_queuecnt, PRIBIO, "lddrn", 0); + rv = cv_timedwait(&sc->sc_stop, dksc->sc_iolock, hz); if (rv) break; } - splx(s); + mutex_exit(sc->sc_mutex); return (rv); } + void ldenddetach(struct ld_softc *sc) { struct dk_softc *dksc = &sc->sc_dksc; - int s, bmaj, cmaj, i, mn; + int bmaj, cmaj, i, mn; if ((sc->sc_flags & LDF_ENABLED) == 0) return; + mutex_enter(sc->sc_mutex); /* Wait for commands queued with the hardware to complete. */ - if (sc->sc_queuecnt != 0) - if (tsleep(&sc->sc_queuecnt, PRIBIO, "lddtch", 30 * hz)) + while (sc->sc_queuecnt != 0) { + cv_timedwait(&sc->sc_stop, dksc->sc_iolock, hz); + if (false) printf("%s: not drained\n", dksc->sc_xname); - - /* Locate the major numbers. */ - bmaj = bdevsw_lookup_major(&ld_bdevsw); - cmaj = cdevsw_lookup_major(&ld_cdevsw); + } /* Kill off any queued buffers. */ - s = splbio(); bufq_drain(dksc->sc_bufq); - splx(s); + mutex_exit(sc->sc_mutex); bufq_free(dksc->sc_bufq); + /* Locate the major numbers. */ + bmaj = bdevsw_lookup_major(&ld_bdevsw); + cmaj = cdevsw_lookup_major(&ld_cdevsw); + /* Nuke the vnodes for any open instances. */ for (i = 0; i < MAXPARTITIONS; i++) { mn = DISKMINOR(device_unit(dksc->sc_dev), i); @@ -263,7 +278,6 @@ ldenddetach(struct ld_softc *sc) if ((*sc->sc_flush)(sc, 0) != 0) aprint_error_dev(dksc->sc_dev, "unable to flush cache\n"); #endif - mutex_destroy(&sc->sc_mutex); } /* ARGSUSED */ @@ -298,7 +312,8 @@ ldopen(dev_t dev, int flags, int fmt, st unit = DISKUNIT(dev); if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) - return (ENXIO); + return ENXIO; + dksc = &sc->sc_dksc; return dk_open(dksc, dev, flags, fmt, l); @@ -358,13 +373,15 @@ ldioctl(dev_t dev, u_long cmd, void *add sc = device_lookup_private(&ld_cd, unit); dksc = &sc->sc_dksc; +// mutex_enter(xxx); + error = disk_ioctl(&dksc->sc_dkdev, dev, cmd, addr, flag, l); if (error != EPASSTHROUGH) - return (error); + return error; error = dk_ioctl(dksc, dev, cmd, addr, flag, l); if (error != EPASSTHROUGH) - return (error); + return error; error = 0; @@ -386,7 +403,7 @@ ldioctl(dev_t dev, u_long cmd, void *add break; } - return (error); + return error; } static void @@ -411,7 +428,7 @@ ld_start(device_t dev) struct buf *bp; int error; - mutex_enter(&sc->sc_mutex); + KASSERT(mutex_owned(dksc->sc_iolock)); while (sc->sc_queuecnt < sc->sc_maxqueuecnt) { /* See if there is work to do. */ @@ -423,8 +440,8 @@ ld_start(device_t dev) if (__predict_true((error = (*sc->sc_start)(sc, bp)) == 0)) { /* - * The back-end is running the job; remove it from - * the queue. + * The back-end is running/will run the job; remove it + * from the queue. */ (void) bufq_get(dksc->sc_bufq); } else { @@ -444,14 +461,14 @@ ld_start(device_t dev) (void) bufq_get(dksc->sc_bufq); bp->b_error = error; bp->b_resid = bp->b_bcount; - mutex_exit(&sc->sc_mutex); + mutex_exit(sc->sc_mutex); biodone(bp); - mutex_enter(&sc->sc_mutex); + return; } } } - mutex_exit(&sc->sc_mutex); + mutex_exit(sc->sc_mutex); } void @@ -459,18 +476,19 @@ lddone(struct ld_softc *sc, struct buf * { struct dk_softc *dksc = &sc->sc_dksc; + KASSERT(mutex_owned(dksc->sc_iolock)); dk_done(dksc, bp); - mutex_enter(&sc->sc_mutex); if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) { if ((sc->sc_flags & LDF_DRAIN) != 0) { sc->sc_flags &= ~LDF_DRAIN; - wakeup(&sc->sc_queuecnt); + cv_broadcast(&sc->sc_stop); } - mutex_exit(&sc->sc_mutex); + /* releases lock */ ld_start(dksc->sc_dev); - } else - mutex_exit(&sc->sc_mutex); + return; + } + mutex_exit(sc->sc_mutex); } static int Index: sys/dev/ldvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/ldvar.h,v retrieving revision 1.23 diff -u -p -w -b -r1.23 ldvar.h --- sys/dev/ldvar.h 2 May 2015 08:00:08 -0000 1.23 +++ sys/dev/ldvar.h 6 Jun 2015 16:55:44 -0000 @@ -39,9 +39,10 @@ struct ld_softc { struct dk_softc sc_dksc; - kmutex_t sc_mutex; + kmutex_t *sc_mutex; /* Protects some members of dk_softc */ krndsource_t sc_rnd_source; + kcondvar_t sc_stop; int sc_queuecnt; /* current h/w queue depth */ int sc_ncylinders; /* # cylinders */ int sc_nheads; /* # heads */