Date: Fri, 16 Aug 2013 12:25:03 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r254408 - in projects/camlock/sys: cam/ata cam/scsi dev/md geom Message-ID: <201308161225.r7GCP3EW061762@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Fri Aug 16 12:25:02 2013 New Revision: 254408 URL: http://svnweb.freebsd.org/changeset/base/254408 Log: Make first steps toward direct BIO dispatch in GEOM: - Define flags, declaring that specific consumer/provider is capable of sending requests/replies (respectively) directly, i,e. doesn't hold any locks and so reenterable, and/or able to directly receive replies/requests, i.e. doesn't depend on GEOM up/down threads semantics. As result, GEOM will make direct calls only if both caller and callee are cpable of it in each case. - Define disk(9) flag to declare that disk is capable of direct request completion, and use it for da(4) and ada(4) drivers. Make GEOM DISK to pass that flag to its provider and also assume that any disk is capable of receiveing requests directly. - Mark GEOM DEV as capable of both direct send and receive. - Make md(4) declare both direct send and receive after adding mutex to serialize its statistics update on request path. Modified: projects/camlock/sys/cam/ata/ata_da.c projects/camlock/sys/cam/scsi/scsi_da.c projects/camlock/sys/dev/md/md.c projects/camlock/sys/geom/geom.h projects/camlock/sys/geom/geom_dev.c projects/camlock/sys/geom/geom_disk.c projects/camlock/sys/geom/geom_disk.h projects/camlock/sys/geom/geom_io.c Modified: projects/camlock/sys/cam/ata/ata_da.c ============================================================================== --- projects/camlock/sys/cam/ata/ata_da.c Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/cam/ata/ata_da.c Fri Aug 16 12:25:02 2013 (r254408) @@ -1246,7 +1246,7 @@ adaregister(struct cam_periph *periph, v maxio = min(maxio, 256 * softc->params.secsize); softc->disk->d_maxsize = maxio; softc->disk->d_unit = periph->unit_number; - softc->disk->d_flags = 0; + softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION; if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; if (softc->flags & ADA_FLAG_CAN_TRIM) { Modified: projects/camlock/sys/cam/scsi/scsi_da.c ============================================================================== --- projects/camlock/sys/cam/scsi/scsi_da.c Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/cam/scsi/scsi_da.c Fri Aug 16 12:25:02 2013 (r254408) @@ -2126,7 +2126,7 @@ daregister(struct cam_periph *periph, vo else softc->disk->d_maxsize = cpi.maxio; softc->disk->d_unit = periph->unit_number; - softc->disk->d_flags = 0; + softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION; if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; if ((cpi.hba_misc & PIM_UNMAPPED) != 0) Modified: projects/camlock/sys/dev/md/md.c ============================================================================== --- projects/camlock/sys/dev/md/md.c Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/dev/md/md.c Fri Aug 16 12:25:02 2013 (r254408) @@ -189,6 +189,7 @@ struct md_s { LIST_ENTRY(md_s) list; struct bio_queue_head bio_queue; struct mtx queue_mtx; + struct mtx stat_mtx; struct cdev *dev; enum md_types type; off_t mediasize; @@ -415,8 +416,11 @@ g_md_start(struct bio *bp) struct md_s *sc; sc = bp->bio_to->geom->softc; - if ((bp->bio_cmd == BIO_READ) || (bp->bio_cmd == BIO_WRITE)) + if ((bp->bio_cmd == BIO_READ) || (bp->bio_cmd == BIO_WRITE)) { + mtx_lock(&sc->stat_mtx); devstat_start_transaction_bio(sc->devstat, bp); + mtx_unlock(&sc->stat_mtx); + } mtx_lock(&sc->queue_mtx); bioq_disksort(&sc->bio_queue, bp); mtx_unlock(&sc->queue_mtx); @@ -988,6 +992,7 @@ mdnew(int unit, int *errp, enum md_types sc->type = type; bioq_init(&sc->bio_queue); mtx_init(&sc->queue_mtx, "md bio queue", NULL, MTX_DEF); + mtx_init(&sc->stat_mtx, "md stat", NULL, MTX_DEF); sc->unit = unit; sprintf(sc->name, "md%d", unit); LIST_INSERT_HEAD(&md_softc_list, sc, list); @@ -995,6 +1000,7 @@ mdnew(int unit, int *errp, enum md_types if (error == 0) return (sc); LIST_REMOVE(sc, list); + mtx_destroy(&sc->stat_mtx); mtx_destroy(&sc->queue_mtx); free_unr(md_uh, sc->unit); free(sc, M_MD); @@ -1012,6 +1018,7 @@ mdinit(struct md_s *sc) gp = g_new_geomf(&g_md_class, "md%d", sc->unit); gp->softc = sc; pp = g_new_providerf(gp, "md%d", sc->unit); + pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; pp->mediasize = sc->mediasize; pp->sectorsize = sc->sectorsize; switch (sc->type) { @@ -1207,6 +1214,7 @@ mddestroy(struct md_s *sc, struct thread while (!(sc->flags & MD_EXITING)) msleep(sc->procp, &sc->queue_mtx, PRIBIO, "mddestroy", hz / 10); mtx_unlock(&sc->queue_mtx); + mtx_destroy(&sc->stat_mtx); mtx_destroy(&sc->queue_mtx); if (sc->vnode != NULL) { vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY); Modified: projects/camlock/sys/geom/geom.h ============================================================================== --- projects/camlock/sys/geom/geom.h Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/geom/geom.h Fri Aug 16 12:25:02 2013 (r254408) @@ -177,6 +177,8 @@ struct g_consumer { int flags; #define G_CF_SPOILED 0x1 #define G_CF_ORPHAN 0x4 +#define G_CF_DIRECT_SEND 0x10 +#define G_CF_DIRECT_RECEIVE 0x20 struct devstat *stat; u_int nstart, nend; @@ -206,6 +208,8 @@ struct g_provider { #define G_PF_WITHER 0x2 #define G_PF_ORPHAN 0x4 #define G_PF_ACCEPT_UNMAPPED 0x8 +#define G_PF_DIRECT_SEND 0x10 +#define G_PF_DIRECT_RECEIVE 0x20 /* Two fields for the implementing class to use */ void *private; Modified: projects/camlock/sys/geom/geom_dev.c ============================================================================== --- projects/camlock/sys/geom/geom_dev.c Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/geom/geom_dev.c Fri Aug 16 12:25:02 2013 (r254408) @@ -222,6 +222,7 @@ g_dev_taste(struct g_class *mp, struct g mtx_init(&sc->sc_mtx, "g_dev", NULL, MTX_DEF); cp = g_new_consumer(gp); cp->private = sc; + cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; error = g_attach(cp, pp); KASSERT(error == 0, ("g_dev_taste(%s) failed to g_attach, err=%d", pp->name, error)); Modified: projects/camlock/sys/geom/geom_disk.c ============================================================================== --- projects/camlock/sys/geom/geom_disk.c Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/geom/geom_disk.c Fri Aug 16 12:25:02 2013 (r254408) @@ -66,6 +66,7 @@ struct g_disk_softc { struct sysctl_oid *sysctl_tree; char led[64]; uint32_t state; + struct mtx start_mtx; }; static g_access_t g_disk_access; @@ -346,7 +347,9 @@ g_disk_start(struct bio *bp) bp2->bio_pblkno = bp2->bio_offset / dp->d_sectorsize; bp2->bio_bcount = bp2->bio_length; bp2->bio_disk = dp; + mtx_lock(&sc->start_mtx); devstat_start_transaction_bio(dp->d_devstat, bp2); + mtx_unlock(&sc->start_mtx); g_disk_lock_giant(dp); dp->d_strategy(bp2); g_disk_unlock_giant(dp); @@ -509,6 +512,7 @@ g_disk_create(void *arg, int flag) g_topology_assert(); dp = arg; sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); + mtx_init(&sc->start_mtx, "g_disk_start", NULL, MTX_DEF); mtx_init(&sc->done_mtx, "g_disk_done", NULL, MTX_DEF); sc->dp = dp; gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit); @@ -520,6 +524,9 @@ g_disk_create(void *arg, int flag) pp->stripesize = dp->d_stripesize; if ((dp->d_flags & DISKFLAG_UNMAPPED_BIO) != 0) pp->flags |= G_PF_ACCEPT_UNMAPPED; + if ((dp->d_flags & DISKFLAG_DIRECT_COMPLETION) != 0) + pp->flags |= G_PF_DIRECT_SEND; + pp->flags |= G_PF_DIRECT_RECEIVE; if (bootverbose) printf("GEOM: new disk %s\n", gp->name); sysctl_ctx_init(&sc->sysctl_ctx); @@ -568,6 +575,7 @@ g_disk_providergone(struct g_provider *p pp->private = NULL; pp->geom->softc = NULL; mtx_destroy(&sc->done_mtx); + mtx_destroy(&sc->start_mtx); g_free(sc); } Modified: projects/camlock/sys/geom/geom_disk.h ============================================================================== --- projects/camlock/sys/geom/geom_disk.h Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/geom/geom_disk.h Fri Aug 16 12:25:02 2013 (r254408) @@ -107,6 +107,7 @@ struct disk { #define DISKFLAG_CANDELETE 0x4 #define DISKFLAG_CANFLUSHCACHE 0x8 #define DISKFLAG_UNMAPPED_BIO 0x10 +#define DISKFLAG_DIRECT_COMPLETION 0x20 struct disk *disk_alloc(void); void disk_create(struct disk *disk, int version); Modified: projects/camlock/sys/geom/geom_io.c ============================================================================== --- projects/camlock/sys/geom/geom_io.c Fri Aug 16 10:53:36 2013 (r254407) +++ projects/camlock/sys/geom/geom_io.c Fri Aug 16 12:25:02 2013 (r254408) @@ -422,7 +422,7 @@ void g_io_request(struct bio *bp, struct g_consumer *cp) { struct g_provider *pp; - int first; + int direct, first; KASSERT(cp != NULL, ("NULL cp in g_io_request")); KASSERT(bp != NULL, ("NULL bp in g_io_request")); @@ -472,13 +472,14 @@ g_io_request(struct bio *bp, struct g_co KASSERT(!(bp->bio_flags & BIO_ONQUEUE), ("Bio already on queue bp=%p", bp)); - bp->bio_flags |= BIO_ONQUEUE; - if (g_collectstats) binuptime(&bp->bio_t0); else getbinuptime(&bp->bio_t0); + direct = (cp->flags & G_CF_DIRECT_SEND) && + (pp->flags & G_PF_DIRECT_RECEIVE); + /* * The statistics collection is lockless, as such, but we * can not update one instance of the statistics from more @@ -498,14 +499,19 @@ g_io_request(struct bio *bp, struct g_co pp->nstart++; cp->nstart++; - first = TAILQ_EMPTY(&g_bio_run_down.bio_queue); - TAILQ_INSERT_TAIL(&g_bio_run_down.bio_queue, bp, bio_queue); - g_bio_run_down.bio_queue_length++; - g_bioq_unlock(&g_bio_run_down); - - /* Pass it on down. */ - if (first) - wakeup(&g_wait_down); + if (direct) { + g_bioq_unlock(&g_bio_run_down); + bp->bio_to->geom->start(bp); + } else { + first = TAILQ_EMPTY(&g_bio_run_down.bio_queue); + TAILQ_INSERT_TAIL(&g_bio_run_down.bio_queue, bp, bio_queue); + bp->bio_flags |= BIO_ONQUEUE; + g_bio_run_down.bio_queue_length++; + g_bioq_unlock(&g_bio_run_down); + /* Pass it on down. */ + if (first) + wakeup(&g_wait_down); + } } void @@ -513,7 +519,7 @@ g_io_deliver(struct bio *bp, int error) { struct g_consumer *cp; struct g_provider *pp; - int first; + int direct, first; KASSERT(bp != NULL, ("NULL bp in g_io_deliver")); pp = bp->bio_to; @@ -559,6 +565,9 @@ g_io_deliver(struct bio *bp, int error) bp->bio_bcount = bp->bio_length; bp->bio_resid = bp->bio_bcount - bp->bio_completed; + direct = (pp->flags & G_PF_DIRECT_SEND) && + (cp->flags & G_CF_DIRECT_RECEIVE); + /* * The statistics collection is lockless, as such, but we * can not update one instance of the statistics from more @@ -574,13 +583,18 @@ g_io_deliver(struct bio *bp, int error) pp->nend++; if (error != ENOMEM) { bp->bio_error = error; - first = TAILQ_EMPTY(&g_bio_run_up.bio_queue); - TAILQ_INSERT_TAIL(&g_bio_run_up.bio_queue, bp, bio_queue); - bp->bio_flags |= BIO_ONQUEUE; - g_bio_run_up.bio_queue_length++; - g_bioq_unlock(&g_bio_run_up); - if (first) - wakeup(&g_wait_up); + if (direct) { + g_bioq_unlock(&g_bio_run_up); + biodone(bp); + } else { + first = TAILQ_EMPTY(&g_bio_run_up.bio_queue); + TAILQ_INSERT_TAIL(&g_bio_run_up.bio_queue, bp, bio_queue); + bp->bio_flags |= BIO_ONQUEUE; + g_bio_run_up.bio_queue_length++; + g_bioq_unlock(&g_bio_run_up); + if (first) + wakeup(&g_wait_up); + } return; } g_bioq_unlock(&g_bio_run_up);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308161225.r7GCP3EW061762>