Date: Thu, 10 May 2018 03:50:20 +0000 (UTC) From: Marcelo Araujo <araujo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333446 - in head: sys/cam/ctl sys/sys usr.sbin/ctladm usr.sbin/ctld Message-ID: <201805100350.w4A3oKBe095134@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <mav@FreeBSD.org> + * Copyright (c) 2017 Jakub Wojciech Klama <jceel@FreeBSD.org> + * Copyright (c) 2018 Marcelo Araujo <araujo@FreeBSD.org> * All rights reserved. * * Portions of this software were developed by Edward Tomasz Napierala @@ -65,6 +67,8 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/endian.h> #include <sys/sysctl.h> +#include <sys/nv.h> +#include <sys/dnv.h> #include <vm/uma.h> #include <cam/cam.h> @@ -1869,6 +1873,7 @@ ctl_init(void) args.mda_gid = GID_OPERATOR; args.mda_mode = 0600; args.mda_si_drv1 = softc; + args.mda_si_drv2 = NULL; error = make_dev_s(&args, &softc->dev, "cam/ctl"); if (error != 0) { free(softc, M_DEVBUF); @@ -2468,105 +2473,6 @@ ctl_copyin_alloc(void *user_addr, unsigned int len, 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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805100350.w4A3oKBe095134>