Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Oct 2015 07:26:12 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r289924 - in stable/10: share/man/man4 sys/cam/scsi
Message-ID:  <201510250726.t9P7QCFX049794@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Oct 25 07:26:12 2015
New Revision: 289924
URL: https://svnweb.freebsd.org/changeset/base/289924

Log:
  MFC r289146:
  Make delete method set via kern.cam.da.X.delete_method persistent.
  
  This allows to set delete method via tunable, before device capabilities
  are known.  Also allow ZERO method for devices not reporting LBP, if user
  explicitly requests it -- it may be useful if storage supports compression
  and WRITE SAME, but does not support UNMAP.

Modified:
  stable/10/share/man/man4/da.4
  stable/10/sys/cam/scsi/scsi_da.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/share/man/man4/da.4
==============================================================================
--- stable/10/share/man/man4/da.4	Sun Oct 25 06:07:46 2015	(r289923)
+++ stable/10/share/man/man4/da.4	Sun Oct 25 07:26:12 2015	(r289924)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 22, 2014
+.Dd October 11, 2015
 .Dt DA 4
 .Os
 .Sh NAME
@@ -133,8 +133,7 @@ variables and
 .Xr loader 8
 tunables:
 .Bl -tag -width 12
-.It kern.cam.da.retry_count
-.Pp
+.It Va kern.cam.da.retry_count
 This variable determines how many times the
 .Nm
 driver will retry a READ or WRITE command.
@@ -143,8 +142,7 @@ the
 .Nm
 driver dump routine.
 This value currently defaults to 4.
-.It kern.cam.da.default_timeout
-.Pp
+.It Va kern.cam.da.default_timeout
 This variable determines how long the
 .Nm
 driver will wait before timing out an outstanding command.
@@ -152,20 +150,31 @@ The units for this value are seconds, an
 seconds.
 .It Va kern.cam.sort_io_queue
 .It Va kern.cam.da. Ns Ar X Ns Va .sort_io_queue
-.Pp
 These variables determine whether request queue should be sorted trying
 to optimize head seeks.
 Set to 1 to enable sorting, 0 to disable, -1 to leave it as-is.
 The default is sorting enabled for HDDs and disabled for SSDs.
-.It kern.cam.da.%d.minimum_cmd_size
-.Pp
+.It Va kern.cam.da. Ns Ar X Ns Va .delete_method
+This variable specifies method to handle BIO_DELETE requests:
+.Bl -tag
+.It ATA_TRIM
+ATA TRIM via ATA COMMAND PASS THROUGH command,
+.It UNMAP
+UNMAP command,
+.It WS16
+WRITE SAME(16) command with UNMAP flag,
+.It WS10
+WRITE SAME(10) command with UNMAP flag,
+.It ZERO
+WRITE SAME(10) command without UNMAP flag,
+.It DISABLE
+disable BIO_DELETE support.
+.El
+.It Va kern.cam.da. Ns Ar X Ns Va .minimum_cmd_size
 This variable determines what the minimum READ/WRITE CDB size is for a
 given
 .Nm
 unit.
-(The %d above denotes the unit number of the
-.Nm
-driver instance, e.g.\& 1, 2, 4, 8, etc.)
 Valid minimum command size values are 6, 10, 12 and 16 bytes.
 The default is 6 bytes.
 .Pp

Modified: stable/10/sys/cam/scsi/scsi_da.c
==============================================================================
--- stable/10/sys/cam/scsi/scsi_da.c	Sun Oct 25 06:07:46 2015	(r289923)
+++ stable/10/sys/cam/scsi/scsi_da.c	Sun Oct 25 07:26:12 2015	(r289924)
@@ -219,6 +219,7 @@ struct da_softc {
 	uint32_t		unmap_max_ranges;
 	uint32_t		unmap_max_lba; /* Max LBAs in UNMAP req */
 	uint64_t		ws_max_blks;
+	da_delete_methods	delete_method_pref;
 	da_delete_methods	delete_method;
 	da_delete_func_t	*delete_func;
 	struct	 disk_params params;
@@ -1805,7 +1806,7 @@ dasysctlinit(void *context, int pending)
 	 * the fly.
 	 */
 	SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
-		OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW,
+		OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RWTUN,
 		softc, 0, dadeletemethodsysctl, "A",
 		"BIO_DELETE execution method");
 	SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
