From owner-svn-src-head@FreeBSD.ORG Wed Jan 22 22:19:53 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9615BB50; Wed, 22 Jan 2014 22:19:53 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 8247819B6; Wed, 22 Jan 2014 22:19:53 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id s0MMJrTH091206; Wed, 22 Jan 2014 22:19:53 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id s0MMJrMd091205; Wed, 22 Jan 2014 22:19:53 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201401222219.s0MMJrMd091205@svn.freebsd.org> From: Alexander Motin Date: Wed, 22 Jan 2014 22:19:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r261042 - head/sys/cam/scsi X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Jan 2014 22:19:53 -0000 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]);