Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Aug 2013 15:12:14 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r254369 - in projects/camlock/sys/cam: ata scsi
Message-ID:  <201308151512.r7FFCE8k079140@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Aug 15 15:12:14 2013
New Revision: 254369
URL: http://svnweb.freebsd.org/changeset/base/254369

Log:
  Make da(4) and ada(4) drivers call biodone() without holding any locks.
  That both reduces lock hold time improving performance, and makes devices
  reenterable, that may be needed for direct-dispatching GEOM.
  
  As side effect this removes limit on number of BIO_DELETEs aggregated in
  single ATA TRIM command.

Modified:
  projects/camlock/sys/cam/ata/ata_da.c
  projects/camlock/sys/cam/scsi/scsi_da.c

Modified: projects/camlock/sys/cam/ata/ata_da.c
==============================================================================
--- projects/camlock/sys/cam/ata/ata_da.c	Thu Aug 15 14:41:39 2013	(r254368)
+++ projects/camlock/sys/cam/ata/ata_da.c	Thu Aug 15 15:12:14 2013	(r254369)
@@ -122,10 +122,9 @@ struct disk_params {
 
 #define TRIM_MAX_BLOCKS	8
 #define TRIM_MAX_RANGES	(TRIM_MAX_BLOCKS * ATA_DSM_BLK_RANGES)
-#define TRIM_MAX_BIOS	(TRIM_MAX_RANGES * 4)
 struct trim_request {
 	uint8_t		data[TRIM_MAX_RANGES * ATA_DSM_RANGE_SIZE];
-	struct bio	*bps[TRIM_MAX_BIOS];
+	TAILQ_HEAD(, bio) bps;
 };
 
 struct ada_softc {
@@ -1375,10 +1374,11 @@ adastart(struct cam_periph *periph, unio
 			struct trim_request *req = &softc->trim_req;
 			struct bio *bp1;
 			uint64_t lastlba = (uint64_t)-1;
-			int bps = 0, c, lastcount = 0, off, ranges = 0;
+			int c, lastcount = 0, off, ranges = 0;
 
 			softc->trim_running = 1;
 			bzero(req, sizeof(*req));
+			TAILQ_INIT(&req->bps);
 			bp1 = bp;
 			do {
 				uint64_t lba = bp1->bio_pblkno;
@@ -1421,10 +1421,9 @@ adastart(struct cam_periph *periph, unio
 					 */
 				}
 				lastlba = lba;
-				req->bps[bps++] = bp1;
+				TAILQ_INSERT_TAIL(&req->bps, bp1, bio_queue);
 				bp1 = bioq_first(&softc->trim_queue);
-				if (bps >= TRIM_MAX_BIOS ||
-				    bp1 == NULL ||
+				if (bp1 == NULL ||
 				    bp1->bio_bcount / softc->params.secsize >
 				    (softc->trim_max_ranges - ranges) *
 				    ATA_DSM_RANGE_MAX)
@@ -1443,6 +1442,7 @@ adastart(struct cam_periph *periph, unio
 			    ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES -
 			    1) / ATA_DSM_BLK_RANGES);
 			start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM;
+			start_ccb->ccb_h.flags |= CAM_UNLOCKED;
 			goto out;
 		}
 		/* Run regular command. */
@@ -1611,6 +1611,7 @@ adastart(struct cam_periph *periph, unio
 			break;
 		}
 		start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO;
+		start_ccb->ccb_h.flags |= CAM_UNLOCKED;
 out:
 		start_ccb->ccb_h.ccb_bp = bp;
 		softc->outstanding_cmds++;
@@ -1678,10 +1679,12 @@ adadone(struct cam_periph *periph, union
 		struct bio *bp;
 		int error;
 
+		cam_periph_lock(periph);
 		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 			error = adaerror(done_ccb, 0, 0);
 			if (error == ERESTART) {
 				/* A retry was scheduled, so just return. */
+				cam_periph_unlock(periph);
 				return;
 			}
 			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
@@ -1711,14 +1714,18 @@ adadone(struct cam_periph *periph, union
 		softc->outstanding_cmds--;
 		if (softc->outstanding_cmds == 0)
 			softc->flags |= ADA_FLAG_WENT_IDLE;
+		xpt_release_ccb(done_ccb);
 		if (state == ADA_CCB_TRIM) {
-			struct trim_request *req =
-			    (struct trim_request *)ataio->data_ptr;
-			int i;
-
-			for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) {
-				struct bio *bp1 = req->bps[i];
+			TAILQ_HEAD(, bio) queue;
+			struct bio *bp1;
 
+			TAILQ_INIT(&queue);
+			TAILQ_CONCAT(&queue, &softc->trim_req.bps, bio_queue);
+			softc->trim_running = 0;
+			adaschedule(periph);
+			cam_periph_unlock(periph);
+			while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
+				TAILQ_REMOVE(&queue, bp1, bio_queue);
 				bp1->bio_error = bp->bio_error;
 				if (bp->bio_flags & BIO_ERROR) {
 					bp1->bio_flags |= BIO_ERROR;
@@ -1727,12 +1734,11 @@ adadone(struct cam_periph *periph, union
 					bp1->bio_resid = 0;
 				biodone(bp1);
 			}
-			softc->trim_running = 0;
-			biodone(bp);
-			adaschedule(periph);
-		} else
+		} else {
+			cam_periph_unlock(periph);
 			biodone(bp);
-		break;
+		}
+		return;
 	}
 	case ADA_CCB_RAHEAD:
 	{

Modified: projects/camlock/sys/cam/scsi/scsi_da.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_da.c	Thu Aug 15 14:41:39 2013	(r254368)
+++ projects/camlock/sys/cam/scsi/scsi_da.c	Thu Aug 15 15:12:14 2013	(r254369)
@@ -2271,6 +2271,7 @@ skipstate:
 			break;
 		}
 		start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
+		start_ccb->ccb_h.flags |= CAM_UNLOCKED;
 
 out:
 		/*
@@ -2583,6 +2584,7 @@ da_delete_unmap(struct cam_periph *perip
 		   /*sense_len*/SSD_FULL_SIZE,
 		   da_default_timeout * 1000);
 	ccb->ccb_h.ccb_state = DA_CCB_DELETE;
+	ccb->ccb_h.flags |= CAM_UNLOCKED;
 }
 
 static void
@@ -2663,6 +2665,7 @@ da_delete_trim(struct cam_periph *periph
 		      /*sense_len*/SSD_FULL_SIZE,
 		      da_default_timeout * 1000);
 	ccb->ccb_h.ccb_state = DA_CCB_DELETE;
+	ccb->ccb_h.flags |= CAM_UNLOCKED;
 }
 
 /*
@@ -2719,6 +2722,7 @@ da_delete_ws(struct cam_periph *periph, 
 			/*sense_len*/SSD_FULL_SIZE,
 			da_default_timeout * 1000);
 	ccb->ccb_h.ccb_state = DA_CCB_DELETE;
