@@ -1888,7 +1888,7 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
18881888 * the target device is present
18891889 */
18901890 if (ctrl -> rport -> remoteport .port_state != FC_OBJSTATE_ONLINE )
1891- return BLK_STS_IOERR ;
1891+ goto busy ;
18921892
18931893 if (!nvme_fc_ctrl_get (ctrl ))
18941894 return BLK_STS_IOERR ;
@@ -1958,22 +1958,25 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
19581958 queue -> lldd_handle , & op -> fcp_req );
19591959
19601960 if (ret ) {
1961- if (op -> rq ) /* normal request */
1961+ if (!( op -> flags & FCOP_FLAGS_AEN ))
19621962 nvme_fc_unmap_data (ctrl , op -> rq , op );
1963- /* else - aen. no cleanup needed */
19641963
19651964 nvme_fc_ctrl_put (ctrl );
19661965
1967- if (ret != - EBUSY )
1966+ if (ctrl -> rport -> remoteport .port_state == FC_OBJSTATE_ONLINE &&
1967+ ret != - EBUSY )
19681968 return BLK_STS_IOERR ;
19691969
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 ;
19741971 }
19751972
19761973 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 ;
19771980}
19781981
19791982static blk_status_t
@@ -2802,66 +2805,70 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
28022805 return ERR_PTR (ret );
28032806}
28042807
2805- enum {
2806- FCT_TRADDR_ERR = 0 ,
2807- FCT_TRADDR_WWNN = 1 << 0 ,
2808- FCT_TRADDR_WWPN = 1 << 1 ,
2809- };
28102808
28112809struct nvmet_fc_traddr {
28122810 u64 nn ;
28132811 u64 pn ;
28142812};
28152813
2816- static const match_table_t traddr_opt_tokens = {
2817- { FCT_TRADDR_WWNN , "nn-%s" },
2818- { FCT_TRADDR_WWPN , "pn-%s" },
2819- { FCT_TRADDR_ERR , NULL }
2820- };
2821-
28222814static int
2823- nvme_fc_parse_address ( struct nvmet_fc_traddr * traddr , char * buf )
2815+ __nvme_fc_parse_u64 ( substring_t * sstr , u64 * val )
28242816{
2825- substring_t args [MAX_OPT_ARGS ];
2826- char * options , * o , * p ;
2827- int token , ret = 0 ;
28282817 u64 token64 ;
28292818
2830- options = o = kstrdup ( buf , GFP_KERNEL );
2831- if (! options )
2832- return - ENOMEM ;
2819+ if ( match_u64 ( sstr , & token64 ))
2820+ return - EINVAL ;
2821+ * val = token64 ;
28332822
2834- while ((p = strsep (& o , ":\n" )) != NULL ) {
2835- if (!* p )
2836- continue ;
2823+ return 0 ;
2824+ }
28372825
2838- token = match_token (p , traddr_opt_tokens , args );
2839- switch (token ) {
2840- case FCT_TRADDR_WWNN :
2841- if (match_u64 (args , & token64 )) {
2842- ret = - EINVAL ;
2843- goto out ;
2844- }
2845- traddr -> nn = token64 ;
2846- break ;
2847- case FCT_TRADDR_WWPN :
2848- if (match_u64 (args , & token64 )) {
2849- ret = - EINVAL ;
2850- goto out ;
2851- }
2852- traddr -> pn = token64 ;
2853- break ;
2854- default :
2855- pr_warn ("unknown traddr token or missing value '%s'\n" ,
2856- p );
2857- ret = - EINVAL ;
2858- goto out ;
2859- }
2860- }
2826+ /*
2827+ * This routine validates and extracts the WWN's from the TRADDR string.
2828+ * As kernel parsers need the 0x to determine number base, universally
2829+ * build string to parse with 0x prefix before parsing name strings.
2830+ */
2831+ static int
2832+ nvme_fc_parse_traddr (struct nvmet_fc_traddr * traddr , char * buf , size_t blen )
2833+ {
2834+ char name [2 + NVME_FC_TRADDR_HEXNAMELEN + 1 ];
2835+ substring_t wwn = { name , & name [sizeof (name )- 1 ] };
2836+ int nnoffset , pnoffset ;
2837+
2838+ /* validate it string one of the 2 allowed formats */
2839+ if (strnlen (buf , blen ) == NVME_FC_TRADDR_MAXLENGTH &&
2840+ !strncmp (buf , "nn-0x" , NVME_FC_TRADDR_OXNNLEN ) &&
2841+ !strncmp (& buf [NVME_FC_TRADDR_MAX_PN_OFFSET ],
2842+ "pn-0x" , NVME_FC_TRADDR_OXNNLEN )) {
2843+ nnoffset = NVME_FC_TRADDR_OXNNLEN ;
2844+ pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET +
2845+ NVME_FC_TRADDR_OXNNLEN ;
2846+ } else if ((strnlen (buf , blen ) == NVME_FC_TRADDR_MINLENGTH &&
2847+ !strncmp (buf , "nn-" , NVME_FC_TRADDR_NNLEN ) &&
2848+ !strncmp (& buf [NVME_FC_TRADDR_MIN_PN_OFFSET ],
2849+ "pn-" , NVME_FC_TRADDR_NNLEN ))) {
2850+ nnoffset = NVME_FC_TRADDR_NNLEN ;
2851+ pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN ;
2852+ } else
2853+ goto out_einval ;
28612854
2862- out :
2863- kfree (options );
2864- return ret ;
2855+ name [0 ] = '0' ;
2856+ name [1 ] = 'x' ;
2857+ name [2 + NVME_FC_TRADDR_HEXNAMELEN ] = 0 ;
2858+
2859+ memcpy (& name [2 ], & buf [nnoffset ], NVME_FC_TRADDR_HEXNAMELEN );
2860+ if (__nvme_fc_parse_u64 (& wwn , & traddr -> nn ))
2861+ goto out_einval ;
2862+
2863+ memcpy (& name [2 ], & buf [pnoffset ], NVME_FC_TRADDR_HEXNAMELEN );
2864+ if (__nvme_fc_parse_u64 (& wwn , & traddr -> pn ))
2865+ goto out_einval ;
2866+
2867+ return 0 ;
2868+
2869+ out_einval :
2870+ pr_warn ("%s: bad traddr string\n" , __func__ );
2871+ return - EINVAL ;
28652872}
28662873
28672874static struct nvme_ctrl *
@@ -2875,11 +2882,11 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
28752882 unsigned long flags ;
28762883 int ret ;
28772884
2878- ret = nvme_fc_parse_address (& raddr , opts -> traddr );
2885+ ret = nvme_fc_parse_traddr (& raddr , opts -> traddr , NVMF_TRADDR_SIZE );
28792886 if (ret || !raddr .nn || !raddr .pn )
28802887 return ERR_PTR (- EINVAL );
28812888
2882- ret = nvme_fc_parse_address (& laddr , opts -> host_traddr );
2889+ ret = nvme_fc_parse_traddr (& laddr , opts -> host_traddr , NVMF_TRADDR_SIZE );
28832890 if (ret || !laddr .nn || !laddr .pn )
28842891 return ERR_PTR (- EINVAL );
28852892
0 commit comments