Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Jan 2014 22:19:53 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r261042 - head/sys/cam/scsi
Message-ID:  <201401222219.s0MMJrMd091205@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Jan 22 22:19:53 2014
New Revision: 261042
URL: http://svnweb.freebsd.org/changeset/base/261042

Log:
  Mostly revert r260267 and hopefully really fix the original problem.
  
  The latest draft of SBC-3 tells: "A MAXIMUM UNMAP LBA COUNT field set to
  a non-zero value indicates the maximum number of LBAs that may be unmapped
  by an UNMAP command."  To me it does not sound like that limit is set per
  single descriptor, but rather per all command.  And I have at least one
  device that behaves exactly that way.  This patch fixes the problem there.
  
  MFC after:	1 week

Modified:
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c	Wed Jan 22 22:01:29 2014	(r261041)
+++ head/sys/cam/scsi/scsi_da.c	Wed Jan 22 22:19:53 2014	(r261042)
@@ -211,7 +211,7 @@ struct da_softc {
 	int	 delete_running;
 	int	 delete_available;	/* Delete methods possibly available */
 	uint32_t		unmap_max_ranges;
-	uint32_t		unmap_max_lba; /* Max LBAs in a single range */
+	uint32_t		unmap_max_lba; /* Max LBAs in UNMAP req */
 	uint64_t		ws_max_blks;
 	da_delete_methods	delete_method;
 	da_delete_func_t	*delete_func;
@@ -1854,7 +1854,7 @@ dadeletemaxsize(struct da_softc *softc, 
 
 	switch(delete_method) {
 	case DA_DELETE_UNMAP:
-		sectors = (off_t)softc->unmap_max_lba * softc->unmap_max_ranges;
+		sectors = (off_t)softc->unmap_max_lba;
 		break;
 	case DA_DELETE_ATA_TRIM:
 		sectors = (off_t)ATA_DSM_RANGE_MAX * softc->trim_max_ranges;
@@ -2526,6 +2526,7 @@ da_delete_unmap(struct cam_periph *perip
 	struct bio *bp1;
 	uint8_t *buf = softc->unmap_buf;
 	uint64_t lba, lastlba = (uint64_t)-1;
+	uint64_t totalcount = 0;
 	uint64_t count;
 	uint32_t lastcount = 0, c;
 	uint32_t off, ranges = 0;
@@ -2552,41 +2553,42 @@ da_delete_unmap(struct cam_periph *perip
 
 		/* Try to extend the previous range. */
 		if (lba == lastlba) {
-			c = min(count, softc->unmap_max_lba - lastcount);
+			c = omin(count, UNMAP_RANGE_MAX - lastcount);
 			lastcount += c;
 			off = ((ranges - 1) * UNMAP_RANGE_SIZE) +
 			      UNMAP_HEAD_SIZE;
 			scsi_ulto4b(lastcount, &buf[off + 8]);
 			count -= c;
 			lba +=c;
+			totalcount += c;
 		}
 
 		while (count > 0) {
-			if (ranges > softc->unmap_max_ranges) {
+			c = omin(count, UNMAP_RANGE_MAX);
+			if (totalcount + c > softc->unmap_max_lba ||
+			    ranges >= softc->unmap_max_ranges) {
 				xpt_print(periph->path,
-				    "%s issuing short delete %d > %d\n",
+				    "%s issuing short delete %ld > %ld"
+				    "|| %d >= %d",
 				    da_delete_method_desc[softc->delete_method],
+				    totalcount + c, softc->unmap_max_lba,
 				    ranges, softc->unmap_max_ranges);
 				break;
 			}
-			c = min(count, softc->unmap_max_lba);
 			off = (ranges * UNMAP_RANGE_SIZE) + UNMAP_HEAD_SIZE;
 			scsi_u64to8b(lba, &buf[off + 0]);
 			scsi_ulto4b(c, &buf[off + 8]);
 			lba += c;
+			totalcount += c;
 			ranges++;
 			count -= c;
 			lastcount = c;
 		}
 		lastlba = lba;
 		bp1 = bioq_first(&softc->delete_queue);
-		/*
-		 * Assume no range extension on the next loop iteration to
-		 * avoid issuing a short delete.
-		 */
 		if (bp1 == NULL || ranges >= softc->unmap_max_ranges ||
-		    bp1->bio_bcount / softc->params.secsize >
-		    softc->unmap_max_lba * (softc->unmap_max_ranges - ranges))
+		    totalcount + bp1->bio_bcount /
+		    softc->params.secsize > softc->unmap_max_lba)
 			break;
 	} while (1);
 	scsi_ulto2b(ranges * 16 + 6, &buf[0]);



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