diff options
author | Karsten Graul <kgraul@linux.ibm.com> | 2018-05-03 11:57:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-03 14:47:31 -0400 |
commit | a6920d1d130c3de039be982eba42542d329dc64c (patch) | |
tree | eb06c1cdb7a9867644730d86ab9e13e12be17b41 /net | |
parent | e63a5f8c19d7807823d68830ebe8cfbd4419ab13 (diff) |
net/smc: handle unregistered buffers
When smc_wr_reg_send() fails then tag (regerr) the affected buffer and
free it in smc_buf_unuse().
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/smc/af_smc.c | 4 | ||||
-rw-r--r-- | net/smc/smc_core.c | 22 | ||||
-rw-r--r-- | net/smc/smc_core.h | 3 |
3 files changed, 24 insertions, 5 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index fdb2976117bd..d03b8d29ffc0 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
@@ -296,8 +296,10 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc) | |||
296 | static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc) | 296 | static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc) |
297 | { | 297 | { |
298 | /* register memory region for new rmb */ | 298 | /* register memory region for new rmb */ |
299 | if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) | 299 | if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) { |
300 | rmb_desc->regerr = 1; | ||
300 | return -EFAULT; | 301 | return -EFAULT; |
302 | } | ||
301 | return 0; | 303 | return 0; |
302 | } | 304 | } |
303 | 305 | ||
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 */ |