Author: araujo
Date: Thu May 10 03:50:20 2018
New Revision: 333446
URL: https://svnweb.freebsd.org/changeset/base/333446

Log:
  Rework CTL frontend & backend options to use nv(3), allow creating multiple
  ioctl frontend ports.
  
  This revision introduces two changes to CTL:
  - Changes the way options are passed to CTL_LUN_REQ and CTL_PORT_REQ ioctls.
    Removes ctl_be_arg structure and associated logic and replaces it with
    nv(3)-based logic for passing in and out arguments.
  - Allows creating multiple ioctl frontend ports using either ctladm(8) or
    ctld(8).
    New frontend ports are represented by /dev/cam/ctl<pp>.<vp> nodes, eg 
/dev/cam/ctl5.3.
    Those device nodes respond only to CTL_IO ioctl.
  
  New command-line options for ctladm:
  # creates new ioctl frontend port with using free pp and vp=0
  ctladm port -c
  # creates new ioctl frontend port with pp=10 and vp=0
  ctladm port -c -O pp=10
  # creates new ioctl frontend port with pp=11 and vp=12
  ctladm port -c -O pp=11 -O vp=12
  # removes port with number 4 (it's a "targ_port" number, not pp number)
  ctladm port -r -p 4
  
  New syntax for ctl.conf:
  target ... {
      port ioctl/<pp>
      ...
  }
  
  target ... {
      port ioctl/<pp>/<vp>
      ...
  
  Note: Most of this work was made by jceel@, thank you.
  
  Submitted by: jceel
  Reworked by:  myself
  Reviewed by:  mav (earlier versions and recently during the rework)
  Obtained from:  FreeNAS and TrueOS
  Relnotes:     Yes
  Sponsored by: iXsystems Inc.
  Differential Revision:        https://reviews.freebsd.org/D9299

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl.h
  head/sys/cam/ctl/ctl_backend.c
  head/sys/cam/ctl/ctl_backend.h
  head/sys/cam/ctl/ctl_backend_block.c
  head/sys/cam/ctl/ctl_backend_ramdisk.c
  head/sys/cam/ctl/ctl_frontend.c
  head/sys/cam/ctl/ctl_frontend.h
  head/sys/cam/ctl/ctl_frontend_ioctl.c
  head/sys/cam/ctl/ctl_frontend_iscsi.c
  head/sys/cam/ctl/ctl_ioctl.h
  head/sys/cam/ctl/ctl_tpc.c
  head/sys/sys/param.h
  head/usr.sbin/ctladm/Makefile
  head/usr.sbin/ctladm/ctladm.8
  head/usr.sbin/ctladm/ctladm.c
  head/usr.sbin/ctld/Makefile
  head/usr.sbin/ctld/ctld.c
  head/usr.sbin/ctld/ctld.h
  head/usr.sbin/ctld/kernel.c
  head/usr.sbin/ctld/parse.y
  head/usr.sbin/ctld/uclparse.c

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c      Thu May 10 02:31:54 2018        (r333445)
+++ head/sys/cam/ctl/ctl.c      Thu May 10 03:50:20 2018        (r333446)
@@ -4,6 +4,8 @@
  * Copyright (c) 2003-2009 Silicon Graphics International Corp.
  * Copyright (c) 2012 The FreeBSD Foundation
  * Copyright (c) 2014-2017 Alexander Motin <m...@freebsd.org>
+ * Copyright (c) 2017 Jakub Wojciech Klama <jc...@freebsd.org>
+ * Copyright (c) 2018 Marcelo Araujo <ara...@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, ch
        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, 
        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, 
                                 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->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 +3147,20 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, 
                                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, 
        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, 
                            "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, 
                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, 
                                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_
            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_
        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
 {
        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
                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
                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 all
        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 all
        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));

Modified: head/sys/cam/ctl/ctl.h
==============================================================================
--- head/sys/cam/ctl/ctl.h      Thu May 10 02:31:54 2018        (r333445)
+++ head/sys/cam/ctl/ctl.h      Thu May 10 03:50:20 2018        (r333446)
@@ -196,24 +196,6 @@ void ctl_isc_announce_iid(struct ctl_port *port, int i
 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 */

Modified: head/sys/cam/ctl/ctl_backend.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend.c      Thu May 10 02:31:54 2018        
(r333445)
+++ head/sys/cam/ctl/ctl_backend.c      Thu May 10 03:50:20 2018        
(r333446)
@@ -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));
-}

Modified: head/sys/cam/ctl/ctl_backend.h
==============================================================================
--- head/sys/cam/ctl/ctl_backend.h      Thu May 10 02:31:54 2018        
(r333445)
+++ head/sys/cam/ctl/ctl_backend.h      Thu May 10 03:50:20 2018        
(r333446)
@@ -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 */
 };
 

Modified: head/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_block.c        Thu May 10 02:31:54 2018        
(r333445)
+++ head/sys/cam/ctl/ctl_backend_block.c        Thu May 10 03:50:20 2018        
(r333446)
@@ -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_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
        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
                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_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,
        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,
                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,
                    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, str
 {
        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, str
        }
        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, str
        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_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, 
        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, 
                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, 
                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, stru
 
        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_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, 
 
        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;

Modified: head/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_ramdisk.c      Thu May 10 02:31:54 2018        
(r333445)
+++ head/sys/cam/ctl/ctl_backend_ramdisk.c      Thu May 10 03:50:20 2018        
(r333446)
@@ -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 *so
        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
        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
        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

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to