···19951995 int serial_len = sizeof(ctrl->serial);19961996 int model_len = sizeof(ctrl->model);1997199719981998+ if (!uuid_is_null(&ns->uuid))19991999+ return sprintf(buf, "uuid.%pU\n", &ns->uuid);20002000+19982001 if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))19992002 return sprintf(buf, "eui.%16phN\n", ns->nguid);20002003···27122709 mutex_lock(&ctrl->namespaces_mutex);2713271027142711 /* Forcibly unquiesce queues to avoid blocking dispatch */27152715- blk_mq_unquiesce_queue(ctrl->admin_q);27122712+ if (ctrl->admin_q)27132713+ blk_mq_unquiesce_queue(ctrl->admin_q);2716271427172715 list_for_each_entry(ns, &ctrl->namespaces, list) {27182716 /*
+64-57
drivers/nvme/host/fc.c
···18881888 * the target device is present18891889 */18901890 if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)18911891- return BLK_STS_IOERR;18911891+ goto busy;1892189218931893 if (!nvme_fc_ctrl_get(ctrl))18941894 return BLK_STS_IOERR;···19581958 queue->lldd_handle, &op->fcp_req);1959195919601960 if (ret) {19611961- if (op->rq) /* normal request */19611961+ if (!(op->flags & FCOP_FLAGS_AEN))19621962 nvme_fc_unmap_data(ctrl, op->rq, op);19631963- /* else - aen. no cleanup needed */1964196319651964 nvme_fc_ctrl_put(ctrl);1966196519671967- if (ret != -EBUSY)19661966+ if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE &&19671967+ ret != -EBUSY)19681968 return BLK_STS_IOERR;1969196919701970- if (op->rq)19711971- blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY);19721972-19731973- return BLK_STS_RESOURCE;19701970+ goto busy;19741971 }1975197219761973 return BLK_STS_OK;19741974+19751975+busy:19761976+ if (!(op->flags & FCOP_FLAGS_AEN) && queue->hctx)19771977+ blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY);19781978+19791979+ return BLK_STS_RESOURCE;19771980}1978198119791982static blk_status_t···28052802 return ERR_PTR(ret);28062803}2807280428082808-enum {28092809- FCT_TRADDR_ERR = 0,28102810- FCT_TRADDR_WWNN = 1 << 0,28112811- FCT_TRADDR_WWPN = 1 << 1,28122812-};2813280528142806struct nvmet_fc_traddr {28152807 u64 nn;28162808 u64 pn;28172809};2818281028192819-static const match_table_t traddr_opt_tokens = {28202820- { FCT_TRADDR_WWNN, "nn-%s" },28212821- { FCT_TRADDR_WWPN, "pn-%s" },28222822- { FCT_TRADDR_ERR, NULL }28232823-};28242824-28252811static int28262826-nvme_fc_parse_address(struct nvmet_fc_traddr *traddr, char *buf)28122812+__nvme_fc_parse_u64(substring_t *sstr, u64 *val)28272813{28282828- substring_t args[MAX_OPT_ARGS];28292829- char *options, *o, *p;28302830- int token, ret = 0;28312814 u64 token64;2832281528332833- options = o = kstrdup(buf, GFP_KERNEL);28342834- if (!options)28352835- return -ENOMEM;28162816+ if (match_u64(sstr, &token64))28172817+ return -EINVAL;28182818+ *val = token64;2836281928372837- while ((p = strsep(&o, ":\n")) != NULL) {28382838- if (!*p)28392839- continue;28202820+ return 0;28212821+}2840282228412841- token = match_token(p, traddr_opt_tokens, args);28422842- switch (token) {28432843- case FCT_TRADDR_WWNN:28442844- if (match_u64(args, &token64)) {28452845- ret = -EINVAL;28462846- goto out;28472847- }28482848- traddr->nn = token64;28492849- break;28502850- case FCT_TRADDR_WWPN:28512851- if (match_u64(args, &token64)) {28522852- ret = -EINVAL;28532853- goto out;28542854- }28552855- traddr->pn = token64;28562856- break;28572857- default:28582858- pr_warn("unknown traddr token or missing value '%s'\n",28592859- p);28602860- ret = -EINVAL;28612861- goto out;28622862- }28632863- }28232823+/*28242824+ * This routine validates and extracts the WWN's from the TRADDR string.28252825+ * As kernel parsers need the 0x to determine number base, universally28262826+ * build string to parse with 0x prefix before parsing name strings.28272827+ */28282828+static int28292829+nvme_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf, size_t blen)28302830+{28312831+ char name[2 + NVME_FC_TRADDR_HEXNAMELEN + 1];28322832+ substring_t wwn = { name, &name[sizeof(name)-1] };28332833+ int nnoffset, pnoffset;2864283428652865-out:28662866- kfree(options);28672867- return ret;28352835+ /* validate it string one of the 2 allowed formats */28362836+ if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH &&28372837+ !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) &&28382838+ !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET],28392839+ "pn-0x", NVME_FC_TRADDR_OXNNLEN)) {28402840+ nnoffset = NVME_FC_TRADDR_OXNNLEN;28412841+ pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET +28422842+ NVME_FC_TRADDR_OXNNLEN;28432843+ } else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH &&28442844+ !strncmp(buf, "nn-", NVME_FC_TRADDR_NNLEN) &&28452845+ !strncmp(&buf[NVME_FC_TRADDR_MIN_PN_OFFSET],28462846+ "pn-", NVME_FC_TRADDR_NNLEN))) {28472847+ nnoffset = NVME_FC_TRADDR_NNLEN;28482848+ pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN;28492849+ } else28502850+ goto out_einval;28512851+28522852+ name[0] = '0';28532853+ name[1] = 'x';28542854+ name[2 + NVME_FC_TRADDR_HEXNAMELEN] = 0;28552855+28562856+ memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN);28572857+ if (__nvme_fc_parse_u64(&wwn, &traddr->nn))28582858+ goto out_einval;28592859+28602860+ memcpy(&name[2], &buf[pnoffset], NVME_FC_TRADDR_HEXNAMELEN);28612861+ if (__nvme_fc_parse_u64(&wwn, &traddr->pn))28622862+ goto out_einval;28632863+28642864+ return 0;28652865+28662866+out_einval:28672867+ pr_warn("%s: bad traddr string\n", __func__);28682868+ return -EINVAL;28682869}2869287028702871static struct nvme_ctrl *···28822875 unsigned long flags;28832876 int ret;2884287728852885- ret = nvme_fc_parse_address(&raddr, opts->traddr);28782878+ ret = nvme_fc_parse_traddr(&raddr, opts->traddr, NVMF_TRADDR_SIZE);28862879 if (ret || !raddr.nn || !raddr.pn)28872880 return ERR_PTR(-EINVAL);2888288128892889- ret = nvme_fc_parse_address(&laddr, opts->host_traddr);28822882+ ret = nvme_fc_parse_traddr(&laddr, opts->host_traddr, NVMF_TRADDR_SIZE);28902883 if (ret || !laddr.nn || !laddr.pn)28912884 return ERR_PTR(-EINVAL);28922885
+3-3
drivers/nvme/host/pci.c
···16191619static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)16201620{16211621 struct nvme_host_mem_buf_desc *descs;16221622- u32 chunk_size, max_entries;16221622+ u32 chunk_size, max_entries, len;16231623 int i = 0;16241624 void **bufs;16251625 u64 size = 0, tmp;···16381638 if (!bufs)16391639 goto out_free_descs;1640164016411641- for (size = 0; size < preferred; size += chunk_size) {16421642- u32 len = min_t(u64, chunk_size, preferred - size);16411641+ for (size = 0; size < preferred; size += len) {16431642 dma_addr_t dma_addr;1644164316441644+ len = min_t(u64, chunk_size, preferred - size);16451645 bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL,16461646 DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);16471647 if (!bufs[i])
+53-48
drivers/nvme/target/fc.c
···22932293}22942294EXPORT_SYMBOL_GPL(nvmet_fc_rcv_fcp_abort);2295229522962296-enum {22972297- FCT_TRADDR_ERR = 0,22982298- FCT_TRADDR_WWNN = 1 << 0,22992299- FCT_TRADDR_WWPN = 1 << 1,23002300-};2301229623022297struct nvmet_fc_traddr {23032298 u64 nn;23042299 u64 pn;23052300};2306230123072307-static const match_table_t traddr_opt_tokens = {23082308- { FCT_TRADDR_WWNN, "nn-%s" },23092309- { FCT_TRADDR_WWPN, "pn-%s" },23102310- { FCT_TRADDR_ERR, NULL }23112311-};23122312-23132302static int23142314-nvmet_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf)23032303+__nvme_fc_parse_u64(substring_t *sstr, u64 *val)23152304{23162316- substring_t args[MAX_OPT_ARGS];23172317- char *options, *o, *p;23182318- int token, ret = 0;23192305 u64 token64;2320230623212321- options = o = kstrdup(buf, GFP_KERNEL);23222322- if (!options)23232323- return -ENOMEM;23072307+ if (match_u64(sstr, &token64))23082308+ return -EINVAL;23092309+ *val = token64;2324231023252325- while ((p = strsep(&o, ":\n")) != NULL) {23262326- if (!*p)23272327- continue;23112311+ return 0;23122312+}2328231323292329- token = match_token(p, traddr_opt_tokens, args);23302330- switch (token) {23312331- case FCT_TRADDR_WWNN:23322332- if (match_u64(args, &token64)) {23332333- ret = -EINVAL;23342334- goto out;23352335- }23362336- traddr->nn = token64;23372337- break;23382338- case FCT_TRADDR_WWPN:23392339- if (match_u64(args, &token64)) {23402340- ret = -EINVAL;23412341- goto out;23422342- }23432343- traddr->pn = token64;23442344- break;23452345- default:23462346- pr_warn("unknown traddr token or missing value '%s'\n",23472347- p);23482348- ret = -EINVAL;23492349- goto out;23502350- }23512351- }23142314+/*23152315+ * This routine validates and extracts the WWN's from the TRADDR string.23162316+ * As kernel parsers need the 0x to determine number base, universally23172317+ * build string to parse with 0x prefix before parsing name strings.23182318+ */23192319+static int23202320+nvme_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf, size_t blen)23212321+{23222322+ char name[2 + NVME_FC_TRADDR_HEXNAMELEN + 1];23232323+ substring_t wwn = { name, &name[sizeof(name)-1] };23242324+ int nnoffset, pnoffset;2352232523532353-out:23542354- kfree(options);23552355- return ret;23262326+ /* validate it string one of the 2 allowed formats */23272327+ if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH &&23282328+ !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) &&23292329+ !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET],23302330+ "pn-0x", NVME_FC_TRADDR_OXNNLEN)) {23312331+ nnoffset = NVME_FC_TRADDR_OXNNLEN;23322332+ pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET +23332333+ NVME_FC_TRADDR_OXNNLEN;23342334+ } else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH &&23352335+ !strncmp(buf, "nn-", NVME_FC_TRADDR_NNLEN) &&23362336+ !strncmp(&buf[NVME_FC_TRADDR_MIN_PN_OFFSET],23372337+ "pn-", NVME_FC_TRADDR_NNLEN))) {23382338+ nnoffset = NVME_FC_TRADDR_NNLEN;23392339+ pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN;23402340+ } else23412341+ goto out_einval;23422342+23432343+ name[0] = '0';23442344+ name[1] = 'x';23452345+ name[2 + NVME_FC_TRADDR_HEXNAMELEN] = 0;23462346+23472347+ memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN);23482348+ if (__nvme_fc_parse_u64(&wwn, &traddr->nn))23492349+ goto out_einval;23502350+23512351+ memcpy(&name[2], &buf[pnoffset], NVME_FC_TRADDR_HEXNAMELEN);23522352+ if (__nvme_fc_parse_u64(&wwn, &traddr->pn))23532353+ goto out_einval;23542354+23552355+ return 0;23562356+23572357+out_einval:23582358+ pr_warn("%s: bad traddr string\n", __func__);23592359+ return -EINVAL;23562360}2357236123582362static int···2374237023752371 /* map the traddr address info to a target port */2376237223772377- ret = nvmet_fc_parse_traddr(&traddr, port->disc_addr.traddr);23732373+ ret = nvme_fc_parse_traddr(&traddr, port->disc_addr.traddr,23742374+ sizeof(port->disc_addr.traddr));23782375 if (ret)23792376 return ret;23802377
+19
include/linux/nvme-fc.h
···334334#define NVME_FC_LS_TIMEOUT_SEC 2 /* 2 seconds */335335#define NVME_FC_TGTOP_TIMEOUT_SEC 2 /* 2 seconds */336336337337+/*338338+ * TRADDR string must be of form "nn-<16hexdigits>:pn-<16hexdigits>"339339+ * the string is allowed to be specified with or without a "0x" prefix340340+ * infront of the <16hexdigits>. Without is considered the "min" string341341+ * and with is considered the "max" string. The hexdigits may be upper342342+ * or lower case.343343+ */344344+#define NVME_FC_TRADDR_NNLEN 3 /* "?n-" */345345+#define NVME_FC_TRADDR_OXNNLEN 5 /* "?n-0x" */346346+#define NVME_FC_TRADDR_HEXNAMELEN 16347347+#define NVME_FC_TRADDR_MINLENGTH \348348+ (2 * (NVME_FC_TRADDR_NNLEN + NVME_FC_TRADDR_HEXNAMELEN) + 1)349349+#define NVME_FC_TRADDR_MAXLENGTH \350350+ (2 * (NVME_FC_TRADDR_OXNNLEN + NVME_FC_TRADDR_HEXNAMELEN) + 1)351351+#define NVME_FC_TRADDR_MIN_PN_OFFSET \352352+ (NVME_FC_TRADDR_NNLEN + NVME_FC_TRADDR_HEXNAMELEN + 1)353353+#define NVME_FC_TRADDR_MAX_PN_OFFSET \354354+ (NVME_FC_TRADDR_OXNNLEN + NVME_FC_TRADDR_HEXNAMELEN + 1)355355+337356338357#endif /* _NVME_FC_H */
+1-1
include/linux/nvme.h
···10061006 * Why can't we simply have a Fabrics In and Fabrics out command?10071007 */10081008 if (unlikely(cmd->common.opcode == nvme_fabrics_command))10091009- return cmd->fabrics.opcode & 1;10091009+ return cmd->fabrics.fctype & 1;10101010 return cmd->common.opcode & 1;10111011}10121012