svn commit: r254408 - in projects/camlock/sys: cam/ata cam/scsi dev/md geom
Alexander Motin
mav at FreeBSD.org
Fri Aug 16 12:25:05 UTC 2013
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);
More information about the svn-src-projects
mailing list