Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'nvme-4.13' of git://git.infradead.org/nvme into for-linus

Pull NVMe fixes from Christoph

+145 -110
+5 -1
drivers/nvme/host/core.c
··· 1995 1995 int serial_len = sizeof(ctrl->serial); 1996 1996 int model_len = sizeof(ctrl->model); 1997 1997 1998 + if (!uuid_is_null(&ns->uuid)) 1999 + return sprintf(buf, "uuid.%pU\n", &ns->uuid); 2000 + 1998 2001 if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) 1999 2002 return sprintf(buf, "eui.%16phN\n", ns->nguid); 2000 2003 ··· 2712 2709 mutex_lock(&ctrl->namespaces_mutex); 2713 2710 2714 2711 /* Forcibly unquiesce queues to avoid blocking dispatch */ 2715 - blk_mq_unquiesce_queue(ctrl->admin_q); 2712 + if (ctrl->admin_q) 2713 + blk_mq_unquiesce_queue(ctrl->admin_q); 2716 2714 2717 2715 list_for_each_entry(ns, &ctrl->namespaces, list) { 2718 2716 /*
+64 -57
drivers/nvme/host/fc.c
··· 1888 1888 * the target device is present 1889 1889 */ 1890 1890 if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE) 1891 - return BLK_STS_IOERR; 1891 + goto busy; 1892 1892 1893 1893 if (!nvme_fc_ctrl_get(ctrl)) 1894 1894 return BLK_STS_IOERR; ··· 1958 1958 queue->lldd_handle, &op->fcp_req); 1959 1959 1960 1960 if (ret) { 1961 - if (op->rq) /* normal request */ 1961 + if (!(op->flags & FCOP_FLAGS_AEN)) 1962 1962 nvme_fc_unmap_data(ctrl, op->rq, op); 1963 - /* else - aen. no cleanup needed */ 1964 1963 1965 1964 nvme_fc_ctrl_put(ctrl); 1966 1965 1967 - if (ret != -EBUSY) 1966 + if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE && 1967 + ret != -EBUSY) 1968 1968 return BLK_STS_IOERR; 1969 1969 1970 - if (op->rq) 1971 - blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY); 1972 - 1973 - return BLK_STS_RESOURCE; 1970 + goto busy; 1974 1971 } 1975 1972 1976 1973 return BLK_STS_OK; 1974 + 1975 + busy: 1976 + if (!(op->flags & FCOP_FLAGS_AEN) && queue->hctx) 1977 + blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY); 1978 + 1979 + return BLK_STS_RESOURCE; 1977 1980 } 1978 1981 1979 1982 static blk_status_t ··· 2805 2802 return ERR_PTR(ret); 2806 2803 } 2807 2804 2808 - enum { 2809 - FCT_TRADDR_ERR = 0, 2810 - FCT_TRADDR_WWNN = 1 << 0, 2811 - FCT_TRADDR_WWPN = 1 << 1, 2812 - }; 2813 2805 2814 2806 struct nvmet_fc_traddr { 2815 2807 u64 nn; 2816 2808 u64 pn; 2817 2809 }; 2818 2810 2819 - static const match_table_t traddr_opt_tokens = { 2820 - { FCT_TRADDR_WWNN, "nn-%s" }, 2821 - { FCT_TRADDR_WWPN, "pn-%s" }, 2822 - { FCT_TRADDR_ERR, NULL } 2823 - }; 2824 - 2825 2811 static int 2826 - nvme_fc_parse_address(struct nvmet_fc_traddr *traddr, char *buf) 2812 + __nvme_fc_parse_u64(substring_t *sstr, u64 *val) 2827 2813 { 2828 - substring_t args[MAX_OPT_ARGS]; 2829 - char *options, *o, *p; 2830 - int token, ret = 0; 2831 2814 u64 token64; 2832 2815 2833 - options = o = kstrdup(buf, GFP_KERNEL); 2834 - if (!options) 2835 - return -ENOMEM; 2816 + if (match_u64(sstr, &token64)) 2817 + return -EINVAL; 2818 + *val = token64; 2836 2819 2837 - while ((p = strsep(&o, ":\n")) != NULL) { 2838 - if (!*p) 2839 - continue; 2820 + return 0; 2821 + } 2840 2822 2841 - token = match_token(p, traddr_opt_tokens, args); 2842 - switch (token) { 2843 - case FCT_TRADDR_WWNN: 2844 - if (match_u64(args, &token64)) { 2845 - ret = -EINVAL; 2846 - goto out; 2847 - } 2848 - traddr->nn = token64; 2849 - break; 2850 - case FCT_TRADDR_WWPN: 2851 - if (match_u64(args, &token64)) { 2852 - ret = -EINVAL; 2853 - goto out; 2854 - } 2855 - traddr->pn = token64; 2856 - break; 2857 - default: 2858 - pr_warn("unknown traddr token or missing value '%s'\n", 2859 - p); 2860 - ret = -EINVAL; 2861 - goto out; 2862 - } 2863 - } 2823 + /* 2824 + * This routine validates and extracts the WWN's from the TRADDR string. 2825 + * As kernel parsers need the 0x to determine number base, universally 2826 + * build string to parse with 0x prefix before parsing name strings. 2827 + */ 2828 + static int 2829 + nvme_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf, size_t blen) 2830 + { 2831 + char name[2 + NVME_FC_TRADDR_HEXNAMELEN + 1]; 2832 + substring_t wwn = { name, &name[sizeof(name)-1] }; 2833 + int nnoffset, pnoffset; 2864 2834 2865 - out: 2866 - kfree(options); 2867 - return ret; 2835 + /* validate it string one of the 2 allowed formats */ 2836 + if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH && 2837 + !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) && 2838 + !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET], 2839 + "pn-0x", NVME_FC_TRADDR_OXNNLEN)) { 2840 + nnoffset = NVME_FC_TRADDR_OXNNLEN; 2841 + pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET + 2842 + NVME_FC_TRADDR_OXNNLEN; 2843 + } else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH && 2844 + !strncmp(buf, "nn-", NVME_FC_TRADDR_NNLEN) && 2845 + !strncmp(&buf[NVME_FC_TRADDR_MIN_PN_OFFSET], 2846 + "pn-", NVME_FC_TRADDR_NNLEN))) { 2847 + nnoffset = NVME_FC_TRADDR_NNLEN; 2848 + pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN; 2849 + } else 2850 + goto out_einval; 2851 + 2852 + name[0] = '0'; 2853 + name[1] = 'x'; 2854 + name[2 + NVME_FC_TRADDR_HEXNAMELEN] = 0; 2855 + 2856 + memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN); 2857 + if (__nvme_fc_parse_u64(&wwn, &traddr->nn)) 2858 + goto out_einval; 2859 + 2860 + memcpy(&name[2], &buf[pnoffset], NVME_FC_TRADDR_HEXNAMELEN); 2861 + if (__nvme_fc_parse_u64(&wwn, &traddr->pn)) 2862 + goto out_einval; 2863 + 2864 + return 0; 2865 + 2866 + out_einval: 2867 + pr_warn("%s: bad traddr string\n", __func__); 2868 + return -EINVAL; 2868 2869 } 2869 2870 2870 2871 static struct nvme_ctrl * ··· 2882 2875 unsigned long flags; 2883 2876 int ret; 2884 2877 2885 - ret = nvme_fc_parse_address(&raddr, opts->traddr); 2878 + ret = nvme_fc_parse_traddr(&raddr, opts->traddr, NVMF_TRADDR_SIZE); 2886 2879 if (ret || !raddr.nn || !raddr.pn) 2887 2880 return ERR_PTR(-EINVAL); 2888 2881 2889 - ret = nvme_fc_parse_address(&laddr, opts->host_traddr); 2882 + ret = nvme_fc_parse_traddr(&laddr, opts->host_traddr, NVMF_TRADDR_SIZE); 2890 2883 if (ret || !laddr.nn || !laddr.pn) 2891 2884 return ERR_PTR(-EINVAL); 2892 2885
+3 -3
drivers/nvme/host/pci.c
··· 1619 1619 static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred) 1620 1620 { 1621 1621 struct nvme_host_mem_buf_desc *descs; 1622 - u32 chunk_size, max_entries; 1622 + u32 chunk_size, max_entries, len; 1623 1623 int i = 0; 1624 1624 void **bufs; 1625 1625 u64 size = 0, tmp; ··· 1638 1638 if (!bufs) 1639 1639 goto out_free_descs; 1640 1640 1641 - for (size = 0; size < preferred; size += chunk_size) { 1642 - u32 len = min_t(u64, chunk_size, preferred - size); 1641 + for (size = 0; size < preferred; size += len) { 1643 1642 dma_addr_t dma_addr; 1644 1643 1644 + len = min_t(u64, chunk_size, preferred - size); 1645 1645 bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL, 1646 1646 DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN); 1647 1647 if (!bufs[i])
+53 -48
drivers/nvme/target/fc.c
··· 2293 2293 } 2294 2294 EXPORT_SYMBOL_GPL(nvmet_fc_rcv_fcp_abort); 2295 2295 2296 - enum { 2297 - FCT_TRADDR_ERR = 0, 2298 - FCT_TRADDR_WWNN = 1 << 0, 2299 - FCT_TRADDR_WWPN = 1 << 1, 2300 - }; 2301 2296 2302 2297 struct nvmet_fc_traddr { 2303 2298 u64 nn; 2304 2299 u64 pn; 2305 2300 }; 2306 2301 2307 - static const match_table_t traddr_opt_tokens = { 2308 - { FCT_TRADDR_WWNN, "nn-%s" }, 2309 - { FCT_TRADDR_WWPN, "pn-%s" }, 2310 - { FCT_TRADDR_ERR, NULL } 2311 - }; 2312 - 2313 2302 static int 2314 - nvmet_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf) 2303 + __nvme_fc_parse_u64(substring_t *sstr, u64 *val) 2315 2304 { 2316 - substring_t args[MAX_OPT_ARGS]; 2317 - char *options, *o, *p; 2318 - int token, ret = 0; 2319 2305 u64 token64; 2320 2306 2321 - options = o = kstrdup(buf, GFP_KERNEL); 2322 - if (!options) 2323 - return -ENOMEM; 2307 + if (match_u64(sstr, &token64)) 2308 + return -EINVAL; 2309 + *val = token64; 2324 2310 2325 - while ((p = strsep(&o, ":\n")) != NULL) { 2326 - if (!*p) 2327 - continue; 2311 + return 0; 2312 + } 2328 2313 2329 - token = match_token(p, traddr_opt_tokens, args); 2330 - switch (token) { 2331 - case FCT_TRADDR_WWNN: 2332 - if (match_u64(args, &token64)) { 2333 - ret = -EINVAL; 2334 - goto out; 2335 - } 2336 - traddr->nn = token64; 2337 - break; 2338 - case FCT_TRADDR_WWPN: 2339 - if (match_u64(args, &token64)) { 2340 - ret = -EINVAL; 2341 - goto out; 2342 - } 2343 - traddr->pn = token64; 2344 - break; 2345 - default: 2346 - pr_warn("unknown traddr token or missing value '%s'\n", 2347 - p); 2348 - ret = -EINVAL; 2349 - goto out; 2350 - } 2351 - } 2314 + /* 2315 + * This routine validates and extracts the WWN's from the TRADDR string. 2316 + * As kernel parsers need the 0x to determine number base, universally 2317 + * build string to parse with 0x prefix before parsing name strings. 2318 + */ 2319 + static int 2320 + nvme_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf, size_t blen) 2321 + { 2322 + char name[2 + NVME_FC_TRADDR_HEXNAMELEN + 1]; 2323 + substring_t wwn = { name, &name[sizeof(name)-1] }; 2324 + int nnoffset, pnoffset; 2352 2325 2353 - out: 2354 - kfree(options); 2355 - return ret; 2326 + /* validate it string one of the 2 allowed formats */ 2327 + if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH && 2328 + !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) && 2329 + !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET], 2330 + "pn-0x", NVME_FC_TRADDR_OXNNLEN)) { 2331 + nnoffset = NVME_FC_TRADDR_OXNNLEN; 2332 + pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET + 2333 + NVME_FC_TRADDR_OXNNLEN; 2334 + } else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH && 2335 + !strncmp(buf, "nn-", NVME_FC_TRADDR_NNLEN) && 2336 + !strncmp(&buf[NVME_FC_TRADDR_MIN_PN_OFFSET], 2337 + "pn-", NVME_FC_TRADDR_NNLEN))) { 2338 + nnoffset = NVME_FC_TRADDR_NNLEN; 2339 + pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN; 2340 + } else 2341 + goto out_einval; 2342 + 2343 + name[0] = '0'; 2344 + name[1] = 'x'; 2345 + name[2 + NVME_FC_TRADDR_HEXNAMELEN] = 0; 2346 + 2347 + memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN); 2348 + if (__nvme_fc_parse_u64(&wwn, &traddr->nn)) 2349 + goto out_einval; 2350 + 2351 + memcpy(&name[2], &buf[pnoffset], NVME_FC_TRADDR_HEXNAMELEN); 2352 + if (__nvme_fc_parse_u64(&wwn, &traddr->pn)) 2353 + goto out_einval; 2354 + 2355 + return 0; 2356 + 2357 + out_einval: 2358 + pr_warn("%s: bad traddr string\n", __func__); 2359 + return -EINVAL; 2356 2360 } 2357 2361 2358 2362 static int ··· 2374 2370 2375 2371 /* map the traddr address info to a target port */ 2376 2372 2377 - ret = nvmet_fc_parse_traddr(&traddr, port->disc_addr.traddr); 2373 + ret = nvme_fc_parse_traddr(&traddr, port->disc_addr.traddr, 2374 + sizeof(port->disc_addr.traddr)); 2378 2375 if (ret) 2379 2376 return ret; 2380 2377
+19
include/linux/nvme-fc.h
··· 334 334 #define NVME_FC_LS_TIMEOUT_SEC 2 /* 2 seconds */ 335 335 #define NVME_FC_TGTOP_TIMEOUT_SEC 2 /* 2 seconds */ 336 336 337 + /* 338 + * TRADDR string must be of form "nn-<16hexdigits>:pn-<16hexdigits>" 339 + * the string is allowed to be specified with or without a "0x" prefix 340 + * infront of the <16hexdigits>. Without is considered the "min" string 341 + * and with is considered the "max" string. The hexdigits may be upper 342 + * or lower case. 343 + */ 344 + #define NVME_FC_TRADDR_NNLEN 3 /* "?n-" */ 345 + #define NVME_FC_TRADDR_OXNNLEN 5 /* "?n-0x" */ 346 + #define NVME_FC_TRADDR_HEXNAMELEN 16 347 + #define NVME_FC_TRADDR_MINLENGTH \ 348 + (2 * (NVME_FC_TRADDR_NNLEN + NVME_FC_TRADDR_HEXNAMELEN) + 1) 349 + #define NVME_FC_TRADDR_MAXLENGTH \ 350 + (2 * (NVME_FC_TRADDR_OXNNLEN + NVME_FC_TRADDR_HEXNAMELEN) + 1) 351 + #define NVME_FC_TRADDR_MIN_PN_OFFSET \ 352 + (NVME_FC_TRADDR_NNLEN + NVME_FC_TRADDR_HEXNAMELEN + 1) 353 + #define NVME_FC_TRADDR_MAX_PN_OFFSET \ 354 + (NVME_FC_TRADDR_OXNNLEN + NVME_FC_TRADDR_HEXNAMELEN + 1) 355 + 337 356 338 357 #endif /* _NVME_FC_H */
+1 -1
include/linux/nvme.h
··· 1006 1006 * Why can't we simply have a Fabrics In and Fabrics out command? 1007 1007 */ 1008 1008 if (unlikely(cmd->common.opcode == nvme_fabrics_command)) 1009 - return cmd->fabrics.opcode & 1; 1009 + return cmd->fabrics.fctype & 1; 1010 1010 return cmd->common.opcode & 1; 1011 1011 } 1012 1012