aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/af_smc.c58
-rw-r--r--net/smc/smc_close.c25
-rw-r--r--net/smc/smc_close.h1
-rw-r--r--net/smc/smc_ism.c5
-rw-r--r--net/smc/smc_pnet.c3
5 files changed, 68 insertions, 24 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 77ef53596d18..6f869ef49b32 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -167,10 +167,9 @@ static int smc_release(struct socket *sock)
167 167
168 if (sk->sk_state == SMC_CLOSED) { 168 if (sk->sk_state == SMC_CLOSED) {
169 if (smc->clcsock) { 169 if (smc->clcsock) {
170 mutex_lock(&smc->clcsock_release_lock); 170 release_sock(sk);
171 sock_release(smc->clcsock); 171 smc_clcsock_release(smc);
172 smc->clcsock = NULL; 172 lock_sock(sk);
173 mutex_unlock(&smc->clcsock_release_lock);
174 } 173 }
175 if (!smc->use_fallback) 174 if (!smc->use_fallback)
176 smc_conn_free(&smc->conn); 175 smc_conn_free(&smc->conn);
@@ -446,10 +445,19 @@ static void smc_link_save_peer_info(struct smc_link *link,
446 link->peer_mtu = clc->qp_mtu; 445 link->peer_mtu = clc->qp_mtu;
447} 446}
448 447
448static void smc_switch_to_fallback(struct smc_sock *smc)
449{
450 smc->use_fallback = true;
451 if (smc->sk.sk_socket && smc->sk.sk_socket->file) {
452 smc->clcsock->file = smc->sk.sk_socket->file;
453 smc->clcsock->file->private_data = smc->clcsock;
454 }
455}
456
449/* fall back during connect */ 457/* fall back during connect */
450static int smc_connect_fallback(struct smc_sock *smc, int reason_code) 458static int smc_connect_fallback(struct smc_sock *smc, int reason_code)
451{ 459{
452 smc->use_fallback = true; 460 smc_switch_to_fallback(smc);
453 smc->fallback_rsn = reason_code; 461 smc->fallback_rsn = reason_code;
454 smc_copy_sock_settings_to_clc(smc); 462 smc_copy_sock_settings_to_clc(smc);
455 if (smc->sk.sk_state == SMC_INIT) 463 if (smc->sk.sk_state == SMC_INIT)
@@ -775,10 +783,14 @@ static void smc_connect_work(struct work_struct *work)
775 smc->sk.sk_err = -rc; 783 smc->sk.sk_err = -rc;
776 784
777out: 785out:
778 if (smc->sk.sk_err) 786 if (!sock_flag(&smc->sk, SOCK_DEAD)) {
779 smc->sk.sk_state_change(&smc->sk); 787 if (smc->sk.sk_err) {
780 else 788 smc->sk.sk_state_change(&smc->sk);
781 smc->sk.sk_write_space(&smc->sk); 789 } else { /* allow polling before and after fallback decision */
790 smc->clcsock->sk->sk_write_space(smc->clcsock->sk);
791 smc->sk.sk_write_space(&smc->sk);
792 }
793 }
782 kfree(smc->connect_info); 794 kfree(smc->connect_info);
783 smc->connect_info = NULL; 795 smc->connect_info = NULL;
784 release_sock(&smc->sk); 796 release_sock(&smc->sk);
@@ -872,11 +884,11 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
872 if (rc < 0) 884 if (rc < 0)
873 lsk->sk_err = -rc; 885 lsk->sk_err = -rc;
874 if (rc < 0 || lsk->sk_state == SMC_CLOSED) { 886 if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
887 new_sk->sk_prot->unhash(new_sk);
875 if (new_clcsock) 888 if (new_clcsock)
876 sock_release(new_clcsock); 889 sock_release(new_clcsock);
877 new_sk->sk_state = SMC_CLOSED; 890 new_sk->sk_state = SMC_CLOSED;
878 sock_set_flag(new_sk, SOCK_DEAD); 891 sock_set_flag(new_sk, SOCK_DEAD);
879 new_sk->sk_prot->unhash(new_sk);
880 sock_put(new_sk); /* final */ 892 sock_put(new_sk); /* final */
881 *new_smc = NULL; 893 *new_smc = NULL;
882 goto out; 894 goto out;
@@ -927,16 +939,21 @@ struct sock *smc_accept_dequeue(struct sock *parent,
927 939
928 smc_accept_unlink(new_sk); 940 smc_accept_unlink(new_sk);
929 if (new_sk->sk_state == SMC_CLOSED) { 941 if (new_sk->sk_state == SMC_CLOSED) {
942 new_sk->sk_prot->unhash(new_sk);
930 if (isk->clcsock) { 943 if (isk->clcsock) {
931 sock_release(isk->clcsock); 944 sock_release(isk->clcsock);
932 isk->clcsock = NULL; 945 isk->clcsock = NULL;
933 } 946 }
934 new_sk->sk_prot->unhash(new_sk);
935 sock_put(new_sk); /* final */ 947 sock_put(new_sk); /* final */
936 continue; 948 continue;
937 } 949 }
938 if (new_sock) 950 if (new_sock) {
939 sock_graft(new_sk, new_sock); 951 sock_graft(new_sk, new_sock);
952 if (isk->use_fallback) {
953 smc_sk(new_sk)->clcsock->file = new_sock->file;
954 isk->clcsock->file->private_data = isk->clcsock;
955 }
956 }
940 return new_sk; 957 return new_sk;
941 } 958 }
942 return NULL; 959 return NULL;
@@ -956,6 +973,7 @@ void smc_close_non_accepted(struct sock *sk)
956 sock_set_flag(sk, SOCK_DEAD); 973 sock_set_flag(sk, SOCK_DEAD);
957 sk->sk_shutdown |= SHUTDOWN_MASK; 974 sk->sk_shutdown |= SHUTDOWN_MASK;
958 } 975 }
976 sk->sk_prot->unhash(sk);
959 if (smc->clcsock) { 977 if (smc->clcsock) {
960 struct socket *tcp; 978 struct socket *tcp;
961 979
@@ -971,7 +989,6 @@ void smc_close_non_accepted(struct sock *sk)
971 smc_conn_free(&smc->conn); 989 smc_conn_free(&smc->conn);
972 } 990 }
973 release_sock(sk); 991 release_sock(sk);
974 sk->sk_prot->unhash(sk);
975 sock_put(sk); /* final sock_put */ 992 sock_put(sk); /* final sock_put */
976} 993}
977 994
@@ -1037,13 +1054,13 @@ static void smc_listen_out(struct smc_sock *new_smc)
1037 struct smc_sock *lsmc = new_smc->listen_smc; 1054 struct smc_sock *lsmc = new_smc->listen_smc;
1038 struct sock *newsmcsk = &new_smc->sk; 1055 struct sock *newsmcsk = &new_smc->sk;
1039 1056
1040 lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
1041 if (lsmc->sk.sk_state == SMC_LISTEN) { 1057 if (lsmc->sk.sk_state == SMC_LISTEN) {
1058 lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
1042 smc_accept_enqueue(&lsmc->sk, newsmcsk); 1059 smc_accept_enqueue(&lsmc->sk, newsmcsk);
1060 release_sock(&lsmc->sk);
1043 } else { /* no longer listening */ 1061 } else { /* no longer listening */
1044 smc_close_non_accepted(newsmcsk); 1062 smc_close_non_accepted(newsmcsk);
1045 } 1063 }
1046 release_sock(&lsmc->sk);
1047 1064
1048 /* Wake up accept */ 1065 /* Wake up accept */
1049 lsmc->sk.sk_data_ready(&lsmc->sk); 1066 lsmc->sk.sk_data_ready(&lsmc->sk);
@@ -1087,7 +1104,7 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
1087 return; 1104 return;
1088 } 1105 }
1089 smc_conn_free(&new_smc->conn); 1106 smc_conn_free(&new_smc->conn);
1090 new_smc->use_fallback = true; 1107 smc_switch_to_fallback(new_smc);
1091 new_smc->fallback_rsn = reason_code; 1108 new_smc->fallback_rsn = reason_code;
1092 if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) { 1109 if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) {
1093 if (smc_clc_send_decline(new_smc, reason_code) < 0) { 1110 if (smc_clc_send_decline(new_smc, reason_code) < 0) {
@@ -1237,6 +1254,9 @@ static void smc_listen_work(struct work_struct *work)
1237 int rc = 0; 1254 int rc = 0;
1238 u8 ibport; 1255 u8 ibport;
1239 1256
1257 if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
1258 return smc_listen_out_err(new_smc);
1259
1240 if (new_smc->use_fallback) { 1260 if (new_smc->use_fallback) {
1241 smc_listen_out_connected(new_smc); 1261 smc_listen_out_connected(new_smc);
1242 return; 1262 return;
@@ -1244,7 +1264,7 @@ static void smc_listen_work(struct work_struct *work)
1244 1264
1245 /* check if peer is smc capable */ 1265 /* check if peer is smc capable */
1246 if (!tcp_sk(newclcsock->sk)->syn_smc) { 1266 if (!tcp_sk(newclcsock->sk)->syn_smc) {
1247 new_smc->use_fallback = true; 1267 smc_switch_to_fallback(new_smc);
1248 new_smc->fallback_rsn = SMC_CLC_DECL_PEERNOSMC; 1268 new_smc->fallback_rsn = SMC_CLC_DECL_PEERNOSMC;
1249 smc_listen_out_connected(new_smc); 1269 smc_listen_out_connected(new_smc);
1250 return; 1270 return;
@@ -1501,7 +1521,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
1501 1521
1502 if (msg->msg_flags & MSG_FASTOPEN) { 1522 if (msg->msg_flags & MSG_FASTOPEN) {
1503 if (sk->sk_state == SMC_INIT) { 1523 if (sk->sk_state == SMC_INIT) {
1504 smc->use_fallback = true; 1524 smc_switch_to_fallback(smc);
1505 smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; 1525 smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
1506 } else { 1526 } else {
1507 rc = -EINVAL; 1527 rc = -EINVAL;
@@ -1703,7 +1723,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
1703 case TCP_FASTOPEN_NO_COOKIE: 1723 case TCP_FASTOPEN_NO_COOKIE:
1704 /* option not supported by SMC */ 1724 /* option not supported by SMC */
1705 if (sk->sk_state == SMC_INIT) { 1725 if (sk->sk_state == SMC_INIT) {
1706 smc->use_fallback = true; 1726 smc_switch_to_fallback(smc);
1707 smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; 1727 smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
1708 } else { 1728 } else {
1709 if (!smc->use_fallback) 1729 if (!smc->use_fallback)
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c
index 2ad37e998509..fc06720b53c1 100644
--- a/net/smc/smc_close.c
+++ b/net/smc/smc_close.c
@@ -21,6 +21,22 @@
21 21
22#define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME (5 * HZ) 22#define SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME (5 * HZ)
23 23
24/* release the clcsock that is assigned to the smc_sock */
25void smc_clcsock_release(struct smc_sock *smc)
26{
27 struct socket *tcp;
28
29 if (smc->listen_smc && current_work() != &smc->smc_listen_work)
30 cancel_work_sync(&smc->smc_listen_work);
31 mutex_lock(&smc->clcsock_release_lock);
32 if (smc->clcsock) {
33 tcp = smc->clcsock;
34 smc->clcsock = NULL;
35 sock_release(tcp);
36 }
37 mutex_unlock(&smc->clcsock_release_lock);
38}
39
24static void smc_close_cleanup_listen(struct sock *parent) 40static void smc_close_cleanup_listen(struct sock *parent)
25{ 41{
26 struct sock *sk; 42 struct sock *sk;
@@ -321,6 +337,7 @@ static void smc_close_passive_work(struct work_struct *work)
321 close_work); 337 close_work);
322 struct smc_sock *smc = container_of(conn, struct smc_sock, conn); 338 struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
323 struct smc_cdc_conn_state_flags *rxflags; 339 struct smc_cdc_conn_state_flags *rxflags;
340 bool release_clcsock = false;
324 struct sock *sk = &smc->sk; 341 struct sock *sk = &smc->sk;
325 int old_state; 342 int old_state;
326 343
@@ -400,13 +417,13 @@ wakeup:
400 if ((sk->sk_state == SMC_CLOSED) && 417 if ((sk->sk_state == SMC_CLOSED) &&
401 (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) { 418 (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) {
402 smc_conn_free(conn); 419 smc_conn_free(conn);
403 if (smc->clcsock) { 420 if (smc->clcsock)
404 sock_release(smc->clcsock); 421 release_clcsock = true;
405 smc->clcsock = NULL;
406 }
407 } 422 }
408 } 423 }
409 release_sock(sk); 424 release_sock(sk);
425 if (release_clcsock)
426 smc_clcsock_release(smc);
410 sock_put(sk); /* sock_hold done by schedulers of close_work */ 427 sock_put(sk); /* sock_hold done by schedulers of close_work */
411} 428}
412 429
diff --git a/net/smc/smc_close.h b/net/smc/smc_close.h
index 19eb6a211c23..e0e3b5df25d2 100644
--- a/net/smc/smc_close.h
+++ b/net/smc/smc_close.h
@@ -23,5 +23,6 @@ void smc_close_wake_tx_prepared(struct smc_sock *smc);
23int smc_close_active(struct smc_sock *smc); 23int smc_close_active(struct smc_sock *smc);
24int smc_close_shutdown_write(struct smc_sock *smc); 24int smc_close_shutdown_write(struct smc_sock *smc);
25void smc_close_init(struct smc_sock *smc); 25void smc_close_init(struct smc_sock *smc);
26void smc_clcsock_release(struct smc_sock *smc);
26 27
27#endif /* SMC_CLOSE_H */ 28#endif /* SMC_CLOSE_H */
diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
index 2fff79db1a59..e89e918b88e0 100644
--- a/net/smc/smc_ism.c
+++ b/net/smc/smc_ism.c
@@ -289,6 +289,11 @@ struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
289 INIT_LIST_HEAD(&smcd->vlan); 289 INIT_LIST_HEAD(&smcd->vlan);
290 smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)", 290 smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
291 WQ_MEM_RECLAIM, name); 291 WQ_MEM_RECLAIM, name);
292 if (!smcd->event_wq) {
293 kfree(smcd->conn);
294 kfree(smcd);
295 return NULL;
296 }
292 return smcd; 297 return smcd;
293} 298}
294EXPORT_SYMBOL_GPL(smcd_alloc_dev); 299EXPORT_SYMBOL_GPL(smcd_alloc_dev);
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index 8d2f6296279c..0285c7f9e79b 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -603,7 +603,8 @@ static int smc_pnet_flush(struct sk_buff *skb, struct genl_info *info)
603{ 603{
604 struct net *net = genl_info_net(info); 604 struct net *net = genl_info_net(info);
605 605
606 return smc_pnet_remove_by_pnetid(net, NULL); 606 smc_pnet_remove_by_pnetid(net, NULL);
607 return 0;
607} 608}
608 609
609/* SMC_PNETID generic netlink operation definition */ 610/* SMC_PNETID generic netlink operation definition */