nvme updates for Linux 7.4

- Fix regressions from the parallel nvme-tcp I/O queue setup: request
    PDU sizing with header digest, a NULL controller dereference when
    reconnecting with more queues, and early lock initialization
  - Handle TLS control records in nvme-tcp: skip records arriving ahead
    of the ICResp, and start error recovery when the socket read fails
  - Fix an nvme-tcp io_work priority inversion stalling I/O
  - Fix nvme-tcp address attribute race with queue teardown
  - Validate the TLS handshake timeout parameters for host and target
  - Fix fabrics connects with isolated CPUs and queue mapping bugs
  - Fix early boot hang and buffer size for the nvme.quirks parameter
  - Fix nvme-rdma NULL metadata SGL dereference with T10-PI
  - Fix ANA underflow check and an nvme-fc discovery reference leak
  - Fix nvme-loop BUG() when a namespace scan races a reset
  - Target port and configfs locking fixes, and port removal races
  - Target auth fixes for CHALLENGE failure and negotiation handling
  - Target fc fixes for a connection use-after-free, read data on failed
    commands, and admin queue allocation failure teardown
  - Target rdma fix for short connection requests
  - Target rdma fix for inline SGL out-of-bounds write
  - Target rdma refcount, locking, and module unload fixes
  - Target pci-epf SGL length and error status fixes
  - Target NULL dereference fixes for pci-epf and debugfs
  - Target ZNS NUMD overflow check
  - Target Connect fix for a controller leak with a zero queue size
  - Target fixes for a metadata SGL double-free and a leaked blk plug
  - Target fix for truncated large discards
  - Misc cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE3Fbyvv+648XNRdHTPe3zGtjzRgkFAmriRVsACgkQPe3zGtjz
 Rgnykw//fATfZCEOzO5mKuPm1k6ImS4U2gxBZFY9zWvXoad91JjwCyfWWHlt94fM
 LCAwwWAQzVZ3FUUjfZqhjfs7MiDVnw2YoH7CG9NGaNskbquGxPSfsk0tlnc4xvMx
 V5tnAbpEquyUDIT1rNDxZix74CBeY0y68SswNiCJUkEJUbfycVlRHIGs5/qJ+GJ/
 0DQXVWo4aFfSTRO9PiCOnQNknLc83UVvotKg7a+FsgTXlkjHXK0Mq6u0WUVqON1S
 Rw7aKN34Bey7a5hIYM+/+eqTtUXDo4mDxIwd0FAJ9VpMIKg6IFKhm9hKtoEkftf/
 b9XX/X8Gfdr6kPNg7r19sxILlYVc+oEDbfbwWfzYciou8ETpy+A2EkmQPGEIMrOQ
 QAmt1FekXaI8W2nNaenue1txZXsFqqw0qzsuy06WnQ4DHugrSXmles9GV0zx9blz
 PpbMSdkNR59RJpwSYx2sbaS4/93ZfPCKiySYDw9Xs+DWf6HE3mNh/zzXvjVwyUsl
 NQCqlmW/AxkuOsx1Q0Lo+wVCtyF8GKnWrtD85NS+SIBGj6VbQZgXbbUWw8DpnzLC
 bNKHNQZmN9VCYTta9UieRAHXUz6TQcnRP5/rVH70nPUvOiGr4qE3CKiKxt9VUYMo
 UuIW5An6WSb9Uz8u5l6eoSTFwLuZpWzJFercnGVO5fg+kVMO29E=
 =BGvn
 -----END PGP SIGNATURE-----

Merge tag 'nvme-7.4-2026-10-28' of git://git.infradead.org/nvme into block-7.4

nvme updates for Linux 7.4

 - Fix regressions from the parallel nvme-tcp I/O queue setup: request
   PDU sizing with header digest, a NULL controller dereference when
   reconnecting with more queues, and early lock initialization
 - Handle TLS control records in nvme-tcp: skip records arriving ahead
   of the ICResp, and start error recovery when the socket read fails
 - Fix an nvme-tcp io_work priority inversion stalling I/O
 - Fix nvme-tcp address attribute race with queue teardown
 - Validate the TLS handshake timeout parameters for host and target
 - Fix fabrics connects with isolated CPUs and queue mapping bugs
 - Fix early boot hang and buffer size for the nvme.quirks parameter
 - Fix nvme-rdma NULL metadata SGL dereference with T10-PI
 - Fix ANA underflow check and an nvme-fc discovery reference leak
 - Fix nvme-loop BUG() when a namespace scan races a reset
 - Target port and configfs locking fixes, and port removal races
 - Target auth fixes for CHALLENGE failure and negotiation handling
 - Target fc fixes for a connection use-after-free, read data on failed
   commands, and admin queue allocation failure teardown
 - Target rdma fix for short connection requests
 - Target rdma fix for inline SGL out-of-bounds write
 - Target rdma refcount, locking, and module unload fixes
 - Target pci-epf SGL length and error status fixes
 - Target NULL dereference fixes for pci-epf and debugfs
 - Target ZNS NUMD overflow check
 - Target Connect fix for a controller leak with a zero queue size
 - Target fixes for a metadata SGL double-free and a leaked blk plug
 - Target fix for truncated large discards
 - Misc cleanups

* tag 'nvme-7.4-2026-10-28' of git://git.infradead.org/nvme: (44 commits)
  nvmet: don't clear sq->ctrl for a Connect with sqsize 0
  nvmet-rdma: fix double puts after a failed RDMA WRITE
  nvmet-rdma: disable interrupts under rsp_wr_wait_lock
  nvmet-rdma: flush nvmet-wq on module exit
  nvme-loop: don't BUG() if a scan runs beside a reset
  nvmet-tcp: don't read a removed port at Connect time
  nvmet: fix NULL dereference in debugfs host_traddr
  nvmet-tcp: stop listening when a port is removed
  nvmet: fix NULL dereference of PCI endpoint targets
  nvmet-auth: take only AUTH_Negotiate for a negotiation
  nvmet: don't truncate the length of big discards
  nvme-tcp: validate the TLS handshake timeout
  nvmet-tcp: validate the TLS handshake timeout
  nvmet: Free the old negotiation state when restarting authentication
  nvmet: Finish the blk plug when integrity allocation fails
  nvme-tcp: fix NULL queue->ctrl dereference on reconnect
  nvme-tcp: Validate the queue state under the queue lock in the address attribute
  nvme-tcp: fix io_work priority inversion when send_mutex is held
  nvme-tcp: fix request PDU size when header digest is enabled
  nvme-tcp: skip TLS control records while waiting for the ICResp
  ...