+	ccb->ccb_h.flags |= CAM_UNLOCKED;
 }
 
 static int
@@ -2853,6 +2857,7 @@ dadone(struct cam_periph *periph, union 
 	{
 		struct bio *bp, *bp1;
 
+		cam_periph_lock(periph);
 		bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 			int error;
@@ -2869,6 +2874,7 @@ dadone(struct cam_periph *periph, union 
 				 * A retry was scheduled, so
 				 * just return.
 				 */
+				cam_periph_unlock(periph);
 				return;
 			}
 			bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
@@ -2945,9 +2951,18 @@ dadone(struct cam_periph *periph, union 
 		if (softc->outstanding_cmds == 0)
 			softc->flags |= DA_FLAG_WENT_IDLE;
 
+		xpt_release_ccb(done_ccb);
 		if (state == DA_CCB_DELETE) {
-			while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
-			    != NULL) {
+			TAILQ_HEAD(, bio) queue;
+
+			TAILQ_INIT(&queue);
+			TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue);
+			softc->delete_run_queue.insert_point = NULL;
+			softc->delete_running = 0;
+			daschedule(periph);
+			cam_periph_unlock(periph);
+			while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
+				TAILQ_REMOVE(&queue, bp1, bio_queue);
 				bp1->bio_error = bp->bio_error;
 				if (bp->bio_flags & BIO_ERROR) {
 					bp1->bio_flags |= BIO_ERROR;
@@ -2956,13 +2971,11 @@ dadone(struct cam_periph *periph, union 
 					bp1->bio_resid = 0;
 				biodone(bp1);
 			}
-			softc->delete_running = 0;
-			if (bp != NULL)
-				biodone(bp);
-			daschedule(periph);
-		} else if (bp != NULL)
+		} else
+			cam_periph_unlock(periph);
+		if (bp != NULL)
 			biodone(bp);
-		break;
+		return;
 	}
 	case DA_CCB_PROBE_RC:
 	case DA_CCB_PROBE_RC16:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308151512.r7FFCE8k079140>