From d2a020590a9d4e32db98e9fd281eb2d63c6fc897 Mon Sep 17 00:00:00 2001 From: mav Date: Sun, 25 Oct 2015 07:26:12 +0000 Subject: [PATCH] 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. git-svn-id: svn://svn.freebsd.org/base/stable/10@289924 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- share/man/man4/da.4 | 31 +++++++++++------- sys/cam/scsi/scsi_da.c | 72 ++++++++++++++++++++---------------------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/share/man/man4/da.4 b/share/man/man4/da.4 index 7d6f83b48..0fabeddfe 100644 --- a/share/man/man4/da.4 +++ b/share/man/man4/da.4 @@ -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, and the default is currently 60 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 diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 0fa5a115a..90c917c07 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -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, union ccb *ccb) 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, union ccb *ccb) 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 ccb *done_ccb) /* 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 ccb *done_ccb) */ 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 ccb *done_ccb) (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 { -- 2.45.0