aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/ctl
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl')
-rw-r--r--sys/cam/ctl/ctl.c355
-rw-r--r--sys/cam/ctl/ctl.h18
-rw-r--r--sys/cam/ctl/ctl_backend.c90
-rw-r--r--sys/cam/ctl/ctl_backend.h3
-rw-r--r--sys/cam/ctl/ctl_backend_block.c53
-rw-r--r--sys/cam/ctl/ctl_backend_ramdisk.c32
-rw-r--r--sys/cam/ctl/ctl_frontend.c10
-rw-r--r--sys/cam/ctl/ctl_frontend.h3
-rw-r--r--sys/cam/ctl/ctl_frontend_ioctl.c236
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c53
-rw-r--r--sys/cam/ctl/ctl_ioctl.h52
-rw-r--r--sys/cam/ctl/ctl_tpc.c10
12 files changed, 510 insertions, 405 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 1e1343d4c0ae..c1e986ea42f1 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -4,6 +4,8 @@
* Copyright (c) 2003-2009 Silicon Graphics International Corp.
* Copyright (c) 2012 The FreeBSD Foundation
* Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org>
+ * Copyright (c) 2017 Jakub Wojciech Klama <jceel@FreeBSD.org>
+ * Copyright (c) 2018 Marcelo Araujo <araujo@FreeBSD.org>
* All rights reserved.
*
* Portions of this software were developed by Edward Tomasz Napierala
@@ -65,6 +67,8 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/endian.h>
#include <sys/sysctl.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <vm/uma.h>
#include <cam/cam.h>
@@ -1869,6 +1873,7 @@ ctl_init(void)
args.mda_gid = GID_OPERATOR;
args.mda_mode = 0600;
args.mda_si_drv1 = softc;
+ args.mda_si_drv2 = NULL;
error = make_dev_s(&args, &softc->dev, "cam/ctl");
if (error != 0) {
free(softc, M_DEVBUF);
@@ -2468,105 +2473,6 @@ ctl_copyin_alloc(void *user_addr, unsigned int len, char *error_str,
return (kptr);
}
-static void
-ctl_free_args(int num_args, struct ctl_be_arg *args)
-{
- int i;
-
- if (args == NULL)
- return;
-
- for (i = 0; i < num_args; i++) {
- free(args[i].kname, M_CTL);
- free(args[i].kvalue, M_CTL);
- }
-
- free(args, M_CTL);
-}
-
-static struct ctl_be_arg *
-ctl_copyin_args(int num_args, struct ctl_be_arg *uargs,
- char *error_str, size_t error_str_len)
-{
- struct ctl_be_arg *args;
- int i;
-
- args = ctl_copyin_alloc(uargs, num_args * sizeof(*args),
- error_str, error_str_len);
-
- if (args == NULL)
- goto bailout;
-
- for (i = 0; i < num_args; i++) {
- args[i].kname = NULL;
- args[i].kvalue = NULL;
- }
-
- for (i = 0; i < num_args; i++) {
- uint8_t *tmpptr;
-
- if (args[i].namelen == 0) {
- snprintf(error_str, error_str_len, "Argument %d "
- "name length is zero", i);
- goto bailout;
- }
-
- args[i].kname = ctl_copyin_alloc(args[i].name,
- args[i].namelen, error_str, error_str_len);
- if (args[i].kname == NULL)
- goto bailout;
-
- if (args[i].kname[args[i].namelen - 1] != '\0') {
- snprintf(error_str, error_str_len, "Argument %d "
- "name is not NUL-terminated", i);
- goto bailout;
- }
-
- if (args[i].flags & CTL_BEARG_RD) {
- if (args[i].vallen == 0) {
- snprintf(error_str, error_str_len, "Argument %d "
- "value length is zero", i);
- goto bailout;
- }
-
- tmpptr = ctl_copyin_alloc(args[i].value,
- args[i].vallen, error_str, error_str_len);
- if (tmpptr == NULL)
- goto bailout;
-
- if ((args[i].flags & CTL_BEARG_ASCII)
- && (tmpptr[args[i].vallen - 1] != '\0')) {
- snprintf(error_str, error_str_len, "Argument "
- "%d value is not NUL-terminated", i);
- free(tmpptr, M_CTL);
- goto bailout;
- }
- args[i].kvalue = tmpptr;
- } else {
- args[i].kvalue = malloc(args[i].vallen,
- M_CTL, M_WAITOK | M_ZERO);
- }
- }
-
- return (args);
-bailout:
-
- ctl_free_args(num_args, args);
-
- return (NULL);
-}
-
-static void
-ctl_copyout_args(int num_args, struct ctl_be_arg *args)
-{
- int i;
-
- for (i = 0; i < num_args; i++) {
- if (args[i].flags & CTL_BEARG_WR)
- copyout(args[i].kvalue, args[i].value, args[i].vallen);
- }
-}
-
/*
* Escape characters that are illegal or not recommended in XML.
*/
@@ -3038,8 +2944,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
case CTL_LUN_REQ: {
struct ctl_lun_req *lun_req;
struct ctl_backend_driver *backend;
+ void *packed;
+ nvlist_t *tmp_args_nvl;
+ size_t packed_len;
lun_req = (struct ctl_lun_req *)addr;
+ tmp_args_nvl = lun_req->args_nvl;
backend = ctl_backend_find(lun_req->backend);
if (backend == NULL) {
@@ -3050,32 +2960,68 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
lun_req->backend);
break;
}
- if (lun_req->num_be_args > 0) {
- lun_req->kern_be_args = ctl_copyin_args(
- lun_req->num_be_args,
- lun_req->be_args,
- lun_req->error_str,
- sizeof(lun_req->error_str));
- if (lun_req->kern_be_args == NULL) {
+
+ if (lun_req->args != NULL) {
+ lun_req->args_nvl = nvlist_unpack(lun_req->args,
+ lun_req->args_len, 0);
+
+ if (lun_req->args_nvl == NULL) {
lun_req->status = CTL_LUN_ERROR;
+ snprintf(lun_req->error_str, sizeof(lun_req->error_str),
+ "Cannot unpack args nvlist.");
break;
}
- }
+ } else
+ lun_req->args_nvl = nvlist_create(0);
retval = backend->ioctl(dev, cmd, addr, flag, td);
+ nvlist_destroy(lun_req->args_nvl);
+ lun_req->args_nvl = tmp_args_nvl;
+
+ if (lun_req->result_nvl != NULL) {
+ if (lun_req->result != NULL) {
+ packed = nvlist_pack(lun_req->result_nvl,
+ &packed_len);
+ if (packed == NULL) {
+ lun_req->status = CTL_LUN_ERROR;
+ snprintf(lun_req->error_str,
+ sizeof(lun_req->error_str),
+ "Cannot pack result nvlist.");
+ break;
+ }
+
+ if (packed_len > lun_req->result_len) {
+ lun_req->status = CTL_LUN_ERROR;
+ snprintf(lun_req->error_str,
+ sizeof(lun_req->error_str),
+ "Result nvlist too large.");
+ free(packed, M_NVLIST);
+ break;
+ }
- if (lun_req->num_be_args > 0) {
- ctl_copyout_args(lun_req->num_be_args,
- lun_req->kern_be_args);
- ctl_free_args(lun_req->num_be_args,
- lun_req->kern_be_args);
+ if (copyout(packed, lun_req->result, packed_len)) {
+ lun_req->status = CTL_LUN_ERROR;
+ snprintf(lun_req->error_str,
+ sizeof(lun_req->error_str),
+ "Cannot copyout() the result.");
+ free(packed, M_NVLIST);
+ break;
+ }
+
+ lun_req->result_len = packed_len;
+ free(packed, M_NVLIST);
+ }
+
+ nvlist_destroy(lun_req->result_nvl);
}
break;
}
case CTL_LUN_LIST: {
struct sbuf *sb;
struct ctl_lun_list *list;
- struct ctl_option *opt;
+ const char *name, *value;
+ void *cookie;
+ int type;
list = (struct ctl_lun_list *)addr;
@@ -3201,11 +3147,20 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (retval != 0)
break;
}
- STAILQ_FOREACH(opt, &lun->be_lun->options, links) {
- retval = sbuf_printf(sb, "\t<%s>%s</%s>\n",
- opt->name, opt->value, opt->name);
- if (retval != 0)
- break;
+
+ cookie = NULL;
+ while ((name = nvlist_next(lun->be_lun->options, &type,
+ &cookie)) != NULL) {
+ sbuf_printf(sb, "\t<%s>", name);
+
+ if (type == NV_TYPE_STRING) {
+ value = dnvlist_get_string(
+ lun->be_lun->options, name, NULL);
+ if (value != NULL)
+ sbuf_printf(sb, "%s", value);
+ }
+
+ sbuf_printf(sb, "</%s>\n", name);
}
retval = sbuf_printf(sb, "</lun>\n");
@@ -3259,8 +3214,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
case CTL_PORT_REQ: {
struct ctl_req *req;
struct ctl_frontend *fe;
+ void *packed;
+ nvlist_t *tmp_args_nvl;
+ size_t packed_len;
req = (struct ctl_req *)addr;
+ tmp_args_nvl = req->args_nvl;
fe = ctl_frontend_find(req->driver);
if (fe == NULL) {
@@ -3269,23 +3228,63 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
"Frontend \"%s\" not found.", req->driver);
break;
}
- if (req->num_args > 0) {
- req->kern_args = ctl_copyin_args(req->num_args,
- req->args, req->error_str, sizeof(req->error_str));
- if (req->kern_args == NULL) {
+
+ if (req->args != NULL) {
+ req->args_nvl = nvlist_unpack(req->args,
+ req->args_len, 0);
+
+ if (req->args_nvl == NULL) {
req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "Cannot unpack args nvlist.");
break;
}
- }
+ } else
+ req->args_nvl = nvlist_create(0);
if (fe->ioctl)
retval = fe->ioctl(dev, cmd, addr, flag, td);
else
retval = ENODEV;
- if (req->num_args > 0) {
- ctl_copyout_args(req->num_args, req->kern_args);
- ctl_free_args(req->num_args, req->kern_args);
+ nvlist_destroy(req->args_nvl);
+ req->args_nvl = tmp_args_nvl;
+
+ if (req->result_nvl != NULL) {
+ if (req->result != NULL) {
+ packed = nvlist_pack(req->result_nvl,
+ &packed_len);
+ if (packed == NULL) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str,
+ sizeof(req->error_str),
+ "Cannot pack result nvlist.");
+ break;
+ }
+
+ if (packed_len > req->result_len) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str,
+ sizeof(req->error_str),
+ "Result nvlist too large.");
+ free(packed, M_NVLIST);
+ break;
+ }
+
+ if (copyout(packed, req->result, packed_len)) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str,
+ sizeof(req->error_str),
+ "Cannot copyout() the result.");
+ free(packed, M_NVLIST);
+ break;
+ }
+
+ req->result_len = packed_len;
+ free(packed, M_NVLIST);
+ }
+
+ nvlist_destroy(req->result_nvl);
}
break;
}
@@ -3293,8 +3292,9 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct sbuf *sb;
struct ctl_port *port;
struct ctl_lun_list *list;
- struct ctl_option *opt;
- int j;
+ const char *name, *value;
+ void *cookie;
+ int j, type;
uint32_t plun;
list = (struct ctl_lun_list *)addr;
@@ -3369,11 +3369,20 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (retval != 0)
break;
}
- STAILQ_FOREACH(opt, &port->options, links) {
- retval = sbuf_printf(sb, "\t<%s>%s</%s>\n",
- opt->name, opt->value, opt->name);
- if (retval != 0)
- break;
+
+ cookie = NULL;
+ while ((name = nvlist_next(port->options, &type,
+ &cookie)) != NULL) {
+ sbuf_printf(sb, "\t<%s>", name);
+
+ if (type == NV_TYPE_STRING) {
+ value = dnvlist_get_string(port->options,
+ name, NULL);
+ if (value != NULL)
+ sbuf_printf(sb, "%s", value);
+ }
+
+ sbuf_printf(sb, "</%s>\n", name);
}
if (port->lun_map != NULL) {
@@ -4180,8 +4189,8 @@ ctl_init_page_index(struct ctl_lun *lun)
CTL_PAGE_DEFAULT];
scsi_ulto3b(cylinders, rigid_disk_page->cylinders);
- if ((value = ctl_get_opt(&lun->be_lun->options,
- "rpm")) != NULL) {
+ if ((value = dnvlist_get_string(lun->be_lun->options,
+ "rpm", NULL)) != NULL) {
scsi_ulto2b(strtol(value, NULL, 0),
rigid_disk_page->rotation_rate);
}
@@ -4234,10 +4243,12 @@ ctl_init_page_index(struct ctl_lun *lun)
sizeof(caching_page_default));
caching_page = &lun->mode_pages.caching_page[
CTL_PAGE_SAVED];
- value = ctl_get_opt(&lun->be_lun->options, "writecache");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "writecache", NULL);
if (value != NULL && strcmp(value, "off") == 0)
caching_page->flags1 &= ~SCP_WCE;
- value = ctl_get_opt(&lun->be_lun->options, "readcache");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "readcache", NULL);
if (value != NULL && strcmp(value, "off") == 0)
caching_page->flags1 |= SCP_RCD;
memcpy(&lun->mode_pages.caching_page[CTL_PAGE_CURRENT],
@@ -4266,8 +4277,8 @@ ctl_init_page_index(struct ctl_lun *lun)
sizeof(control_page_default));
control_page = &lun->mode_pages.control_page[
CTL_PAGE_SAVED];
- value = ctl_get_opt(&lun->be_lun->options,
- "reordering");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "reordering", NULL);
if (value != NULL &&
strcmp(value, "unrestricted") == 0) {
control_page->queue_flags &=
@@ -4342,8 +4353,8 @@ ctl_init_page_index(struct ctl_lun *lun)
&lbp_page_default,
sizeof(lbp_page_default));
page = &lun->mode_pages.lbp_page[CTL_PAGE_SAVED];
- value = ctl_get_opt(&lun->be_lun->options,
- "avail-threshold");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "avail-threshold", NULL);
if (value != NULL &&
ctl_expand_number(value, &ival) == 0) {
page->descr[0].flags |= SLBPPD_ENABLED |
@@ -4355,8 +4366,8 @@ ctl_init_page_index(struct ctl_lun *lun)
scsi_ulto4b(ival >> CTL_LBP_EXPONENT,
page->descr[0].count);
}
- value = ctl_get_opt(&lun->be_lun->options,
- "used-threshold");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "used-threshold", NULL);
if (value != NULL &&
ctl_expand_number(value, &ival) == 0) {
page->descr[1].flags |= SLBPPD_ENABLED |
@@ -4368,8 +4379,8 @@ ctl_init_page_index(struct ctl_lun *lun)
scsi_ulto4b(ival >> CTL_LBP_EXPONENT,
page->descr[1].count);
}
- value = ctl_get_opt(&lun->be_lun->options,
- "pool-avail-threshold");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "pool-avail-threshold", NULL);
if (value != NULL &&
ctl_expand_number(value, &ival) == 0) {
page->descr[2].flags |= SLBPPD_ENABLED |
@@ -4381,8 +4392,8 @@ ctl_init_page_index(struct ctl_lun *lun)
scsi_ulto4b(ival >> CTL_LBP_EXPONENT,
page->descr[2].count);
}
- value = ctl_get_opt(&lun->be_lun->options,
- "pool-used-threshold");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "pool-used-threshold", NULL);
if (value != NULL &&
ctl_expand_number(value, &ival) == 0) {
page->descr[3].flags |= SLBPPD_ENABLED |
@@ -4581,20 +4592,20 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
strnlen(be_lun->device_id, CTL_DEVID_LEN));
idlen1 = sizeof(*t10id) + devidlen;
len = sizeof(struct scsi_vpd_id_descriptor) + idlen1;
- scsiname = ctl_get_opt(&be_lun->options, "scsiname");
+ scsiname = dnvlist_get_string(be_lun->options, "scsiname", NULL);
if (scsiname != NULL) {
idlen2 = roundup2(strlen(scsiname) + 1, 4);
len += sizeof(struct scsi_vpd_id_descriptor) + idlen2;
}
- eui = ctl_get_opt(&be_lun->options, "eui");
+ eui = dnvlist_get_string(be_lun->options, "eui", NULL);
if (eui != NULL) {
len += sizeof(struct scsi_vpd_id_descriptor) + 16;
}
- naa = ctl_get_opt(&be_lun->options, "naa");
+ naa = dnvlist_get_string(be_lun->options, "naa", NULL);
if (naa != NULL) {
len += sizeof(struct scsi_vpd_id_descriptor) + 16;
}
- uuid = ctl_get_opt(&be_lun->options, "uuid");
+ uuid = dnvlist_get_string(be_lun->options, "uuid", NULL);
if (uuid != NULL) {
len += sizeof(struct scsi_vpd_id_descriptor) + 18;
}
@@ -4606,7 +4617,7 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
desc->length = idlen1;
t10id = (struct scsi_vpd_id_t10 *)&desc->identifier[0];
memset(t10id->vendor, ' ', sizeof(t10id->vendor));
- if ((vendor = ctl_get_opt(&be_lun->options, "vendor")) == NULL) {
+ if ((vendor = dnvlist_get_string(be_lun->options, "vendor", NULL)) == NULL) {
strncpy((char *)t10id->vendor, CTL_VENDOR, sizeof(t10id->vendor));
} else {
strncpy(t10id->vendor, vendor,
@@ -4719,7 +4730,7 @@ fail:
if (be_lun->flags & CTL_LUN_FLAG_PRIMARY)
lun->flags |= CTL_LUN_PRIMARY_SC;
- value = ctl_get_opt(&be_lun->options, "removable");
+ value = dnvlist_get_string(be_lun->options, "removable", NULL);
if (value != NULL) {
if (strcmp(value, "on") == 0)
lun->flags |= CTL_LUN_REMOVABLE;
@@ -9772,6 +9783,7 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
{
struct ctl_lun *lun = CTL_LUN(ctsio);
struct scsi_vpd_block_limits *bl_ptr;
+ const char *val;
uint64_t ival;
ctsio->kern_data_ptr = malloc(sizeof(*bl_ptr), M_CTL, M_WAITOK | M_ZERO);
@@ -9801,12 +9813,16 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
scsi_ulto4b(lun->be_lun->opttxferlen, bl_ptr->opt_txfer_len);
if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
ival = 0xffffffff;
- ctl_get_opt_number(&lun->be_lun->options,
- "unmap_max_lba", &ival);
+ val = dnvlist_get_string(lun->be_lun->options,
+ "unmap_max_lba", NULL);
+ if (val != NULL)
+ ctl_expand_number(val, &ival);
scsi_ulto4b(ival, bl_ptr->max_unmap_lba_cnt);
ival = 0xffffffff;
- ctl_get_opt_number(&lun->be_lun->options,
- "unmap_max_descr", &ival);
+ val = dnvlist_get_string(lun->be_lun->options,
+ "unmap_max_descr", NULL);
+ if (val != NULL)
+ ctl_expand_number(val, &ival);
scsi_ulto4b(ival, bl_ptr->max_unmap_blk_cnt);
if (lun->be_lun->ublockexp != 0) {
scsi_ulto4b((1 << lun->be_lun->ublockexp),
@@ -9822,7 +9838,10 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
scsi_ulto4b(0, bl_ptr->max_atomic_transfer_length_with_atomic_boundary);
scsi_ulto4b(0, bl_ptr->max_atomic_boundary_size);
ival = UINT64_MAX;
- ctl_get_opt_number(&lun->be_lun->options, "write_same_max_lba", &ival);
+ val = dnvlist_get_string(lun->be_lun->options,
+ "write_same_max_lba", NULL);
+ if (val != NULL)
+ ctl_expand_number(val, &ival);
scsi_u64to8b(ival, bl_ptr->max_write_same_length);
}
@@ -9861,13 +9880,13 @@ ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len)
bdc_ptr->page_code = SVPD_BDC;
scsi_ulto2b(sizeof(*bdc_ptr) - 4, bdc_ptr->page_length);
if (lun != NULL &&
- (value = ctl_get_opt(&lun->be_lun->options, "rpm")) != NULL)
+ (value = dnvlist_get_string(lun->be_lun->options, "rpm", NULL)) != NULL)
i = strtol(value, NULL, 0);
else
i = CTL_DEFAULT_ROTATION_RATE;
scsi_ulto2b(i, bdc_ptr->medium_rotation_rate);
if (lun != NULL &&
- (value = ctl_get_opt(&lun->be_lun->options, "formfactor")) != NULL)
+ (value = dnvlist_get_string(lun->be_lun->options, "formfactor", NULL)) != NULL)
i = strtol(value, NULL, 0);
else
i = 0;
@@ -9912,7 +9931,8 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
if (lun != NULL && lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
lbp_ptr->flags = SVPD_LBP_UNMAP | SVPD_LBP_WS16 |
SVPD_LBP_WS10 | SVPD_LBP_RZ | SVPD_LBP_ANC_SUP;
- value = ctl_get_opt(&lun->be_lun->options, "provisioning_type");
+ value = dnvlist_get_string(lun->be_lun->options,
+ "provisioning_type", NULL);
if (value != NULL) {
if (strcmp(value, "resource") == 0)
lbp_ptr->prov_type = SVPD_LBP_RESOURCE;
@@ -10006,7 +10026,7 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
struct ctl_lun *lun = CTL_LUN(ctsio);
struct scsi_inquiry_data *inq_ptr;
struct scsi_inquiry *cdb;
- char *val;
+ const char *val;
uint32_t alloc_len, data_len;
ctl_port_type port_type;
@@ -10084,8 +10104,8 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
* We have 8 bytes for the vendor name, and 16 bytes for the device
* name and 4 bytes for the revision.
*/
- if (lun == NULL || (val = ctl_get_opt(&lun->be_lun->options,
- "vendor")) == NULL) {
+ if (lun == NULL || (val = dnvlist_get_string(lun->be_lun->options,
+ "vendor", NULL)) == NULL) {
strncpy(inq_ptr->vendor, CTL_VENDOR, sizeof(inq_ptr->vendor));
} else {
memset(inq_ptr->vendor, ' ', sizeof(inq_ptr->vendor));
@@ -10095,7 +10115,8 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
if (lun == NULL) {
strncpy(inq_ptr->product, CTL_DIRECT_PRODUCT,
sizeof(inq_ptr->product));
- } else if ((val = ctl_get_opt(&lun->be_lun->options, "product")) == NULL) {
+ } else if ((val = dnvlist_get_string(lun->be_lun->options, "product",
+ NULL)) == NULL) {
switch (lun->be_lun->lun_type) {
case T_DIRECT:
strncpy(inq_ptr->product, CTL_DIRECT_PRODUCT,
@@ -10124,8 +10145,8 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
* XXX make this a macro somewhere so it automatically gets
* incremented when we make changes.
*/
- if (lun == NULL || (val = ctl_get_opt(&lun->be_lun->options,
- "revision")) == NULL) {
+ if (lun == NULL || (val = dnvlist_get_string(lun->be_lun->options,
+ "revision", NULL)) == NULL) {
strncpy(inq_ptr->revision, "0001", sizeof(inq_ptr->revision));
} else {
memset(inq_ptr->revision, ' ', sizeof(inq_ptr->revision));
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index 05f62e75c862..9f8fd32e72f1 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -196,24 +196,6 @@ void ctl_isc_announce_iid(struct ctl_port *port, int iid);
void ctl_isc_announce_mode(struct ctl_lun *lun, uint32_t initidx,
uint8_t page, uint8_t subpage);
-/*
- * KPI to manipulate LUN/port options
- */
-
-struct ctl_option {
- STAILQ_ENTRY(ctl_option) links;
- char *name;
- char *value;
-};
-typedef STAILQ_HEAD(ctl_options, ctl_option) ctl_options_t;
-
-struct ctl_be_arg;
-void ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args);
-void ctl_update_opts(ctl_options_t *opts, int num_args,
- struct ctl_be_arg *args);
-void ctl_free_opts(ctl_options_t *opts);
-char * ctl_get_opt(ctl_options_t *opts, const char *name);
-int ctl_get_opt_number(ctl_options_t *opts, const char *name, uint64_t *num);
int ctl_expand_number(const char *buf, uint64_t *num);
#endif /* _KERNEL */
diff --git a/sys/cam/ctl/ctl_backend.c b/sys/cam/ctl/ctl_backend.c
index 9918ce404d58..0a0645556636 100644
--- a/sys/cam/ctl/ctl_backend.c
+++ b/sys/cam/ctl/ctl_backend.c
@@ -141,93 +141,3 @@ ctl_backend_find(char *backend_name)
return (NULL);
}
-void
-ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
-{
- struct ctl_option *opt;
- int i;
-
- STAILQ_INIT(opts);
- for (i = 0; i < num_args; i++) {
- if ((args[i].flags & CTL_BEARG_RD) == 0)
- continue;
- if ((args[i].flags & CTL_BEARG_ASCII) == 0)
- continue;
- opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
- opt->name = strdup(args[i].kname, M_CTL);
- opt->value = strdup(args[i].kvalue, M_CTL);
- STAILQ_INSERT_TAIL(opts, opt, links);
- }
-}
-
-void
-ctl_update_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
-{
- struct ctl_option *opt;
- int i;
-
- for (i = 0; i < num_args; i++) {
- if ((args[i].flags & CTL_BEARG_RD) == 0)
- continue;
- if ((args[i].flags & CTL_BEARG_ASCII) == 0)
- continue;
- STAILQ_FOREACH(opt, opts, links) {
- if (strcmp(opt->name, args[i].kname) == 0)
- break;
- }
- if (args[i].kvalue != NULL &&
- ((char *)args[i].kvalue)[0] != 0) {
- if (opt) {
- free(opt->value, M_CTL);
- opt->value = strdup(args[i].kvalue, M_CTL);
- } else {
- opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
- opt->name = strdup(args[i].kname, M_CTL);
- opt->value = strdup(args[i].kvalue, M_CTL);
- STAILQ_INSERT_TAIL(opts, opt, links);
- }
- } else if (opt) {
- STAILQ_REMOVE(opts, opt, ctl_option, links);
- free(opt->name, M_CTL);
- free(opt->value, M_CTL);
- free(opt, M_CTL);
- }
- }
-}
-
-void
-ctl_free_opts(ctl_options_t *opts)
-{
- struct ctl_option *opt;
-
- while ((opt = STAILQ_FIRST(opts)) != NULL) {
- STAILQ_REMOVE_HEAD(opts, links);
- free(opt->name, M_CTL);
- free(opt->value, M_CTL);
- free(opt, M_CTL);
- }
-}
-
-char *
-ctl_get_opt(ctl_options_t *opts, const char *name)
-{
- struct ctl_option *opt;
-
- STAILQ_FOREACH(opt, opts, links) {
- if (strcmp(opt->name, name) == 0) {
- return (opt->value);
- }
- }
- return (NULL);
-}
-
-int
-ctl_get_opt_number(ctl_options_t *opts, const char *name, uint64_t *val)
-{
- const char *value;
-
- value = ctl_get_opt(opts, name);
- if (value == NULL)
- return (-2);
- return (ctl_expand_number(value, val));
-}
diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h
index a330497a604f..587bb70a8b81 100644
--- a/sys/cam/ctl/ctl_backend.h
+++ b/sys/cam/ctl/ctl_backend.h
@@ -43,6 +43,7 @@
#define _CTL_BACKEND_H_
#include <cam/ctl/ctl_ioctl.h>
+#include <sys/nv.h>
typedef enum {
CTL_LUN_SERSEQ_OFF,
@@ -175,7 +176,7 @@ struct ctl_be_lun {
be_lun_config_t lun_config_status; /* passed to CTL */
struct ctl_backend_driver *be; /* passed to CTL */
void *ctl_lun; /* used by CTL */
- ctl_options_t options; /* passed to CTL */
+ nvlist_t *options; /* passed to CTL */
STAILQ_ENTRY(ctl_be_lun) links; /* used by CTL */
};
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index b415424d2a07..a0cb085e0ca2 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -78,6 +78,8 @@ __FBSDID("$FreeBSD$");
#include <sys/sdt.h>
#include <sys/devicestat.h>
#include <sys/sysctl.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <geom/geom.h>
@@ -1817,7 +1819,7 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
struct ctl_be_lun *cbe_lun;
struct ctl_be_block_filedata *file_data;
struct ctl_lun_create_params *params;
- char *value;
+ const char *value;
struct vattr vattr;
off_t ps, pss, po, pos, us, uss, uo, uos;
int error;
@@ -1867,10 +1869,10 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
us = ps = vattr.va_blocksize;
uo = po = 0;
- value = ctl_get_opt(&cbe_lun->options, "pblocksize");
+ value = dnvlist_get_string(cbe_lun->options, "pblocksize", NULL);
if (value != NULL)
ctl_expand_number(value, &ps);
- value = ctl_get_opt(&cbe_lun->options, "pblockoffset");
+ value = dnvlist_get_string(cbe_lun->options, "pblockoffset", NULL);
if (value != NULL)
ctl_expand_number(value, &po);
pss = ps / cbe_lun->blocksize;
@@ -1881,10 +1883,10 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
cbe_lun->pblockoff = (pss - pos) % pss;
}
- value = ctl_get_opt(&cbe_lun->options, "ublocksize");
+ value = dnvlist_get_string(cbe_lun->options, "ublocksize", NULL);
if (value != NULL)
ctl_expand_number(value, &us);
- value = ctl_get_opt(&cbe_lun->options, "ublockoffset");
+ value = dnvlist_get_string(cbe_lun->options, "ublockoffset", NULL);
if (value != NULL)
ctl_expand_number(value, &uo);
uss = us / cbe_lun->blocksize;
@@ -1917,7 +1919,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
struct ctl_lun_create_params *params;
struct cdevsw *csw;
struct cdev *dev;
- char *value;
+ const char *value;
int error, atomic, maxio, ref, unmap, tmp;
off_t ps, pss, po, pos, us, uss, uo, uos, otmp;
@@ -2033,10 +2035,10 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
us = ps;
uo = po;
- value = ctl_get_opt(&cbe_lun->options, "pblocksize");
+ value = dnvlist_get_string(cbe_lun->options, "pblocksize", NULL);
if (value != NULL)
ctl_expand_number(value, &ps);
- value = ctl_get_opt(&cbe_lun->options, "pblockoffset");
+ value = dnvlist_get_string(cbe_lun->options, "pblockoffset", NULL);
if (value != NULL)
ctl_expand_number(value, &po);
pss = ps / cbe_lun->blocksize;
@@ -2047,10 +2049,10 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
cbe_lun->pblockoff = (pss - pos) % pss;
}
- value = ctl_get_opt(&cbe_lun->options, "ublocksize");
+ value = dnvlist_get_string(cbe_lun->options, "ublocksize", NULL);
if (value != NULL)
ctl_expand_number(value, &us);
- value = ctl_get_opt(&cbe_lun->options, "ublockoffset");
+ value = dnvlist_get_string(cbe_lun->options, "ublockoffset", NULL);
if (value != NULL)
ctl_expand_number(value, &uo);
uss = us / cbe_lun->blocksize;
@@ -2075,7 +2077,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
curthread);
unmap = (error == 0) ? arg.value.i : 0;
}
- value = ctl_get_opt(&cbe_lun->options, "unmap");
+ value = dnvlist_get_string(cbe_lun->options, "unmap", NULL);
if (value != NULL)
unmap = (strcmp(value, "on") == 0);
if (unmap)
@@ -2125,7 +2127,7 @@ ctl_be_block_open(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
{
struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
struct nameidata nd;
- char *value;
+ const char *value;
int error, flags;
error = 0;
@@ -2136,7 +2138,7 @@ ctl_be_block_open(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
}
pwd_ensure_dirs();
- value = ctl_get_opt(&cbe_lun->options, "file");
+ value = dnvlist_get_string(cbe_lun->options, "file", NULL);
if (value == NULL) {
snprintf(req->error_str, sizeof(req->error_str),
"no file argument specified");
@@ -2146,7 +2148,7 @@ ctl_be_block_open(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
be_lun->dev_path = strdup(value, M_CTLBLK);
flags = FREAD;
- value = ctl_get_opt(&cbe_lun->options, "readonly");
+ value = dnvlist_get_string(cbe_lun->options, "readonly", NULL);
if (value != NULL) {
if (strcmp(value, "on") != 0)
flags |= FWRITE;
@@ -2205,7 +2207,7 @@ again:
cbe_lun->serseq = CTL_LUN_SERSEQ_OFF;
if (be_lun->dispatch != ctl_be_block_dispatch_dev)
cbe_lun->serseq = CTL_LUN_SERSEQ_READ;
- value = ctl_get_opt(&cbe_lun->options, "serseq");
+ value = dnvlist_get_string(cbe_lun->options, "serseq", NULL);
if (value != NULL && strcmp(value, "on") == 0)
cbe_lun->serseq = CTL_LUN_SERSEQ_ON;
else if (value != NULL && strcmp(value, "read") == 0)
@@ -2223,7 +2225,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
struct ctl_lun_create_params *params;
char num_thread_str[16];
char tmpstr[32];
- char *value;
+ const char *value;
int retval, num_threads;
int tmp_num_threads;
@@ -2243,8 +2245,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
mtx_init(&be_lun->io_lock, "cblk io lock", NULL, MTX_DEF);
mtx_init(&be_lun->queue_lock, "cblk queue lock", NULL, MTX_DEF);
- ctl_init_opts(&cbe_lun->options,
- req->num_be_args, req->kern_be_args);
+ cbe_lun->options = nvlist_clone(req->args_nvl);
be_lun->lun_zone = uma_zcreate(be_lun->lunname, CTLBLK_MAX_SEG,
NULL, NULL, NULL, NULL, /*align*/ 0, /*flags*/0);
if (be_lun->lun_zone == NULL) {
@@ -2259,7 +2260,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
cbe_lun->lun_type = T_DIRECT;
be_lun->flags = CTL_BE_BLOCK_LUN_UNCONFIGURED;
cbe_lun->flags = 0;
- value = ctl_get_opt(&cbe_lun->options, "ha_role");
+ value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
if (value != NULL) {
if (strcmp(value, "primary") == 0)
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
@@ -2292,7 +2293,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
num_threads = 1;
}
- value = ctl_get_opt(&cbe_lun->options, "num_threads");
+ value = dnvlist_get_string(cbe_lun->options, "num_threads", NULL);
if (value != NULL) {
tmp_num_threads = strtol(value, NULL, 0);
@@ -2457,7 +2458,7 @@ bailout_error:
free(be_lun->dev_path, M_CTLBLK);
if (be_lun->lun_zone != NULL)
uma_zdestroy(be_lun->lun_zone);
- ctl_free_opts(&cbe_lun->options);
+ nvlist_destroy(cbe_lun->options);
mtx_destroy(&be_lun->queue_lock);
mtx_destroy(&be_lun->io_lock);
free(be_lun, M_CTLBLK);
@@ -2541,7 +2542,7 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
uma_zdestroy(be_lun->lun_zone);
- ctl_free_opts(&cbe_lun->options);
+ nvlist_destroy(cbe_lun->options);
free(be_lun->dev_path, M_CTLBLK);
mtx_destroy(&be_lun->queue_lock);
mtx_destroy(&be_lun->io_lock);
@@ -2561,7 +2562,7 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
struct ctl_lun_modify_params *params;
struct ctl_be_block_lun *be_lun;
struct ctl_be_lun *cbe_lun;
- char *value;
+ const char *value;
uint64_t oldsize;
int error, wasprim;
@@ -2583,10 +2584,12 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
if (params->lun_size_bytes != 0)
be_lun->params.lun_size_bytes = params->lun_size_bytes;
- ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
+
+ nvlist_destroy(cbe_lun->options);
+ cbe_lun->options = nvlist_clone(req->args_nvl);
wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY);
- value = ctl_get_opt(&cbe_lun->options, "ha_role");
+ value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
if (value != NULL) {
if (strcmp(value, "primary") == 0)
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c
index 9a29a0ff9315..e7ac5ec53f69 100644
--- a/sys/cam/ctl/ctl_backend_ramdisk.c
+++ b/sys/cam/ctl/ctl_backend_ramdisk.c
@@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$");
#include <sys/ioccom.h>
#include <sys/module.h>
#include <sys/sysctl.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_da.h>
@@ -956,7 +958,7 @@ ctl_backend_ramdisk_rm(struct ctl_be_ramdisk_softc *softc,
if (retval == 0) {
taskqueue_drain_all(be_lun->io_taskqueue);
taskqueue_free(be_lun->io_taskqueue);
- ctl_free_opts(&be_lun->cbe_lun.options);
+ nvlist_destroy(be_lun->cbe_lun.options);
free(be_lun->zero_page, M_RAMDISK);
ctl_backend_ramdisk_freeallpages(be_lun->pages, be_lun->indir);
sx_destroy(&be_lun->page_lock);
@@ -979,7 +981,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
struct ctl_be_ramdisk_lun *be_lun;
struct ctl_be_lun *cbe_lun;
struct ctl_lun_create_params *params;
- char *value;
+ const char *value;
char tmpstr[32];
uint64_t t;
int retval;
@@ -990,10 +992,10 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
be_lun = malloc(sizeof(*be_lun), M_RAMDISK, M_ZERO | M_WAITOK);
cbe_lun = &be_lun->cbe_lun;
cbe_lun->be_lun = be_lun;
+ cbe_lun->options = nvlist_clone(req->args_nvl);
be_lun->params = req->reqdata.create;
be_lun->softc = softc;
sprintf(be_lun->lunname, "cram%d", softc->num_luns);
- ctl_init_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
if (params->flags & CTL_LUN_FLAG_DEV_TYPE)
cbe_lun->lun_type = params->device_type;
@@ -1001,7 +1003,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
cbe_lun->lun_type = T_DIRECT;
be_lun->flags = CTL_BE_RAMDISK_LUN_UNCONFIGURED;
cbe_lun->flags = 0;
- value = ctl_get_opt(&cbe_lun->options, "ha_role");
+ value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
if (value != NULL) {
if (strcmp(value, "primary") == 0)
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
@@ -1009,7 +1011,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
be_lun->pblocksize = PAGE_SIZE;
- value = ctl_get_opt(&cbe_lun->options, "pblocksize");
+ value = dnvlist_get_string(cbe_lun->options, "pblocksize", NULL);
if (value != NULL) {
ctl_expand_number(value, &t);
be_lun->pblocksize = t;
@@ -1058,7 +1060,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
cbe_lun->ublockoff = 0;
cbe_lun->atomicblock = be_lun->pblocksize;
cbe_lun->opttxferlen = SGPP * be_lun->pblocksize;
- value = ctl_get_opt(&cbe_lun->options, "capacity");
+ value = dnvlist_get_string(cbe_lun->options, "capacity", NULL);
if (value != NULL)
ctl_expand_number(value, &be_lun->cap_bytes);
} else {
@@ -1070,17 +1072,17 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
params->blocksize_bytes = cbe_lun->blocksize;
params->lun_size_bytes = be_lun->size_bytes;
- value = ctl_get_opt(&cbe_lun->options, "unmap");
- if (value == NULL || strcmp(value, "off") != 0)
+ value = dnvlist_get_string(cbe_lun->options, "unmap", NULL);
+ if (value != NULL && strcmp(value, "off") != 0)
cbe_lun->flags |= CTL_LUN_FLAG_UNMAP;
- value = ctl_get_opt(&cbe_lun->options, "readonly");
+ value = dnvlist_get_string(cbe_lun->options, "readonly", NULL);
if (value != NULL) {
if (strcmp(value, "on") == 0)
cbe_lun->flags |= CTL_LUN_FLAG_READONLY;
} else if (cbe_lun->lun_type != T_DIRECT)
cbe_lun->flags |= CTL_LUN_FLAG_READONLY;
cbe_lun->serseq = CTL_LUN_SERSEQ_OFF;
- value = ctl_get_opt(&cbe_lun->options, "serseq");
+ value = dnvlist_get_string(cbe_lun->options, "serseq", NULL);
if (value != NULL && strcmp(value, "on") == 0)
cbe_lun->serseq = CTL_LUN_SERSEQ_ON;
else if (value != NULL && strcmp(value, "read") == 0)
@@ -1209,7 +1211,7 @@ bailout_error:
if (be_lun != NULL) {
if (be_lun->io_taskqueue != NULL)
taskqueue_free(be_lun->io_taskqueue);
- ctl_free_opts(&cbe_lun->options);
+ nvlist_destroy(cbe_lun->options);
free(be_lun->zero_page, M_RAMDISK);
ctl_backend_ramdisk_freeallpages(be_lun->pages, be_lun->indir);
sx_destroy(&be_lun->page_lock);
@@ -1226,7 +1228,7 @@ ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc,
struct ctl_be_ramdisk_lun *be_lun;
struct ctl_be_lun *cbe_lun;
struct ctl_lun_modify_params *params;
- char *value;
+ const char *value;
uint32_t blocksize;
int wasprim;
@@ -1248,10 +1250,12 @@ ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc,
if (params->lun_size_bytes != 0)
be_lun->params.lun_size_bytes = params->lun_size_bytes;
- ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
+
+ nvlist_destroy(cbe_lun->options);
+ cbe_lun->options = nvlist_clone(req->args_nvl);
wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY);
- value = ctl_get_opt(&cbe_lun->options, "ha_role");
+ value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
if (value != NULL) {
if (strcmp(value, "primary") == 0)
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c
index 9a206d0c1423..d481c1b8f003 100644
--- a/sys/cam/ctl/ctl_frontend.c
+++ b/sys/cam/ctl/ctl_frontend.c
@@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_da.h>
@@ -200,8 +202,8 @@ error:
}
port->targ_port = port_num;
port->ctl_pool_ref = pool;
- if (port->options.stqh_first == NULL)
- STAILQ_INIT(&port->options);
+ if (port->options == NULL)
+ port->options = nvlist_create(0);
port->stats.item = port_num;
mtx_init(&port->port_lock, "CTL port", NULL, MTX_DEF);
@@ -240,7 +242,7 @@ ctl_port_deregister(struct ctl_port *port)
mtx_unlock(&softc->ctl_lock);
ctl_pool_free(pool);
- ctl_free_opts(&port->options);
+ nvlist_destroy(port->options);
ctl_lun_map_deinit(port);
free(port->port_devid, M_CTL);
@@ -333,7 +335,7 @@ ctl_port_online(struct ctl_port *port)
port->port_online(port->onoff_arg);
mtx_lock(&softc->ctl_lock);
if (softc->is_single == 0) {
- value = ctl_get_opt(&port->options, "ha_shared");
+ value = dnvlist_get_string(port->options, "ha_shared", NULL);
if (value != NULL && strcmp(value, "on") == 0)
port->status |= CTL_PORT_STATUS_HA_SHARED;
else
diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h
index 22980d555d11..bdcb7a2e1abd 100644
--- a/sys/cam/ctl/ctl_frontend.h
+++ b/sys/cam/ctl/ctl_frontend.h
@@ -43,6 +43,7 @@
#define _CTL_FRONTEND_H_
#include <cam/ctl/ctl_ioctl.h>
+#include <sys/nv.h>
typedef enum {
CTL_PORT_STATUS_NONE = 0x00,
@@ -237,7 +238,7 @@ struct ctl_port {
uint64_t wwnn; /* set by CTL before online */
uint64_t wwpn; /* set by CTL before online */
ctl_port_status status; /* used by CTL */
- ctl_options_t options; /* passed to CTL */
+ nvlist_t *options; /* passed to CTL */
struct ctl_devid *port_devid; /* passed to CTL */
struct ctl_devid *target_devid; /* passed to CTL */
struct ctl_devid *init_devid; /* passed to CTL */
diff --git a/sys/cam/ctl/ctl_frontend_ioctl.c b/sys/cam/ctl/ctl_frontend_ioctl.c
index 63a9504016ef..221d912714b7 100644
--- a/sys/cam/ctl/ctl_frontend_ioctl.c
+++ b/sys/cam/ctl/ctl_frontend_ioctl.c
@@ -1,7 +1,10 @@
/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
* Copyright (c) 2003-2009 Silicon Graphics International Corp.
* Copyright (c) 2012 The FreeBSD Foundation
* Copyright (c) 2015 Alexander Motin <mav@FreeBSD.org>
+ * Copyright (c) 2017 Jakub Wojciech Klama <jceel@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +44,8 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <cam/cam.h>
#include <cam/scsi/scsi_all.h>
@@ -68,22 +73,41 @@ struct ctl_fe_ioctl_params {
ctl_fe_ioctl_state state;
};
-struct cfi_softc {
+struct cfi_port {
+ TAILQ_ENTRY(cfi_port) link;
uint32_t cur_tag_num;
+ struct cdev * dev;
struct ctl_port port;
};
+struct cfi_softc {
+ TAILQ_HEAD(, cfi_port) ports;
+};
+
+
static struct cfi_softc cfi_softc;
+
static int cfi_init(void);
static int cfi_shutdown(void);
static void cfi_datamove(union ctl_io *io);
static void cfi_done(union ctl_io *io);
+static int cfi_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
+ struct thread *td);
+static void cfi_ioctl_port_create(struct ctl_req *req);
+static void cfi_ioctl_port_remove(struct ctl_req *req);
+
+static struct cdevsw cfi_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = 0,
+ .d_ioctl = ctl_ioctl_io
+};
static struct ctl_frontend cfi_frontend =
{
.name = "ioctl",
.init = cfi_init,
+ .ioctl = cfi_ioctl,
.shutdown = cfi_shutdown,
};
CTL_FRONTEND_DECLARE(ctlioctl, cfi_frontend);
@@ -92,26 +116,31 @@ static int
cfi_init(void)
{
struct cfi_softc *isoftc = &cfi_softc;
+ struct cfi_port *cfi;
struct ctl_port *port;
int error = 0;
memset(isoftc, 0, sizeof(*isoftc));
+ TAILQ_INIT(&isoftc->ports);
- port = &isoftc->port;
+ cfi = malloc(sizeof(*cfi), M_CTL, M_WAITOK | M_ZERO);
+ port = &cfi->port;
port->frontend = &cfi_frontend;
port->port_type = CTL_PORT_IOCTL;
port->num_requested_ctl_io = 100;
port->port_name = "ioctl";
port->fe_datamove = cfi_datamove;
port->fe_done = cfi_done;
+ port->physical_port = 0;
port->targ_port = -1;
- port->max_initiators = 1;
if ((error = ctl_port_register(port)) != 0) {
printf("%s: ioctl port registration failed\n", __func__);
return (error);
}
+
ctl_port_online(port);
+ TAILQ_INSERT_TAIL(&isoftc->ports, cfi, link);
return (0);
}
@@ -119,13 +148,185 @@ static int
cfi_shutdown(void)
{
struct cfi_softc *isoftc = &cfi_softc;
- struct ctl_port *port = &isoftc->port;
- int error = 0;
+ struct cfi_port *cfi, *temp;
+ struct ctl_port *port;
+ int error;
+
+ TAILQ_FOREACH_SAFE(cfi, &isoftc->ports, link, temp) {
+ port = &cfi->port;
+ ctl_port_offline(port);
+ error = ctl_port_deregister(port);
+ if (error != 0) {
+ printf("%s: ctl_frontend_deregister() failed\n",
+ __func__);
+ return (error);
+ }
- ctl_port_offline(port);
- if ((error = ctl_port_deregister(port)) != 0)
- printf("%s: ioctl port deregistration failed\n", __func__);
- return (error);
+ TAILQ_REMOVE(&isoftc->ports, cfi, link);
+ free(cfi, M_CTL);
+ }
+
+ return (0);
+}
+
+static void
+cfi_ioctl_port_create(struct ctl_req *req)
+{
+ struct cfi_softc *isoftc = &cfi_softc;
+ struct cfi_port *cfi;
+ struct ctl_port *port;
+ struct make_dev_args args;
+ const char *val;
+ int retval;
+ int pp = -1, vp = 0;
+
+ val = dnvlist_get_string(req->args_nvl, "pp", NULL);
+ if (val != NULL)
+ pp = strtol(val, NULL, 10);
+
+ val = dnvlist_get_string(req->args_nvl, "vp", NULL);
+ if (val != NULL)
+ vp = strtol(val, NULL, 10);
+
+ if (pp != -1) {
+ /* Check for duplicates */
+ TAILQ_FOREACH(cfi, &isoftc->ports, link) {
+ if (pp == cfi->port.physical_port &&
+ vp == cfi->port.virtual_port) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "port %d already exists", pp);
+
+ return;
+ }
+ }
+ } else {
+ /* Find free port number */
+ TAILQ_FOREACH(cfi, &isoftc->ports, link) {
+ pp = MAX(pp, cfi->port.physical_port);
+ }
+
+ pp++;
+ }
+
+ cfi = malloc(sizeof(*cfi), M_CTL, M_WAITOK | M_ZERO);
+ port = &cfi->port;
+ port->frontend = &cfi_frontend;
+ port->port_type = CTL_PORT_IOCTL;
+ port->num_requested_ctl_io = 100;
+ port->port_name = "ioctl";
+ port->fe_datamove = cfi_datamove;
+ port->fe_done = cfi_done;
+ port->physical_port = pp;
+ port->virtual_port = vp;
+ port->targ_port = -1;
+
+ retval = ctl_port_register(port);
+ if (retval != 0) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "ctl_port_register() failed with error %d", retval);
+ free(port, M_CTL);
+ return;
+ }
+
+ req->result_nvl = nvlist_create(0);
+ nvlist_add_number(req->result_nvl, "port_id", port->targ_port);
+ ctl_port_online(port);
+
+ make_dev_args_init(&args);
+ args.mda_devsw = &cfi_cdevsw;
+ args.mda_uid = UID_ROOT;
+ args.mda_gid = GID_OPERATOR;
+ args.mda_mode = 0600;
+ args.mda_si_drv1 = NULL;
+ args.mda_si_drv2 = cfi;
+
+ retval = make_dev_s(&args, &cfi->dev, "cam/ctl%d.%d", pp, vp);
+ if (retval != 0) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "make_dev_s() failed with error %d", retval);
+ free(port, M_CTL);
+ return;
+ }
+
+ req->status = CTL_LUN_OK;
+ TAILQ_INSERT_TAIL(&isoftc->ports, cfi, link);
+}
+
+static void
+cfi_ioctl_port_remove(struct ctl_req *req)
+{
+ struct cfi_softc *isoftc = &cfi_softc;
+ struct cfi_port *cfi = NULL;
+ const char *val;
+ int port_id = -1;
+
+ val = dnvlist_get_string(req->args_nvl, "port_id", NULL);
+ if (val != NULL)
+ port_id = strtol(val, NULL, 10);
+
+ if (port_id == -1) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "port_id not provided");
+ return;
+ }
+
+ TAILQ_FOREACH(cfi, &isoftc->ports, link) {
+ if (cfi->port.targ_port == port_id)
+ break;
+ }
+
+ if (cfi == NULL) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "cannot find port %d", port_id);
+
+ return;
+ }
+
+ if (cfi->port.physical_port == 0 && cfi->port.virtual_port == 0) {
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "cannot destroy default ioctl port");
+
+ return;
+ }
+
+ ctl_port_offline(&cfi->port);
+ ctl_port_deregister(&cfi->port);
+ TAILQ_REMOVE(&isoftc->ports, cfi, link);
+ destroy_dev(cfi->dev);
+ free(cfi, M_CTL);
+ req->status = CTL_LUN_OK;
+}
+
+static int
+cfi_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
+ struct thread *td)
+{
+ struct ctl_req *req;
+
+ if (cmd == CTL_PORT_REQ) {
+ req = (struct ctl_req *)addr;
+ switch (req->reqtype) {
+ case CTL_REQ_CREATE:
+ cfi_ioctl_port_create(req);
+ break;
+ case CTL_REQ_REMOVE:
+ cfi_ioctl_port_remove(req);
+ break;
+ default:
+ req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "Unsupported request type %d", req->reqtype);
+ }
+ return (0);
+ }
+
+ return (ENOTTY);
}
/*
@@ -389,18 +590,26 @@ int
ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td)
{
+ struct cfi_port *cfi;
union ctl_io *io;
void *pool_tmp, *sc_tmp;
int retval = 0;
+ if (cmd != CTL_IO)
+ return (ENOTTY);
+
+ cfi = dev->si_drv2 == NULL
+ ? TAILQ_FIRST(&cfi_softc.ports)
+ : dev->si_drv2;
+
/*
* If we haven't been "enabled", don't allow any SCSI I/O
* to this FETD.
*/
- if ((cfi_softc.port.status & CTL_PORT_STATUS_ONLINE) == 0)
+ if ((cfi->port.status & CTL_PORT_STATUS_ONLINE) == 0)
return (EPERM);
- io = ctl_alloc_io(cfi_softc.port.ctl_pool_ref);
+ io = ctl_alloc_io(cfi->port.ctl_pool_ref);
/*
* Need to save the pool reference so it doesn't get
@@ -420,15 +629,16 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
/*
* The user sets the initiator ID, target and LUN IDs.
*/
- io->io_hdr.nexus.targ_port = cfi_softc.port.targ_port;
+ io->io_hdr.nexus.targ_port = cfi->port.targ_port;
io->io_hdr.flags |= CTL_FLAG_USER_REQ;
if ((io->io_hdr.io_type == CTL_IO_SCSI) &&
(io->scsiio.tag_type != CTL_TAG_UNTAGGED))
- io->scsiio.tag_num = cfi_softc.cur_tag_num++;
+ io->scsiio.tag_num = cfi->cur_tag_num++;
retval = cfi_submit_wait(io);
if (retval == 0)
memcpy((void *)addr, io, sizeof(*io));
+
ctl_free_io(io);
return (retval);
}
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index a46aa002c136..22a5b3e1fb9d 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/unistd.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <vm/uma.h>
#include <cam/scsi/scsi_all.h>
@@ -2105,30 +2107,30 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
{
struct cfiscsi_target *ct;
struct ctl_port *port;
- const char *target, *alias, *tags;
+ const char *target, *alias, *val;
struct scsi_vpd_id_descriptor *desc;
- ctl_options_t opts;
int retval, len, idlen;
uint16_t tag;
- ctl_init_opts(&opts, req->num_args, req->kern_args);
- target = ctl_get_opt(&opts, "cfiscsi_target");
- alias = ctl_get_opt(&opts, "cfiscsi_target_alias");
- tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
- if (target == NULL || tags == NULL) {
+ target = dnvlist_get_string(req->args_nvl, "cfiscsi_target", NULL);
+ alias = dnvlist_get_string(req->args_nvl, "cfiscsi_target_alias", NULL);
+ val = dnvlist_get_string(req->args_nvl, "cfiscsi_portal_group_tag",
+ NULL);
+
+
+ if (target == NULL || val == NULL) {
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"Missing required argument");
- ctl_free_opts(&opts);
return;
}
- tag = strtol(tags, (char **)NULL, 10);
+
+ tag = strtoul(val, NULL, 0);
ct = cfiscsi_target_find_or_create(&cfiscsi_softc, target, alias, tag);
if (ct == NULL) {
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"failed to create target \"%s\"", target);
- ctl_free_opts(&opts);
return;
}
if (ct->ct_state == CFISCSI_TARGET_STATE_ACTIVE) {
@@ -2137,7 +2139,6 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
"target \"%s\" for portal group tag %u already exists",
target, tag);
cfiscsi_target_release(ct);
- ctl_free_opts(&opts);
return;
}
port = &ct->ct_port;
@@ -2150,7 +2151,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
/* XXX KDM what should the real number be here? */
port->num_requested_ctl_io = 4096;
port->port_name = "iscsi";
- port->physical_port = tag;
+ port->physical_port = (int)tag;
port->virtual_port = ct->ct_target_id;
port->port_online = cfiscsi_online;
port->port_offline = cfiscsi_offline;
@@ -2159,9 +2160,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
port->fe_datamove = cfiscsi_datamove;
port->fe_done = cfiscsi_done;
port->targ_port = -1;
-
- port->options = opts;
- STAILQ_INIT(&opts);
+ port->options = nvlist_clone(req->args_nvl);
/* Generate Port ID. */
idlen = strlen(target) + strlen(",t,0x0001") + 1;
@@ -2193,7 +2192,6 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
retval = ctl_port_register(port);
if (retval != 0) {
- ctl_free_opts(&port->options);
free(port->port_devid, M_CFISCSI);
free(port->target_devid, M_CFISCSI);
cfiscsi_target_release(ct);
@@ -2205,45 +2203,42 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
done:
ct->ct_state = CFISCSI_TARGET_STATE_ACTIVE;
req->status = CTL_LUN_OK;
- memcpy(req->kern_args[0].kvalue, &port->targ_port,
- sizeof(port->targ_port)); //XXX
+ req->result_nvl = nvlist_create(0);
+ nvlist_add_number(req->result_nvl, "port_id", port->targ_port);
}
static void
cfiscsi_ioctl_port_remove(struct ctl_req *req)
{
struct cfiscsi_target *ct;
- const char *target, *tags;
- ctl_options_t opts;
+ const char *target, *val;
uint16_t tag;
- ctl_init_opts(&opts, req->num_args, req->kern_args);
- target = ctl_get_opt(&opts, "cfiscsi_target");
- tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
- if (target == NULL || tags == NULL) {
- ctl_free_opts(&opts);
+ target = dnvlist_get_string(req->args_nvl, "cfiscsi_target", NULL);
+ val = dnvlist_get_string(req->args_nvl, "cfiscsi_portal_group_tag",
+ NULL);
+
+ if (target == NULL || val == NULL) {
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"Missing required argument");
return;
}
- tag = strtol(tags, (char **)NULL, 10);
+
+ tag = strtoul(val, NULL, 0);
ct = cfiscsi_target_find(&cfiscsi_softc, target, tag);
if (ct == NULL) {
- ctl_free_opts(&opts);
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"can't find target \"%s\"", target);
return;
}
if (ct->ct_state != CFISCSI_TARGET_STATE_ACTIVE) {
- ctl_free_opts(&opts);
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"target \"%s\" is already dying", target);
return;
}
- ctl_free_opts(&opts);
ct->ct_state = CFISCSI_TARGET_STATE_DYING;
ctl_port_offline(&ct->ct_port);
diff --git a/sys/cam/ctl/ctl_ioctl.h b/sys/cam/ctl/ctl_ioctl.h
index f7297504dcc1..0c3aa1e1095c 100644
--- a/sys/cam/ctl/ctl_ioctl.h
+++ b/sys/cam/ctl/ctl_ioctl.h
@@ -48,6 +48,7 @@
#endif
#include <sys/ioccom.h>
+#include <sys/nv.h>
#define CTL_DEFAULT_DEV "/dev/cam/ctl"
/*
@@ -316,39 +317,6 @@ typedef enum {
#define CTL_ERROR_STR_LEN 160
-#define CTL_BEARG_RD 0x01
-#define CTL_BEARG_WR 0x02
-#define CTL_BEARG_RW (CTL_BEARG_RD|CTL_BEARG_WR)
-#define CTL_BEARG_ASCII 0x04
-
-/*
- * Backend Argument:
- *
- * namelen: Length of the name field, including the terminating NUL.
- *
- * name: Name of the parameter. This must be NUL-terminated.
- *
- * flags: Flags for the parameter, see above for values.
- *
- * vallen: Length of the value in bytes, including the terminating NUL.
- *
- * value: Value to be set/fetched. This must be NUL-terminated.
- *
- * kname: For kernel use only.
- *
- * kvalue: For kernel use only.
- */
-struct ctl_be_arg {
- unsigned int namelen;
- char *name;
- int flags;
- unsigned int vallen;
- void *value;
-
- char *kname;
- void *kvalue;
-};
-
typedef enum {
CTL_LUNREQ_CREATE,
CTL_LUNREQ_RM,
@@ -524,11 +492,14 @@ struct ctl_lun_req {
char backend[CTL_BE_NAME_LEN];
ctl_lunreq_type reqtype;
union ctl_lunreq_data reqdata;
- int num_be_args;
- struct ctl_be_arg *be_args;
+ void * args;
+ nvlist_t * args_nvl;
+ size_t args_len;
+ void * result;
+ nvlist_t * result_nvl;
+ size_t result_len;
ctl_lun_status status;
char error_str[CTL_ERROR_STR_LEN];
- struct ctl_be_arg *kern_be_args;
};
/*
@@ -617,11 +588,14 @@ typedef enum {
struct ctl_req {
char driver[CTL_DRIVER_NAME_LEN];
ctl_req_type reqtype;
- int num_args;
- struct ctl_be_arg *args;
+ void * args;
+ nvlist_t * args_nvl;
+ size_t args_len;
+ void * result;
+ nvlist_t * result_nvl;
+ size_t result_len;
ctl_lun_status status;
char error_str[CTL_ERROR_STR_LEN];
- struct ctl_be_arg *kern_args;
};
/*
diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c
index 572d93a90078..00fb3a52b3d4 100644
--- a/sys/cam/ctl/ctl_tpc.c
+++ b/sys/cam/ctl/ctl_tpc.c
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
+#include <sys/nv.h>
+#include <sys/dnv.h>
#include <machine/atomic.h>
#include <cam/cam.h>
@@ -1668,7 +1670,7 @@ ctl_extended_copy_lid1(struct ctl_scsiio *ctsio)
struct scsi_ec_segment *seg;
struct tpc_list *list, *tlist;
uint8_t *ptr;
- char *value;
+ const char *value;
int len, off, lencscd, lenseg, leninl, nseg;
CTL_DEBUG_PRINT(("ctl_extended_copy_lid1\n"));
@@ -1731,7 +1733,7 @@ ctl_extended_copy_lid1(struct ctl_scsiio *ctsio)
list = malloc(sizeof(struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
list->service_action = cdb->service_action;
- value = ctl_get_opt(&lun->be_lun->options, "insecure_tpc");
+ value = dnvlist_get_string(lun->be_lun->options, "insecure_tpc", NULL);
if (value != NULL && strcmp(value, "on") == 0)
list->init_port = -1;
else
@@ -1822,7 +1824,7 @@ ctl_extended_copy_lid4(struct ctl_scsiio *ctsio)
struct scsi_ec_segment *seg;
struct tpc_list *list, *tlist;
uint8_t *ptr;
- char *value;
+ const char *value;
int len, off, lencscd, lenseg, leninl, nseg;
CTL_DEBUG_PRINT(("ctl_extended_copy_lid4\n"));
@@ -1885,7 +1887,7 @@ ctl_extended_copy_lid4(struct ctl_scsiio *ctsio)
list = malloc(sizeof(struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
list->service_action = cdb->service_action;
- value = ctl_get_opt(&lun->be_lun->options, "insecure_tpc");
+ value = dnvlist_get_string(lun->be_lun->options, "insecure_tpc", NULL);
if (value != NULL && strcmp(value, "on") == 0)
list->init_port = -1;
else