Skip site navigation (1)Skip section navigation (2)
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>