Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: target: iscsi: 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.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20241202010844.144356-20-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>

+49 -182
+2 -1
drivers/target/iscsi/Kconfig
··· 2 2 config ISCSI_TARGET 3 3 tristate "SCSI Target Mode Stack" 4 4 depends on INET 5 + select CRC32 5 6 select CRYPTO 6 - select CRYPTO_CRC32C 7 + select CRYPTO_HASH 7 8 help 8 9 Say M to enable the SCSI target mode stack. A SCSI target mode stack 9 10 is software that makes local storage available over a storage network
+45 -108
drivers/target/iscsi/iscsi_target.c
··· 8 8 * 9 9 ******************************************************************************/ 10 10 11 - #include <crypto/hash.h> 11 + #include <linux/crc32c.h> 12 12 #include <linux/string.h> 13 13 #include <linux/kthread.h> 14 14 #include <linux/completion.h> ··· 490 490 } 491 491 EXPORT_SYMBOL(iscsit_aborted_task); 492 492 493 - static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *, 494 - u32, u32, const void *, void *); 493 + static u32 iscsit_crc_buf(const void *buf, u32 payload_length, 494 + u32 padding, const void *pad_bytes); 495 495 static void iscsit_tx_thread_wait_for_tcp(struct iscsit_conn *); 496 496 497 497 static int ··· 510 510 if (conn->conn_ops->HeaderDigest) { 511 511 u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; 512 512 513 - iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, 514 - ISCSI_HDR_LEN, 0, NULL, 515 - header_digest); 513 + *header_digest = iscsit_crc_buf(hdr, ISCSI_HDR_LEN, 0, NULL); 516 514 517 515 iov[0].iov_len += ISCSI_CRC_LEN; 518 516 tx_size += ISCSI_CRC_LEN; ··· 535 537 } 536 538 537 539 if (conn->conn_ops->DataDigest) { 538 - iscsit_do_crypto_hash_buf(conn->conn_tx_hash, 539 - data_buf, data_buf_len, 540 - padding, &cmd->pad_bytes, 541 - &cmd->data_crc); 542 - 540 + cmd->data_crc = iscsit_crc_buf(data_buf, data_buf_len, 541 + padding, 542 + &cmd->pad_bytes); 543 543 iov[niov].iov_base = &cmd->data_crc; 544 544 iov[niov++].iov_len = ISCSI_CRC_LEN; 545 545 tx_size += ISCSI_CRC_LEN; ··· 562 566 static int iscsit_map_iovec(struct iscsit_cmd *cmd, struct kvec *iov, int nvec, 563 567 u32 data_offset, u32 data_length); 564 568 static void iscsit_unmap_iovec(struct iscsit_cmd *); 565 - static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsit_cmd *, 566 - u32, u32, u32, u8 *); 569 + static u32 iscsit_crc_sglist(const struct iscsit_cmd *cmd, u32 data_length, 570 + u32 padding, const u8 *pad_bytes); 567 571 static int 568 572 iscsit_xmit_datain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, 569 573 const struct iscsi_datain *datain) ··· 580 584 if (conn->conn_ops->HeaderDigest) { 581 585 u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; 582 586 583 - iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, 584 - ISCSI_HDR_LEN, 0, NULL, 585 - header_digest); 586 - 587 + *header_digest = iscsit_crc_buf(cmd->pdu, ISCSI_HDR_LEN, 0, 588 + NULL); 587 589 iov[0].iov_len += ISCSI_CRC_LEN; 588 590 tx_size += ISCSI_CRC_LEN; 589 591 ··· 608 614 } 609 615 610 616 if (conn->conn_ops->DataDigest) { 611 - cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash, 612 - cmd, datain->offset, 613 - datain->length, 614 - cmd->padding, 615 - cmd->pad_bytes); 616 - 617 + cmd->data_crc = iscsit_crc_sglist(cmd, datain->length, 618 + cmd->padding, cmd->pad_bytes); 617 619 iov[iov_count].iov_base = &cmd->data_crc; 618 620 iov[iov_count++].iov_len = ISCSI_CRC_LEN; 619 621 tx_size += ISCSI_CRC_LEN; ··· 1394 1404 return iscsit_get_immediate_data(cmd, hdr, dump_payload); 1395 1405 } 1396 1406 1397 - static u32 iscsit_do_crypto_hash_sg( 1398 - struct ahash_request *hash, 1399 - struct iscsit_cmd *cmd, 1400 - u32 data_offset, 1401 - u32 data_length, 1402 - u32 padding, 1403 - u8 *pad_bytes) 1407 + static u32 iscsit_crc_sglist(const struct iscsit_cmd *cmd, u32 data_length, 1408 + u32 padding, const u8 *pad_bytes) 1404 1409 { 1405 - u32 data_crc; 1406 - struct scatterlist *sg; 1407 - unsigned int page_off; 1408 - 1409 - crypto_ahash_init(hash); 1410 - 1411 - sg = cmd->first_data_sg; 1412 - page_off = cmd->first_data_sg_off; 1413 - 1414 - if (data_length && page_off) { 1415 - struct scatterlist first_sg; 1416 - u32 len = min_t(u32, data_length, sg->length - page_off); 1417 - 1418 - sg_init_table(&first_sg, 1); 1419 - sg_set_page(&first_sg, sg_page(sg), len, sg->offset + page_off); 1420 - 1421 - ahash_request_set_crypt(hash, &first_sg, NULL, len); 1422 - crypto_ahash_update(hash); 1423 - 1424 - data_length -= len; 1425 - sg = sg_next(sg); 1426 - } 1410 + struct scatterlist *sg = cmd->first_data_sg; 1411 + unsigned int page_off = cmd->first_data_sg_off; 1412 + u32 crc = ~0; 1427 1413 1428 1414 while (data_length) { 1429 - u32 cur_len = min_t(u32, data_length, sg->length); 1415 + u32 cur_len = min_t(u32, data_length, sg->length - page_off); 1416 + const void *virt; 1430 1417 1431 - ahash_request_set_crypt(hash, sg, NULL, cur_len); 1432 - crypto_ahash_update(hash); 1418 + virt = kmap_local_page(sg_page(sg)) + sg->offset + page_off; 1419 + crc = crc32c(crc, virt, cur_len); 1420 + kunmap_local(virt); 1433 1421 1434 - data_length -= cur_len; 1435 1422 /* iscsit_map_iovec has already checked for invalid sg pointers */ 1436 1423 sg = sg_next(sg); 1424 + 1425 + page_off = 0; 1426 + data_length -= cur_len; 1437 1427 } 1438 1428 1439 - if (padding) { 1440 - struct scatterlist pad_sg; 1429 + if (padding) 1430 + crc = crc32c(crc, pad_bytes, padding); 1441 1431 1442 - sg_init_one(&pad_sg, pad_bytes, padding); 1443 - ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc, 1444 - padding); 1445 - crypto_ahash_finup(hash); 1446 - } else { 1447 - ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0); 1448 - crypto_ahash_final(hash); 1449 - } 1450 - 1451 - return data_crc; 1432 + return ~crc; 1452 1433 } 1453 1434 1454 - static void iscsit_do_crypto_hash_buf(struct ahash_request *hash, 1455 - const void *buf, u32 payload_length, u32 padding, 1456 - const void *pad_bytes, void *data_crc) 1435 + static u32 iscsit_crc_buf(const void *buf, u32 payload_length, 1436 + u32 padding, const void *pad_bytes) 1457 1437 { 1458 - struct scatterlist sg[2]; 1438 + u32 crc = ~0; 1459 1439 1460 - sg_init_table(sg, ARRAY_SIZE(sg)); 1461 - sg_set_buf(sg, buf, payload_length); 1440 + crc = crc32c(crc, buf, payload_length); 1441 + 1462 1442 if (padding) 1463 - sg_set_buf(sg + 1, pad_bytes, padding); 1443 + crc = crc32c(crc, pad_bytes, padding); 1464 1444 1465 - ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding); 1466 - 1467 - crypto_ahash_digest(hash); 1445 + return ~crc; 1468 1446 } 1469 1447 1470 1448 int ··· 1620 1662 if (conn->conn_ops->DataDigest) { 1621 1663 u32 data_crc; 1622 1664 1623 - data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, 1624 - be32_to_cpu(hdr->offset), 1625 - payload_length, padding, 1626 - cmd->pad_bytes); 1627 - 1665 + data_crc = iscsit_crc_sglist(cmd, payload_length, padding, 1666 + cmd->pad_bytes); 1628 1667 if (checksum != data_crc) { 1629 1668 pr_err("ITT: 0x%08x, Offset: %u, Length: %u," 1630 1669 " DataSN: 0x%08x, CRC32C DataDigest 0x%08x" ··· 1880 1925 } 1881 1926 1882 1927 if (conn->conn_ops->DataDigest) { 1883 - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data, 1884 - payload_length, padding, 1885 - cmd->pad_bytes, &data_crc); 1886 - 1928 + data_crc = iscsit_crc_buf(ping_data, payload_length, 1929 + padding, cmd->pad_bytes); 1887 1930 if (checksum != data_crc) { 1888 1931 pr_err("Ping data CRC32C DataDigest" 1889 1932 " 0x%08x does not match computed 0x%08x\n", ··· 2281 2328 goto reject; 2282 2329 2283 2330 if (conn->conn_ops->DataDigest) { 2284 - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, 2285 - text_in, rx_size, 0, NULL, 2286 - &data_crc); 2287 - 2331 + data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL); 2288 2332 if (checksum != data_crc) { 2289 2333 pr_err("Text data CRC32C DataDigest" 2290 2334 " 0x%08x does not match computed" ··· 2638 2688 if (conn->conn_ops->DataDigest) { 2639 2689 u32 data_crc; 2640 2690 2641 - data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, 2642 - cmd->write_data_done, length, padding, 2643 - cmd->pad_bytes); 2644 - 2691 + data_crc = iscsit_crc_sglist(cmd, length, padding, 2692 + cmd->pad_bytes); 2645 2693 if (checksum != data_crc) { 2646 2694 pr_err("ImmediateData CRC32C DataDigest 0x%08x" 2647 2695 " does not match computed 0x%08x\n", checksum, ··· 4064 4116 break; 4065 4117 } 4066 4118 4067 - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer, 4068 - ISCSI_HDR_LEN, 0, NULL, 4069 - &checksum); 4070 - 4119 + checksum = iscsit_crc_buf(buffer, ISCSI_HDR_LEN, 0, 4120 + NULL); 4071 4121 if (digest != checksum) { 4072 4122 pr_err("HeaderDigest CRC32C failed," 4073 4123 " received 0x%08x, computed 0x%08x\n", ··· 4351 4405 * must wait until they have completed. 4352 4406 */ 4353 4407 iscsit_check_conn_usage_count(conn); 4354 - 4355 - ahash_request_free(conn->conn_tx_hash); 4356 - if (conn->conn_rx_hash) { 4357 - struct crypto_ahash *tfm; 4358 - 4359 - tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); 4360 - ahash_request_free(conn->conn_rx_hash); 4361 - crypto_free_ahash(tfm); 4362 - } 4363 4408 4364 4409 if (conn->sock) 4365 4410 sock_release(conn->sock);
-50
drivers/target/iscsi/iscsi_target_login.c
··· 8 8 * 9 9 ******************************************************************************/ 10 10 11 - #include <crypto/hash.h> 12 11 #include <linux/module.h> 13 12 #include <linux/string.h> 14 13 #include <linux/kthread.h> ··· 68 69 out_login: 69 70 kfree(login); 70 71 return NULL; 71 - } 72 - 73 - /* 74 - * Used by iscsi_target_nego.c:iscsi_target_locate_portal() to setup 75 - * per struct iscsit_conn libcrypto contexts for crc32c and crc32-intel 76 - */ 77 - int iscsi_login_setup_crypto(struct iscsit_conn *conn) 78 - { 79 - struct crypto_ahash *tfm; 80 - 81 - /* 82 - * Setup slicing by CRC32C algorithm for RX and TX libcrypto contexts 83 - * which will default to crc32c_intel.ko for cpu_has_xmm4_2, or fallback 84 - * to software 1x8 byte slicing from crc32c.ko 85 - */ 86 - tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); 87 - if (IS_ERR(tfm)) { 88 - pr_err("crypto_alloc_ahash() failed\n"); 89 - return -ENOMEM; 90 - } 91 - 92 - conn->conn_rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); 93 - if (!conn->conn_rx_hash) { 94 - pr_err("ahash_request_alloc() failed for conn_rx_hash\n"); 95 - crypto_free_ahash(tfm); 96 - return -ENOMEM; 97 - } 98 - ahash_request_set_callback(conn->conn_rx_hash, 0, NULL, NULL); 99 - 100 - conn->conn_tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); 101 - if (!conn->conn_tx_hash) { 102 - pr_err("ahash_request_alloc() failed for conn_tx_hash\n"); 103 - ahash_request_free(conn->conn_rx_hash); 104 - conn->conn_rx_hash = NULL; 105 - crypto_free_ahash(tfm); 106 - return -ENOMEM; 107 - } 108 - ahash_request_set_callback(conn->conn_tx_hash, 0, NULL, NULL); 109 - 110 - return 0; 111 72 } 112 73 113 74 static int iscsi_login_check_initiator_version( ··· 1122 1163 } else 1123 1164 spin_unlock_bh(&conn->sess->conn_lock); 1124 1165 iscsit_dec_session_usage_count(conn->sess); 1125 - } 1126 - 1127 - ahash_request_free(conn->conn_tx_hash); 1128 - if (conn->conn_rx_hash) { 1129 - struct crypto_ahash *tfm; 1130 - 1131 - tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); 1132 - ahash_request_free(conn->conn_rx_hash); 1133 - crypto_free_ahash(tfm); 1134 1166 } 1135 1167 1136 1168 if (conn->param_list) {
-1
drivers/target/iscsi/iscsi_target_login.h
··· 9 9 struct iscsi_np; 10 10 struct sockaddr_storage; 11 11 12 - extern int iscsi_login_setup_crypto(struct iscsit_conn *); 13 12 extern int iscsi_check_for_session_reinstatement(struct iscsit_conn *); 14 13 extern int iscsi_login_post_auth_non_zero_tsih(struct iscsit_conn *, u16, u32); 15 14 extern int iscsit_setup_np(struct iscsi_np *,
+2 -19
drivers/target/iscsi/iscsi_target_nego.c
··· 1194 1194 goto get_target; 1195 1195 1196 1196 sess->sess_ops->SessionType = 1; 1197 - /* 1198 - * Setup crc32c modules from libcrypto 1199 - */ 1200 - if (iscsi_login_setup_crypto(conn) < 0) { 1201 - pr_err("iscsi_login_setup_crypto() failed\n"); 1202 - ret = -1; 1203 - goto out; 1204 - } 1197 + 1205 1198 /* 1206 1199 * Serialize access across the discovery struct iscsi_portal_group to 1207 1200 * process login attempt. ··· 1251 1258 } 1252 1259 conn->tpg_np = tpg_np; 1253 1260 pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt); 1254 - /* 1255 - * Setup crc32c modules from libcrypto 1256 - */ 1257 - if (iscsi_login_setup_crypto(conn) < 0) { 1258 - pr_err("iscsi_login_setup_crypto() failed\n"); 1259 - kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); 1260 - iscsit_put_tiqn_for_login(tiqn); 1261 - conn->tpg = NULL; 1262 - ret = -1; 1263 - goto out; 1264 - } 1261 + 1265 1262 /* 1266 1263 * Serialize access across the struct iscsi_portal_group to 1267 1264 * process login attempt.
-3
include/target/iscsi/iscsi_target_core.h
··· 576 576 spinlock_t state_lock; 577 577 spinlock_t login_timer_lock; 578 578 spinlock_t login_worker_lock; 579 - /* libcrypto RX and TX contexts for crc32c */ 580 - struct ahash_request *conn_rx_hash; 581 - struct ahash_request *conn_tx_hash; 582 579 /* Used for scheduling TX and RX connection kthreads */ 583 580 cpumask_var_t conn_cpumask; 584 581 cpumask_var_t allowed_cpumask;