mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 00:51:51 -04:00
Merge tag 'nvme-7.1-2026-04-24' of git://git.infradead.org/nvme into block-7.1
Pull NVMe fixes from Keith: "- Target data transfer size confiruation (Aurelien) - Enable P2P for RDMA (Shivaji Kant) - TCP target updates (Maurizio, Alistair, Chaitanya, Shivam Kumar) - TCP host updates (Alistair, Chaitanya) - Authentication updates (Alistair, Daniel, Chris Leech) - Multipath fixes (John Garry) - New quirks (Alan Cui, Tao Jiang) - Apple driver fix (Fedor Pchelkin) - PCI admin doorbell update fix (Keith)" * tag 'nvme-7.1-2026-04-24' of git://git.infradead.org/nvme: (22 commits) nvme-auth: Hash DH shared secret to create session key nvme-pci: fix missed admin queue sq doorbell write nvme-auth: Include SC_C in RVAL controller hash nvme-tcp: teardown circular locking fixes nvmet-tcp: Don't clear tls_key when freeing sq Revert "nvmet-tcp: Don't free SQ on authentication success" nvme: skip trace completion for host path errors nvme-pci: add quirk for Memblaze Pblaze5 (0x1c5f:0x0555) nvme-multipath: put module reference when delayed removal work is canceled nvme: expose TLS mode nvme-apple: drop invalid put of admin queue reference count nvme-core: fix parameter name in comment nvmet: avoid recursive nvmet-wq flush in nvmet_ctrl_free nvme-multipath: drop head pointer check in nvme_mpath_clear_current_path() nvme: add quirk NVME_QUIRK_IGNORE_DEV_SUBNQN for 144d:a808 (Samsung PM981/983/970 EVO Plus ) nvmet-tcp: fix race between ICReq handling and queue teardown nvmet-tcp: remove redundant calls to nvmet_tcp_fatal_error() nvmet-tcp: propagate nvmet_tcp_build_pdu_iovec() errors to its callers nvme: enable PCI P2PDMA support for RDMA transport nvmet: introduce new mdts configuration entry ...
This commit is contained in:
@@ -351,18 +351,29 @@ struct nvme_dhchap_key *nvme_auth_transform_key(
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_auth_transform_key);
|
||||
|
||||
/**
|
||||
* nvme_auth_augmented_challenge() - Compute the augmented DH-HMAC-CHAP challenge
|
||||
* @hmac_id: Hash algorithm identifier
|
||||
* @skey: Session key
|
||||
* @skey_len: Length of @skey
|
||||
* @challenge: Challenge value
|
||||
* @aug: Output buffer for the augmented challenge
|
||||
* @hlen: Hash output length (length of @challenge and @aug)
|
||||
*
|
||||
* NVMe base specification 8.3.5.5.4: The augmented challenge is computed
|
||||
* applying the HMAC function using the hash function H() selected by the
|
||||
* HashID parameter ... with the hash of the ephemeral DH key ... as HMAC key
|
||||
* to the challenge C (i.e., Ca = HMAC(H(g^xy mod p), C)).
|
||||
*
|
||||
* As the session key skey is already H(g^xy mod p) per section 8.3.5.5.9, use
|
||||
* it directly as the HMAC key without additional hashing.
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure.
|
||||
*/
|
||||
int nvme_auth_augmented_challenge(u8 hmac_id, const u8 *skey, size_t skey_len,
|
||||
const u8 *challenge, u8 *aug, size_t hlen)
|
||||
{
|
||||
u8 hashed_key[NVME_AUTH_MAX_DIGEST_SIZE];
|
||||
int ret;
|
||||
|
||||
ret = nvme_auth_hash(hmac_id, skey, skey_len, hashed_key);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nvme_auth_hmac(hmac_id, hashed_key, hlen, challenge, hlen, aug);
|
||||
memzero_explicit(hashed_key, sizeof(hashed_key));
|
||||
return ret;
|
||||
return nvme_auth_hmac(hmac_id, skey, skey_len, challenge, hlen, aug);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_auth_augmented_challenge);
|
||||
|
||||
@@ -403,33 +414,76 @@ int nvme_auth_gen_pubkey(struct crypto_kpp *dh_tfm,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_auth_gen_pubkey);
|
||||
|
||||
int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm,
|
||||
const u8 *ctrl_key, size_t ctrl_key_len,
|
||||
u8 *sess_key, size_t sess_key_len)
|
||||
/**
|
||||
* nvme_auth_gen_session_key() - Generate an ephemeral session key
|
||||
* @dh_tfm: Diffie-Hellman transform with local private key already set
|
||||
* @public_key: Peer's public key
|
||||
* @public_key_len: Length of @public_key
|
||||
* @sess_key: Output buffer for the session key
|
||||
* @sess_key_len: Size of @sess_key buffer
|
||||
* @hash_id: Hash algorithm identifier
|
||||
*
|
||||
* NVMe base specification 8.3.5.5.9: The session key Ks shall be computed from
|
||||
* the ephemeral DH key (i.e., g^xy mod p) ... by applying the hash function
|
||||
* H() selected by the HashID parameter ... (i.e., Ks = H(g^xy mod p)).
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure.
|
||||
*/
|
||||
int nvme_auth_gen_session_key(struct crypto_kpp *dh_tfm,
|
||||
const u8 *public_key, size_t public_key_len,
|
||||
u8 *sess_key, size_t sess_key_len, u8 hash_id)
|
||||
{
|
||||
struct kpp_request *req;
|
||||
struct crypto_wait wait;
|
||||
struct scatterlist src, dst;
|
||||
u8 *dh_secret;
|
||||
size_t dh_secret_len, hash_len;
|
||||
int ret;
|
||||
|
||||
req = kpp_request_alloc(dh_tfm, GFP_KERNEL);
|
||||
if (!req)
|
||||
hash_len = nvme_auth_hmac_hash_len(hash_id);
|
||||
if (!hash_len) {
|
||||
pr_warn("%s: invalid hash algorithm %d\n", __func__, hash_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sess_key_len != hash_len) {
|
||||
pr_warn("%s: sess_key buffer missized (%zu != %zu)\n",
|
||||
__func__, sess_key_len, hash_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dh_secret_len = crypto_kpp_maxsize(dh_tfm);
|
||||
dh_secret = kzalloc(dh_secret_len, GFP_KERNEL);
|
||||
if (!dh_secret)
|
||||
return -ENOMEM;
|
||||
|
||||
req = kpp_request_alloc(dh_tfm, GFP_KERNEL);
|
||||
if (!req) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_secret;
|
||||
}
|
||||
|
||||
crypto_init_wait(&wait);
|
||||
sg_init_one(&src, ctrl_key, ctrl_key_len);
|
||||
kpp_request_set_input(req, &src, ctrl_key_len);
|
||||
sg_init_one(&dst, sess_key, sess_key_len);
|
||||
kpp_request_set_output(req, &dst, sess_key_len);
|
||||
sg_init_one(&src, public_key, public_key_len);
|
||||
kpp_request_set_input(req, &src, public_key_len);
|
||||
sg_init_one(&dst, dh_secret, dh_secret_len);
|
||||
kpp_request_set_output(req, &dst, dh_secret_len);
|
||||
kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
||||
crypto_req_done, &wait);
|
||||
|
||||
ret = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
|
||||
|
||||
kpp_request_free(req);
|
||||
|
||||
if (ret)
|
||||
goto out_free_secret;
|
||||
|
||||
ret = nvme_auth_hash(hash_id, dh_secret, dh_secret_len, sess_key);
|
||||
|
||||
out_free_secret:
|
||||
kfree_sensitive(dh_secret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_auth_gen_shared_secret);
|
||||
EXPORT_SYMBOL_GPL(nvme_auth_gen_session_key);
|
||||
|
||||
int nvme_auth_parse_key(const char *secret, struct nvme_dhchap_key **ret_key)
|
||||
{
|
||||
|
||||
@@ -1267,11 +1267,7 @@ static int apple_nvme_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
|
||||
|
||||
static void apple_nvme_free_ctrl(struct nvme_ctrl *ctrl)
|
||||
{
|
||||
struct apple_nvme *anv = ctrl_to_apple_nvme(ctrl);
|
||||
|
||||
if (anv->ctrl.admin_q)
|
||||
blk_put_queue(anv->ctrl.admin_q);
|
||||
put_device(anv->dev);
|
||||
put_device(ctrl->dev);
|
||||
}
|
||||
|
||||
static const struct nvme_ctrl_ops nvme_ctrl_ops = {
|
||||
|
||||
@@ -535,11 +535,12 @@ static int nvme_auth_dhchap_setup_ctrl_response(struct nvme_ctrl *ctrl,
|
||||
put_unaligned_le16(chap->transaction, buf);
|
||||
nvme_auth_hmac_update(&hmac, buf, 2);
|
||||
|
||||
memset(buf, 0, 4);
|
||||
*buf = chap->sc_c;
|
||||
nvme_auth_hmac_update(&hmac, buf, 1);
|
||||
nvme_auth_hmac_update(&hmac, "Controller", 10);
|
||||
nvme_auth_hmac_update(&hmac, ctrl->opts->subsysnqn,
|
||||
strlen(ctrl->opts->subsysnqn));
|
||||
memset(buf, 0, 4);
|
||||
nvme_auth_hmac_update(&hmac, buf, 1);
|
||||
nvme_auth_hmac_update(&hmac, ctrl->opts->host->nqn,
|
||||
strlen(ctrl->opts->host->nqn));
|
||||
@@ -587,7 +588,7 @@ static int nvme_auth_dhchap_exponential(struct nvme_ctrl *ctrl,
|
||||
}
|
||||
|
||||
gen_sesskey:
|
||||
chap->sess_key_len = chap->host_key_len;
|
||||
chap->sess_key_len = chap->hash_len;
|
||||
chap->sess_key = kmalloc(chap->sess_key_len, GFP_KERNEL);
|
||||
if (!chap->sess_key) {
|
||||
chap->sess_key_len = 0;
|
||||
@@ -595,16 +596,17 @@ static int nvme_auth_dhchap_exponential(struct nvme_ctrl *ctrl,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = nvme_auth_gen_shared_secret(chap->dh_tfm,
|
||||
chap->ctrl_key, chap->ctrl_key_len,
|
||||
chap->sess_key, chap->sess_key_len);
|
||||
ret = nvme_auth_gen_session_key(chap->dh_tfm,
|
||||
chap->ctrl_key, chap->ctrl_key_len,
|
||||
chap->sess_key, chap->sess_key_len,
|
||||
chap->hash_id);
|
||||
if (ret) {
|
||||
dev_dbg(ctrl->device,
|
||||
"failed to generate shared secret, error %d\n", ret);
|
||||
"failed to generate session key, error %d\n", ret);
|
||||
chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
|
||||
return ret;
|
||||
}
|
||||
dev_dbg(ctrl->device, "shared secret %*ph\n",
|
||||
dev_dbg(ctrl->device, "session key %*ph\n",
|
||||
(int)chap->sess_key_len, chap->sess_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -454,11 +454,10 @@ void nvme_end_req(struct request *req)
|
||||
blk_mq_end_request(req, status);
|
||||
}
|
||||
|
||||
void nvme_complete_rq(struct request *req)
|
||||
static void __nvme_complete_rq(struct request *req)
|
||||
{
|
||||
struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
|
||||
|
||||
trace_nvme_complete_rq(req);
|
||||
nvme_cleanup_cmd(req);
|
||||
|
||||
/*
|
||||
@@ -493,6 +492,12 @@ void nvme_complete_rq(struct request *req)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void nvme_complete_rq(struct request *req)
|
||||
{
|
||||
trace_nvme_complete_rq(req);
|
||||
__nvme_complete_rq(req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_complete_rq);
|
||||
|
||||
void nvme_complete_batch_req(struct request *req)
|
||||
@@ -513,7 +518,7 @@ blk_status_t nvme_host_path_error(struct request *req)
|
||||
{
|
||||
nvme_req(req)->status = NVME_SC_HOST_PATH_ERROR;
|
||||
blk_mq_set_request_complete(req);
|
||||
nvme_complete_rq(req);
|
||||
__nvme_complete_rq(req);
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_host_path_error);
|
||||
@@ -3044,7 +3049,7 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
|
||||
*
|
||||
* The device is left in a state where it is also not possible
|
||||
* to use "nvme set-feature" to disable APST, but booting with
|
||||
* nvme_core.default_ps_max_latency=0 works.
|
||||
* nvme_core.default_ps_max_latency_us=0 works.
|
||||
*/
|
||||
.vid = 0x1e0f,
|
||||
.mn = "KCD6XVUL6T40",
|
||||
@@ -4083,7 +4088,8 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
|
||||
mutex_unlock(&ctrl->subsys->lock);
|
||||
|
||||
#ifdef CONFIG_NVME_MULTIPATH
|
||||
cancel_delayed_work(&head->remove_work);
|
||||
if (cancel_delayed_work(&head->remove_work))
|
||||
module_put(THIS_MODULE);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -3968,3 +3968,4 @@ module_exit(nvme_fc_exit_module);
|
||||
|
||||
MODULE_DESCRIPTION("NVMe host FC transport driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("nvme-fc");
|
||||
|
||||
@@ -231,16 +231,12 @@ bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
|
||||
bool changed = false;
|
||||
int node;
|
||||
|
||||
if (!head)
|
||||
goto out;
|
||||
|
||||
for_each_node(node) {
|
||||
if (ns == rcu_access_pointer(head->current_path[node])) {
|
||||
rcu_assign_pointer(head->current_path[node], NULL);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@@ -2241,6 +2241,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled)
|
||||
static const struct blk_mq_ops nvme_mq_admin_ops = {
|
||||
.queue_rq = nvme_queue_rq,
|
||||
.complete = nvme_pci_complete_rq,
|
||||
.commit_rqs = nvme_commit_rqs,
|
||||
.init_hctx = nvme_admin_init_hctx,
|
||||
.init_request = nvme_pci_init_request,
|
||||
.timeout = nvme_timeout,
|
||||
@@ -4104,6 +4105,10 @@ static const struct pci_device_id nvme_id_table[] = {
|
||||
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
|
||||
{ PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
|
||||
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
|
||||
{ PCI_DEVICE(0x1c5f, 0x0555), /* Memblaze Pblaze5 adapter */
|
||||
.driver_data = NVME_QUIRK_NO_NS_DESC_LIST, },
|
||||
{ PCI_DEVICE(0x144d, 0xa808), /* Samsung PM981/983 */
|
||||
.driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
|
||||
{ PCI_DEVICE(0x144d, 0xa821), /* Samsung PM1725 */
|
||||
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
|
||||
{ PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */
|
||||
|
||||
@@ -2189,6 +2189,13 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
|
||||
nvme_rdma_reconnect_or_remove(ctrl, ret);
|
||||
}
|
||||
|
||||
static bool nvme_rdma_supports_pci_p2pdma(struct nvme_ctrl *ctrl)
|
||||
{
|
||||
struct nvme_rdma_ctrl *r_ctrl = to_rdma_ctrl(ctrl);
|
||||
|
||||
return ib_dma_pci_p2p_dma_supported(r_ctrl->device->dev);
|
||||
}
|
||||
|
||||
static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
|
||||
.name = "rdma",
|
||||
.module = THIS_MODULE,
|
||||
@@ -2203,6 +2210,7 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
|
||||
.get_address = nvmf_get_address,
|
||||
.stop_ctrl = nvme_rdma_stop_ctrl,
|
||||
.get_virt_boundary = nvme_get_virt_boundary,
|
||||
.supports_pci_p2pdma = nvme_rdma_supports_pci_p2pdma,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2432,3 +2440,4 @@ module_exit(nvme_rdma_cleanup_module);
|
||||
|
||||
MODULE_DESCRIPTION("NVMe host RDMA transport driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("nvme-rdma");
|
||||
|
||||
@@ -883,10 +883,26 @@ static ssize_t tls_keyring_show(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR_RO(tls_keyring);
|
||||
|
||||
static ssize_t tls_mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
||||
const char *mode;
|
||||
|
||||
if (ctrl->opts->tls)
|
||||
mode = "tls";
|
||||
else
|
||||
mode = "concat";
|
||||
|
||||
return sysfs_emit(buf, "%s\n", mode);
|
||||
}
|
||||
static DEVICE_ATTR_RO(tls_mode);
|
||||
|
||||
static struct attribute *nvme_tls_attrs[] = {
|
||||
&dev_attr_tls_key.attr,
|
||||
&dev_attr_tls_configured_key.attr,
|
||||
&dev_attr_tls_keyring.attr,
|
||||
&dev_attr_tls_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -908,6 +924,9 @@ static umode_t nvme_tls_attrs_are_visible(struct kobject *kobj,
|
||||
if (a == &dev_attr_tls_keyring.attr &&
|
||||
!ctrl->opts->keyring)
|
||||
return 0;
|
||||
if (a == &dev_attr_tls_mode.attr &&
|
||||
!ctrl->opts->tls && !ctrl->opts->concat)
|
||||
return 0;
|
||||
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
@@ -1438,18 +1438,32 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
|
||||
{
|
||||
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
|
||||
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
|
||||
unsigned int noreclaim_flag;
|
||||
unsigned int noio_flag;
|
||||
|
||||
if (!test_and_clear_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
|
||||
return;
|
||||
|
||||
page_frag_cache_drain(&queue->pf_cache);
|
||||
|
||||
noreclaim_flag = memalloc_noreclaim_save();
|
||||
/* ->sock will be released by fput() */
|
||||
fput(queue->sock->file);
|
||||
/**
|
||||
* Prevent memory reclaim from triggering block I/O during socket
|
||||
* teardown. The socket release path fput -> tcp_close ->
|
||||
* tcp_disconnect -> tcp_send_active_reset may allocate memory, and
|
||||
* allowing reclaim to issue I/O could deadlock if we're being called
|
||||
* from block device teardown (e.g., del_gendisk -> elevator cleanup)
|
||||
* which holds locks that the I/O completion path needs.
|
||||
*/
|
||||
noio_flag = memalloc_noio_save();
|
||||
|
||||
/**
|
||||
* Release the socket synchronously. During reset in
|
||||
* 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.
|
||||
*/
|
||||
__fput_sync(queue->sock->file);
|
||||
queue->sock = NULL;
|
||||
memalloc_noreclaim_restore(noreclaim_flag);
|
||||
memalloc_noio_restore(noio_flag);
|
||||
|
||||
kfree(queue->pdu);
|
||||
mutex_destroy(&queue->send_mutex);
|
||||
@@ -1901,8 +1915,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
|
||||
err_rcv_pdu:
|
||||
kfree(queue->pdu);
|
||||
err_sock:
|
||||
/* ->sock will be released by fput() */
|
||||
fput(queue->sock->file);
|
||||
/* 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);
|
||||
@@ -3071,3 +3085,4 @@ module_exit(nvme_tcp_cleanup_module);
|
||||
|
||||
MODULE_DESCRIPTION("NVMe host TCP transport driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("nvme-tcp");
|
||||
|
||||
@@ -687,12 +687,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
|
||||
id->cmic = NVME_CTRL_CMIC_MULTI_PORT | NVME_CTRL_CMIC_MULTI_CTRL |
|
||||
NVME_CTRL_CMIC_ANA;
|
||||
|
||||
/* Limit MDTS according to transport capability */
|
||||
if (ctrl->ops->get_mdts)
|
||||
id->mdts = ctrl->ops->get_mdts(ctrl);
|
||||
else
|
||||
id->mdts = 0;
|
||||
|
||||
/* Limit MDTS according to port config or transport capability */
|
||||
id->mdts = nvmet_ctrl_mdts(req);
|
||||
id->cntlid = cpu_to_le16(ctrl->cntlid);
|
||||
id->ver = cpu_to_le32(ctrl->subsys->ver);
|
||||
|
||||
|
||||
@@ -229,9 +229,6 @@ u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, bool reset)
|
||||
void nvmet_auth_sq_free(struct nvmet_sq *sq)
|
||||
{
|
||||
cancel_delayed_work(&sq->auth_expired_work);
|
||||
#ifdef CONFIG_NVME_TARGET_TCP_TLS
|
||||
sq->tls_key = NULL;
|
||||
#endif
|
||||
kfree(sq->dhchap_c1);
|
||||
sq->dhchap_c1 = NULL;
|
||||
kfree(sq->dhchap_c2);
|
||||
@@ -402,11 +399,12 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
|
||||
put_unaligned_le16(req->sq->dhchap_tid, buf);
|
||||
nvme_auth_hmac_update(&hmac, buf, 2);
|
||||
|
||||
memset(buf, 0, 4);
|
||||
*buf = req->sq->sc_c;
|
||||
nvme_auth_hmac_update(&hmac, buf, 1);
|
||||
nvme_auth_hmac_update(&hmac, "Controller", 10);
|
||||
nvme_auth_hmac_update(&hmac, ctrl->subsys->subsysnqn,
|
||||
strlen(ctrl->subsys->subsysnqn));
|
||||
memset(buf, 0, 4);
|
||||
nvme_auth_hmac_update(&hmac, buf, 1);
|
||||
nvme_auth_hmac_update(&hmac, ctrl->hostnqn, strlen(ctrl->hostnqn));
|
||||
nvme_auth_hmac_final(&hmac, response);
|
||||
@@ -449,18 +447,19 @@ int nvmet_auth_ctrl_sesskey(struct nvmet_req *req,
|
||||
struct nvmet_ctrl *ctrl = req->sq->ctrl;
|
||||
int ret;
|
||||
|
||||
req->sq->dhchap_skey_len = ctrl->dh_keysize;
|
||||
req->sq->dhchap_skey_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
|
||||
req->sq->dhchap_skey = kzalloc(req->sq->dhchap_skey_len, GFP_KERNEL);
|
||||
if (!req->sq->dhchap_skey)
|
||||
return -ENOMEM;
|
||||
ret = nvme_auth_gen_shared_secret(ctrl->dh_tfm,
|
||||
pkey, pkey_size,
|
||||
req->sq->dhchap_skey,
|
||||
req->sq->dhchap_skey_len);
|
||||
ret = nvme_auth_gen_session_key(ctrl->dh_tfm,
|
||||
pkey, pkey_size,
|
||||
req->sq->dhchap_skey,
|
||||
req->sq->dhchap_skey_len,
|
||||
ctrl->shash_id);
|
||||
if (ret)
|
||||
pr_debug("failed to compute shared secret, err %d\n", ret);
|
||||
pr_debug("failed to compute session key, err %d\n", ret);
|
||||
else
|
||||
pr_debug("%s: shared secret %*ph\n", __func__,
|
||||
pr_debug("%s: session key %*ph\n", __func__,
|
||||
(int)req->sq->dhchap_skey_len,
|
||||
req->sq->dhchap_skey);
|
||||
|
||||
|
||||
@@ -301,6 +301,31 @@ static ssize_t nvmet_param_max_queue_size_store(struct config_item *item,
|
||||
|
||||
CONFIGFS_ATTR(nvmet_, param_max_queue_size);
|
||||
|
||||
static ssize_t nvmet_param_mdts_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct nvmet_port *port = to_nvmet_port(item);
|
||||
|
||||
return snprintf(page, PAGE_SIZE, "%d\n", port->mdts);
|
||||
}
|
||||
|
||||
static ssize_t nvmet_param_mdts_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct nvmet_port *port = to_nvmet_port(item);
|
||||
int ret;
|
||||
|
||||
if (nvmet_is_port_enabled(port, __func__))
|
||||
return -EACCES;
|
||||
ret = kstrtoint(page, 0, &port->mdts);
|
||||
if (ret) {
|
||||
pr_err("Invalid value '%s' for mdts\n", page);
|
||||
return -EINVAL;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(nvmet_, param_mdts);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
||||
static ssize_t nvmet_param_pi_enable_show(struct config_item *item,
|
||||
char *page)
|
||||
@@ -1995,6 +2020,7 @@ static struct configfs_attribute *nvmet_port_attrs[] = {
|
||||
&nvmet_attr_addr_tsas,
|
||||
&nvmet_attr_param_inline_data_size,
|
||||
&nvmet_attr_param_max_queue_size,
|
||||
&nvmet_attr_param_mdts,
|
||||
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
||||
&nvmet_attr_param_pi_enable,
|
||||
#endif
|
||||
@@ -2053,6 +2079,7 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
|
||||
INIT_LIST_HEAD(&port->referrals);
|
||||
port->inline_data_size = -1; /* < 0 == let the transport choose */
|
||||
port->max_queue_size = -1; /* < 0 == let the transport choose */
|
||||
port->mdts = -1; /* < 0 == let the transport choose */
|
||||
|
||||
port->disc_addr.trtype = NVMF_TRTYPE_MAX;
|
||||
port->disc_addr.portid = cpu_to_le16(portid);
|
||||
|
||||
@@ -370,6 +370,14 @@ int nvmet_enable_port(struct nvmet_port *port)
|
||||
NVMET_MIN_QUEUE_SIZE,
|
||||
NVMET_MAX_QUEUE_SIZE);
|
||||
|
||||
/*
|
||||
* If the transport didn't set the mdts properly, then clamp it to the
|
||||
* target limits. Also set default values in case the transport didn't
|
||||
* set it at all.
|
||||
*/
|
||||
if (port->mdts < 0 || port->mdts > NVMET_MAX_MDTS)
|
||||
port->mdts = 0;
|
||||
|
||||
port->enabled = true;
|
||||
port->tr_ops = ops;
|
||||
return 0;
|
||||
@@ -1743,7 +1751,7 @@ static void nvmet_ctrl_free(struct kref *ref)
|
||||
|
||||
nvmet_stop_keep_alive_timer(ctrl);
|
||||
|
||||
flush_work(&ctrl->async_event_work);
|
||||
cancel_work_sync(&ctrl->async_event_work);
|
||||
cancel_work_sync(&ctrl->fatal_err_work);
|
||||
|
||||
nvmet_destroy_auth(ctrl);
|
||||
|
||||
@@ -395,10 +395,9 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
|
||||
goto complete;
|
||||
}
|
||||
/* Final states, clear up variables */
|
||||
if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) {
|
||||
nvmet_auth_sq_free(req->sq);
|
||||
nvmet_auth_sq_free(req->sq);
|
||||
if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
|
||||
nvmet_ctrl_fatal_error(ctrl);
|
||||
}
|
||||
|
||||
complete:
|
||||
nvmet_req_complete(req, status);
|
||||
@@ -574,7 +573,9 @@ void nvmet_execute_auth_receive(struct nvmet_req *req)
|
||||
status = nvmet_copy_to_sgl(req, 0, d, al);
|
||||
kfree(d);
|
||||
done:
|
||||
if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
|
||||
if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2)
|
||||
nvmet_auth_sq_free(req->sq);
|
||||
else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
|
||||
nvmet_auth_sq_free(req->sq);
|
||||
nvmet_ctrl_fatal_error(ctrl);
|
||||
}
|
||||
|
||||
@@ -214,6 +214,7 @@ struct nvmet_port {
|
||||
bool enabled;
|
||||
int inline_data_size;
|
||||
int max_queue_size;
|
||||
int mdts;
|
||||
const struct nvmet_fabrics_ops *tr_ops;
|
||||
bool pi_enable;
|
||||
};
|
||||
@@ -673,6 +674,7 @@ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
|
||||
#define NVMET_MAX_QUEUE_SIZE 1024
|
||||
#define NVMET_NR_QUEUES 128
|
||||
#define NVMET_MAX_CMD(ctrl) (NVME_CAP_MQES(ctrl->cap) + 1)
|
||||
#define NVMET_MAX_MDTS 255
|
||||
|
||||
/*
|
||||
* Nice round number that makes a list of nsids fit into a page.
|
||||
@@ -761,6 +763,17 @@ static inline bool nvmet_is_pci_ctrl(struct nvmet_ctrl *ctrl)
|
||||
return ctrl->port->disc_addr.trtype == NVMF_TRTYPE_PCI;
|
||||
}
|
||||
|
||||
/* Limit MDTS according to port config or transport capability */
|
||||
static inline u8 nvmet_ctrl_mdts(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_ctrl *ctrl = req->sq->ctrl;
|
||||
u8 mdts = req->port->mdts;
|
||||
|
||||
if (!ctrl->ops->get_mdts)
|
||||
return mdts;
|
||||
return min_not_zero(ctrl->ops->get_mdts(ctrl), mdts);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NVME_TARGET_PASSTHRU
|
||||
void nvmet_passthru_subsys_free(struct nvmet_subsys *subsys);
|
||||
int nvmet_passthru_ctrl_enable(struct nvmet_subsys *subsys);
|
||||
|
||||
@@ -349,9 +349,7 @@ static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
|
||||
cmd->req.sg = NULL;
|
||||
}
|
||||
|
||||
static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue);
|
||||
|
||||
static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
|
||||
static int nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
|
||||
{
|
||||
struct bio_vec *iov = cmd->iov;
|
||||
struct scatterlist *sg;
|
||||
@@ -364,22 +362,19 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
|
||||
offset = cmd->rbytes_done;
|
||||
cmd->sg_idx = offset / PAGE_SIZE;
|
||||
sg_offset = offset % PAGE_SIZE;
|
||||
if (!cmd->req.sg_cnt || cmd->sg_idx >= cmd->req.sg_cnt) {
|
||||
nvmet_tcp_fatal_error(cmd->queue);
|
||||
return;
|
||||
}
|
||||
if (!cmd->req.sg_cnt || cmd->sg_idx >= cmd->req.sg_cnt)
|
||||
return -EPROTO;
|
||||
|
||||
sg = &cmd->req.sg[cmd->sg_idx];
|
||||
sg_remaining = cmd->req.sg_cnt - cmd->sg_idx;
|
||||
|
||||
while (length) {
|
||||
if (!sg_remaining) {
|
||||
nvmet_tcp_fatal_error(cmd->queue);
|
||||
return;
|
||||
}
|
||||
if (!sg->length || sg->length <= sg_offset) {
|
||||
nvmet_tcp_fatal_error(cmd->queue);
|
||||
return;
|
||||
}
|
||||
if (!sg_remaining)
|
||||
return -EPROTO;
|
||||
|
||||
if (!sg->length || sg->length <= sg_offset)
|
||||
return -EPROTO;
|
||||
|
||||
u32 iov_len = min_t(u32, length, sg->length - sg_offset);
|
||||
|
||||
bvec_set_page(iov, sg_page(sg), iov_len,
|
||||
@@ -394,24 +389,29 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
|
||||
|
||||
iov_iter_bvec(&cmd->recv_msg.msg_iter, ITER_DEST, cmd->iov,
|
||||
nr_pages, cmd->pdu_len);
|
||||
}
|
||||
|
||||
static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue)
|
||||
{
|
||||
queue->rcv_state = NVMET_TCP_RECV_ERR;
|
||||
if (queue->nvme_sq.ctrl)
|
||||
nvmet_ctrl_fatal_error(queue->nvme_sq.ctrl);
|
||||
else
|
||||
kernel_sock_shutdown(queue->sock, SHUT_RDWR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status)
|
||||
{
|
||||
/*
|
||||
* Keep rcv_state at RECV_ERR even for the internal -ESHUTDOWN path.
|
||||
* nvmet_tcp_handle_icreq() can return -ESHUTDOWN after the ICReq has
|
||||
* already been consumed and queue teardown has started.
|
||||
*
|
||||
* If nvmet_tcp_data_ready() or nvmet_tcp_write_space() queues
|
||||
* nvmet_tcp_io_work() again before nvmet_tcp_release_queue_work()
|
||||
* cancels it, the queue must not keep that old receive state.
|
||||
* Otherwise the next nvmet_tcp_io_work() run can reach
|
||||
* nvmet_tcp_done_recv_pdu() and try to handle the same ICReq again.
|
||||
*
|
||||
* That is why queue->rcv_state needs to be updated before we return.
|
||||
*/
|
||||
queue->rcv_state = NVMET_TCP_RECV_ERR;
|
||||
if (status == -EPIPE || status == -ECONNRESET)
|
||||
if (status == -EPIPE || status == -ECONNRESET || !queue->nvme_sq.ctrl)
|
||||
kernel_sock_shutdown(queue->sock, SHUT_RDWR);
|
||||
else
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
nvmet_ctrl_fatal_error(queue->nvme_sq.ctrl);
|
||||
}
|
||||
|
||||
static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
|
||||
@@ -887,7 +887,6 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
|
||||
if (le32_to_cpu(icreq->hdr.plen) != sizeof(struct nvme_tcp_icreq_pdu)) {
|
||||
pr_err("bad nvme-tcp pdu length (%d)\n",
|
||||
le32_to_cpu(icreq->hdr.plen));
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
@@ -922,16 +921,29 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
|
||||
iov.iov_len = sizeof(*icresp);
|
||||
ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len);
|
||||
if (ret < 0) {
|
||||
spin_lock_bh(&queue->state_lock);
|
||||
if (queue->state == NVMET_TCP_Q_DISCONNECTING) {
|
||||
spin_unlock_bh(&queue->state_lock);
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
queue->state = NVMET_TCP_Q_FAILED;
|
||||
spin_unlock_bh(&queue->state_lock);
|
||||
return ret; /* queue removal will cleanup */
|
||||
}
|
||||
|
||||
spin_lock_bh(&queue->state_lock);
|
||||
if (queue->state == NVMET_TCP_Q_DISCONNECTING) {
|
||||
spin_unlock_bh(&queue->state_lock);
|
||||
/* Tell nvmet_tcp_socket_error() teardown is in progress. */
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
queue->state = NVMET_TCP_Q_LIVE;
|
||||
spin_unlock_bh(&queue->state_lock);
|
||||
nvmet_prepare_receive_pdu(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
|
||||
static int nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
|
||||
struct nvmet_tcp_cmd *cmd, struct nvmet_req *req)
|
||||
{
|
||||
size_t data_len = le32_to_cpu(req->cmd->common.dptr.sgl.length);
|
||||
@@ -947,19 +959,22 @@ static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
|
||||
if (!nvme_is_write(cmd->req.cmd) || !data_len ||
|
||||
data_len > cmd->req.port->inline_data_size) {
|
||||
nvmet_prepare_receive_pdu(queue);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = nvmet_tcp_map_data(cmd);
|
||||
if (unlikely(ret)) {
|
||||
pr_err("queue %d: failed to map data\n", queue->idx);
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
queue->rcv_state = NVMET_TCP_RECV_DATA;
|
||||
nvmet_tcp_build_pdu_iovec(cmd);
|
||||
cmd->flags |= NVMET_TCP_F_INIT_FAILED;
|
||||
ret = nvmet_tcp_build_pdu_iovec(cmd);
|
||||
if (unlikely(ret))
|
||||
pr_err("queue %d: failed to build PDU iovec\n", queue->idx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
|
||||
@@ -1011,7 +1026,10 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
|
||||
goto err_proto;
|
||||
}
|
||||
cmd->pdu_recv = 0;
|
||||
nvmet_tcp_build_pdu_iovec(cmd);
|
||||
if (unlikely(nvmet_tcp_build_pdu_iovec(cmd))) {
|
||||
pr_err("queue %d: failed to build PDU iovec\n", queue->idx);
|
||||
goto err_proto;
|
||||
}
|
||||
queue->cmd = cmd;
|
||||
queue->rcv_state = NVMET_TCP_RECV_DATA;
|
||||
|
||||
@@ -1019,7 +1037,6 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
|
||||
|
||||
err_proto:
|
||||
/* FIXME: use proper transport errors */
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
@@ -1034,7 +1051,6 @@ static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
if (hdr->type != nvme_tcp_icreq) {
|
||||
pr_err("unexpected pdu type (%d) before icreq\n",
|
||||
hdr->type);
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -EPROTO;
|
||||
}
|
||||
return nvmet_tcp_handle_icreq(queue);
|
||||
@@ -1043,7 +1059,6 @@ static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
if (unlikely(hdr->type == nvme_tcp_icreq)) {
|
||||
pr_err("queue %d: received icreq pdu in state %d\n",
|
||||
queue->idx, queue->state);
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
@@ -1060,7 +1075,6 @@ static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
pr_err("queue %d: out of commands (%d) send_list_len: %d, opcode: %d",
|
||||
queue->idx, queue->nr_cmds, queue->send_list_len,
|
||||
nvme_cmd->common.opcode);
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -1074,17 +1088,16 @@ static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
le32_to_cpu(req->cmd->common.dptr.sgl.length),
|
||||
le16_to_cpu(req->cqe->status));
|
||||
|
||||
nvmet_tcp_handle_req_failure(queue, queue->cmd, req);
|
||||
return 0;
|
||||
return nvmet_tcp_handle_req_failure(queue, queue->cmd, req);
|
||||
}
|
||||
|
||||
ret = nvmet_tcp_map_data(queue->cmd);
|
||||
if (unlikely(ret)) {
|
||||
pr_err("queue %d: failed to map data\n", queue->idx);
|
||||
if (nvmet_tcp_has_inline_data(queue->cmd))
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
else
|
||||
nvmet_req_complete(req, ret);
|
||||
return -EPROTO;
|
||||
|
||||
nvmet_req_complete(req, ret);
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
@@ -1092,8 +1105,11 @@ static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
if (nvmet_tcp_need_data_in(queue->cmd)) {
|
||||
if (nvmet_tcp_has_inline_data(queue->cmd)) {
|
||||
queue->rcv_state = NVMET_TCP_RECV_DATA;
|
||||
nvmet_tcp_build_pdu_iovec(queue->cmd);
|
||||
return 0;
|
||||
ret = nvmet_tcp_build_pdu_iovec(queue->cmd);
|
||||
if (unlikely(ret))
|
||||
pr_err("queue %d: failed to build PDU iovec\n",
|
||||
queue->idx);
|
||||
return ret;
|
||||
}
|
||||
/* send back R2T */
|
||||
nvmet_tcp_queue_response(&queue->cmd->req);
|
||||
@@ -1204,7 +1220,6 @@ static int nvmet_tcp_try_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
|
||||
if (unlikely(!nvmet_tcp_pdu_valid(hdr->type))) {
|
||||
pr_err("unexpected pdu type %d\n", hdr->type);
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1218,16 +1233,12 @@ static int nvmet_tcp_try_recv_pdu(struct nvmet_tcp_queue *queue)
|
||||
}
|
||||
|
||||
if (queue->hdr_digest &&
|
||||
nvmet_tcp_verify_hdgst(queue, &queue->pdu, hdr->hlen)) {
|
||||
nvmet_tcp_fatal_error(queue); /* fatal */
|
||||
nvmet_tcp_verify_hdgst(queue, &queue->pdu, hdr->hlen))
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (queue->data_digest &&
|
||||
nvmet_tcp_check_ddgst(queue, &queue->pdu)) {
|
||||
nvmet_tcp_fatal_error(queue); /* fatal */
|
||||
nvmet_tcp_check_ddgst(queue, &queue->pdu))
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return nvmet_tcp_done_recv_pdu(queue);
|
||||
}
|
||||
@@ -1310,9 +1321,9 @@ static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue)
|
||||
queue->idx, cmd->req.cmd->common.command_id,
|
||||
queue->pdu.cmd.hdr.type, le32_to_cpu(cmd->recv_ddgst),
|
||||
le32_to_cpu(cmd->exp_ddgst));
|
||||
nvmet_req_uninit(&cmd->req);
|
||||
if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED))
|
||||
nvmet_req_uninit(&cmd->req);
|
||||
nvmet_tcp_free_cmd_buffers(cmd);
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
ret = -EPROTO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ bool nvmet_bdev_zns_enable(struct nvmet_ns *ns)
|
||||
void nvmet_execute_identify_ctrl_zns(struct nvmet_req *req)
|
||||
{
|
||||
u8 zasl = req->sq->ctrl->subsys->zasl;
|
||||
struct nvmet_ctrl *ctrl = req->sq->ctrl;
|
||||
struct nvme_id_ctrl_zns *id;
|
||||
u16 status;
|
||||
|
||||
@@ -79,10 +78,7 @@ void nvmet_execute_identify_ctrl_zns(struct nvmet_req *req)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctrl->ops->get_mdts)
|
||||
id->zasl = min_t(u8, ctrl->ops->get_mdts(ctrl), zasl);
|
||||
else
|
||||
id->zasl = zasl;
|
||||
id->zasl = min_not_zero(nvmet_ctrl_mdts(req), zasl);
|
||||
|
||||
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ int nvme_auth_augmented_challenge(u8 hmac_id, const u8 *skey, size_t skey_len,
|
||||
int nvme_auth_gen_privkey(struct crypto_kpp *dh_tfm, u8 dh_gid);
|
||||
int nvme_auth_gen_pubkey(struct crypto_kpp *dh_tfm,
|
||||
u8 *host_key, size_t host_key_len);
|
||||
int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm,
|
||||
const u8 *ctrl_key, size_t ctrl_key_len,
|
||||
u8 *sess_key, size_t sess_key_len);
|
||||
int nvme_auth_gen_session_key(struct crypto_kpp *dh_tfm,
|
||||
const u8 *public_key, size_t public_key_len,
|
||||
u8 *sess_key, size_t sess_key_len, u8 hash_id);
|
||||
int nvme_auth_generate_psk(u8 hmac_id, const u8 *skey, size_t skey_len,
|
||||
const u8 *c1, const u8 *c2, size_t hash_len,
|
||||
u8 **ret_psk, size_t *ret_len);
|
||||
|
||||
Reference in New Issue
Block a user