summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-25 07:26:12 +0000
committermav <mav@FreeBSD.org>2015-10-25 07:26:12 +0000
commit8bb27e0d32095ceac091c0ececaf0ac91fbdb1ee (patch)
tree89a9205f3051ca9da24f99cf471222cbcbbfaee6 /sys/cam
parentbef317767a95df3d2c01aeedba0ec877e4757e3f (diff)
downloadFreeBSD-src-8bb27e0d32095ceac091c0ececaf0ac91fbdb1ee.zip
FreeBSD-src-8bb27e0d32095ceac091c0ececaf0ac91fbdb1ee.tar.gz
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.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/scsi/scsi_da.c72
1 files changed, 35 insertions, 37 deletions
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 0fa5a11..90c917c 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 {
OpenPOWER on IntegriCloud