diff options
author | David S. Miller <davem@davemloft.net> | 2018-05-03 14:47:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-03 14:47:32 -0400 |
commit | 31140b47fe4b90ea38f29a48214e76d8b7f64176 (patch) | |
tree | 886341f8a24668c1f8a4a7c813f0404e9bb72187 | |
parent | df80b8fb3c0ef510649d2d6e350cf11be240d15c (diff) | |
parent | bda27ff5c4526f80a7620a94ecfe8dca153e3696 (diff) |
Merge branch 'smc-fixes'
Ursula Braun says:
====================
net/smc: fixes 2018/05/03
here are smc fixes for 2 problems:
* receive buffers in SMC must be registered. If registration fails
these buffers must not be kept within the link group for reuse.
Patch 1 is a preparational patch; patch 2 contains the fix.
* sendpage: do not hold the sock lock when calling kernel_sendpage()
or sock_no_sendpage()
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/smc/af_smc.c | 43 | ||||
-rw-r--r-- | net/smc/smc_core.c | 22 | ||||
-rw-r--r-- | net/smc/smc_core.h | 3 |
3 files changed, 42 insertions, 26 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 8b4c059bd13b..544bab42f925 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
@@ -292,6 +292,17 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc) | |||
292 | smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC); | 292 | smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC); |
293 | } | 293 | } |
294 | 294 | ||
295 | /* register a new rmb */ | ||
296 | static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc) | ||
297 | { | ||
298 | /* register memory region for new rmb */ | ||
299 | if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) { | ||
300 | rmb_desc->regerr = 1; | ||
301 | return -EFAULT; | ||
302 | } | ||
303 | return 0; | ||
304 | } | ||
305 | |||
295 | static int smc_clnt_conf_first_link(struct smc_sock *smc) | 306 | static int smc_clnt_conf_first_link(struct smc_sock *smc) |
296 | { | 307 | { |
297 | struct smc_link_group *lgr = smc->conn.lgr; | 308 | struct smc_link_group *lgr = smc->conn.lgr; |
@@ -321,9 +332,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc) | |||
321 | 332 | ||
322 | smc_wr_remember_qp_attr(link); | 333 | smc_wr_remember_qp_attr(link); |
323 | 334 | ||
324 | rc = smc_wr_reg_send(link, | 335 | if (smc_reg_rmb(link, smc->conn.rmb_desc)) |
325 | smc->conn.rmb_desc->mr_rx[SMC_SINGLE_LINK]); | ||
326 | if (rc) | ||
327 | return SMC_CLC_DECL_INTERR; | 336 | return SMC_CLC_DECL_INTERR; |
328 | 337 | ||
329 | /* send CONFIRM LINK response over RoCE fabric */ | 338 | /* send CONFIRM LINK response over RoCE fabric */ |
@@ -473,13 +482,8 @@ static int smc_connect_rdma(struct smc_sock *smc) | |||
473 | goto decline_rdma_unlock; | 482 | goto decline_rdma_unlock; |
474 | } | 483 | } |
475 | } else { | 484 | } else { |
476 | struct smc_buf_desc *buf_desc = smc->conn.rmb_desc; | 485 | if (!smc->conn.rmb_desc->reused) { |
477 | 486 | if (smc_reg_rmb(link, smc->conn.rmb_desc)) { | |
478 | if (!buf_desc->reused) { | ||
479 | /* register memory region for new rmb */ | ||
480 | rc = smc_wr_reg_send(link, | ||
481 | buf_desc->mr_rx[SMC_SINGLE_LINK]); | ||
482 | if (rc) { | ||
483 | reason_code = SMC_CLC_DECL_INTERR; | 487 | reason_code = SMC_CLC_DECL_INTERR; |
484 | goto decline_rdma_unlock; | 488 | goto decline_rdma_unlock; |
485 | } | 489 | } |
@@ -719,9 +723,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc) | |||
719 | 723 | ||
720 | link = &lgr->lnk[SMC_SINGLE_LINK]; | 724 | link = &lgr->lnk[SMC_SINGLE_LINK]; |
721 | 725 | ||
722 | rc = smc_wr_reg_send(link, | 726 | if (smc_reg_rmb(link, smc->conn.rmb_desc)) |
723 | smc->conn.rmb_desc->mr_rx[SMC_SINGLE_LINK]); | ||
724 | if (rc) | ||
725 | return SMC_CLC_DECL_INTERR; | 727 | return SMC_CLC_DECL_INTERR; |
726 | 728 | ||
727 | /* send CONFIRM LINK request to client over the RoCE fabric */ | 729 | /* send CONFIRM LINK request to client over the RoCE fabric */ |
@@ -854,13 +856,8 @@ static void smc_listen_work(struct work_struct *work) | |||
854 | smc_rx_init(new_smc); | 856 | smc_rx_init(new_smc); |
855 | 857 | ||
856 | if (local_contact != SMC_FIRST_CONTACT) { | 858 | if (local_contact != SMC_FIRST_CONTACT) { |
857 | struct smc_buf_desc *buf_desc = new_smc->conn.rmb_desc; | 859 | if (!new_smc->conn.rmb_desc->reused) { |
858 | 860 | if (smc_reg_rmb(link, new_smc->conn.rmb_desc)) { | |
859 | if (!buf_desc->reused) { | ||
860 | /* register memory region for new rmb */ | ||
861 | rc = smc_wr_reg_send(link, | ||
862 | buf_desc->mr_rx[SMC_SINGLE_LINK]); | ||
863 | if (rc) { | ||
864 | reason_code = SMC_CLC_DECL_INTERR; | 861 | reason_code = SMC_CLC_DECL_INTERR; |
865 | goto decline_rdma_unlock; | 862 | goto decline_rdma_unlock; |
866 | } | 863 | } |
@@ -1318,8 +1315,11 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page, | |||
1318 | 1315 | ||
1319 | smc = smc_sk(sk); | 1316 | smc = smc_sk(sk); |
1320 | lock_sock(sk); | 1317 | lock_sock(sk); |
1321 | if (sk->sk_state != SMC_ACTIVE) | 1318 | if (sk->sk_state != SMC_ACTIVE) { |
1319 | release_sock(sk); | ||
1322 | goto out; | 1320 | goto out; |
1321 | } | ||
1322 | release_sock(sk); | ||
1323 | if (smc->use_fallback) | 1323 | if (smc->use_fallback) |
1324 | rc = kernel_sendpage(smc->clcsock, page, offset, | 1324 | rc = kernel_sendpage(smc->clcsock, page, offset, |
1325 | size, flags); | 1325 | size, flags); |
@@ -1327,7 +1327,6 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page, | |||
1327 | rc = sock_no_sendpage(sock, page, offset, size, flags); | 1327 | rc = sock_no_sendpage(sock, page, offset, size, flags); |
1328 | 1328 | ||
1329 | out: | 1329 | out: |
1330 | release_sock(sk); | ||
1331 | return rc; | 1330 | return rc; |
1332 | } | 1331 | } |
1333 | 1332 | ||
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index f44f6803f7ff..d4bd01bb44e1 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c | |||
@@ -32,6 +32,9 @@ | |||
32 | 32 | ||
33 | static u32 smc_lgr_num; /* unique link group number */ | 33 | static u32 smc_lgr_num; /* unique link group number */ |
34 | 34 | ||
35 | static void smc_buf_free(struct smc_buf_desc *buf_desc, struct smc_link *lnk, | ||
36 | bool is_rmb); | ||
37 | |||
35 | static void smc_lgr_schedule_free_work(struct smc_link_group *lgr) | 38 | static void smc_lgr_schedule_free_work(struct smc_link_group *lgr) |
36 | { | 39 | { |
37 | /* client link group creation always follows the server link group | 40 | /* client link group creation always follows the server link group |
@@ -234,9 +237,22 @@ static void smc_buf_unuse(struct smc_connection *conn) | |||
234 | conn->sndbuf_size = 0; | 237 | conn->sndbuf_size = 0; |
235 | } | 238 | } |
236 | if (conn->rmb_desc) { | 239 | if (conn->rmb_desc) { |
237 | conn->rmb_desc->reused = true; | 240 | if (!conn->rmb_desc->regerr) { |
238 | conn->rmb_desc->used = 0; | 241 | conn->rmb_desc->reused = 1; |
239 | conn->rmbe_size = 0; | 242 | conn->rmb_desc->used = 0; |
243 | conn->rmbe_size = 0; | ||
244 | } else { | ||
245 | /* buf registration failed, reuse not possible */ | ||
246 | struct smc_link_group *lgr = conn->lgr; | ||
247 | struct smc_link *lnk; | ||
248 | |||
249 | write_lock_bh(&lgr->rmbs_lock); | ||
250 | list_del(&conn->rmb_desc->list); | ||
251 | write_unlock_bh(&lgr->rmbs_lock); | ||
252 | |||
253 | lnk = &lgr->lnk[SMC_SINGLE_LINK]; | ||
254 | smc_buf_free(conn->rmb_desc, lnk, true); | ||
255 | } | ||
240 | } | 256 | } |
241 | } | 257 | } |
242 | 258 | ||
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h index 07e2a393e6d9..5dfcb15d529f 100644 --- a/net/smc/smc_core.h +++ b/net/smc/smc_core.h | |||
@@ -123,7 +123,8 @@ struct smc_buf_desc { | |||
123 | */ | 123 | */ |
124 | u32 order; /* allocation order */ | 124 | u32 order; /* allocation order */ |
125 | u32 used; /* currently used / unused */ | 125 | u32 used; /* currently used / unused */ |
126 | bool reused; /* new created / reused */ | 126 | u8 reused : 1; /* new created / reused */ |
127 | u8 regerr : 1; /* err during registration */ | ||
127 | }; | 128 | }; |
128 | 129 | ||
129 | struct smc_rtoken { /* address/key of remote RMB */ | 130 | struct smc_rtoken { /* address/key of remote RMB */ |