svn commit: r249621 - stable/9/sys/geom

Alexander Motin mav at FreeBSD.org
Thu Apr 18 11:13:49 UTC 2013


Author: mav
Date: Thu Apr 18 11:13:48 2013
New Revision: 249621
URL: http://svnweb.freebsd.org/changeset/base/249621

Log:
  MFC r248694:
  In GEOM DISK:
   - Replace single done mutex with per-disk ones.  On system with several
  disks on several HBAs that removes small, but measurable lock congestion.
   - Modify disk destruction process to not destroy the mutex prematurely.
   - Remove some extra pointer derefences.

Modified:
  stable/9/sys/geom/geom_disk.c

Modified: stable/9/sys/geom/geom_disk.c
==============================================================================
--- stable/9/sys/geom/geom_disk.c	Thu Apr 18 10:57:56 2013	(r249620)
+++ stable/9/sys/geom/geom_disk.c	Thu Apr 18 11:13:48 2013	(r249621)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/led/led.h>
 
 struct g_disk_softc {
+	struct mtx		 done_mtx;
 	struct disk		*dp;
 	struct sysctl_ctx_list	sysctl_ctx;
 	struct sysctl_oid	*sysctl_tree;
@@ -67,11 +68,7 @@ struct g_disk_softc {
 	uint32_t		state;
 };
 
-static struct mtx g_disk_done_mtx;
-
 static g_access_t g_disk_access;
-static g_init_t g_disk_init;
-static g_fini_t g_disk_fini;
 static g_start_t g_disk_start;
 static g_ioctl_t g_disk_ioctl;
 static g_dumpconf_t g_disk_dumpconf;
@@ -80,8 +77,6 @@ static g_provgone_t g_disk_providergone;
 static struct g_class g_disk_class = {
 	.name = "DISK",
 	.version = G_VERSION,
-	.init = g_disk_init,
-	.fini = g_disk_fini,
 	.start = g_disk_start,
 	.access = g_disk_access,
 	.ioctl = g_disk_ioctl,
@@ -93,20 +88,6 @@ SYSCTL_DECL(_kern_geom);
 static SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0,
     "GEOM_DISK stuff");
 
-static void
-g_disk_init(struct g_class *mp __unused)
-{
-
-	mtx_init(&g_disk_done_mtx, "g_disk_done", NULL, MTX_DEF);
-}
-
-static void
-g_disk_fini(struct g_class *mp __unused)
-{
-
-	mtx_destroy(&g_disk_done_mtx);
-}
-
 DECLARE_GEOM_CLASS(g_disk_class, g_disk);
 
 static void __inline
@@ -135,7 +116,7 @@ g_disk_access(struct g_provider *pp, int
 	g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
 	    pp->name, r, w, e);
 	g_topology_assert();
-	sc = pp->geom->softc;
+	sc = pp->private;
 	if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
 		/*
 		 * Allow decreasing access count even if disk is not
@@ -244,42 +225,36 @@ static void
 g_disk_done(struct bio *bp)
 {
 	struct bio *bp2;
-	struct disk *dp;
 	struct g_disk_softc *sc;
 
 	/* See "notes" for why we need a mutex here */
 	/* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
-	mtx_lock(&g_disk_done_mtx);
-	bp->bio_completed = bp->bio_length - bp->bio_resid;
-
 	bp2 = bp->bio_parent;
+	sc = bp2->bio_to->private;
+	bp->bio_completed = bp->bio_length - bp->bio_resid;
+	mtx_lock(&sc->done_mtx);
 	if (bp2->bio_error == 0)
 		bp2->bio_error = bp->bio_error;
 	bp2->bio_completed += bp->bio_completed;
-	if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0 &&
-	    (sc = bp2->bio_to->geom->softc) != NULL &&
-	    (dp = sc->dp) != NULL) {
-		devstat_end_transaction_bio(dp->d_devstat, bp);
-	}
+	if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0)
+		devstat_end_transaction_bio(sc->dp->d_devstat, bp);
 	g_destroy_bio(bp);
 	bp2->bio_inbed++;
 	if (bp2->bio_children == bp2->bio_inbed) {
 		bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
 		g_io_deliver(bp2, bp2->bio_error);
 	}
-	mtx_unlock(&g_disk_done_mtx);
+	mtx_unlock(&sc->done_mtx);
 }
 
 static int
 g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
 {
-	struct g_geom *gp;
 	struct disk *dp;
 	struct g_disk_softc *sc;
 	int error;
 
-	gp = pp->geom;
-	sc = gp->softc;
+	sc = pp->private;
 	dp = sc->dp;
 
 	if (dp->d_ioctl == NULL)
@@ -299,7 +274,7 @@ g_disk_start(struct bio *bp)
 	int error;
 	off_t off;
 
-	sc = bp->bio_to->geom->softc;
+	sc = bp->bio_to->private;
 	if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
 		g_io_deliver(bp, ENXIO);
 		return;
@@ -458,6 +433,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->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);
 	gp->softc = sc;
@@ -501,15 +477,7 @@ g_disk_providergone(struct g_provider *p
 	struct disk *dp;
 	struct g_disk_softc *sc;
 
-	sc = (struct g_disk_softc *)pp->geom->softc;
-
-	/*
-	 * If the softc is already NULL, then we've probably been through
-	 * g_disk_destroy already; there is nothing for us to do anyway.
-	 */
-	if (sc == NULL)
-		return;
-
+	sc = (struct g_disk_softc *)pp->private;
 	dp = sc->dp;
 
 	/*
@@ -519,8 +487,21 @@ g_disk_providergone(struct g_provider *p
 	 * in g_disk_create for VERSION_01 and avoid touching the d_gone
 	 * field for old consumers.
 	 */
-	if (!(dp->d_flags & DISKFLAG_LACKS_GONE) && dp->d_gone != NULL)
+	if (dp != NULL && (dp->d_flags & DISKFLAG_LACKS_GONE) == 0 &&
+	    dp->d_gone != NULL)
 		dp->d_gone(dp);
+	if (sc->sysctl_tree != NULL) {
+		sysctl_ctx_free(&sc->sysctl_ctx);
+		sc->sysctl_tree = NULL;
+	}
+	if (sc->led[0] != 0) {
+		led_set(sc->led, "0");
+		sc->led[0] = 0;
+	}
+	pp->private = NULL;
+	pp->geom->softc = NULL;
+	mtx_destroy(&sc->done_mtx);
+	g_free(sc);
 }
 
 static void
@@ -535,16 +516,9 @@ g_disk_destroy(void *ptr, int flag)
 	gp = dp->d_geom;
 	if (gp != NULL) {
 		sc = gp->softc;
-		if (sc->sysctl_tree != NULL) {
-			sysctl_ctx_free(&sc->sysctl_ctx);
-			sc->sysctl_tree = NULL;
-		}
-		if (sc->led[0] != 0) {
-			led_set(sc->led, "0");
-			sc->led[0] = 0;
-		}
-		g_free(sc);
-		gp->softc = NULL;
+		if (sc != NULL)
+			sc->dp = NULL;
+		dp->d_geom = NULL;
 		g_wither_geom(gp, ENXIO);
 	}
 	g_free(dp);


More information about the svn-src-stable-9 mailing list