svn commit: r222628 - head/sys/cam/ata

Alexander Motin mav at FreeBSD.org
Thu Jun 2 20:56:42 UTC 2011


Author: mav
Date: Thu Jun  2 20:56:42 2011
New Revision: 222628
URL: http://svn.freebsd.org/changeset/base/222628

Log:
  When possible, join ranges of subsequest BIO_DELETE requests to handle more
  (up to 2048 instead of 256 or even 64) of them with single TRIM request.
  
  OCZ Vertex2/Vertex3 SSDs can handle no more then 64 ranges per TRIM request.
  Due to lack of BIO_DELETE clustering now, it means that we could delete no
  more then 2MB per request (on FS with 32K block) with limited request rate.
  This change increases delete rate on Vertex2 from 250MB/s to 950MB/s.

Modified:
  head/sys/cam/ata/ata_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c	Thu Jun  2 20:15:32 2011	(r222627)
+++ head/sys/cam/ata/ata_da.c	Thu Jun  2 20:56:42 2011	(r222628)
@@ -115,10 +115,11 @@ struct disk_params {
 };
 
 #define TRIM_MAX_BLOCKS	4
-#define TRIM_MAX_RANGES	TRIM_MAX_BLOCKS * 64
+#define TRIM_MAX_RANGES	(TRIM_MAX_BLOCKS * 64)
+#define TRIM_MAX_BIOS	(TRIM_MAX_RANGES * 8)
 struct trim_request {
 	uint8_t		data[TRIM_MAX_RANGES * 8];
-	struct bio	*bps[TRIM_MAX_RANGES];
+	struct bio	*bps[TRIM_MAX_BIOS];
 };
 
 struct ada_softc {
@@ -1067,7 +1068,8 @@ adastart(struct cam_periph *periph, unio
 		    (bp = bioq_first(&softc->trim_queue)) != 0) {
 			struct trim_request *req = &softc->trim_req;
 			struct bio *bp1;
-			int bps = 0, ranges = 0;
+			uint64_t lastlba = (uint64_t)-1;
+			int bps = 0, c, lastcount = 0, off, ranges = 0;
 
 			softc->trim_running = 1;
 			bzero(req, sizeof(*req));
@@ -1078,10 +1080,22 @@ adastart(struct cam_periph *periph, unio
 				    softc->params.secsize;
 
 				bioq_remove(&softc->trim_queue, bp1);
-				while (count > 0) {
-					int c = min(count, 0xffff);
-					int off = ranges * 8;
 
+				/* Try to extend the previous range. */
+				if (lba == lastlba) {
+					c = min(count, 0xffff - lastcount);
+					lastcount += c;
+					off = (ranges - 1) * 8;
+					req->data[off + 6] = lastcount & 0xff;
+					req->data[off + 7] =
+					    (lastcount >> 8) & 0xff;
+					count -= c;
+					lba += c;
+				}
+
+				while (count > 0) {
+					c = min(count, 0xffff);
+					off = ranges * 8;
 					req->data[off + 0] = lba & 0xff;
 					req->data[off + 1] = (lba >> 8) & 0xff;
 					req->data[off + 2] = (lba >> 16) & 0xff;
@@ -1092,11 +1106,14 @@ adastart(struct cam_periph *periph, unio
 					req->data[off + 7] = (c >> 8) & 0xff;
 					lba += c;
 					count -= c;
+					lastcount = c;
 					ranges++;
 				}
+				lastlba = lba;
 				req->bps[bps++] = bp1;
 				bp1 = bioq_first(&softc->trim_queue);
-				if (bp1 == NULL ||
+				if (bps >= TRIM_MAX_BIOS ||
+				    bp1 == NULL ||
 				    bp1->bio_bcount / softc->params.secsize >
 				    (softc->trim_max_ranges - ranges) * 0xffff)
 					break;
@@ -1370,8 +1387,7 @@ adadone(struct cam_periph *periph, union
 			    (struct trim_request *)ataio->data_ptr;
 			int i;
 
-			for (i = 1; i < softc->trim_max_ranges &&
-			    req->bps[i]; i++) {
+			for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) {
 				struct bio *bp1 = req->bps[i];
 				
 				bp1->bio_resid = bp->bio_resid;


More information about the svn-src-all mailing list