Skip to content

Commit 6b868de

Browse files
ebiggersChristoph Hellwig
authored andcommitted
nvmet-tcp: switch to using the crc32c library
Now that the crc32c() library function directly takes advantage of architecture-specific optimizations, it is unnecessary to go through the crypto API. Just use crc32c(). This is much simpler, and it improves performance due to eliminating the crypto API overhead. Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent 5df496e commit 6b868de

1 file changed

Lines changed: 26 additions & 66 deletions

File tree

drivers/nvme/target/tcp.c

Lines changed: 26 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/module.h>
88
#include <linux/init.h>
99
#include <linux/slab.h>
10+
#include <linux/crc32c.h>
1011
#include <linux/err.h>
1112
#include <linux/nvme-tcp.h>
1213
#include <linux/nvme-keyring.h>
@@ -17,7 +18,6 @@
1718
#include <net/handshake.h>
1819
#include <linux/inet.h>
1920
#include <linux/llist.h>
20-
#include <crypto/hash.h>
2121
#include <trace/events/sock.h>
2222

2323
#include "nvmet.h"
@@ -172,8 +172,6 @@ struct nvmet_tcp_queue {
172172
/* digest state */
173173
bool hdr_digest;
174174
bool data_digest;
175-
struct ahash_request *snd_hash;
176-
struct ahash_request *rcv_hash;
177175

178176
/* TLS state */
179177
key_serial_t tls_pskid;
@@ -294,14 +292,9 @@ static inline u8 nvmet_tcp_ddgst_len(struct nvmet_tcp_queue *queue)
294292
return queue->data_digest ? NVME_TCP_DIGEST_LENGTH : 0;
295293
}
296294

297-
static inline void nvmet_tcp_hdgst(struct ahash_request *hash,
298-
void *pdu, size_t len)
295+
static inline void nvmet_tcp_hdgst(void *pdu, size_t len)
299296
{
300-
struct scatterlist sg;
301-
302-
sg_init_one(&sg, pdu, len);
303-
ahash_request_set_crypt(hash, &sg, pdu + len, len);
304-
crypto_ahash_digest(hash);
297+
put_unaligned_le32(~crc32c(~0, pdu, len), pdu + len);
305298
}
306299

307300
static int nvmet_tcp_verify_hdgst(struct nvmet_tcp_queue *queue,
@@ -318,7 +311,7 @@ static int nvmet_tcp_verify_hdgst(struct nvmet_tcp_queue *queue,
318311
}
319312

320313
recv_digest = *(__le32 *)(pdu + hdr->hlen);
321-
nvmet_tcp_hdgst(queue->rcv_hash, pdu, len);
314+
nvmet_tcp_hdgst(pdu, len);
322315
exp_digest = *(__le32 *)(pdu + hdr->hlen);
323316
if (recv_digest != exp_digest) {
324317
pr_err("queue %d: header digest error: recv %#x expected %#x\n",
@@ -441,12 +434,24 @@ static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
441434
return NVME_SC_INTERNAL;
442435
}
443436

444-
static void nvmet_tcp_calc_ddgst(struct ahash_request *hash,
445-
struct nvmet_tcp_cmd *cmd)
437+
static void nvmet_tcp_calc_ddgst(struct nvmet_tcp_cmd *cmd)
446438
{
447-
ahash_request_set_crypt(hash, cmd->req.sg,
448-
(void *)&cmd->exp_ddgst, cmd->req.transfer_len);
449-
crypto_ahash_digest(hash);
439+
size_t total_len = cmd->req.transfer_len;
440+
struct scatterlist *sg = cmd->req.sg;
441+
u32 crc = ~0;
442+
443+
while (total_len) {
444+
size_t len = min_t(size_t, total_len, sg->length);
445+
446+
/*
447+
* Note that the scatterlist does not contain any highmem pages,
448+
* as it was allocated by sgl_alloc() with GFP_KERNEL.
449+
*/
450+
crc = crc32c(crc, sg_virt(sg), len);
451+
total_len -= len;
452+
sg = sg_next(sg);
453+
}
454+
cmd->exp_ddgst = cpu_to_le32(~crc);
450455
}
451456

452457
static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
@@ -473,19 +478,18 @@ static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
473478

474479
if (queue->data_digest) {
475480
pdu->hdr.flags |= NVME_TCP_F_DDGST;
476-
nvmet_tcp_calc_ddgst(queue->snd_hash, cmd);
481+
nvmet_tcp_calc_ddgst(cmd);
477482
}
478483

479484
if (cmd->queue->hdr_digest) {
480485
pdu->hdr.flags |= NVME_TCP_F_HDGST;
481-
nvmet_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
486+
nvmet_tcp_hdgst(pdu, sizeof(*pdu));
482487
}
483488
}
484489

485490
static void nvmet_setup_r2t_pdu(struct nvmet_tcp_cmd *cmd)
486491
{
487492
struct nvme_tcp_r2t_pdu *pdu = cmd->r2t_pdu;
488-
struct nvmet_tcp_queue *queue = cmd->queue;
489493
u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
490494

491495
cmd->offset = 0;
@@ -503,14 +507,13 @@ static void nvmet_setup_r2t_pdu(struct nvmet_tcp_cmd *cmd)
503507
pdu->r2t_offset = cpu_to_le32(cmd->rbytes_done);
504508
if (cmd->queue->hdr_digest) {
505509
pdu->hdr.flags |= NVME_TCP_F_HDGST;
506-
nvmet_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
510+
nvmet_tcp_hdgst(pdu, sizeof(*pdu));
507511
}
508512
}
509513

510514
static void nvmet_setup_response_pdu(struct nvmet_tcp_cmd *cmd)
511515
{
512516
struct nvme_tcp_rsp_pdu *pdu = cmd->rsp_pdu;
513-
struct nvmet_tcp_queue *queue = cmd->queue;
514517
u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
515518

516519
cmd->offset = 0;
@@ -523,7 +526,7 @@ static void nvmet_setup_response_pdu(struct nvmet_tcp_cmd *cmd)
523526
pdu->hdr.plen = cpu_to_le32(pdu->hdr.hlen + hdgst);
524527
if (cmd->queue->hdr_digest) {
525528
pdu->hdr.flags |= NVME_TCP_F_HDGST;
526-
nvmet_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
529+
nvmet_tcp_hdgst(pdu, sizeof(*pdu));
527530
}
528531
}
529532

@@ -857,42 +860,6 @@ static void nvmet_prepare_receive_pdu(struct nvmet_tcp_queue *queue)
857860
smp_store_release(&queue->rcv_state, NVMET_TCP_RECV_PDU);
858861
}
859862

