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

net/smc: {at|de}tach sndbuf to peer DMB if supported

If the device used by SMC-D supports merging local sndbuf to peer DMB,
then create sndbuf descriptor and attach it to peer DMB once peer
token is obtained, and detach and free the sndbuf descriptor when the
connection is freed.

Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
Reviewed-and-tested-by: Jan Karcher <jaka@linux.ibm.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Wen Gu and committed by
Paolo Abeni
ae2be35c 43988882

+77 -1
+16
net/smc/af_smc.c
··· 1436 1436 } 1437 1437 1438 1438 smc_conn_save_peer_info(smc, aclc); 1439 + 1440 + if (smc_ism_support_dmb_nocopy(smc->conn.lgr->smcd)) { 1441 + rc = smcd_buf_attach(smc); 1442 + if (rc) { 1443 + rc = SMC_CLC_DECL_MEM; /* try to fallback */ 1444 + goto connect_abort; 1445 + } 1446 + } 1439 1447 smc_close_init(smc); 1440 1448 smc_rx_init(smc); 1441 1449 smc_tx_init(smc); ··· 2548 2540 mutex_unlock(&smc_server_lgr_pending); 2549 2541 } 2550 2542 smc_conn_save_peer_info(new_smc, cclc); 2543 + 2544 + if (ini->is_smcd && 2545 + smc_ism_support_dmb_nocopy(new_smc->conn.lgr->smcd)) { 2546 + rc = smcd_buf_attach(new_smc); 2547 + if (rc) 2548 + goto out_decl; 2549 + } 2550 + 2551 2551 smc_listen_out_connected(new_smc); 2552 2552 SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini); 2553 2553 goto out_free;
+60 -1
net/smc/smc_core.c
··· 1149 1149 } 1150 1150 } 1151 1151 1152 + static void smcd_buf_detach(struct smc_connection *conn) 1153 + { 1154 + struct smcd_dev *smcd = conn->lgr->smcd; 1155 + u64 peer_token = conn->peer_token; 1156 + 1157 + if (!conn->sndbuf_desc) 1158 + return; 1159 + 1160 + smc_ism_detach_dmb(smcd, peer_token); 1161 + 1162 + kfree(conn->sndbuf_desc); 1163 + conn->sndbuf_desc = NULL; 1164 + } 1165 + 1152 1166 static void smc_buf_unuse(struct smc_connection *conn, 1153 1167 struct smc_link_group *lgr) 1154 1168 { ··· 1206 1192 if (lgr->is_smcd) { 1207 1193 if (!list_empty(&lgr->list)) 1208 1194 smc_ism_unset_conn(conn); 1195 + if (smc_ism_support_dmb_nocopy(lgr->smcd)) 1196 + smcd_buf_detach(conn); 1209 1197 tasklet_kill(&conn->rx_tsklet); 1210 1198 } else { 1211 1199 smc_cdc_wait_pend_tx_wr(conn); ··· 1461 1445 smc_sk_wake_ups(smc); 1462 1446 if (conn->lgr->is_smcd) { 1463 1447 smc_ism_unset_conn(conn); 1448 + if (smc_ism_support_dmb_nocopy(conn->lgr->smcd)) 1449 + smcd_buf_detach(conn); 1464 1450 if (soft) 1465 1451 tasklet_kill(&conn->rx_tsklet); 1466 1452 else ··· 2482 2464 int rc; 2483 2465 2484 2466 /* create send buffer */ 2467 + if (is_smcd && 2468 + smc_ism_support_dmb_nocopy(smc->conn.lgr->smcd)) 2469 + goto create_rmb; 2470 + 2485 2471 rc = __smc_buf_create(smc, is_smcd, false); 2486 2472 if (rc) 2487 2473 return rc; 2474 + 2475 + create_rmb: 2488 2476 /* create rmb */ 2489 2477 rc = __smc_buf_create(smc, is_smcd, true); 2490 - if (rc) { 2478 + if (rc && smc->conn.sndbuf_desc) { 2491 2479 down_write(&smc->conn.lgr->sndbufs_lock); 2492 2480 list_del(&smc->conn.sndbuf_desc->list); 2493 2481 up_write(&smc->conn.lgr->sndbufs_lock); 2494 2482 smc_buf_free(smc->conn.lgr, false, smc->conn.sndbuf_desc); 2495 2483 smc->conn.sndbuf_desc = NULL; 2496 2484 } 2485 + return rc; 2486 + } 2487 + 2488 + int smcd_buf_attach(struct smc_sock *smc) 2489 + { 2490 + struct smc_connection *conn = &smc->conn; 2491 + struct smcd_dev *smcd = conn->lgr->smcd; 2492 + u64 peer_token = conn->peer_token; 2493 + struct smc_buf_desc *buf_desc; 2494 + int rc; 2495 + 2496 + buf_desc = kzalloc(sizeof(*buf_desc), GFP_KERNEL); 2497 + if (!buf_desc) 2498 + return -ENOMEM; 2499 + 2500 + /* The ghost sndbuf_desc describes the same memory region as 2501 + * peer RMB. Its lifecycle is consistent with the connection's 2502 + * and it will be freed with the connections instead of the 2503 + * link group. 2504 + */ 2505 + rc = smc_ism_attach_dmb(smcd, peer_token, buf_desc); 2506 + if (rc) 2507 + goto free; 2508 + 2509 + smc->sk.sk_sndbuf = buf_desc->len; 2510 + buf_desc->cpu_addr = 2511 + (u8 *)buf_desc->cpu_addr + sizeof(struct smcd_cdc_msg); 2512 + buf_desc->len -= sizeof(struct smcd_cdc_msg); 2513 + conn->sndbuf_desc = buf_desc; 2514 + conn->sndbuf_desc->used = 1; 2515 + atomic_set(&conn->sndbuf_space, conn->sndbuf_desc->len); 2516 + return 0; 2517 + 2518 + free: 2519 + kfree(buf_desc); 2497 2520 return rc; 2498 2521 } 2499 2522
+1
net/smc/smc_core.h
··· 557 557 void smc_smcd_terminate_all(struct smcd_dev *dev); 558 558 void smc_smcr_terminate_all(struct smc_ib_device *smcibdev); 559 559 int smc_buf_create(struct smc_sock *smc, bool is_smcd); 560 + int smcd_buf_attach(struct smc_sock *smc); 560 561 int smc_uncompress_bufsize(u8 compressed); 561 562 int smc_rmb_rtoken_handling(struct smc_connection *conn, struct smc_link *link, 562 563 struct smc_clc_msg_accept_confirm *clc);