This commit is contained in:
Jens Axboe 2026-10-29 09:27:59 -06:00
commit deb2326729
20 changed files with 434 additions and 128 deletions

View File

@ -4791,6 +4791,16 @@ Kernel parameters
Example:
nvme.quirks=7710:2267:bogus_nid,^identify_cns-9900:7711:broken_msi
nvme_tcp.tls_handshake_timeout=
[NVME] NVMe/TCP host TLS handshake timeout in seconds.
Valid values range from 0 to the smaller of
UINT_MAX / 1000 and MAX_JIFFY_OFFSET / HZ. Default: 10
nvmet_tcp.tls_handshake_timeout=
[NVME] NVMe/TCP target TLS handshake timeout in seconds.
Valid values range from 0 to the smaller of
UINT_MAX / 1000 and MAX_JIFFY_OFFSET / HZ. Default: 10
ohci1394_dma=early [HW,EARLY] enable debugging via the ohci1394 driver.
See Documentation/core-api/debugging-via-ohci1394.rst for more
info.

View File

@ -85,10 +85,12 @@ static int nvme_auth_submit(struct nvme_ctrl *ctrl, int qid,
qid == 0 ? NVME_QID_ANY : qid, flags);
if (ret > 0)
dev_warn(ctrl->device,
"qid %d auth_send failed with status %d\n", qid, ret);
"qid %d auth_%s failed with status %d\n",
qid, auth_send ? "send" : "receive", ret);
else if (ret < 0)
dev_err(ctrl->device,
"qid %d auth_send failed with error %d\n", qid, ret);
"qid %d auth_%s failed with error %d\n",
qid, auth_send ? "send" : "receive", ret);
return ret;
}

View File

@ -1125,16 +1125,27 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues,
u32 io_queues[HCTX_MAX_TYPES])
{
if (opts->nr_write_queues && opts->nr_io_queues < nr_io_queues) {
/*
* Each queue type is mapped to the CPUs separately, so a type with
* more queues than online CPUs has hardware contexts without an online
* CPU. Use the same limits as nvmf_nr_io_queues.
*/
u32 nr_io = min(opts->nr_io_queues, num_online_cpus());
u32 nr_write = min(opts->nr_write_queues, num_online_cpus());
u32 nr_poll = min(opts->nr_poll_queues, num_online_cpus());
memset(io_queues, 0, sizeof(*io_queues) * HCTX_MAX_TYPES);
if (nr_write && nr_io < nr_io_queues) {
/*
* separate read/write queues
* hand out dedicated default queues only after we have
* sufficient read queues.
*/
io_queues[HCTX_TYPE_READ] = opts->nr_io_queues;
io_queues[HCTX_TYPE_READ] = nr_io;
nr_io_queues -= io_queues[HCTX_TYPE_READ];
io_queues[HCTX_TYPE_DEFAULT] =
min(opts->nr_write_queues, nr_io_queues);
min(nr_write, nr_io_queues);
nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT];
} else {
/*
@ -1143,14 +1154,14 @@ void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues,
* sufficient queue count to have dedicated default queues.
*/
io_queues[HCTX_TYPE_DEFAULT] =
min(opts->nr_io_queues, nr_io_queues);
min(nr_io, nr_io_queues);
nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT];
}
if (opts->nr_poll_queues && nr_io_queues) {
if (nr_poll && nr_io_queues) {
/* map dedicated poll queues only if we have queues left */
io_queues[HCTX_TYPE_POLL] =
min(opts->nr_poll_queues, nr_io_queues);
min(nr_poll, nr_io_queues);
}
}
EXPORT_SYMBOL_GPL(nvmf_set_io_queues);
@ -1188,6 +1199,13 @@ void nvmf_map_queues(struct blk_mq_tag_set *set, struct nvme_ctrl *ctrl,
io_queues[HCTX_TYPE_DEFAULT] +
io_queues[HCTX_TYPE_READ];
blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
} else {
/*
* blk_mq_alloc_tag_set sets nr_queues of all maps to
* nr_hw_queues. Clear the poll map, otherwise the queue claims
* poll support and polled I/O ends up on hctx 0.
*/
set->map[HCTX_TYPE_POLL].nr_queues = 0;
}
dev_info(ctrl->device,

View File

@ -3778,6 +3778,9 @@ static ssize_t nvme_fc_nvme_discovery_store(struct device *dev,
restart:
list_for_each_entry(lport, &nvme_fc_lport_list, port_list) {
list_for_each_entry(rport, &lport->endp_list, endp_list) {
/* skip rports already queued for discovery */
if (!list_empty(&rport->disc_list))
continue;
if (!nvme_fc_lport_get(lport))
continue;
if (!nvme_fc_rport_get(rport)) {
@ -3799,9 +3802,7 @@ static ssize_t nvme_fc_nvme_discovery_store(struct device *dev,
"failures\n");
goto process_local_list;
}
if (list_empty(&rport->disc_list))
list_add_tail(&rport->disc_list,
&local_disc_list);
list_add_tail(&rport->disc_list, &local_disc_list);
}
}

View File

@ -232,7 +232,7 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp)
return err;
}
static char quirks_param[128];
static char quirks_param[256];
static const struct kernel_param_ops quirks_param_ops = {
.set = quirks_param_set,
.get = param_get_string,
@ -243,7 +243,7 @@ static struct kparam_string quirks_param_string = {
.string = quirks_param,
};
module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0444);
device_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0444);
MODULE_PARM_DESC(quirks, "Enable/disable NVMe quirks by specifying "
"quirks=VID:DID:quirk_names");

View File

