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. MFC after: 2 weeks
This commit is contained in:
parent
eaccd9b323
commit
0ac03010f6
@ -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
|
||||
|
@ -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;
|
||||
@ -1801,7 +1802,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),
|
||||
@ -1912,7 +1913,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];
|
||||
@ -1965,25 +1965,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,
|
||||
@ -2013,21 +2005,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
|
||||
@ -2051,13 +2050,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
|
||||
@ -3288,6 +3288,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
|
||||
@ -3304,7 +3305,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);
|
||||
@ -3333,8 +3333,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 {
|
||||
|
Loading…
Reference in New Issue
Block a user