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

Merge branch 'for-linus' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:
"A small collection of fixes that should go into this series. This
contains:

- NVMe pull request from Christoph, with various fixes for nvme
proper and nvme-fc.

- disable runtime PM for blk-mq for now.

With scsi now defaulting to using blk-mq, this reared its head as
an issue. Longer term we'll fix up runtime PM for blk-mq, for now
just disable it to prevent a hang on laptop resume for some folks.

- blk-mq CPU <-> hw queue map fix from Christoph.

- xen/blkfront pull request from Konrad, with two small fixes for the
blkfront driver.

- a few fixups for nbd from Joseph.

- a stable fix for pblk from Javier"

* 'for-linus' of git://git.kernel.dk/linux-block:
lightnvm: pblk: advance bio according to lba index
nvme: validate admin queue before unquiesce
nbd: clear disconnected on reconnect
nvme-pci: fix HMB size calculation
nvme-fc: revise TRADDR parsing
nvme-fc: address target disconnect race conditions in fcp io submit
nvme: fabrics commands should use the fctype field for data direction
nvme: also provide a UUID in the WWID sysfs attribute
xen/blkfront: always allocate grants first from per-queue persistent grants
xen-blkfront: fix mq start/stop race
blk-mq: map queues to all present CPUs
block: disable runtime-pm for blk-mq
xen-blkfront: Fix handling of non-supported operations
nbd: only set sndtimeo if we have a timeout set
nbd: take tx_lock before disconnecting
nbd: allow multiple disconnects to be sent

