Page MenuHomeFreeBSD

D9299.id41609.diff
No OneTemporary

D9299.id41609.diff

Index: sys/cam/ctl/ctl.h
===================================================================
--- sys/cam/ctl/ctl.h
+++ sys/cam/ctl/ctl.h
@@ -196,24 +196,6 @@
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 */
Index: sys/cam/ctl/ctl.c
===================================================================
--- sys/cam/ctl/ctl.c
+++ sys/cam/ctl/ctl.c
@@ -4,6 +4,7 @@
* 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) 2018 Marcelo Araujo <araujo@FreeBSD.org>
* All rights reserved.
*
* Portions of this software were developed by Edward Tomasz Napierala
@@ -65,6 +66,8 @@
#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 +1872,7 @@
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 +2472,6 @@
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 +2943,12 @@
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 +2959,75 @@
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 = ctl_copyin_alloc(lun_req->args,
+ lun_req->args_len, lun_req->error_str,
+ sizeof(lun_req->error_str));
+
+ if (lun_req->args == NULL) {
lun_req->status = CTL_LUN_ERROR;
break;
}
- }
+ 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;
+ 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->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 (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 (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 +3153,20 @@
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 +3220,12 @@
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 +3234,74 @@
"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 = ctl_copyin_alloc(req->args,
+ req->args_len, req->error_str,
+ sizeof(req->error_str));
+
+ if (req->args == NULL) {
req->status = CTL_LUN_ERROR;
+ snprintf(req->error_str, sizeof(req->error_str),
+ "Cannot copyin args.");
break;
}
- }
+ 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 +3309,10 @@
struct sbuf *sb;
struct ctl_port *port;
struct ctl_lun_list *list;
- struct ctl_option *opt;
+ const char *name, *value;
+ void *cookie;
int j;
+ int type;
uint32_t plun;
list = (struct ctl_lun_list *)addr;
@@ -3369,11 +3387,20 @@
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 +4207,8 @@
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 +4261,12 @@
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 +4295,8 @@
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 +4371,8 @@
&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 +4384,8 @@
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 +4397,8 @@
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 +4410,8 @@
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 +4610,20 @@
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 +4635,7 @@
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 +4748,7 @@
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 +9801,7 @@
{
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 +9831,16 @@
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 +9856,10 @@
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 +9898,13 @@
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 +9949,8 @@
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 +10044,7 @@
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 +10122,8 @@
* 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 +10133,8 @@
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 +10163,8 @@
* 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));
Index: sys/cam/ctl/ctl_backend.h
===================================================================
--- sys/cam/ctl/ctl_backend.h
+++ 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 @@
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 */
};
Index: sys/cam/ctl/ctl_backend.c
===================================================================
--- sys/cam/ctl/ctl_backend.c
+++ sys/cam/ctl/ctl_backend.c
@@ -141,93 +141,3 @@
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));
-}
Index: sys/cam/ctl/ctl_backend_block.c
===================================================================
--- sys/cam/ctl/ctl_backend_block.c
+++ sys/cam/ctl/ctl_backend_block.c
@@ -78,6 +78,8 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
Index: sys/cam/ctl/ctl_backend_ramdisk.c
===================================================================
--- sys/cam/ctl/ctl_backend_ramdisk.c
+++ sys/cam/ctl/ctl_backend_ramdisk.c
@@ -62,6 +62,8 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
Index: sys/cam/ctl/ctl_frontend.h
===================================================================
--- sys/cam/ctl/ctl_frontend.h
+++ 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 @@
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 */
Index: sys/cam/ctl/ctl_frontend.c
===================================================================
--- sys/cam/ctl/ctl_frontend.c
+++ sys/cam/ctl/ctl_frontend.c
@@ -52,6 +52,8 @@
#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 @@
}
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 @@
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 @@
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
Index: sys/cam/ctl/ctl_frontend_ioctl.c
===================================================================
--- sys/cam/ctl/ctl_frontend_ioctl.c
+++ sys/cam/ctl/ctl_frontend_ioctl.c
@@ -41,6 +41,8 @@
#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 +70,41 @@
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 +113,31 @@
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,15 +145,187 @@
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;
- ctl_port_offline(port);
- if ((error = ctl_port_deregister(port)) != 0)
- printf("%s: ioctl port deregistration failed\n", __func__);
- return (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);
+ }
+
+ 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);
+}
+
/*
* Data movement routine for the CTL ioctl frontend port.
*/
@@ -389,18 +587,26 @@
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 +626,16 @@
/*
* 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);
}
Index: sys/cam/ctl/ctl_frontend_iscsi.c
===================================================================
--- sys/cam/ctl/ctl_frontend_iscsi.c
+++ sys/cam/ctl/ctl_frontend_iscsi.c
@@ -56,6 +56,8 @@
#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 @@
{
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 @@
"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 @@
/* 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,10 +2160,8 @@
port->fe_datamove = cfiscsi_datamove;
port->fe_done = cfiscsi_done;
port->targ_port = -1;
+ port->options = nvlist_clone(req->args_nvl);
- port->options = opts;
- STAILQ_INIT(&opts);
-
/* Generate Port ID. */
idlen = strlen(target) + strlen(",t,0x0001") + 1;
idlen = roundup2(idlen, 4);
@@ -2193,7 +2192,6 @@
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 @@
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);
Index: sys/cam/ctl/ctl_ioctl.h
===================================================================
--- sys/cam/ctl/ctl_ioctl.h
+++ 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 @@
#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 @@
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 @@
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;
};
/*
Index: sys/cam/ctl/ctl_tpc.c
===================================================================
--- sys/cam/ctl/ctl_tpc.c
+++ sys/cam/ctl/ctl_tpc.c
@@ -41,6 +41,8 @@
#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 @@
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 @@
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 @@
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 @@
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
Index: sys/sys/param.h
===================================================================
--- sys/sys/param.h
+++ sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1200061 /* Master, propagated to newvers */
+#define __FreeBSD_version 1200062 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Index: usr.sbin/ctladm/Makefile
===================================================================
--- usr.sbin/ctladm/Makefile
+++ usr.sbin/ctladm/Makefile
@@ -16,7 +16,7 @@
WARNS?= 3
.endif
-LIBADD= cam sbuf bsdxml util
+LIBADD= cam sbuf bsdxml util nv
MAN= ctladm.8
.if ${MK_ISCSI} != "no"
Index: usr.sbin/ctladm/ctladm.c
===================================================================
--- usr.sbin/ctladm/ctladm.c
+++ usr.sbin/ctladm/ctladm.c
@@ -50,6 +50,7 @@
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/sbuf.h>
+#include <sys/nv.h>
#include <sys/stat.h>
#include <bsdxml.h>
#include <ctype.h>
@@ -178,7 +179,7 @@
{"lunmap", CTLADM_CMD_LUNMAP, CTLADM_ARG_NONE, "p:l:L:"},
{"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"},
{"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:o:s:"},
- {"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:p:qt:w:W:x"},
+ {"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:O:d:crp:qt:w:W:x"},
{"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ilp:qvx"},
{"prin", CTLADM_CMD_PRES_IN, CTLADM_ARG_NEED_TL, "a:"},
{"prout", CTLADM_CMD_PRES_OUT, CTLADM_ARG_NEED_TL, "a:k:r:s:"},
@@ -369,7 +370,9 @@
CCTL_PORT_MODE_LIST,
CCTL_PORT_MODE_SET,
CCTL_PORT_MODE_ON,
- CCTL_PORT_MODE_OFF
+ CCTL_PORT_MODE_OFF,
+ CCTL_PORT_MODE_CREATE,
+ CCTL_PORT_MODE_REMOVE
} cctl_port_mode;
static struct ctladm_opts cctl_fe_table[] = {
@@ -392,9 +395,16 @@
uint64_t wwnn = 0, wwpn = 0;
cctl_port_mode port_mode = CCTL_PORT_MODE_NONE;
struct ctl_port_entry entry;
+ struct ctl_req req;
+ char *driver = NULL;
+ nvlist_t *option_list;
ctl_port_type port_type = CTL_PORT_NONE;
int quiet = 0, xml = 0;
+ option_list = nvlist_create(0);
+ if (option_list == NULL)
+ err(1, "%s: unable to allocate nvlist", __func__);
+
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch (c) {
case 'l':
@@ -403,6 +413,12 @@
port_mode = CCTL_PORT_MODE_LIST;
break;
+ case 'c':
+ port_mode = CCTL_PORT_MODE_CREATE;
+ break;
+ case 'r':
+ port_mode = CCTL_PORT_MODE_REMOVE;
+ break;
case 'o':
if (port_mode != CCTL_PORT_MODE_NONE)
goto bailout_badarg;
@@ -419,6 +435,40 @@
goto bailout;
}
break;
+ case 'O': {
+ char *tmpstr;
+ char *name, *value;
+
+ tmpstr = strdup(optarg);
+ name = strsep(&tmpstr, "=");
+ if (name == NULL) {
+ warnx("%s: option -O takes \"name=value\""
+ "argument", __func__);
+ retval = 1;
+ goto bailout;
+ }
+ value = strsep(&tmpstr, "=");
+ if (value == NULL) {
+ warnx("%s: option -O takes \"name=value\""
+ "argument", __func__);
+ retval = 1;
+ goto bailout;
+ }
+
+ free(tmpstr);
+ nvlist_add_string(option_list, name, value);
+ break;
+ }
+ case 'd':
+ if (driver != NULL) {
+ warnx("%s: option -d cannot be specified twice",
+ __func__);
+ retval = 1;
+ goto bailout;
+ }
+
+ driver = strdup(optarg);
+ break;
case 'p':
targ_port = strtol(optarg, NULL, 0);
break;
@@ -474,6 +524,9 @@
}
}
+ if (driver == NULL)
+ driver = strdup("ioctl");
+
/*
* The user can specify either one or more frontend types (-t), or
* a specific frontend, but not both.
@@ -515,6 +568,56 @@
cctl_portlist(fd, argcx, argvx, opts);
break;
}
+ case CCTL_PORT_MODE_REMOVE:
+ if (targ_port == -1) {
+ warnx("%s: -r require -p", __func__);
+ retval = 1;
+ goto bailout;
+ }
+ case CCTL_PORT_MODE_CREATE: {
+ bzero(&req, sizeof(req));
+ strlcpy(req.driver, driver, sizeof(req.driver));
+
+ if (port_mode == CCTL_PORT_MODE_REMOVE) {
+ req.reqtype = CTL_REQ_REMOVE;
+ nvlist_add_stringf(option_list, "port_id", "%d",
+ targ_port);
+ } else
+ req.reqtype = CTL_REQ_CREATE;
+
+ req.args = nvlist_pack(option_list, &req.args_len);
+ if (req.args == NULL) {
+ warn("%s: error packing nvlist", __func__);
+ retval = 1;
+ goto bailout;
+ }
+
+ retval = ioctl(fd, CTL_PORT_REQ, &req);
+ //free(req.args);
+ if (retval == -1) {
+ warn("%s: CTL_PORT_REQ ioctl failed", __func__);
+ retval = 1;
+ goto bailout;
+ }
+
+ switch (req.status) {
+ case CTL_LUN_ERROR:
+ warnx("error: %s", req.error_str);
+ retval = 1;
+ goto bailout;
+ case CTL_LUN_WARNING:
+ warnx("warning: %s", req.error_str);
+ break;
+ case CTL_LUN_OK:
+ break;
+ default:
+ warnx("unknown status: %d", req.status);
+ retval = 1;
+ goto bailout;
+ }
+
+ break;
+ }
case CCTL_PORT_MODE_SET:
if (targ_port == -1) {
warnx("%s: -w and -W require -n", __func__);
@@ -561,7 +664,8 @@
}
bailout:
-
+ nvlist_destroy(req.args_nvl);
+ free(driver);
return (retval);
bailout_badarg:
@@ -2271,14 +2375,6 @@
return (retval);
}
-struct cctl_req_option {
- char *name;
- int namelen;
- char *value;
- int vallen;
- STAILQ_ENTRY(cctl_req_option) links;
-};
-
static int
cctl_create_lun(int fd, int argc, char **argv, char *combinedopt)
{
@@ -2290,11 +2386,12 @@
char *device_id = NULL;
int lun_size_set = 0, blocksize_set = 0, lun_id_set = 0;
char *backend_name = NULL;
- STAILQ_HEAD(, cctl_req_option) option_list;
- int num_options = 0;
+ nvlist_t *option_list;
int retval = 0, c;
- STAILQ_INIT(&option_list);
+ option_list = nvlist_create(0);
+ if (option_list == NULL)
+ err(1, "%s: unable to allocate nvlist", __func__);
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch (c) {
@@ -2313,7 +2410,6 @@
lun_id_set = 1;
break;
case 'o': {
- struct cctl_req_option *option;
char *tmpstr;
char *name, *value;
@@ -2332,21 +2428,9 @@
retval = 1;
goto bailout;
}
- option = malloc(sizeof(*option));
- if (option == NULL) {
- warn("%s: error allocating %zd bytes",
- __func__, sizeof(*option));
- retval = 1;
- goto bailout;
- }
- option->name = strdup(name);
- option->namelen = strlen(name) + 1;
- option->value = strdup(value);
- option->vallen = strlen(value) + 1;
- free(tmpstr);
- STAILQ_INSERT_TAIL(&option_list, option, links);
- num_options++;
+ free(tmpstr);
+ nvlist_add_string(option_list, name, value);
break;
}
case 's':
@@ -2413,43 +2497,16 @@
req.reqdata.create.flags |= CTL_LUN_FLAG_DEVID;
}
- req.num_be_args = num_options;
- if (num_options > 0) {
- struct cctl_req_option *option, *next_option;
- int i;
-
- req.be_args = malloc(num_options * sizeof(*req.be_args));
- if (req.be_args == NULL) {
- warn("%s: error allocating %zd bytes", __func__,
- num_options * sizeof(*req.be_args));
- retval = 1;
- goto bailout;
- }
-
- for (i = 0, option = STAILQ_FIRST(&option_list);
- i < num_options; i++, option = next_option) {
- next_option = STAILQ_NEXT(option, links);
-
- req.be_args[i].namelen = option->namelen;
- req.be_args[i].name = strdup(option->name);
- req.be_args[i].vallen = option->vallen;
- req.be_args[i].value = strdup(option->value);
- /*
- * XXX KDM do we want a way to specify a writeable
- * flag of some sort? Do we want a way to specify
- * binary data?
- */
- req.be_args[i].flags = CTL_BEARG_ASCII | CTL_BEARG_RD;
-
- STAILQ_REMOVE(&option_list, option, cctl_req_option,
- links);
- free(option->name);
- free(option->value);
- free(option);
- }
+ req.args = nvlist_pack(option_list, &req.args_len);
+ if (req.args == NULL) {
+ warn("%s: error packing nvlist", __func__);
+ retval = 1;
+ goto bailout;
}
- if (ioctl(fd, CTL_LUN_REQ, &req) == -1) {
+ retval = ioctl(fd, CTL_LUN_REQ, &req);
+ free(req.args);
+ if (retval == -1) {
warn("%s: error issuing CTL_LUN_REQ ioctl", __func__);
retval = 1;
goto bailout;
@@ -2480,9 +2537,10 @@
req.reqdata.create.blocksize_bytes);
fprintf(stdout, "LUN ID: %d\n", req.reqdata.create.req_lun_id);
fprintf(stdout, "Serial Number: %s\n", req.reqdata.create.serial_num);
- fprintf(stdout, "Device ID; %s\n", req.reqdata.create.device_id);
+ fprintf(stdout, "Device ID: %s\n", req.reqdata.create.device_id);
bailout:
+ nvlist_destroy(req.args_nvl);
return (retval);
}
@@ -2493,11 +2551,12 @@
uint32_t lun_id = 0;
int lun_id_set = 0;
char *backend_name = NULL;
- STAILQ_HEAD(, cctl_req_option) option_list;
- int num_options = 0;
+ nvlist_t *option_list;
int retval = 0, c;
- STAILQ_INIT(&option_list);
+ option_list = nvlist_create(0);
+ if (option_list == NULL)
+ err(1, "%s: unable to allocate nvlist", __func__);
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch (c) {
@@ -2509,7 +2568,6 @@
lun_id_set = 1;
break;
case 'o': {
- struct cctl_req_option *option;
char *tmpstr;
char *name, *value;
@@ -2528,21 +2586,9 @@
retval = 1;
goto bailout;
}
- option = malloc(sizeof(*option));
- if (option == NULL) {
- warn("%s: error allocating %zd bytes",
- __func__, sizeof(*option));
- retval = 1;
- goto bailout;
- }
- option->name = strdup(name);
- option->namelen = strlen(name) + 1;
- option->value = strdup(value);
- option->vallen = strlen(value) + 1;
- free(tmpstr);
- STAILQ_INSERT_TAIL(&option_list, option, links);
- num_options++;
+ free(tmpstr);
+ nvlist_add_string(option_list, name, value);
break;
}
default:
@@ -2562,44 +2608,17 @@
req.reqtype = CTL_LUNREQ_RM;
req.reqdata.rm.lun_id = lun_id;
-
- req.num_be_args = num_options;
- if (num_options > 0) {
- struct cctl_req_option *option, *next_option;
- int i;
-
- req.be_args = malloc(num_options * sizeof(*req.be_args));
- if (req.be_args == NULL) {
- warn("%s: error allocating %zd bytes", __func__,
- num_options * sizeof(*req.be_args));
- retval = 1;
- goto bailout;
- }
-
- for (i = 0, option = STAILQ_FIRST(&option_list);
- i < num_options; i++, option = next_option) {
- next_option = STAILQ_NEXT(option, links);
-
- req.be_args[i].namelen = option->namelen;
- req.be_args[i].name = strdup(option->name);
- req.be_args[i].vallen = option->vallen;
- req.be_args[i].value = strdup(option->value);
- /*
- * XXX KDM do we want a way to specify a writeable
- * flag of some sort? Do we want a way to specify
- * binary data?
- */
- req.be_args[i].flags = CTL_BEARG_ASCII | CTL_BEARG_RD;
-
- STAILQ_REMOVE(&option_list, option, cctl_req_option,
- links);
- free(option->name);
- free(option->value);
- free(option);
- }
+
+ req.args = nvlist_pack(option_list, &req.args_len);
+ if (req.args == NULL) {
+ warn("%s: error packing nvlist", __func__);
+ retval = 1;
+ goto bailout;
}
- if (ioctl(fd, CTL_LUN_REQ, &req) == -1) {
+ retval = ioctl(fd, CTL_LUN_REQ, &req);
+ free(req.args);
+ if (retval == -1) {
warn("%s: error issuing CTL_LUN_REQ ioctl", __func__);
retval = 1;
goto bailout;
@@ -2624,6 +2643,7 @@
printf("LUN %d removed successfully\n", lun_id);
bailout:
+ nvlist_destroy(req.args_nvl);
return (retval);
}
@@ -2635,11 +2655,13 @@
uint32_t lun_id = 0;
int lun_id_set = 0, lun_size_set = 0;
char *backend_name = NULL;
- STAILQ_HEAD(, cctl_req_option) option_list;
- int num_options = 0;
+ nvlist_t *option_list;
int retval = 0, c;
- STAILQ_INIT(&option_list);
+ option_list = nvlist_create(0);
+ if (option_list == NULL)
+ err(1, "%s: unable to allocate nvlist", __func__);
+
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch (c) {
case 'b':
@@ -2650,7 +2672,6 @@
lun_id_set = 1;
break;
case 'o': {
- struct cctl_req_option *option;
char *tmpstr;
char *name, *value;
@@ -2669,21 +2690,9 @@
retval = 1;
goto bailout;
}
- option = malloc(sizeof(*option));
- if (option == NULL) {
- warn("%s: error allocating %zd bytes",
- __func__, sizeof(*option));
- retval = 1;
- goto bailout;
- }
- option->name = strdup(name);
- option->namelen = strlen(name) + 1;
- option->value = strdup(value);
- option->vallen = strlen(value) + 1;
- free(tmpstr);
- STAILQ_INSERT_TAIL(&option_list, option, links);
- num_options++;
+ free(tmpstr);
+ nvlist_add_string(option_list, name, value);
break;
}
case 's':
@@ -2709,7 +2718,7 @@
if (lun_id_set == 0)
errx(1, "%s: LUN id (-l) must be specified", __func__);
- if (lun_size_set == 0 && num_options == 0)
+ if (lun_size_set == 0 && nvlist_empty(option_list))
errx(1, "%s: size (-s) or options (-o) must be specified",
__func__);
@@ -2721,43 +2730,16 @@
req.reqdata.modify.lun_id = lun_id;
req.reqdata.modify.lun_size_bytes = lun_size;
- req.num_be_args = num_options;
- if (num_options > 0) {
- struct cctl_req_option *option, *next_option;
- int i;
-
- req.be_args = malloc(num_options * sizeof(*req.be_args));
- if (req.be_args == NULL) {
- warn("%s: error allocating %zd bytes", __func__,
- num_options * sizeof(*req.be_args));
- retval = 1;
- goto bailout;
- }
-
- for (i = 0, option = STAILQ_FIRST(&option_list);
- i < num_options; i++, option = next_option) {
- next_option = STAILQ_NEXT(option, links);
-
- req.be_args[i].namelen = option->namelen;
- req.be_args[i].name = strdup(option->name);
- req.be_args[i].vallen = option->vallen;
- req.be_args[i].value = strdup(option->value);
- /*
- * XXX KDM do we want a way to specify a writeable
- * flag of some sort? Do we want a way to specify
- * binary data?
- */
- req.be_args[i].flags = CTL_BEARG_ASCII | CTL_BEARG_RD;
-
- STAILQ_REMOVE(&option_list, option, cctl_req_option,
- links);
- free(option->name);
- free(option->value);
- free(option);
- }
+ req.args = nvlist_pack(option_list, &req.args_len);
+ if (req.args == NULL) {
+ warn("%s: error packing nvlist", __func__);
+ retval = 1;
+ goto bailout;
}
- if (ioctl(fd, CTL_LUN_REQ, &req) == -1) {
+ retval = ioctl(fd, CTL_LUN_REQ, &req);
+ free(req.args);
+ if (retval == -1) {
warn("%s: error issuing CTL_LUN_REQ ioctl", __func__);
retval = 1;
goto bailout;
@@ -2782,6 +2764,7 @@
printf("LUN %d modified successfully\n", lun_id);
bailout:
+ nvlist_destroy(req.args_nvl);
return (retval);
}
@@ -3661,7 +3644,7 @@
struct cctl_portlist_data portlist;
struct cctl_port *port;
XML_Parser parser;
- char *port_str;
+ char *port_str = NULL;
int port_len;
int dump_xml = 0;
int retval, c;
@@ -3704,7 +3687,8 @@
}
retry:
- port_str = malloc(port_len);
+ //port_str = malloc(port_len);
+ port_str = (char *)realloc(NULL, port_len);
bzero(&list, sizeof(list));
list.alloc_len = port_len;
@@ -3876,6 +3860,8 @@
" [-s len fmt [args]] [-c] [-d delete_id]\n"
" ctladm port <-o <on|off> | [-w wwnn][-W wwpn]>\n"
" [-p targ_port] [-t port_type]\n"
+" <-c> [-d driver] [-O name=value]\n"
+" <-d> <-p targ_port>\n"
" ctladm portlist [-f frontend] [-i] [-p targ_port] [-q] [-v] [-x]\n"
" ctladm islist [-v | -x]\n"
" ctladm islogout <-a | -c connection-id | -i name | -p portal>\n"
@@ -3956,6 +3942,7 @@
"port options:\n"
"-l : list frontend ports\n"
"-o on|off : turn frontend ports on or off\n"
+"-O pp|vp : creates new ioctl frontend port using pp and/or vp\n"
"-w wwnn : set WWNN for one frontend\n"
"-W wwpn : set WWPN for one frontend\n"
"-t port_type : specify fc, scsi, ioctl, internal frontend type\n"
@@ -4008,8 +3995,7 @@
usage(1);
retval = 1;
goto bailout;
- }
-
+ }
/*
* Get the base option.
*/
Index: usr.sbin/ctld/Makefile
===================================================================
--- usr.sbin/ctld/Makefile
+++ usr.sbin/ctld/Makefile
@@ -15,7 +15,7 @@
#CFLAGS+= -DICL_KERNEL_PROXY
MAN= ctld.8 ctl.conf.5
-LIBADD= bsdxml l md sbuf util ucl m
+LIBADD= bsdxml l md sbuf util ucl m nv
YFLAGS+= -v
CLEANFILES= y.tab.c y.tab.h y.output
Index: usr.sbin/ctld/ctld.h
===================================================================
--- usr.sbin/ctld/ctld.h
+++ usr.sbin/ctld/ctld.h
@@ -152,6 +152,9 @@
struct pport *p_pport;
struct target *p_target;
+ int p_ioctl_port;
+ int p_ioctl_pp;
+ int p_ioctl_vp;
uint32_t p_ctl_port;
};
@@ -368,6 +371,8 @@
struct port *port_new(struct conf *conf, struct target *target,
struct portal_group *pg);
+struct port *port_new_ioctl(struct conf *conf, struct target *target,
+ int pp, int vp);
struct port *port_new_pp(struct conf *conf, struct target *target,
struct pport *pp);
struct port *port_find(const struct conf *conf, const char *name);
Index: usr.sbin/ctld/ctld.c
===================================================================
--- usr.sbin/ctld/ctld.c
+++ usr.sbin/ctld/ctld.c
@@ -1234,6 +1234,7 @@
log_err(1, "calloc");
port->p_conf = conf;
port->p_name = name;
+ port->p_ioctl_port = 0;
TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts);
port->p_target = target;
@@ -1243,6 +1244,51 @@
}
struct port *
+port_new_ioctl(struct conf *conf, struct target *target, int pp, int vp)
+{
+ struct pport *pport;
+ struct port *port;
+ char *pname;
+ char *name;
+ int ret;
+
+ ret = asprintf(&pname, "ioctl/%d/%d", pp, vp);
+ if (ret <= 0) {
+ log_err(1, "asprintf");
+ return (NULL);
+ }
+
+ pport = pport_find(conf, pname);
+ if (pport != NULL) {
+ free(pname);
+ return (port_new_pp(conf, target, pport));
+ }
+
+ ret = asprintf(&name, "%s-%s", pname, target->t_name);
+ free(pname);
+
+ if (ret <= 0)
+ log_err(1, "asprintf");
+ if (port_find(conf, name) != NULL) {
+ log_warnx("duplicate port \"%s\"", name);
+ free(name);
+ return (NULL);
+ }
+ port = calloc(1, sizeof(*port));
+ if (port == NULL)
+ log_err(1, "calloc");
+ port->p_conf = conf;
+ port->p_name = name;
+ port->p_ioctl_port = 1;
+ port->p_ioctl_pp = pp;
+ port->p_ioctl_vp = vp;
+ TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
+ TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts);
+ port->p_target = target;
+ return (port);
+}
+
+struct port *
port_new_pp(struct conf *conf, struct target *target, struct pport *pp)
{
struct port *port;
@@ -1627,9 +1673,9 @@
TAILQ_FOREACH(auth_name, &ag->ag_names, an_next)
fprintf(stderr, "\t initiator-name %s\n",
auth_name->an_initator_name);
- TAILQ_FOREACH(auth_portal, &ag->ag_portals, an_next)
+ TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next)
fprintf(stderr, "\t initiator-portal %s\n",
- auth_portal->an_initator_portal);
+ auth_portal->ap_initator_portal);
fprintf(stderr, "}\n");
}
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
@@ -1643,7 +1689,7 @@
fprintf(stderr, "\t\tpath %s\n", lun->l_path);
TAILQ_FOREACH(o, &lun->l_options, o_next)
fprintf(stderr, "\t\toption %s %s\n",
- lo->o_name, lo->o_value);
+ o->o_name, o->o_value);
fprintf(stderr, "\t}\n");
}
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
Index: usr.sbin/ctld/kernel.c
===================================================================
--- usr.sbin/ctld/kernel.c
+++ usr.sbin/ctld/kernel.c
@@ -47,6 +47,7 @@
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/sbuf.h>
+#include <sys/nv.h>
#include <sys/stat.h>
#include <assert.h>
#include <bsdxml.h>
@@ -73,6 +74,8 @@
#include <netdb.h>
#endif
+#define NVLIST_BUFSIZE 1024
+
extern bool proxy_mode;
static int ctl_fd = 0;
@@ -652,23 +655,12 @@
return (conf);
}
-static void
-str_arg(struct ctl_be_arg *arg, const char *name, const char *value)
-{
-
- arg->namelen = strlen(name) + 1;
- arg->name = __DECONST(char *, name);
- arg->vallen = strlen(value) + 1;
- arg->value = __DECONST(char *, value);
- arg->flags = CTL_BEARG_ASCII | CTL_BEARG_RD;
-}
-
int
kernel_lun_add(struct lun *lun)
{
struct option *o;
struct ctl_lun_req req;
- int error, i, num_options;
+ int error;
bzero(&req, sizeof(req));
@@ -724,29 +716,26 @@
assert(o != NULL);
}
- num_options = 0;
- TAILQ_FOREACH(o, &lun->l_options, o_next)
- num_options++;
-
- req.num_be_args = num_options;
- if (num_options > 0) {
- req.be_args = malloc(num_options * sizeof(*req.be_args));
- if (req.be_args == NULL) {
- log_warn("error allocating %zd bytes",
- num_options * sizeof(*req.be_args));
+ if (!TAILQ_EMPTY(&lun->l_options)) {
+ req.args_nvl = nvlist_create(0);
+ if (req.args_nvl == NULL) {
+ log_warn("error allocating nvlist");
return (1);
}
- i = 0;
- TAILQ_FOREACH(o, &lun->l_options, o_next) {
- str_arg(&req.be_args[i], o->o_name, o->o_value);
- i++;
+ TAILQ_FOREACH(o, &lun->l_options, o_next)
+ nvlist_add_string(req.args_nvl, o->o_name, o->o_value);
+
+ req.args = nvlist_pack(req.args_nvl, &req.args_len);
+ if (req.args == NULL) {
+ log_warn("error packing nvlist");
+ return (1);
}
- assert(i == num_options);
}
error = ioctl(ctl_fd, CTL_LUN_REQ, &req);
- free(req.be_args);
+ nvlist_destroy(req.args_nvl);
+
if (error != 0) {
log_warn("error issuing CTL_LUN_REQ ioctl");
return (1);
@@ -776,7 +765,7 @@
{
struct option *o;
struct ctl_lun_req req;
- int error, i, num_options;
+ int error;
bzero(&req, sizeof(req));
@@ -786,29 +775,26 @@
req.reqdata.modify.lun_id = lun->l_ctl_lun;
req.reqdata.modify.lun_size_bytes = lun->l_size;
- num_options = 0;
- TAILQ_FOREACH(o, &lun->l_options, o_next)
- num_options++;
-
- req.num_be_args = num_options;
- if (num_options > 0) {
- req.be_args = malloc(num_options * sizeof(*req.be_args));
- if (req.be_args == NULL) {
- log_warn("error allocating %zd bytes",
- num_options * sizeof(*req.be_args));
+ if (!TAILQ_EMPTY(&lun->l_options)) {
+ req.args_nvl = nvlist_create(0);
+ if (req.args_nvl == NULL) {
+ log_warn("error allocating nvlist");
return (1);
}
- i = 0;
- TAILQ_FOREACH(o, &lun->l_options, o_next) {
- str_arg(&req.be_args[i], o->o_name, o->o_value);
- i++;
+ TAILQ_FOREACH(o, &lun->l_options, o_next)
+ nvlist_add_string(req.args_nvl, o->o_name, o->o_value);
+
+ req.args = nvlist_pack(req.args_nvl, &req.args_len);
+ if (req.args == NULL) {
+ log_warn("error packing nvlist");
+ return (1);
}
- assert(i == num_options);
}
error = ioctl(ctl_fd, CTL_LUN_REQ, &req);
- free(req.be_args);
+ nvlist_destroy(req.args_nvl);
+
if (error != 0) {
log_warn("error issuing CTL_LUN_REQ ioctl");
return (1);
@@ -988,37 +974,54 @@
struct ctl_lun_map lm;
struct target *targ = port->p_target;
struct portal_group *pg = port->p_portal_group;
- char tagstr[16];
- int error, i, n;
+ char result_buf[NVLIST_BUFSIZE];
+ int error, i;
/* Create iSCSI port. */
- if (port->p_portal_group) {
+ if (port->p_portal_group || port->p_ioctl_port) {
bzero(&req, sizeof(req));
- strlcpy(req.driver, "iscsi", sizeof(req.driver));
req.reqtype = CTL_REQ_CREATE;
- req.num_args = 5;
- TAILQ_FOREACH(o, &pg->pg_options, o_next)
- req.num_args++;
- req.args = malloc(req.num_args * sizeof(*req.args));
- if (req.args == NULL)
- log_err(1, "malloc");
- n = 0;
- req.args[n].namelen = sizeof("port_id");
- req.args[n].name = __DECONST(char *, "port_id");
- req.args[n].vallen = sizeof(port->p_ctl_port);
- req.args[n].value = &port->p_ctl_port;
- req.args[n++].flags = CTL_BEARG_WR;
- str_arg(&req.args[n++], "cfiscsi_target", targ->t_name);
- snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
- str_arg(&req.args[n++], "cfiscsi_portal_group_tag", tagstr);
- if (targ->t_alias)
- str_arg(&req.args[n++], "cfiscsi_target_alias", targ->t_alias);
- str_arg(&req.args[n++], "ctld_portal_group_name", pg->pg_name);
- TAILQ_FOREACH(o, &pg->pg_options, o_next)
- str_arg(&req.args[n++], o->o_name, o->o_value);
- req.num_args = n;
+
+ if (port->p_portal_group) {
+ strlcpy(req.driver, "iscsi", sizeof(req.driver));
+ req.args_nvl = nvlist_create(0);
+ nvlist_add_string(req.args_nvl, "cfiscsi_target",
+ targ->t_name);
+ nvlist_add_string(req.args_nvl,
+ "ctld_portal_group_name", pg->pg_name);
+ nvlist_add_stringf(req.args_nvl,
+ "cfiscsi_portal_group_tag", "%u", pg->pg_tag);
+
+ if (targ->t_alias) {
+ nvlist_add_string(req.args_nvl,
+ "cfiscsi_target_alias", targ->t_alias);
+ }
+
+ TAILQ_FOREACH(o, &pg->pg_options, o_next)
+ nvlist_add_string(req.args_nvl, o->o_name,
+ o->o_value);
+ }
+
+ if (port->p_ioctl_port) {
+ strlcpy(req.driver, "ioctl", sizeof(req.driver));
+ req.args_nvl = nvlist_create(0);
+ nvlist_add_stringf(req.args_nvl, "pp", "%d",
+ port->p_ioctl_pp);
+ nvlist_add_stringf(req.args_nvl, "vp", "%d",
+ port->p_ioctl_vp);
+ }
+
+ req.args = nvlist_pack(req.args_nvl, &req.args_len);
+ if (req.args == NULL) {
+ log_warn("error packing nvlist");
+ return (1);
+ }
+
+ req.result = result_buf;
+ req.result_len = sizeof(result_buf);
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
- free(req.args);
+ nvlist_destroy(req.args_nvl);
+
if (error != 0) {
log_warn("error issuing CTL_PORT_REQ ioctl");
return (1);
@@ -1033,6 +1036,15 @@
req.status);
return (1);
}
+
+ req.result_nvl = nvlist_unpack(result_buf, req.result_len, 0);
+ if (req.result_nvl == NULL) {
+ log_warnx("error unpacking result nvlist");
+ return (1);
+ }
+
+ port->p_ctl_port = nvlist_get_number(req.result_nvl, "port_id");
+ nvlist_destroy(req.result_nvl);
} else if (port->p_pport) {
port->p_ctl_port = port->p_pport->pp_ctl_port;
@@ -1116,7 +1128,6 @@
struct ctl_port_entry entry;
struct ctl_lun_map lm;
struct ctl_req req;
- char tagstr[16];
struct target *targ = port->p_target;
struct portal_group *pg = port->p_portal_group;
int error;
@@ -1130,20 +1141,35 @@
return (-1);
}
- /* Remove iSCSI port. */
- if (port->p_portal_group) {
+ /* Remove iSCSI or ioctl port. */
+ if (port->p_portal_group || port->p_ioctl_port) {
bzero(&req, sizeof(req));
- strlcpy(req.driver, "iscsi", sizeof(req.driver));
+ strlcpy(req.driver, port->p_ioctl_port ? "ioctl" : "iscsi",
+ sizeof(req.driver));
req.reqtype = CTL_REQ_REMOVE;
- req.num_args = 2;
- req.args = malloc(req.num_args * sizeof(*req.args));
- if (req.args == NULL)
- log_err(1, "malloc");
- str_arg(&req.args[0], "cfiscsi_target", targ->t_name);
- snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
- str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
+ req.args_nvl = nvlist_create(0);
+ if (req.args_nvl == NULL)
+ log_err(1, "nvlist_create");
+
+ if (port->p_ioctl_port)
+ nvlist_add_stringf(req.args_nvl, "port_id", "%d",
+ port->p_ctl_port);
+ else {
+ nvlist_add_string(req.args_nvl, "cfiscsi_target",
+ targ->t_name);
+ nvlist_add_stringf(req.args_nvl,
+ "cfiscsi_portal_group_tag", "%u", pg->pg_tag);
+ }
+
+ req.args = nvlist_pack(req.args_nvl, &req.args_len);
+ if (req.args == NULL) {
+ log_warn("error packing nvlist");
+ return (1);
+ }
+
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
- free(req.args);
+ nvlist_destroy(req.args_nvl);
+
if (error != 0) {
log_warn("error issuing CTL_PORT_REQ ioctl");
return (1);
Index: usr.sbin/ctld/parse.y
===================================================================
--- usr.sbin/ctld/parse.y
+++ usr.sbin/ctld/parse.y
@@ -768,28 +768,41 @@
{
struct pport *pp;
struct port *tp;
+ int ret, i_pp, i_vp = 0;
- pp = pport_find(conf, $2);
- if (pp == NULL) {
- log_warnx("unknown port \"%s\" for target \"%s\"",
- $2, target->t_name);
- free($2);
- return (1);
+ ret = sscanf($2, "ioctl/%d/%d", &i_pp, &i_vp);
+ if (ret > 0) {
+ tp = port_new_ioctl(conf, target, i_pp, i_vp);
+ if (tp == NULL) {
+ log_warnx("can't create new ioctl port for "
+ "target \"%s\"", target->t_name);
+ free($2);
+ return (1);
+ }
+ } else {
+ pp = pport_find(conf, $2);
+ if (pp == NULL) {
+ log_warnx("unknown port \"%s\" for target \"%s\"",
+ $2, target->t_name);
+ free($2);
+ return (1);
+ }
+ if (!TAILQ_EMPTY(&pp->pp_ports)) {
+ log_warnx("can't link port \"%s\" to target \"%s\", "
+ "port already linked to some target",
+ $2, target->t_name);
+ free($2);
+ return (1);
+ }
+ tp = port_new_pp(conf, target, pp);
+ if (tp == NULL) {
+ log_warnx("can't link port \"%s\" to target \"%s\"",
+ $2, target->t_name);
+ free($2);
+ return (1);
+ }
}
- if (!TAILQ_EMPTY(&pp->pp_ports)) {
- log_warnx("can't link port \"%s\" to target \"%s\", "
- "port already linked to some target",
- $2, target->t_name);
- free($2);
- return (1);
- }
- tp = port_new_pp(conf, target, pp);
- if (tp == NULL) {
- log_warnx("can't link port \"%s\" to target \"%s\"",
- $2, target->t_name);
- free($2);
- return (1);
- }
+
free($2);
}
;
Index: usr.sbin/ctld/uclparse.c
===================================================================
--- usr.sbin/ctld/uclparse.c
+++ usr.sbin/ctld/uclparse.c
@@ -758,6 +758,19 @@
struct pport *pp;
struct port *tp;
const char *value = ucl_object_tostring(obj);
+ int ret, i_pp, i_vp = 0;
+
+ ret = sscanf(value, "ioctl/%d/%d", &i_pp, &i_vp);
+ if (ret > 0) {
+ tp = port_new_ioctl(conf, target, i_pp, i_vp);
+ if (tp == NULL) {
+ log_warnx("can't create new ioctl port "
+ "for target \"%s\"", target->t_name);
+ return (1);
+ }
+
+ return (0);
+ }
pp = pport_find(conf, value);
if (pp == NULL) {

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 27, 3:27 AM (16 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24267598
Default Alt Text
D9299.id41609.diff (79 KB)

Event Timeline