@ -313,7 +313,7 @@ static int nvme_rdma_init_request(struct blk_mq_tag_set *set,
return -ENOMEM;
/* metadata nvme_rdma_sgl struct is located after command's data SGL */
if (queue->pi_support)
if (queue_idx && ctrl->ctrl.max_integrity_segments)
req->metadata_sgl = (void *)nvme_req(rq) +
sizeof(struct nvme_rdma_request) +
NVME_RDMA_DATA_SGL_SIZE;

View File

@ -6,6 +6,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/async.h>
#include <linux/err.h>
@ -48,13 +49,34 @@ MODULE_PARM_DESC(wq_unbound, "Use unbound workqueue for nvme-tcp IO context (def
/*
* TLS handshake timeout
*/
static int tls_handshake_timeout = 10;
static unsigned int tls_handshake_timeout = 10;
#ifdef CONFIG_NVME_TCP_TLS
module_param(tls_handshake_timeout, int, 0644);
static int tls_handshake_timeout_set(const char *val,
const struct kernel_param *kp)
{
return param_set_uint_minmax(val, kp, 0,
min_t(unsigned long, UINT_MAX / MSEC_PER_SEC,
MAX_JIFFY_OFFSET / HZ));
}
static const struct kernel_param_ops tls_handshake_timeout_ops = {
.set = tls_handshake_timeout_set,
.get = param_get_uint,
};
module_param_cb(tls_handshake_timeout, &tls_handshake_timeout_ops,
&tls_handshake_timeout, 0644);
__MODULE_PARM_TYPE(tls_handshake_timeout, "uint");
MODULE_PARM_DESC(tls_handshake_timeout,
"nvme TLS handshake timeout in seconds (default 10)");
#endif
/* read a TLS control record in chunks of this size */
#define NVME_TCP_TLS_REC_CHUNK 256
/* TLS records read while waiting for the ICResp, the ICResp included */
#define NVME_TCP_ICRESP_MAX_RECORDS 8
static int nvme_tcp_cpu_queues[NR_CPUS];
static DEFINE_SPINLOCK(nvme_tcp_cpu_queues_lock);
@ -97,6 +119,9 @@ enum nvme_tcp_queue_flags {
NVME_TCP_Q_IO_CPU_SET = 3,
};
#define NVME_TCP_OPT_NR_QUEUES(opts) ((opts)->nr_io_queues + \
(opts)->nr_write_queues + (opts)->nr_poll_queues + 1)
enum nvme_tcp_recv_state {
NVME_TCP_RECV_PDU = 0,
NVME_TCP_RECV_DATA,
@ -1430,6 +1455,19 @@ static int nvme_tcp_try_recv(struct nvme_tcp_queue *queue)
lock_sock(sk);
queue->nr_cqe = 0;
consumed = sock->ops->read_sock(sk, &rd_desc, nvme_tcp_recv_skb);
/*
* nvme_tcp_recv_skb() handles its own errors, so a queue that is
* still enabled failed inside read_sock(). Handle it before
* release_sock() processes the backlog.
*/
if (unlikely(consumed < 0 && consumed != -EAGAIN &&
queue->rd_enabled)) {
dev_err(queue->ctrl->ctrl.device,
"queue %d: receive failed: %d\n",
nvme_tcp_queue_id(queue), consumed);
queue->rd_enabled = false;
nvme_tcp_error_recovery(&queue->ctrl->ctrl);
}
release_sock(sk);
return consumed == -EAGAIN ? 0 : consumed;
}
@ -1442,9 +1480,11 @@ static void nvme_tcp_io_work(struct work_struct *w)
do {
bool pending = false;
bool got_send_mutex = false;
int result;
if (mutex_trylock(&queue->send_mutex)) {
got_send_mutex = true;
result = nvme_tcp_try_send(queue);
mutex_unlock(&queue->send_mutex);
if (result > 0)
@ -1459,8 +1499,13 @@ static void nvme_tcp_io_work(struct work_struct *w)
else if (unlikely(result < 0))
return;
/* did we get some space after spending time in recv? */
if (nvme_tcp_queue_has_pending(queue) &&
/*
* did we get some space after spending time in recv?
* Only check this if we could take send_mutex. Otherwise
* the task holding it sends the requests and queues io_work
* again after it releases the mutex.
*/
if (got_send_mutex && nvme_tcp_queue_has_pending(queue) &&
sk_stream_is_writeable(queue->sock->sk))
pending = true;
@ -1523,23 +1568,159 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
* nvme_reset_ctrl_work(), queue teardown is immediately followed by
* re-allocation. fput() defers socket cleanup to delayed_fput_work
* in workqueue context, which can race with new queue setup.
*
* Clear queue->sock under the queue lock so that a sysfs reader in
* nvme_tcp_get_address() either observes the NVME_TCP_Q_LIVE bit
* cleared or a still valid socket. The queue lock itself is owned
* by the controller and only destroyed when the controller is
* freed, so readers blocked on it cannot race its teardown.
*/
mutex_lock(&queue->queue_lock);
__fput_sync(queue->sock->file);
queue->sock = NULL;
mutex_unlock(&queue->queue_lock);
memalloc_noio_restore(noio_flag);
kfree(queue->pdu);
mutex_destroy(&queue->send_mutex);
mutex_destroy(&queue->queue_lock);
mutex_destroy(&queue->pf_cache_lock);
}
static int nvme_tcp_recv_tls_alert(struct nvme_tcp_queue *queue,
struct msghdr *msg, int len)
{
struct sock *sk = queue->sock->sk;
u8 level, description;
if (len < 2) {
dev_err(queue->ctrl->ctrl.device,
"queue %d: truncated TLS alert\n",
nvme_tcp_queue_id(queue));
return -ENOTCONN;
}
/* tls_alert_recv() reads through the iterator */
iov_iter_revert(&msg->msg_iter, len);
tls_alert_recv(sk, msg, &level, &description);
if (level == TLS_ALERT_LEVEL_FATAL) {
dev_err(queue->ctrl->ctrl.device,
"queue %d: fatal TLS alert %u\n",
nvme_tcp_queue_id(queue), description);
return -ENOTCONN;
}
/* a peer shutting down normally is not worth a warning */
if (description == TLS_ALERT_DESC_CLOSE_NOTIFY)
dev_dbg(queue->ctrl->ctrl.device,
"queue %d: TLS close_notify\n",
nvme_tcp_queue_id(queue));
else
dev_warn(queue->ctrl->ctrl.device,
"queue %d: TLS alert %u\n",
nvme_tcp_queue_id(queue), description);
return 0;
}
/*
* Discard a TLS record that arrived in place of the ICResp. A peer may send
* a NewSessionTicket as soon as the handshake completes.
*
* Returns 0 when the record was discarded and the ICResp can be read, or a
* negative errno if the connection cannot continue.
*/
static int nvme_tcp_skip_tls_record(struct nvme_tcp_queue *queue,
struct msghdr *msg, u8 ctype, int len)
{
u8 buf[NVME_TCP_TLS_REC_CHUNK];
int ret;
switch (ctype) {
case TLS_RECORD_TYPE_HANDSHAKE:
break;
case TLS_RECORD_TYPE_ALERT:
ret = nvme_tcp_recv_tls_alert(queue, msg, len);
return ret ? : -ENOTCONN;
default:
pr_err("queue %d: unhandled TLS record %u\n",
nvme_tcp_queue_id(queue), ctype);
return -ENOTCONN;
}
/* the ICResp is in a later record, drain this one first */
while (!(msg->msg_flags & MSG_EOR)) {
struct kvec iov = {
.iov_base = buf,
.iov_len = sizeof(buf),
};
char cbuf[CMSG_LEN(sizeof(char))] = {};
/* kTLS fails a control record read without a cmsg buffer */
struct msghdr drain = {
.msg_control = cbuf,
.msg_controllen = sizeof(cbuf),
};
ret = kernel_recvmsg(queue->sock, &drain, &iov, 1, sizeof(buf),
0);
if (ret <= 0) {
pr_warn("queue %d: failed to drain TLS record: %d\n",
nvme_tcp_queue_id(queue), ret);
return ret ? : -ECONNRESET;
}
msg->msg_flags = drain.msg_flags;
}
return 0;
}
/*
* Receive the ICResp. Over TLS, skip the records that a peer may send
* ahead of it.
*
* Returns the length received, or a negative errno.
*/
static int nvme_tcp_recv_icresp(struct nvme_tcp_queue *queue,
struct nvme_tcp_icresp_pdu *icresp)
{
char cbuf[CMSG_LEN(sizeof(char))];
struct msghdr msg;
struct kvec iov;
u8 ctype;
int i, ret;
for (i = 0; i < NVME_TCP_ICRESP_MAX_RECORDS; i++) {
memset(&msg, 0, sizeof(msg));
memset(cbuf, 0, sizeof(cbuf));
iov.iov_base = icresp;
iov.iov_len = sizeof(*icresp);
if (nvme_tcp_queue_tls(queue)) {
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
}
msg.msg_flags = MSG_WAITALL;
ret = kernel_recvmsg(queue->sock, &msg, &iov, 1,
iov.iov_len, msg.msg_flags);
if (ret <= 0 || !nvme_tcp_queue_tls(queue))
return ret;
ctype = tls_get_record_type(queue->sock->sk,
(struct cmsghdr *)cbuf);
if (ctype == TLS_RECORD_TYPE_DATA)
return ret;
ret = nvme_tcp_skip_tls_record(queue, &msg, ctype, ret);
if (ret < 0)
return ret;
}
pr_err("queue %d: too many TLS records before the ICResp\n",
nvme_tcp_queue_id(queue));
return -EPROTO;
}
static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
{
struct nvme_tcp_icreq_pdu *icreq;
struct nvme_tcp_icresp_pdu *icresp;
char cbuf[CMSG_LEN(sizeof(char))] = {};
u8 ctype;
struct msghdr msg = {};
struct kvec iov;
bool ctrl_hdgst, ctrl_ddgst;
@ -1577,16 +1758,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
goto free_icresp;
}
memset(&msg, 0, sizeof(msg));
iov.iov_base = icresp;
iov.iov_len = sizeof(*icresp);
if (nvme_tcp_queue_tls(queue)) {
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
}
msg.msg_flags = MSG_WAITALL;
ret = kernel_recvmsg(queue->sock, &msg, &iov, 1,
iov.iov_len, msg.msg_flags);
ret = nvme_tcp_recv_icresp(queue, icresp);
if (ret >= 0 && ret < sizeof(*icresp))
ret = -ECONNRESET;
if (ret < 0) {
@ -1594,16 +1766,6 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
nvme_tcp_queue_id(queue), ret);
goto free_icresp;
}
ret = -ENOTCONN;
if (nvme_tcp_queue_tls(queue)) {
ctype = tls_get_record_type(queue->sock->sk,
(struct cmsghdr *)cbuf);
if (ctype != TLS_RECORD_TYPE_DATA) {
pr_err("queue %d: unhandled TLS record %d\n",
nvme_tcp_queue_id(queue), ctype);
goto free_icresp;
}
}
ret = -EINVAL;
if (icresp->hdr.type != nvme_tcp_icresp) {
pr_err("queue %d: bad type returned %d\n",
@ -1795,8 +1957,10 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
{
int qid = nvme_tcp_queue_id(queue);
int ret;
long wait_ret;
struct tls_handshake_args args;
unsigned long tmo = tls_handshake_timeout * HZ;
unsigned int timeout = READ_ONCE(tls_handshake_timeout);
unsigned long tmo = (unsigned long)timeout * HZ;
key_serial_t keyring = nvme_keyring_id();
dev_dbg(nctrl->device, "queue %d: start TLS with key %x\n",
@ -1810,7 +1974,7 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
if (nctrl->opts->keyring)
keyring = key_serial(nctrl->opts->keyring);
args.ta_keyring = keyring;
args.ta_timeout_ms = tls_handshake_timeout * 1000;
args.ta_timeout_ms = timeout * MSEC_PER_SEC;
queue->tls_err = -EOPNOTSUPP;
init_completion(&queue->tls_complete);
ret = tls_client_hello_psk(&args, GFP_KERNEL);
@ -1819,10 +1983,10 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
qid, ret);
return ret;
}
ret = wait_for_completion_interruptible_timeout(&queue->tls_complete, tmo);
if (ret <= 0) {
if (ret == 0)
ret = -ETIMEDOUT;
wait_ret = wait_for_completion_interruptible_timeout(&queue->tls_complete,
tmo);
if (wait_ret <= 0) {
ret = wait_ret < 0 ? -ERESTARTSYS : -ETIMEDOUT;
dev_err(nctrl->device,
"queue %d: TLS handshake failed, error %d\n",
@ -1842,6 +2006,28 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
return ret;
}
static void nvme_tcp_init_queue(struct nvme_tcp_ctrl *ctrl, int qid)
{
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
queue->ctrl = ctrl;
mutex_init(&queue->queue_lock);
mutex_init(&queue->send_mutex);
mutex_init(&queue->pf_cache_lock);
INIT_WORK(&queue->io_work, nvme_tcp_io_work);
queue->hdr_digest = ctrl->ctrl.opts->hdr_digest;
queue->data_digest = ctrl->ctrl.opts->data_digest;
}
static void nvme_tcp_exit_queue(struct nvme_tcp_ctrl *ctrl, int qid)
{
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
mutex_destroy(&queue->queue_lock);
mutex_destroy(&queue->send_mutex);
mutex_destroy(&queue->pf_cache_lock);
}
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
key_serial_t pskid)
{
@ -1850,13 +2036,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
int ret, rcv_pdu_size;
struct file *sock_file;
mutex_init(&queue->queue_lock);
queue->ctrl = ctrl;
init_llist_head(&queue->req_list);
INIT_LIST_HEAD(&queue->send_list);
mutex_init(&queue->send_mutex);
INIT_WORK(&queue->io_work, nvme_tcp_io_work);
mutex_init(&queue->pf_cache_lock);
if (qid > 0)
queue->cmnd_capsule_len = nctrl->ioccsz * 16;
@ -1870,14 +2051,12 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
if (ret) {
dev_err(nctrl->device,
"failed to create socket: %d\n", ret);
goto err_destroy_mutex;
return ret;
}
sock_file = sock_alloc_file(queue->sock, O_CLOEXEC, NULL);
if (IS_ERR(sock_file)) {
ret = PTR_ERR(sock_file);
goto err_destroy_mutex;
}
if (IS_ERR(sock_file))
return PTR_ERR(sock_file);
sk_net_refcnt_upgrade(queue->sock->sk);
@ -1939,9 +2118,6 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
}
}
queue->hdr_digest = nctrl->opts->hdr_digest;
queue->data_digest = nctrl->opts->data_digest;
rcv_pdu_size = sizeof(struct nvme_tcp_rsp_pdu) +
nvme_tcp_hdgst_len(queue);
queue->pdu = kmalloc(rcv_pdu_size, GFP_KERNEL);
@ -1986,10 +2162,6 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
/* Use sync variant - see nvme_tcp_free_queue() for explanation */
__fput_sync(queue->sock->file);
queue->sock = NULL;
err_destroy_mutex:
mutex_destroy(&queue->send_mutex);
mutex_destroy(&queue->queue_lock);
mutex_destroy(&queue->pf_cache_lock);
return ret;
}
@ -2676,6 +2848,9 @@ static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl)
static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
{
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
/* the same count used to size and initialize the queue array */
unsigned int nr_queues = NVME_TCP_OPT_NR_QUEUES(nctrl->opts);
unsigned int i;
if (list_empty_careful(&ctrl->list))
goto free_ctrl;
@ -2687,6 +2862,8 @@ static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
nvmf_free_options(nctrl->opts);
free_ctrl:
put_net(ctrl->net);
for (i = 0; i < nr_queues; i++)
nvme_tcp_exit_queue(ctrl, i);
kfree(ctrl->queues);
kfree(ctrl);
}
@ -2939,17 +3116,18 @@ static int nvme_tcp_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
len = nvmf_get_address(ctrl, buf, size);
if (!test_bit(NVME_TCP_Q_LIVE, &queue->flags))
return len;
mutex_lock(&queue->queue_lock);
ret = kernel_getsockname(queue->sock, (struct sockaddr *)&src_addr);
if (ret > 0) {
if (len > 0)
len--; /* strip trailing newline */
len += scnprintf(buf + len, size - len, "%ssrc_addr=%pISc\n",
(len) ? "," : "", &src_addr);
if (test_bit(NVME_TCP_Q_LIVE, &queue->flags)) {
ret = kernel_getsockname(queue->sock,
(struct sockaddr *)&src_addr);
if (ret > 0) {
if (len > 0)
len--; /* strip trailing newline */
len += scnprintf(buf + len, size - len,
"%ssrc_addr=%pISc\n",
(len) ? "," : "", &src_addr);
}
}
mutex_unlock(&queue->queue_lock);
@ -3015,7 +3193,7 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(struct device *dev,
struct nvmf_ctrl_options *opts)
{
struct nvme_tcp_ctrl *ctrl;
int ret;
int ret, i;
ctrl = kzalloc_obj(*ctrl);
if (!ctrl)
@ -3026,8 +3204,7 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(struct device *dev,
*/
context_unsafe(INIT_LIST_HEAD(&ctrl->list));
ctrl->ctrl.opts = opts;
ctrl->ctrl.queue_count = opts->nr_io_queues + opts->nr_write_queues +
opts->nr_poll_queues + 1;
ctrl->ctrl.queue_count = NVME_TCP_OPT_NR_QUEUES(opts);
ctrl->ctrl.sqsize = opts->queue_size - 1;
ctrl->ctrl.kato = opts->kato;
@ -3085,8 +3262,10 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(struct device *dev,
goto out_free_ctrl;
}
ctrl->net = get_net(current->nsproxy->net_ns);
for (i = 0; i < ctrl->ctrl.queue_count; i++)
nvme_tcp_init_queue(ctrl, i);
ctrl->net = get_net(current->nsproxy->net_ns);
ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_tcp_ctrl_ops, 0);
if (ret)
goto out_kfree_queues;

View File

@ -237,6 +237,7 @@ void nvmet_auth_sq_free(struct nvmet_sq *sq)
sq->dhchap_c2 = NULL;
kfree(sq->dhchap_skey);
sq->dhchap_skey = NULL;
sq->dhchap_skey_len = 0;
}
void nvmet_auth_sq_destroy(struct nvmet_sq *sq)

View File

@ -387,10 +387,15 @@ static ssize_t nvmet_addr_trtype_store(struct config_item *item,
const char *page, size_t count)
{
struct nvmet_port *port = to_nvmet_port(item);
ssize_t ret = count;
int i;
if (nvmet_is_port_enabled(port, __func__))
return -EACCES;
down_write(&nvmet_config_sem);
if (nvmet_is_port_enabled(port, __func__)) {
ret = -EACCES;
goto out;
}
for (i = 0; i < ARRAY_SIZE(nvmet_transport); i++) {
if (sysfs_streq(page, nvmet_transport[i].name))
@ -398,7 +403,8 @@ static ssize_t nvmet_addr_trtype_store(struct config_item *item,
}
pr_err("Invalid value '%s' for trtype\n", page);
return -EINVAL;
ret = -EINVAL;
goto out;
found:
memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
@ -407,7 +413,9 @@ static ssize_t nvmet_addr_trtype_store(struct config_item *item,
nvmet_port_init_tsas_rdma(port);
else if (port->disc_addr.trtype == NVMF_TRTYPE_TCP)
nvmet_port_init_tsas_tcp(port, NVMF_TCP_SECTYPE_NONE);
return count;
out:
up_write(&nvmet_config_sem);
return ret;
}
CONFIGFS_ATTR(nvmet_, addr_trtype);
@ -1783,8 +1791,10 @@ static ssize_t nvmet_subsys_attr_qid_max_store(struct config_item *item,
subsys->max_qid = qid_max;
/* Force reconnect */
mutex_lock(&subsys->lock);
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
ctrl->ops->delete_ctrl(ctrl);
mutex_unlock(&subsys->lock);
up_write(&nvmet_config_sem);
return cnt;
@ -2104,7 +2114,9 @@ static void nvmet_port_release(struct config_item *item)
/* Let inflight controllers teardown complete */
flush_workqueue(nvmet_wq);
down_write(&nvmet_config_sem);
list_del(&port->global_entry);
up_write(&nvmet_config_sem);
key_put(port->keyring);
kfree(port);
@ -2165,8 +2177,6 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
port->ana_state[i] = NVME_ANA_INACCESSIBLE;
}
list_add(&port->global_entry, &nvmet_ports_list);
INIT_LIST_HEAD(&port->entry);
INIT_LIST_HEAD(&port->subsystems);
INIT_LIST_HEAD(&port->referrals);
@ -2200,6 +2210,10 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
configfs_add_default_group(&port->ana_default_group.group,
&port->ana_groups_group);
down_write(&nvmet_config_sem);
list_add(&port->global_entry, &nvmet_ports_list);
up_write(&nvmet_config_sem);
return &port->group;
}

View File

@ -393,11 +393,13 @@ void nvmet_disable_port(struct nvmet_port *port)
lockdep_assert_held(&nvmet_config_sem);
port->enabled = false;
port->tr_ops = NULL;
if (!port->enabled)
return;
ops = nvmet_transports[port->disc_addr.trtype];
ops = port->tr_ops;
port->enabled = false;
ops->remove_port(port);
port->tr_ops = NULL;
module_put(ops->owner);
}
@ -1101,6 +1103,9 @@ static u32 nvmet_io_cmd_transfer_len(struct nvmet_req *req)
case nvme_cmd_dsm:
return nvmet_dsm_len(req);
case nvme_cmd_zone_mgmt_recv:
/* The handler rejects a NUMD whose byte count would wrap. */
if (le32_to_cpu(req->cmd->zmr.numd) >= U32_MAX / 4)
return 0;
return (le32_to_cpu(req->cmd->zmr.numd) + 1) << 2;
default:
return 0;
@ -1362,7 +1367,7 @@ int nvmet_req_alloc_sgls(struct nvmet_req *req)
return 0;
out_free:
sgl_free(req->sg);
nvmet_req_free_sgls(req);
out:
return -ENOMEM;
}
@ -1823,6 +1828,9 @@ ssize_t nvmet_ctrl_host_traddr(struct nvmet_ctrl *ctrl,
{
if (!ctrl->ops->host_traddr)
return -EOPNOTSUPP;
/* They all take the address from the admin queue */
if (!ctrl->sqs[0])
return -ENOTCONN;
return ctrl->ops->host_traddr(ctrl, traddr, traddr_len);
}

View File

@ -330,6 +330,7 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
/* Restart negotiation */
pr_debug("%s: ctrl %d qid %d reset negotiation\n",
__func__, ctrl->cntlid, req->sq->qid);
nvmet_auth_sq_free(req->sq);
if (!req->sq->qid) {
dhchap_status = nvmet_setup_auth(ctrl, req->sq,
true);
@ -344,8 +345,9 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
}
req->sq->dhchap_step =
NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
} else if (data->auth_id != req->sq->dhchap_step)
} else {
goto done_failure1;
}
/* Validate negotiation parameters */
dhchap_status = nvmet_auth_negotiate(req, d, tl);
if (dhchap_status == 0)
@ -605,10 +607,11 @@ void nvmet_execute_auth_receive(struct nvmet_req *req)
switch (req->sq->dhchap_step) {
case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE:
if (nvmet_auth_challenge(req, d, al) < 0) {
pr_warn("ctrl %d qid %d: challenge error (%d)\n",
ctrl->cntlid, req->sq->qid, status);
pr_warn("ctrl %d qid %d: challenge error\n",
ctrl->cntlid, req->sq->qid);
status = NVME_SC_INTERNAL;
break;
kfree(d);
goto done;
}
req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
break;

View File

@ -186,8 +186,7 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
pr_warn("queue size zero!\n");
req->error_loc = offsetof(struct nvmf_connect_command, sqsize);
req->cqe->result.u32 = IPO_IATTR_CONNECT_SQE(sqsize);
ret = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
goto err;
return NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
}
if (ctrl->sqs[qid] != NULL) {

View File

@ -1708,7 +1708,7 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
be16_to_cpu(rqst->assoc_cmd.sqsize));
if (!queue) {
ret = VERR_QUEUE_ALLOC_FAIL;
nvmet_fc_tgt_a_put(iod->assoc);
nvmet_fc_schedule_delete_assoc(iod->assoc);
}
}
}
@ -1799,9 +1799,6 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
be16_to_cpu(rqst->connect_cmd.sqsize));
if (!queue)
ret = VERR_QUEUE_ALLOC_FAIL;
/* release get taken in nvmet_fc_find_target_assoc */
nvmet_fc_tgt_a_put(iod->assoc);
}
}
@ -1815,6 +1812,8 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
FCNVME_RJT_RC_INV_ASSOC :
FCNVME_RJT_RC_LOGIC,
FCNVME_RJT_EXP_NONE, 0);
if (iod->assoc)
nvmet_fc_tgt_a_put(iod->assoc);
return;
}
@ -1836,6 +1835,9 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
acc->connectid.connection_id =
cpu_to_be64(nvmet_fc_makeconnid(iod->assoc,
be16_to_cpu(rqst->connect_cmd.qid)));
/* release get taken in nvmet_fc_find_target_assoc */
nvmet_fc_tgt_a_put(iod->assoc);
}
/*
@ -2487,11 +2489,11 @@ __nvmet_fc_fcp_nvme_cmd_done(struct nvmet_fc_tgtport *tgtport,
} else {
/*
* try to push the data even if the SQE status is non-zero.
* There may be a status where data still was intended to
* be moved
* A failed command may not have filled its read buffer, so
* only push data for success, as the tcp and rdma targets do.
*/
if ((fod->io_dir == NVMET_FCP_READ) && (fod->data_sg_cnt)) {
if (fod->io_dir == NVMET_FCP_READ && fod->data_sg_cnt &&
!cqe->status) {
/* push the data over before sending rsp */
nvmet_fc_transfer_fcp_data(tgtport, fod,
NVMET_FCOP_READDATA);

View File

@ -316,7 +316,7 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
&prot_miter);
if (unlikely(rc)) {
bio_io_error(bio);
return;
goto out_plug;
}
}
@ -336,11 +336,12 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
rc = nvmet_bdev_alloc_bip(req, bio, &prot_miter);
if (unlikely(rc)) {
bio_io_error(bio);
return;
goto out_plug;
}
}
submit_bio(bio);
out_plug:
blk_finish_plug(&plug);
}
@ -389,7 +390,8 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req)
if (status)
break;
nr_sects = le32_to_cpu(range.nlb) << (ns->blksize_shift - 9);
nr_sects = (sector_t)le32_to_cpu(range.nlb) <<
(ns->blksize_shift - 9);
__blkdev_issue_discard(ns->bdev,
nvmet_lba_to_sect(ns, range.slba), nr_sects,
GFP_KERNEL, &bio);