860-
static void nvmet_tcp_free_crypto(struct nvmet_tcp_queue *queue)
861-
{
862-
struct crypto_ahash *tfm = crypto_ahash_reqtfm(queue->rcv_hash);
863-
864-
ahash_request_free(queue->rcv_hash);
865-
ahash_request_free(queue->snd_hash);
866-
crypto_free_ahash(tfm);
867-
}
868-
869-
static int nvmet_tcp_alloc_crypto(struct nvmet_tcp_queue *queue)
870-
{
871-
struct crypto_ahash *tfm;
872-
873-
tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC);
874-
if (IS_ERR(tfm))
875-
return PTR_ERR(tfm);
876-
877-
queue->snd_hash = ahash_request_alloc(tfm, GFP_KERNEL);
878-
if (!queue->snd_hash)
879-
goto free_tfm;
880-
ahash_request_set_callback(queue->snd_hash, 0, NULL, NULL);
881-
882-
queue->rcv_hash = ahash_request_alloc(tfm, GFP_KERNEL);
883-
if (!queue->rcv_hash)
884-
goto free_snd_hash;
885-
ahash_request_set_callback(queue->rcv_hash, 0, NULL, NULL);
886-
887-
return 0;
888-
free_snd_hash:
889-
ahash_request_free(queue->snd_hash);
890-
free_tfm:
891-
crypto_free_ahash(tfm);
892-
return -ENOMEM;
893-
}
894-
895-
896863
static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
897864
{
898865
struct nvme_tcp_icreq_pdu *icreq = &queue->pdu.icreq;
@@ -921,11 +888,6 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
921888

922889
queue->hdr_digest = !!(icreq->digest & NVME_TCP_HDR_DIGEST_ENABLE);
923890
queue->data_digest = !!(icreq->digest & NVME_TCP_DATA_DIGEST_ENABLE);
924-
if (queue->hdr_digest || queue->data_digest) {
925-
ret = nvmet_tcp_alloc_crypto(queue);
926-
if (ret)
927-
return ret;
928-
}
929891

930892
memset(icresp, 0, sizeof(*icresp));
931893
icresp->hdr.type = nvme_tcp_icresp;
@@ -1247,7 +1209,7 @@ static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd)
12471209
{
12481210
struct nvmet_tcp_queue *queue = cmd->queue;
12491211

1250-
nvmet_tcp_calc_ddgst(queue->rcv_hash, cmd);
1212+
nvmet_tcp_calc_ddgst(cmd);
12511213
queue->offset = 0;
12521214
queue->left = NVME_TCP_DIGEST_LENGTH;
12531215
queue->rcv_state = NVMET_TCP_RECV_DDGST;
@@ -1620,8 +1582,6 @@ static void nvmet_tcp_release_queue_work(struct work_struct *w)
16201582
/* ->sock will be released by fput() */
16211583
fput(queue->sock->file);
16221584
nvmet_tcp_free_cmds(queue);
1623-
if (queue->hdr_digest || queue->data_digest)
1624-
nvmet_tcp_free_crypto(queue);
16251585
ida_free(&nvmet_tcp_queue_ida, queue->idx);
16261586
page_frag_cache_drain(&queue->pf_cache);
16271587
kfree(queue);

0 commit comments

Comments
 (0)