+197 -138
+4
block/blk-core.c
··· 3421 3421 */ 3422 3422 void blk_pm_runtime_init(struct request_queue *q, struct device *dev) 3423 3423 { 3424 + /* not support for RQF_PM and ->rpm_status in blk-mq yet */ 3425 + if (q->mq_ops) 3426 + return; 3427 + 3424 3428 q->dev = dev; 3425 3429 q->rpm_status = RPM_ACTIVE; 3426 3430 pm_runtime_set_autosuspend_delay(q->dev, -1);
+2 -2
block/blk-mq-cpumap.c
··· 17 17 static int cpu_to_queue_index(unsigned int nr_queues, const int cpu) 18 18 { 19 19 /* 20 - * Non online CPU will be mapped to queue index 0. 20 + * Non present CPU will be mapped to queue index 0. 21 21 */ 22 - if (!cpu_online(cpu)) 22 + if (!cpu_present(cpu)) 23 23 return 0; 24 24 return cpu % nr_queues; 25 25 }
+13 -5
drivers/block/nbd.c
··· 908 908 continue; 909 909 } 910 910 sk_set_memalloc(sock->sk); 911 - sock->sk->sk_sndtimeo = nbd->tag_set.timeout; 911 + if (nbd->tag_set.timeout) 912 + sock->sk->sk_sndtimeo = nbd->tag_set.timeout; 912 913 atomic_inc(&config->recv_threads); 913 914 refcount_inc(&nbd->config_refs); 914 915 old = nsock->sock; ··· 922 921 nsock->cookie++; 923 922 mutex_unlock(&nsock->tx_lock); 924 923 sockfd_put(old); 924 + 925 + clear_bit(NBD_DISCONNECTED, &config->runtime_flags); 925 926 926 927 /* We take the tx_mutex in an error path in the recv_work, so we 927 928 * need to queue_work outside of the tx_mutex. ··· 981 978 int i, ret; 982 979 983 980 for (i = 0; i < config->num_connections; i++) { 981 + struct nbd_sock *nsock = config->socks[i]; 982 + 984 983 iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request)); 984 + mutex_lock(&nsock->tx_lock); 985 985 ret = sock_xmit(nbd, i, 1, &from, 0, NULL); 986 986 if (ret <= 0) 987 987 dev_err(disk_to_dev(nbd->disk), 988 988 "Send disconnect failed %d\n", ret); 989 + mutex_unlock(&nsock->tx_lock); 989 990 } 990 991 } 991 992 ··· 998 991 struct nbd_config *config = nbd->config; 999 992 1000 993 dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n"); 1001 - if (!test_and_set_bit(NBD_DISCONNECT_REQUESTED, 1002 - &config->runtime_flags)) 1003 - send_disconnects(nbd); 994 + set_bit(NBD_DISCONNECT_REQUESTED, &config->runtime_flags); 995 + send_disconnects(nbd); 1004 996 return 0; 1005 997 } 1006 998 ··· 1080 1074 return -ENOMEM; 1081 1075 } 1082 1076 sk_set_memalloc(config->socks[i]->sock->sk); 1083 - config->socks[i]->sock->sk->sk_sndtimeo = nbd->tag_set.timeout; 1077 + if (nbd->tag_set.timeout) 1078 + config->socks[i]->sock->sk->sk_sndtimeo = 1079 + nbd->tag_set.timeout; 1084 1080 atomic_inc(&config->recv_threads); 1085 1081 refcount_inc(&nbd->config_refs); 1086 1082 INIT_WORK(&args->work, recv_work);
+14 -11
drivers/block/xen-blkfront.c
··· 111 111 }; 112 112 113 113 struct blkif_req { 114 - int error; 114 + blk_status_t error; 115 115 }; 116 116 117 117 static inline struct blkif_req *blkif_req(struct request *rq) ··· 708 708 * existing persistent grants, or if we have to get new grants, 709 709 * as there are not sufficiently many free. 710 710 */ 711 + bool new_persistent_gnts = false; 711 712 struct scatterlist *sg; 712 713 int num_sg, max_grefs, num_grant; 713 714 ··· 720 719 */ 721 720 max_grefs += INDIRECT_GREFS(max_grefs); 722 721 723 - /* 724 - * We have to reserve 'max_grefs' grants because persistent 725 - * grants are shared by all rings. 726 - */ 727 - if (max_grefs > 0) 728 - if (gnttab_alloc_grant_references(max_grefs, &setup.gref_head) < 0) { 722 + /* Check if we have enough persistent grants to allocate a requests */ 723 + if (rinfo->persistent_gnts_c < max_grefs) { 724 + new_persistent_gnts = true; 725 + 726 + if (gnttab_alloc_grant_references( 727 + max_grefs - rinfo->persistent_gnts_c, 728 + &setup.gref_head) < 0) { 729 729 gnttab_request_free_callback( 730 730 &rinfo->callback, 731 731 blkif_restart_queue_callback, 732 732 rinfo, 733 - max_grefs); 733 + max_grefs - rinfo->persistent_gnts_c); 734 734 return 1; 735 735 } 736 + } 736 737 737 738 /* Fill out a communications ring structure. */ 738 739 id = blkif_ring_get_request(rinfo, req, &ring_req); ··· 835 832 if (unlikely(require_extra_req)) 836 833 rinfo->shadow[extra_id].req = *extra_ring_req; 837 834 838 - if (max_grefs > 0) 835 + if (new_persistent_gnts) 839 836 gnttab_free_grant_references(setup.gref_head); 840 837 841 838 return 0; ··· 909 906 return BLK_STS_IOERR; 910 907 911 908 out_busy: 912 - spin_unlock_irqrestore(&rinfo->ring_lock, flags); 913 909 blk_mq_stop_hw_queue(hctx); 910 + spin_unlock_irqrestore(&rinfo->ring_lock, flags); 914 911 return BLK_STS_RESOURCE; 915 912 } 916 913 ··· 1619 1616 if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { 1620 1617 printk(KERN_WARNING "blkfront: %s: %s op failed\n", 1621 1618 info->gd->disk_name, op_name(bret->operation)); 1622 - blkif_req(req)->error = -EOPNOTSUPP; 1619 + blkif_req(req)->error = BLK_STS_NOTSUPP; 1623 1620 } 1624 1621 if (unlikely(bret->status == BLKIF_RSP_ERROR && 1625 1622 rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
+2 -2
drivers/lightnvm/pblk-rb.c
··· 657 657 * be directed to disk. 658 658 */ 659 659 int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba, 660 - struct ppa_addr ppa, int bio_iter) 660 + struct ppa_addr ppa, int bio_iter, bool advanced_bio) 661 661 { 662 662 struct pblk *pblk = container_of(rb, struct pblk, rwb); 663 663 struct pblk_rb_entry *entry; ··· 694 694 * filled with data from the cache). If part of the data resides on the 695 695 * media, we will read later on 696 696 */ 697 - if (unlikely(!bio->bi_iter.bi_idx)) 697 + if (unlikely(!advanced_bio)) 698 698 bio_advance(bio, bio_iter * PBLK_EXPOSED_PAGE_SIZE); 699 699 700 700 data = bio_data(bio);
+16 -7
drivers/lightnvm/pblk-read.c
··· 26 26 */ 27 27 static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio, 28 28 sector_t lba, struct ppa_addr ppa, 29 - int bio_iter) 29 + int bio_iter, bool advanced_bio) 30 30 { 31 31 #ifdef CONFIG_NVM_DEBUG 32 32 /* Callers must ensure that the ppa points to a cache address */ ··· 34 34 BUG_ON(!pblk_addr_in_cache(ppa)); 35 35 #endif 36 36 37 - return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa, bio_iter); 37 + return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa, 38 + bio_iter, advanced_bio); 38 39 } 39 40 40 41 static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd, ··· 45 44 struct ppa_addr ppas[PBLK_MAX_REQ_ADDRS]; 46 45 sector_t blba = pblk_get_lba(bio); 47 46 int nr_secs = rqd->nr_ppas; 48 - int advanced_bio = 0; 47 + bool advanced_bio = false; 49 48 int i, j = 0; 50 49 51 50 /* logic error: lba out-of-bounds. Ignore read request */ ··· 63 62 retry: 64 63 if (pblk_ppa_empty(p)) { 65 64 WARN_ON(test_and_set_bit(i, read_bitmap)); 66 - continue; 65 + 66 + if (unlikely(!advanced_bio)) { 67 + bio_advance(bio, (i) * PBLK_EXPOSED_PAGE_SIZE); 68 + advanced_bio = true; 69 + } 70 + 71 + goto next; 67 72 } 68 73 69 74 /* Try to read from write buffer. The address is later checked 70 75 * on the write buffer to prevent retrieving overwritten data. 71 76 */ 72 77 if (pblk_addr_in_cache(p)) { 73 - if (!pblk_read_from_cache(pblk, bio, lba, p, i)) { 78 + if (!pblk_read_from_cache(pblk, bio, lba, p, i, 79 + advanced_bio)) { 74 80 pblk_lookup_l2p_seq(pblk, &p, lba, 1); 75 81 goto retry; 76 82 } 77 83 WARN_ON(test_and_set_bit(i, read_bitmap)); 78 - advanced_bio = 1; 84 + advanced_bio = true; 79 85 #ifdef CONFIG_NVM_DEBUG 80 86 atomic_long_inc(&pblk->cache_reads); 81 87 #endif ··· 91 83 rqd->ppa_list[j++] = p; 92 84 } 93 85 86 + next: 94 87 if (advanced_bio) 95 88 bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE); 96 89 } ··· 291 282 * write buffer to prevent retrieving overwritten data. 292 283 */ 293 284 if (pblk_addr_in_cache(ppa)) { 294 - if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0)) { 285 + if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0, 1)) { 295 286 pblk_lookup_l2p_seq(pblk, &ppa, lba, 1); 296 287 goto retry; 297 288 }
+1 -1
drivers/lightnvm/pblk.h
··· 670 670 struct list_head *list, 671 671 unsigned int max); 672 672 int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba, 673 - struct ppa_addr ppa, int bio_iter); 673 + struct ppa_addr ppa, int bio_iter, bool advanced_bio); 674 674 unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries); 675 675 676 676 unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);
+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