View File

@ -221,8 +221,6 @@ static int nvme_loop_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
struct nvme_loop_ctrl *ctrl = to_loop_ctrl(data);
struct nvme_loop_queue *queue = &ctrl->queues[hctx_idx + 1];
BUG_ON(hctx_idx >= ctrl->ctrl.queue_count);
/*
* flush_end_io() can be called recursively for us, so use our own
* lock class key for avoiding lockdep possible recursive locking,

View File

@ -959,7 +959,8 @@ static inline void nvmet_req_bio_put(struct nvmet_req *req, struct bio *bio)
#ifdef CONFIG_NVME_TARGET_TCP_TLS
static inline key_serial_t nvmet_queue_tls_keyid(struct nvmet_sq *sq)
{
return sq->tls_key ? key_serial(sq->tls_key) : 0;
/* A PCI endpoint controller is created without a queue */
return sq && sq->tls_key ? key_serial(sq->tls_key) : 0;
}
static inline void nvmet_sq_put_tls_key(struct nvmet_sq *sq)
{

View File

@ -1073,10 +1073,22 @@ static int nvmet_pci_epf_iod_parse_sgl_segments(struct nvmet_pci_epf_ctrl *ctrl,
return 0;
}
static u64 nvmet_pci_epf_iod_data_segs_len(struct nvmet_pci_epf_iod *iod)
{
u64 len = 0;
int i;
for (i = 0; i < iod->nr_data_segs; i++)
len += iod->data_segs[i].length;
return len;
}
static int nvmet_pci_epf_iod_parse_sgls(struct nvmet_pci_epf_iod *iod)
{
struct nvmet_pci_epf_ctrl *ctrl = iod->ctrl;
struct nvme_sgl_desc *sgl = &iod->cmd.common.dptr.sgl;
int ret;
if (sgl->type == (NVME_SGL_FMT_DATA_DESC << 4)) {
/* Single data descriptor case. */
@ -1084,10 +1096,23 @@ static int nvmet_pci_epf_iod_parse_sgls(struct nvmet_pci_epf_iod *iod)
iod->data_segs = &iod->data_seg;
iod->data_seg.pci_addr = le64_to_cpu(sgl->addr);
iod->data_seg.length = le32_to_cpu(sgl->length);
return 0;
} else {
ret = nvmet_pci_epf_iod_parse_sgl_segments(ctrl, iod);
if (ret)
return ret;
}
return nvmet_pci_epf_iod_parse_sgl_segments(ctrl, iod);
/*
* The command executes on data_len bytes, but each segment is
* allocated and transferred in full, so they must describe exactly
* data_len bytes.
*/
if (nvmet_pci_epf_iod_data_segs_len(iod) != iod->data_len) {
iod->status = NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
return -EINVAL;
}
return 0;
}
static int nvmet_pci_epf_alloc_iod_data_buf(struct nvmet_pci_epf_iod *iod)
@ -1152,7 +1177,6 @@ static void nvmet_pci_epf_complete_iod(struct nvmet_pci_epf_iod *iod)
unsigned long flags;
/* Print an error message for failed commands, except AENs. */
iod->status = le16_to_cpu(iod->cqe.status) >> 1;
if (iod->status && iod->cmd.common.opcode != nvme_admin_async_event)
dev_err(iod->ctrl->dev,
"CQ[%d]: Command %s (0x%x) status 0x%0x\n",

View File

@ -513,7 +513,9 @@ static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev,
static void nvmet_rdma_process_wr_wait_list(struct nvmet_rdma_queue *queue)
{
spin_lock(&queue->rsp_wr_wait_lock);
unsigned long flags;
spin_lock_irqsave(&queue->rsp_wr_wait_lock, flags);
while (!list_empty(&queue->rsp_wr_wait_list)) {
struct nvmet_rdma_rsp *rsp;
bool ret;
@ -522,16 +524,16 @@ static void nvmet_rdma_process_wr_wait_list(struct nvmet_rdma_queue *queue)
struct nvmet_rdma_rsp, wait_list);
list_del(&rsp->wait_list);
spin_unlock(&queue->rsp_wr_wait_lock);
spin_unlock_irqrestore(&queue->rsp_wr_wait_lock, flags);
ret = nvmet_rdma_execute_command(rsp);
spin_lock(&queue->rsp_wr_wait_lock);
spin_lock_irqsave(&queue->rsp_wr_wait_lock, flags);
if (!ret) {
list_add(&rsp->wait_list, &queue->rsp_wr_wait_list);
break;
}
}
spin_unlock(&queue->rsp_wr_wait_lock);
spin_unlock_irqrestore(&queue->rsp_wr_wait_lock, flags);
}
static u16 nvmet_rdma_check_pi_status(struct ib_mr *sig_mr)
@ -801,7 +803,10 @@ static void nvmet_rdma_write_data_done(struct ib_cq *cq, struct ib_wc *wc)
if (unlikely(wc->status != IB_WC_SUCCESS)) {
nvmet_rdma_rw_ctx_destroy(rsp);
nvmet_req_uninit(&rsp->req);
/*
* Unlike in nvmet_rdma_read_data_done(), the request has been
* completed and its references are put: no nvmet_req_uninit().
*/
nvmet_rdma_release_rsp(rsp);
if (wc->status != IB_WC_WR_FLUSH_ERR) {
pr_info("RDMA WRITE for CQE failed with status %s (%d).\n",
@ -864,7 +869,8 @@ static u16 nvmet_rdma_map_sgl_inline(struct nvmet_rdma_rsp *rsp)
return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
if (off + len > rsp->queue->dev->inline_data_size) {
if (off > (u64)rsp->queue->dev->inline_data_size ||
len > (u64)rsp->queue->dev->inline_data_size - off) {
pr_err("invalid inline data offset!\n");
return NVME_SC_SGL_INVALID_OFFSET | NVME_STATUS_DNR;
}
@ -976,6 +982,7 @@ static bool nvmet_rdma_execute_command(struct nvmet_rdma_rsp *rsp)
static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue,
struct nvmet_rdma_rsp *cmd)
{
unsigned long flags;
u16 status;
ib_dma_sync_single_for_cpu(queue->dev->device,
@ -993,9 +1000,9 @@ static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue,
goto out_err;
if (unlikely(!nvmet_rdma_execute_command(cmd))) {
spin_lock(&queue->rsp_wr_wait_lock);
spin_lock_irqsave(&queue->rsp_wr_wait_lock, flags);
list_add_tail(&cmd->wait_list, &queue->rsp_wr_wait_list);
spin_unlock(&queue->rsp_wr_wait_lock);
spin_unlock_irqrestore(&queue->rsp_wr_wait_lock, flags);
}
return;
@ -1412,7 +1419,7 @@ nvmet_rdma_parse_cm_connect_req(struct rdma_conn_param *conn,
struct nvme_rdma_cm_req *req;
req = (struct nvme_rdma_cm_req *)conn->private_data;
if (!req || conn->private_data_len == 0)
if (!req || conn->private_data_len < sizeof(*req))
return NVME_RDMA_CM_INVALID_LEN;
if (le16_to_cpu(req->recfmt) != NVME_RDMA_CM_FMT_1_0)
@ -2150,6 +2157,12 @@ static void __exit nvmet_rdma_exit(void)
{
nvmet_unregister_transport(&nvmet_rdma_ops);
ib_unregister_client(&nvmet_rdma_ib_client);
/*
* nvmet_rdma_remove_one() does not flush for a device that has left
* device_list, and the release work that took it off still has to
* return from nvmet_rdma_free_dev().
*/
flush_workqueue(nvmet_wq);
WARN_ON_ONCE(!list_empty(&nvmet_rdma_queue_list));
ida_destroy(&nvmet_rdma_queue_ida);
}

View File

@ -6,6 +6,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/crc32c.h>
#include <linux/err.h>
@ -76,8 +77,24 @@ MODULE_PARM_DESC(idle_poll_period_usecs,
/*
* TLS handshake timeout
*/
static int tls_handshake_timeout = 10;
module_param(tls_handshake_timeout, int, 0644);
static unsigned int tls_handshake_timeout = 10;
static int tls_handshake_timeout_set(const char *val,
const struct kernel_param *kp)
{
return param_set_uint_minmax(val, kp, 0,
min_t(unsigned long, UINT_MAX / MSEC_PER_SEC,
MAX_JIFFY_OFFSET / HZ));
}
static const struct kernel_param_ops tls_handshake_timeout_ops = {
.set = tls_handshake_timeout_set,
.get = param_get_uint,
};
module_param_cb(tls_handshake_timeout, &tls_handshake_timeout_ops,
&tls_handshake_timeout, 0644);
__MODULE_PARM_TYPE(tls_handshake_timeout, "uint");
MODULE_PARM_DESC(tls_handshake_timeout,
"nvme TLS handshake timeout in seconds (default 10)");
#endif
@ -149,6 +166,7 @@ enum nvmet_tcp_queue_state {
struct nvmet_tcp_queue {
struct socket *sock;
struct nvmet_tcp_port *port;
struct nvmet_port *nport;
struct work_struct io_work;
struct nvmet_cq nvme_cq;
struct nvmet_sq nvme_sq;
@ -1495,7 +1513,7 @@ static int nvmet_tcp_alloc_cmd(struct nvmet_tcp_queue *queue,
u8 hdgst = nvmet_tcp_hdgst_len(queue);
c->queue = queue;
c->req.port = queue->port->nport;
c->req.port = queue->nport;
c->cmd_pdu = page_frag_alloc(&queue->pf_cache,
sizeof(*c->cmd_pdu) + hdgst, GFP_KERNEL | __GFP_ZERO);
@ -1904,6 +1922,7 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue)
{
int ret = -EOPNOTSUPP;
struct tls_handshake_args args;
unsigned int timeout = READ_ONCE(tls_handshake_timeout);
if (queue->state != NVMET_TCP_Q_TLS_HANDSHAKE) {
pr_warn("cannot start TLS in state %d\n", queue->state);
@ -1917,7 +1936,7 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue)
args.ta_done = nvmet_tcp_tls_handshake_done;
args.ta_data = queue;
args.ta_keyring = key_serial(queue->port->nport->keyring);
args.ta_timeout_ms = tls_handshake_timeout * 1000;
args.ta_timeout_ms = timeout * MSEC_PER_SEC;
ret = tls_server_hello_psk(&args, GFP_KERNEL);
if (ret) {
@ -1925,7 +1944,7 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue)
pr_err("failed to start TLS, err=%d\n", ret);
} else {
queue_delayed_work(nvmet_wq, &queue->tls_handshake_tmo_work,
tls_handshake_timeout * HZ);
(unsigned long)timeout * HZ);
}
return ret;
}
@ -1951,6 +1970,8 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
kref_init(&queue->kref);
queue->sock = newsock;
queue->port = port;
/* The port may be gone when the commands are allocated */
queue->nport = port->nport;
queue->nr_cmds = 0;
spin_lock_init(&queue->state_lock);
if (queue->port->nport->disc_addr.tsas.tcp.sectype ==
@ -2173,6 +2194,8 @@ static void nvmet_tcp_remove_port(struct nvmet_port *nport)
port->sock->sk->sk_data_ready = port->data_ready;
port->sock->sk->sk_user_data = NULL;
write_unlock_bh(&port->sock->sk->sk_callback_lock);
/* The accept work goes on for as long as there is something to accept */
kernel_sock_shutdown(port->sock, SHUT_RDWR);
cancel_work_sync(&port->accept_work);
/*
* Destroy the remaining queues, which are not belong to any

View File

@ -322,9 +322,17 @@ static void nvmet_bdev_zone_zmgmt_recv_work(struct work_struct *w)
void nvmet_bdev_execute_zone_mgmt_recv(struct nvmet_req *req)
{
u32 out_bufsize = (le32_to_cpu(req->cmd->zmr.numd) + 1) << 2;
u32 numd = le32_to_cpu(req->cmd->zmr.numd);
if (!nvmet_check_transfer_len(req, out_bufsize))
/* From U32_MAX / 4 up, (numd + 1) << 2 wraps here and in the work. */
if (numd >= U32_MAX / 4) {
req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd, numd);
nvmet_req_complete(req,
NVME_SC_INVALID_FIELD | NVME_STATUS_DNR);
return;
}
if (!nvmet_check_transfer_len(req, (numd + 1) << 2))
return;
INIT_WORK(&req->z.zmgmt_work, nvmet_bdev_zone_zmgmt_recv_work);