net/smc: enhancements 2018/05/15
cover net/smc: enhancements 2018/05/15
From: Ursula Braun <[email protected]>
Dave,
here are smc patches for net-next. The first one is a fix for net-next commit 01d2f7e2cdd3 "net/smc: sockopts TCP_NODELAY and TCP_CORK". Patch 7 improves Connection Layer Control error handling, patch 10 improves abnormal termination of link groups. The remaining patches from Karsten improve Link Layer Control code.
Thanks, Ursula
Karsten Graul (9):
net/smc: register new rmbs with the peer net/smc: remove unnecessary cast
net/smc: simplify test_link function usage net/smc: move link llc initialization to llc layer net/smc: use a workqueue to defer llc send net/smc: handle all error codes from smc_conn_create() net/smc: set link inactive before calling smc_lgr_free() net/smc: drop messages when link state is inactive net/smc: check for pending termination
Ursula Braun (1):
net/smc: no tx work trigger for fallback sockets
net/smc/af_smc.c | 27 +++++--- net/smc/smc_clc.c | 2 +- net/smc/smc_core.c | 23 ++++--- net/smc/smc_core.h | 6 +- net/smc/smc_llc.c | 196 +++++++++++++++++++++++++++++++++++++++++------------ net/smc/smc_llc.h | 7 +- 6 files changed, 196 insertions(+), 65 deletions(-)
Signature · 1 line
2.16.3
PATCH 1/10 net/smc: no tx work trigger for fallback sockets
If TCP_NODELAY is set or TCP_CORK is reset, setsockopt triggers the tx worker. This does not make sense, if the SMC socket switched to the TCP fallback when the connection is created. This patch adds the additional check for the fallback case.
--- net/smc/af_smc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/smc/af_smc.c +2 -2
@@ -1353,14 +1353,14 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,break ;case TCP_NODELAY :if (sk->sk_state !=SMC_INIT && sk->sk_state !=SMC_LISTEN ) { -if (val) +if (val && !smc->use_fallback)mod_delayed_work (system_wq, &smc->conn.tx_work,0 ); }break ;case TCP_CORK :if (sk->sk_state !=SMC_INIT && sk->sk_state !=SMC_LISTEN ) { -if (!val) +if (!val && !smc->use_fallback)mod_delayed_work (system_wq, &smc->conn.tx_work,0 ); }
Signature · 1 line
2.16.3
PATCH 2/10 net/smc: register new rmbs with the peer
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Register new rmb buffers with the remote peer by exchanging a confirm_rkey llc message.
--- net/smc/af_smc.c | 20 ++++++++++++++------ net/smc/smc_core.c | 1 + net/smc/smc_core.h | 2 ++ net/smc/smc_llc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- net/smc/smc_llc.h | 2 ++ 5 files changed, 64 insertions(+), 8 deletions(-)
net/smc/af_smc.c +14 -6
@@ -293,14 +293,22 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc)smc_copy_sock_settings (&smc->sk, smc->clcsock->sk,SK_FLAGS_CLC_TO_SMC ); } -/* register a new rmb */ -static int smc_reg_rmb (struct smc_link *link,struct smc_buf_desc *rmb_desc) +/* register a new rmb, optionally send confirm_rkey msg to register with peer */ +static int smc_reg_rmb (struct smc_link *link,struct smc_buf_desc *rmb_desc, +bool conf_rkey) {/* register memory region for new rmb */ if (smc_wr_reg_send (link, rmb_desc->mr_rx[SMC_SINGLE_LINK ])) { rmb_desc->regerr =1 ;return -EFAULT ; } +if (!conf_rkey) +return 0 ; +/* exchange confirm_rkey msg with peer */ +if (smc_llc_do_confirm_rkey (link, rmb_desc)) { + rmb_desc->regerr =1 ; +return -EFAULT ; + }return 0 ; }
@@ -334,7 +342,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)smc_wr_remember_qp_attr (link); -if (smc_reg_rmb (link, smc->conn.rmb_desc)) +if (smc_reg_rmb (link, smc->conn.rmb_desc, false))return SMC_CLC_DECL_INTERR ;/* send CONFIRM LINK response over RoCE fabric */
@@ -488,7 +496,7 @@ static int smc_connect_rdma(struct smc_sock *smc) } }else {if (!smc->conn.rmb_desc->reused) { -if (smc_reg_rmb (link, smc->conn.rmb_desc)) { +if (smc_reg_rmb (link, smc->conn.rmb_desc, true)) { reason_code =SMC_CLC_DECL_INTERR ; goto decline_rdma_unlock; }
@@ -729,7 +737,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc) link = &lgr->lnk[SMC_SINGLE_LINK ]; -if (smc_reg_rmb (link, smc->conn.rmb_desc)) +if (smc_reg_rmb (link, smc->conn.rmb_desc, false))return SMC_CLC_DECL_INTERR ;/* send CONFIRM LINK request to client over the RoCE fabric */
@@ -866,7 +874,7 @@ static void smc_listen_work(struct work_struct *work)if (local_contact !=SMC_FIRST_CONTACT ) {if (!new_smc->conn.rmb_desc->reused) { -if (smc_reg_rmb (link, new_smc->conn.rmb_desc)) { +if (smc_reg_rmb (link, new_smc->conn.rmb_desc, true)) { reason_code =SMC_CLC_DECL_INTERR ; goto decline_rdma_unlock; }
net/smc/smc_core.c +1 -0
@@ -210,6 +210,7 @@ static int smc_lgr_create(struct smc_sock *smc,init_completion (&lnk->llc_confirm_resp);init_completion (&lnk->llc_add);init_completion (&lnk->llc_add_resp); +init_completion (&lnk->llc_confirm_rkey); smc->conn.lgr = lgr;rwlock_init (&lgr->conns_lock);
net/smc/smc_core.h +2 -0
@@ -105,6 +105,8 @@ struct smc_link {struct delayed_work llc_testlink_wrk;/* testlink worker */ struct completion llc_testlink_resp;/* wait for rx of testlink */ int llc_testlink_time;/* testlink interval */ +struct completion llc_confirm_rkey;/* wait 4 rx of cnf rkey */ +int llc_confirm_rkey_rc;/* rc from cnf rkey msg */ };/* For now we just allow one parallel link per link group. The SMC protocol
net/smc/smc_llc.c +45 -2
71 lines not on this page · raw message
net/smc/smc_llc.h +2 -0
@@ -47,6 +47,8 @@ int smc_llc_send_test_link(struct smc_link *lnk, u8 user_data[16],void smc_llc_link_active (struct smc_link *link,int testlink_time);void smc_llc_link_inactive (struct smc_link *link);void smc_llc_link_flush (struct smc_link *link); +int smc_llc_do_confirm_rkey (struct smc_link *link, +struct smc_buf_desc *rmb_desc);int smc_llc_init (void )__init ;#endif /* SMC_LLC_H */
Signature · 1 line
2.16.3
PATCH 3/10 net/smc: remove unnecessary cast
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Remove an unneeded (void *) cast from the calls to smc_llc_send_message(). No functional changes.
--- net/smc/smc_llc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/smc/smc_llc.c +3 -3
@@ -451,7 +451,7 @@ static void smc_llc_rx_confirm_rkey(struct smc_link *link, llc->hd.flags |=SMC_LLC_FLAG_RESP ;if (rc <0 ) llc->hd.flags |=SMC_LLC_FLAG_RKEY_NEG ; -smc_llc_send_message (link, (void *)llc,sizeof (*llc)); +smc_llc_send_message (link, llc,sizeof (*llc)); } }
@@ -463,7 +463,7 @@ static void smc_llc_rx_confirm_rkey_cont(struct smc_link *link, }else {/* ignore rtokens for other links, we have only one link */ llc->hd.flags |=SMC_LLC_FLAG_RESP ; -smc_llc_send_message (link, (void *)llc,sizeof (*llc)); +smc_llc_send_message (link, llc,sizeof (*llc)); } }
@@ -491,7 +491,7 @@ static void smc_llc_rx_delete_rkey(struct smc_link *link, } llc->hd.flags |=SMC_LLC_FLAG_RESP ; -smc_llc_send_message (link, (void *)llc,sizeof (*llc)); +smc_llc_send_message (link, llc,sizeof (*llc)); } }
Signature · 1 line
2.16.3
PATCH 4/10 net/smc: simplify test_link function usage
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Make smc_llc_send_test_link() static and remove it from the header file. And to send a test_link response set the response flag and send the message back as-is, without using smc_llc_send_test_link(). And because smc_llc_send_test_link() must no longer send responses, remove the response flag handling from the function.
--- net/smc/smc_llc.c | 12 +++++------- net/smc/smc_llc.h | 2 -- 2 files changed, 5 insertions(+), 9 deletions(-)
net/smc/smc_llc.c +5 -7
@@ -296,9 +296,8 @@ int smc_llc_send_delete_link(struct smc_link *link,return rc; } -/* send LLC test link request or response */ -int smc_llc_send_test_link (struct smc_link *link,u8 user_data[16 ], -enum smc_llc_reqresp reqresp) +/* send LLC test link request */ +static int smc_llc_send_test_link (struct smc_link *link,u8 user_data[16 ]) {struct smc_llc_msg_test_link *testllc;struct smc_wr_tx_pend_priv *pend;
@@ -312,8 +311,6 @@ int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16],memset (testllc,0 ,sizeof (*testllc)); testllc->hd.common.type =SMC_LLC_TEST_LINK ; testllc->hd.length =sizeof (struct smc_llc_msg_test_link ); -if (reqresp ==SMC_LLC_RESP ) - testllc->hd.flags |=SMC_LLC_FLAG_RESP ;memcpy (testllc->user_data, user_data,sizeof (testllc->user_data));/* send llc message */ rc =smc_wr_tx_send (link, pend);
@@ -425,7 +422,8 @@ static void smc_llc_rx_test_link(struct smc_link *link,if (link->state ==SMC_LNK_ACTIVE )complete (&link->llc_testlink_resp); }else { -smc_llc_send_test_link (link, llc->user_data,SMC_LLC_RESP ); + llc->hd.flags |=SMC_LLC_FLAG_RESP ; +smc_llc_send_message (link, llc,sizeof (*llc)); } }
@@ -551,7 +549,7 @@ static void smc_llc_testlink_work(struct work_struct *work) goto out; }reinit_completion (&link->llc_testlink_resp); -smc_llc_send_test_link (link, user_data,SMC_LLC_REQ ); +smc_llc_send_test_link (link, user_data);/* receive TEST LINK response over RoCE fabric */ rc =wait_for_completion_interruptible_timeout (&link->llc_testlink_resp,SMC_LLC_WAIT_TIME );
net/smc/smc_llc.h +0 -2
@@ -42,8 +42,6 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], union ib_gid *gid, enum smc_llc_reqresp reqresp);int smc_llc_send_delete_link (struct smc_link *link,enum smc_llc_reqresp reqresp); -int smc_llc_send_test_link (struct smc_link *lnk,u8 user_data[16 ], -enum smc_llc_reqresp reqresp);void smc_llc_link_active (struct smc_link *link,int testlink_time);void smc_llc_link_inactive (struct smc_link *link);void smc_llc_link_flush (struct smc_link *link);
Signature · 1 line
2.16.3
PATCH 5/10 net/smc: move link llc initialization to llc layer
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Move the llc layer specific initialization and cleanup out of smc_core.c into smc_llc.c (smc_llc_link_init and smc_llc_link_clear). Move all initialization of a link into the new init function.
--- net/smc/smc_core.c | 6 +----- net/smc/smc_llc.c | 11 ++++++++++- net/smc/smc_llc.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-)
net/smc/smc_core.c +1 -5
@@ -194,6 +194,7 @@ static int smc_lgr_create(struct smc_sock *smc,smc_ib_setup_per_ibdev (smcibdev);get_random_bytes (rndvec,sizeof (rndvec)); lnk->psn_initial = rndvec[0 ] + (rndvec[1 ] <<8 ) + (rndvec[2 ] <<16 ); +smc_llc_link_init (lnk); rc =smc_wr_alloc_link_mem (lnk);if (rc) goto free_lgr;
@@ -206,11 +207,6 @@ static int smc_lgr_create(struct smc_sock *smc, rc =smc_wr_create_link (lnk);if (rc) goto destroy_qp; -init_completion (&lnk->llc_confirm); -init_completion (&lnk->llc_confirm_resp); -init_completion (&lnk->llc_add); -init_completion (&lnk->llc_add_resp); -init_completion (&lnk->llc_confirm_rkey); smc->conn.lgr = lgr;rwlock_init (&lgr->conns_lock);
net/smc/smc_llc.c +10 -1
@@ -562,10 +562,19 @@ static void smc_llc_testlink_work(struct work_struct *work)schedule_delayed_work (&link->llc_testlink_wrk, next_interval); } -void smc_llc_link_active (struct smc_link *link,int testlink_time) +void smc_llc_link_init (struct smc_link *link) { +init_completion (&link->llc_confirm); +init_completion (&link->llc_confirm_resp); +init_completion (&link->llc_add); +init_completion (&link->llc_add_resp); +init_completion (&link->llc_confirm_rkey);init_completion (&link->llc_testlink_resp);INIT_DELAYED_WORK (&link->llc_testlink_wrk, smc_llc_testlink_work); +} + +void smc_llc_link_active (struct smc_link *link,int testlink_time) +{ link->state =SMC_LNK_ACTIVE ;if (testlink_time) { link->llc_testlink_time = testlink_time *HZ ;
net/smc/smc_llc.h +1 -0
@@ -42,6 +42,7 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], union ib_gid *gid, enum smc_llc_reqresp reqresp);int smc_llc_send_delete_link (struct smc_link *link,enum smc_llc_reqresp reqresp); +void smc_llc_link_init (struct smc_link *link);void smc_llc_link_active (struct smc_link *link,int testlink_time);void smc_llc_link_inactive (struct smc_link *link);void smc_llc_link_flush (struct smc_link *link);
Signature · 1 line
2.16.3
PATCH 6/10 net/smc: use a workqueue to defer llc send
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
SMC handles deferred work in tasklets. As tasklets cannot sleep this can result in rare EBUSY conditions, so defer this work in a work queue. The high level api functions do not defer work because they can sleep until the llc send is actually completed.
--- net/smc/smc_core.c | 10 ++-- net/smc/smc_core.h | 1 + net/smc/smc_llc.c | 132 ++++++++++++++++++++++++++++++++++++++--------------- net/smc/smc_llc.h | 4 +- 4 files changed, 104 insertions(+), 43 deletions(-)
net/smc/smc_core.c +7 -3
@@ -194,10 +194,12 @@ static int smc_lgr_create(struct smc_sock *smc,smc_ib_setup_per_ibdev (smcibdev);get_random_bytes (rndvec,sizeof (rndvec)); lnk->psn_initial = rndvec[0 ] + (rndvec[1 ] <<8 ) + (rndvec[2 ] <<16 ); -smc_llc_link_init (lnk); - rc =smc_wr_alloc_link_mem (lnk); + rc =smc_llc_link_init (lnk);if (rc) goto free_lgr; + rc =smc_wr_alloc_link_mem (lnk); +if (rc) + goto clear_llc_lnk; rc =smc_ib_create_protection_domain (lnk);if (rc) goto free_link_mem;
@@ -221,6 +223,8 @@ static int smc_lgr_create(struct smc_sock *smc,smc_ib_dealloc_protection_domain (lnk); free_link_mem:smc_wr_free_link_mem (lnk); +clear_llc_lnk: +smc_llc_link_clear (lnk); free_lgr:kfree (lgr); out:
@@ -266,6 +270,7 @@ void smc_conn_free(struct smc_connection *conn)static void smc_link_clear (struct smc_link *lnk) { lnk->peer_qpn =0 ; +smc_llc_link_clear (lnk);smc_ib_modify_qp_reset (lnk);smc_wr_free_link (lnk);smc_ib_destroy_queue_pair (lnk);
@@ -323,7 +328,6 @@ static void smc_lgr_free_bufs(struct smc_link_group *lgr)/* remove a link group */ void smc_lgr_free (struct smc_link_group *lgr) { -smc_llc_link_flush (&lgr->lnk[SMC_SINGLE_LINK ]);smc_lgr_free_bufs (lgr);smc_link_clear (&lgr->lnk[SMC_SINGLE_LINK ]);kfree (lgr);
net/smc/smc_core.h +1 -0
@@ -96,6 +96,7 @@ struct smc_link {u8 link_id;/* unique # within link group */ enum smc_link_state state;/* state of link */ +struct workqueue_struct *llc_wq;/* single thread work queue */ struct completion llc_confirm;/* wait for rx of conf link */ struct completion llc_confirm_resp;/* wait 4 rx of cnf lnk rsp */ int llc_confirm_rc;/* rc from confirm link msg */
net/smc/smc_llc.c +94 -38
217 lines not on this page · raw message
net/smc/smc_llc.h +2 -2
@@ -42,10 +42,10 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], union ib_gid *gid, enum smc_llc_reqresp reqresp);int smc_llc_send_delete_link (struct smc_link *link,enum smc_llc_reqresp reqresp); -void smc_llc_link_init (struct smc_link *link); +int smc_llc_link_init (struct smc_link *link);void smc_llc_link_active (struct smc_link *link,int testlink_time);void smc_llc_link_inactive (struct smc_link *link); -void smc_llc_link_flush (struct smc_link *link); +void smc_llc_link_clear (struct smc_link *link);int smc_llc_do_confirm_rkey (struct smc_link *link,struct smc_buf_desc *rmb_desc);int smc_llc_init (void )__init ;
Signature · 1 line
2.16.3
PATCH 7/10 net/smc: handle all error codes from smc_conn_create()
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Always set a reason_code when smc_conn_create() returns an error code.
--- net/smc/af_smc.c | 2 ++ 1 file changed, 2 insertions(+)
net/smc/af_smc.c +2 -0
@@ -463,6 +463,8 @@ static int smc_connect_rdma(struct smc_sock *smc) reason_code =SMC_CLC_DECL_MEM ;/* insufficient memory*/ else if (rc == -ENOLINK) reason_code =SMC_CLC_DECL_SYNCERR ;/* synchr. error */ + else + reason_code =SMC_CLC_DECL_INTERR ;/* other error */ goto decline_rdma_unlock; } link = &smc->conn.lgr->lnk[SMC_SINGLE_LINK ];
Signature · 1 line
2.16.3
PATCH 8/10 net/smc: set link inactive before calling smc_lgr_free()
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Before smc_lgr_free() is called the link must be set inactive by calling smc_llc_link_inactive().
--- net/smc/af_smc.c | 1 + net/smc/smc_core.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-)
net/smc/af_smc.c +1 -0
@@ -1644,6 +1644,7 @@ static void __exit smc_exit(void)spin_unlock_bh (&smc_lgr_list.lock);list_for_each_entry_safe (lgr, lg, &lgr_freeing_list, list) {list_del_init (&lgr->list); +smc_llc_link_inactive (&lgr->lnk[SMC_SINGLE_LINK ]);cancel_delayed_work_sync (&lgr->free_work);smc_lgr_free (lgr);/* free link group */ }
net/smc/smc_core.c +4 -1
@@ -148,8 +148,11 @@ static void smc_lgr_free_work(struct work_struct *work)list_del_init (&lgr->list);/* remove from smc_lgr_list */ free:spin_unlock_bh (&smc_lgr_list.lock); -if (!delayed_work_pending (&lgr->free_work)) +if (!delayed_work_pending (&lgr->free_work)) { +if (lgr->lnk[SMC_SINGLE_LINK ].state !=SMC_LNK_INACTIVE ) +smc_llc_link_inactive (&lgr->lnk[SMC_SINGLE_LINK ]);smc_lgr_free (lgr); + } }/* create a new SMC link group */
Signature · 1 line
2.16.3
PATCH 9/10 net/smc: drop messages when link state is inactive
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Drop incoming messages when the link is flagged as inactive.
--- net/smc/smc_llc.c | 2 ++ 1 file changed, 2 insertions(+)
net/smc/smc_llc.c +2 -0
@@ -548,6 +548,8 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)return ;/* short message */ if (llc->raw.hdr.length !=sizeof (*llc))return ;/* invalid message */ +if (link->state ==SMC_LNK_INACTIVE ) +return ;/* link not active, drop msg */ switch (llc->raw.hdr.common.type) {case SMC_LLC_TEST_LINK :
Signature · 1 line
2.16.3
PATCH 10/10 net/smc: check for pending termination
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Avoid to run the processing in smc_lgr_terminate() more than once, remember when the link group termination is triggered.
--- net/smc/smc_clc.c | 2 +- net/smc/smc_core.c | 5 ++++- net/smc/smc_core.h | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-)
net/smc/smc_clc.c +1 -1
@@ -316,7 +316,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,if (clcm->type ==SMC_CLC_DECLINE ) { reason_code =SMC_CLC_DECL_REPLY ;if (((struct smc_clc_msg_decline *)buf)->hdr.flag) { - smc->conn.lgr->sync_err = true; + smc->conn.lgr->sync_err =1 ;smc_lgr_terminate (smc->conn.lgr); } }
net/smc/smc_core.c +4 -1
@@ -172,7 +172,7 @@ static int smc_lgr_create(struct smc_sock *smc, goto out; } lgr->role = smc->listen_smc ?SMC_SERV :SMC_CLNT ; - lgr->sync_err = false; + lgr->sync_err =0 ;memcpy (lgr->peer_systemid, peer_systemid,SMC_SYSTEMID_LEN ); lgr->vlan_id = vlan_id;rwlock_init (&lgr->sndbufs_lock);
@@ -352,6 +352,9 @@ void smc_lgr_terminate(struct smc_link_group *lgr)struct smc_sock *smc;struct rb_node *node; +if (lgr->terminating) +return ;/* lgr already terminating */ + lgr->terminating =1 ;smc_lgr_forget (lgr);smc_llc_link_inactive (&lgr->lnk[SMC_SINGLE_LINK ]);
net/smc/smc_core.h +2 -1
@@ -166,7 +166,8 @@ struct smc_link_group {u8 id[SMC_LGR_ID_SIZE ];/* unique lgr id */ struct delayed_work free_work;/* delayed freeing of an lgr */ -bool sync_err;/* lgr no longer fits to peer */ + u8 sync_err : 1; /* lgr no longer fits to peer */ + u8 terminating : 1;/* lgr is terminating */ };/* Find the connection associated with the given alert token in the link group.
Signature · 1 line
2.16.3
David Miller
maintainerFrom: Ursula Braun <[email protected]>
Date: Tue, 15 May 2018 17:04:53 +0200
Quoted 5 lines
here are smc patches for net-next. The first one is a fix for net-next commit
01d2f7e2cdd3"net/smc: sockoptsTCP_NODELAYandTCP_CORK". Patch 7 improves Connection Layer Control error handling, patch 10 improves abnormal termination of link groups. The remaining patches from Karsten improve Link Layer Control code.
Series applied, thank you.