Skip to content

Commit 5a60f4b

Browse files
committed
Merge branch 'nvme-4.13' of git://git.infradead.org/nvme into for-linus
Pull NVMe fixes from Christoph
2 parents e9193da + 7dd1ab1 commit 5a60f4b

File tree

6 files changed

+145
-110
lines changed

6 files changed

+145
-110
lines changed

drivers/nvme/host/core.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,9 @@ static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
19951995
int serial_len = sizeof(ctrl->serial);
19961996
int model_len = sizeof(ctrl->model);
19971997

1998+
if (!uuid_is_null(&ns->uuid))
1999+
return sprintf(buf, "uuid.%pU\n", &ns->uuid);
2000+
19982001
if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
19992002
return sprintf(buf, "eui.%16phN\n", ns->nguid);
20002003

@@ -2709,7 +2712,8 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
27092712
mutex_lock(&ctrl->namespaces_mutex);
27102713

27112714
/* Forcibly unquiesce queues to avoid blocking dispatch */
2712-
blk_mq_unquiesce_queue(ctrl->admin_q);
2715+
if (ctrl->admin_q)
2716+
blk_mq_unquiesce_queue(ctrl->admin_q);
27132717

27142718
list_for_each_entry(ns, &ctrl->namespaces, list) {
27152719
/*

drivers/nvme/host/fc.c

Lines changed: 64 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -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

19791982
static 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

28112809
struct 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-
28222814
static 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

28672874
static 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

drivers/nvme/host/pci.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,7 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
16191619
static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
16201620
{
16211621
struct nvme_host_mem_buf_desc *descs;
1622-
u32 chunk_size, max_entries;
1622+
u32 chunk_size, max_entries, len;
16231623
int i = 0;
16241624
void **bufs;
16251625
u64 size = 0, tmp;
@@ -1638,10 +1638,10 @@ static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
16381638
if (!bufs)
16391639
goto out_free_descs;
16401640

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) {
16431642
dma_addr_t dma_addr;
16441643

1644+
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])

drivers/nvme/target/fc.c

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,66 +2293,70 @@ nvmet_fc_rcv_fcp_abort(struct nvmet_fc_target_port *target_port,
22932293
}
22942294
EXPORT_SYMBOL_GPL(nvmet_fc_rcv_fcp_abort);
22952295

2296-
enum {
2297-
FCT_TRADDR_ERR = 0,
2298-
FCT_TRADDR_WWNN = 1 << 0,
2299-
FCT_TRADDR_WWPN = 1 << 1,
2300-
};
23012296

23022297
struct nvmet_fc_traddr {
23032298
u64 nn;
23042299
u64 pn;
23052300
};
23062301

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-
23132302
static int
2314-
nvmet_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf)
2303+
__nvme_fc_parse_u64(substring_t *sstr, u64 *val)
23152304
{
2316-
substring_t args[MAX_OPT_ARGS];
2317-
char *options, *o, *p;
2318-
int token, ret = 0;
23192305
u64 token64;
23202306

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;
23242310

2325-
while ((p = strsep(&o, ":\n")) != NULL) {
2326-
if (!*p)
2327-
continue;
2311+
return 0;
2312+
}
23282313

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;
2325+
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;
23522354

2353-
out:
2354-
kfree(options);
2355-
return ret;
2355+
return 0;
2356+
2357+
out_einval:
2358+
pr_warn("%s: bad traddr string\n", __func__);
2359+
return -EINVAL;
23562360
}
23572361

23582362
static int
@@ -2370,7 +2374,8 @@ nvmet_fc_add_port(struct nvmet_port *port)
23702374

23712375
/* map the traddr address info to a target port */
23722376

2373-
ret = nvmet_fc_parse_traddr(&traddr, port->disc_addr.traddr);
2377+
ret = nvme_fc_parse_traddr(&traddr, port->disc_addr.traddr,
2378+
sizeof(port->disc_addr.traddr));
23742379
if (ret)
23752380
return ret;
23762381

include/linux/nvme-fc.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,5 +334,24 @@ struct fcnvme_ls_disconnect_acc {
334334
#define NVME_FC_LS_TIMEOUT_SEC 2 /* 2 seconds */
335335
#define NVME_FC_TGTOP_TIMEOUT_SEC 2 /* 2 seconds */
336336

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+
337356

338357
#endif /* _NVME_FC_H */

include/linux/nvme.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ static inline bool nvme_is_write(struct nvme_command *cmd)
10061006
* Why can't we simply have a Fabrics In and Fabrics out command?
10071007
*/
10081008
if (unlikely(cmd->common.opcode == nvme_fabrics_command))
1009-
return cmd->fabrics.opcode & 1;
1009+
return cmd->fabrics.fctype & 1;
10101010
return cmd->common.opcode & 1;
10111011
}
10121012

0 commit comments

Comments
 (0)