@@ -1916,7 +1917,6 @@ static void
 dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
 {
 
-
 	softc->delete_method = delete_method;
 	softc->disk->d_delmaxsize = dadeletemaxsize(softc, delete_method);
 	softc->delete_func = da_delete_functions[delete_method];
@@ -1969,25 +1969,17 @@ daprobedone(struct cam_periph *periph, u
 
 		snprintf(buf, sizeof(buf), "Delete methods: <");
 		sep = 0;
-		for (i = DA_DELETE_MIN; i <= DA_DELETE_MAX; i++) {
-			if (softc->delete_available & (1 << i)) {
-				if (sep) {
-					strlcat(buf, ",", sizeof(buf));
-				} else {
-				    sep = 1;
-				}
-				strlcat(buf, da_delete_method_names[i],
-				    sizeof(buf));
-				if (i == softc->delete_method) {
-					strlcat(buf, "(*)", sizeof(buf));
-				}
-			}
-		}
-		if (sep == 0) {
-			if (softc->delete_method == DA_DELETE_NONE) 
-				strlcat(buf, "NONE(*)", sizeof(buf));
-			else
-				strlcat(buf, "DISABLED(*)", sizeof(buf));
+		for (i = 0; i <= DA_DELETE_MAX; i++) {
+			if ((softc->delete_available & (1 << i)) == 0 &&
+			    i != softc->delete_method)
+				continue;
+			if (sep)
+				strlcat(buf, ",", sizeof(buf));
+			strlcat(buf, da_delete_method_names[i],
+			    sizeof(buf));
+			if (i == softc->delete_method)
+				strlcat(buf, "(*)", sizeof(buf));
+			sep = 1;
 		}
 		strlcat(buf, ">", sizeof(buf));
 		printf("%s%d: %s\n", periph->periph_name,
@@ -2017,21 +2009,28 @@ daprobedone(struct cam_periph *periph, u
 static void
 dadeletemethodchoose(struct da_softc *softc, da_delete_methods default_method)
 {
-	int i, delete_method;
+	int i, methods;
 
-	delete_method = default_method;
+	/* If available, prefer the method requested by user. */
+	i = softc->delete_method_pref;
+	methods = softc->delete_available | (1 << DA_DELETE_DISABLE);
+	if (methods & (1 << i)) {
+		dadeletemethodset(softc, i);
+		return;
+	}
 
-	/*
-	 * Use the pre-defined order to choose the best
-	 * performing delete.
-	 */
+	/* Use the pre-defined order to choose the best performing delete. */
 	for (i = DA_DELETE_MIN; i <= DA_DELETE_MAX; i++) {
+		if (i == DA_DELETE_ZERO)
+			continue;
 		if (softc->delete_available & (1 << i)) {
 			dadeletemethodset(softc, i);
 			return;
 		}
 	}
-	dadeletemethodset(softc, delete_method);
+
+	/* Fallback to default. */
+	dadeletemethodset(softc, default_method);
 }
 
 static int
@@ -2055,13 +2054,14 @@ dadeletemethodsysctl(SYSCTL_HANDLER_ARGS
 		return (error);
 	methods = softc->delete_available | (1 << DA_DELETE_DISABLE);
 	for (i = 0; i <= DA_DELETE_MAX; i++) {
-		if (!(methods & (1 << i)) ||
-		    strcmp(buf, da_delete_method_names[i]) != 0)
-			continue;
-		dadeletemethodset(softc, i);
-		return (0);
+		if (strcmp(buf, da_delete_method_names[i]) == 0)
+			break;
 	}
-	return (EINVAL);
+	if (i > DA_DELETE_MAX)
+		return (EINVAL);
+	softc->delete_method_pref = i;
+	dadeletemethodchoose(softc, DA_DELETE_NONE);
+	return (0);
 }
 
 static cam_status
@@ -3298,6 +3298,7 @@ dadone(struct cam_periph *periph, union 
 
 		/* Ensure re-probe doesn't see old delete. */
 		softc->delete_available = 0;
+		dadeleteflag(softc, DA_DELETE_ZERO, 1);
 		if (lbp && (softc->quirks & DA_Q_NO_UNMAP) == 0) {
 			/*
 			 * Based on older SBC-3 spec revisions
@@ -3314,7 +3315,6 @@ dadone(struct cam_periph *periph, union 
 			 */
 			dadeleteflag(softc, DA_DELETE_WS16, 1);
 			dadeleteflag(softc, DA_DELETE_WS10, 1);
-			dadeleteflag(softc, DA_DELETE_ZERO, 1);
 			dadeleteflag(softc, DA_DELETE_UNMAP, 1);
 
 			xpt_release_ccb(done_ccb);
@@ -3343,8 +3343,6 @@ dadone(struct cam_periph *periph, union 
 				     (lbp->flags & SVPD_LBP_WS16));
 			dadeleteflag(softc, DA_DELETE_WS10,
 				     (lbp->flags & SVPD_LBP_WS10));
-			dadeleteflag(softc, DA_DELETE_ZERO,
-				     (lbp->flags & SVPD_LBP_WS10));
 			dadeleteflag(softc, DA_DELETE_UNMAP,
 				     (lbp->flags & SVPD_LBP_UNMAP));
 		} else {



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