aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-12-19 16:42:56 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 10:58:13 -0500
commit7da358625c056b631b0abf2fcf50dad5bcbc22d9 (patch)
treebddb07eb9171846ddc48119c9549b078b0d395ac /drivers/block/drbd/drbd_receiver.c
parenta01842ebeea315cbe4382703c065f671d8cd7622 (diff)
drbd: Restore late assigning of tconn->data.sock and meta.sock
With commit from Mon Mar 28 16:33:12 2011 +0200 "drbd: drbd_connect(): Initialize struct drbd_socket before sending anything" tconn->data.sock and tconn->meta.sock get assigned early, in conn_connect. The early assigning can trigger an OOPS, because it may released the socket without acquiring the mutex protecting the socket. An other thread (worker) might use setsockopt() on the socket while it gets free()ed. Restored the (proven) 8.3 behavior of assigning these sockets after the two connections are established. Credits for reporting the issue are going to Arne Redlich. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_receiver.c')
-rw-r--r--drivers/block/drbd/drbd_receiver.c106
1 files changed, 57 insertions, 49 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 1b6845a6ba8d..c8d3f38d539f 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -842,7 +842,7 @@ int drbd_connected(struct drbd_conf *mdev)
842 */ 842 */
843static int conn_connect(struct drbd_tconn *tconn) 843static int conn_connect(struct drbd_tconn *tconn)
844{ 844{
845 struct socket *sock, *msock; 845 struct drbd_socket sock, msock;
846 struct drbd_conf *mdev; 846 struct drbd_conf *mdev;
847 struct net_conf *nc; 847 struct net_conf *nc;
848 int vnr, timeout, try, h, ok; 848 int vnr, timeout, try, h, ok;
@@ -851,6 +851,15 @@ static int conn_connect(struct drbd_tconn *tconn)
851 if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS) 851 if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS)
852 return -2; 852 return -2;
853 853
854 mutex_init(&sock.mutex);
855 sock.sbuf = tconn->data.sbuf;
856 sock.rbuf = tconn->data.rbuf;
857 sock.socket = NULL;
858 mutex_init(&msock.mutex);
859 msock.sbuf = tconn->meta.sbuf;
860 msock.rbuf = tconn->meta.rbuf;
861 msock.socket = NULL;
862
854 clear_bit(DISCARD_CONCURRENT, &tconn->flags); 863 clear_bit(DISCARD_CONCURRENT, &tconn->flags);
855 864
856 /* Assume that the peer only understands protocol 80 until we know better. */ 865 /* Assume that the peer only understands protocol 80 until we know better. */
@@ -869,22 +878,26 @@ static int conn_connect(struct drbd_tconn *tconn)
869 } 878 }
870 879
871 if (s) { 880 if (s) {
872 if (!tconn->data.socket) { 881 if (!sock.socket) {
873 tconn->data.socket = s; 882 sock.socket = s;
874 send_first_packet(tconn, &tconn->data, P_INITIAL_DATA); 883 send_first_packet(tconn, &sock, P_INITIAL_DATA);
875 } else if (!tconn->meta.socket) { 884 } else if (!msock.socket) {
876 tconn->meta.socket = s; 885 msock.socket = s;
877 send_first_packet(tconn, &tconn->meta, P_INITIAL_META); 886 send_first_packet(tconn, &msock, P_INITIAL_META);
878 } else { 887 } else {
879 conn_err(tconn, "Logic error in conn_connect()\n"); 888 conn_err(tconn, "Logic error in conn_connect()\n");
880 goto out_release_sockets; 889 goto out_release_sockets;
881 } 890 }
882 } 891 }
883 892
884 if (tconn->data.socket && tconn->meta.socket) { 893 if (sock.socket && msock.socket) {
885 schedule_timeout_interruptible(tconn->net_conf->ping_timeo*HZ/10); 894 rcu_read_lock();
886 ok = drbd_socket_okay(&tconn->data.socket); 895 nc = rcu_dereference(tconn->net_conf);
887 ok = drbd_socket_okay(&tconn->meta.socket) && ok; 896 timeout = nc->ping_timeo * HZ / 10;
897 rcu_read_unlock();
898 schedule_timeout_interruptible(timeout);
899 ok = drbd_socket_okay(&sock.socket);
900 ok = drbd_socket_okay(&msock.socket) && ok;
888 if (ok) 901 if (ok)
889 break; 902 break;
890 } 903 }
@@ -893,22 +906,22 @@ retry:
893 s = drbd_wait_for_connect(tconn); 906 s = drbd_wait_for_connect(tconn);
894 if (s) { 907 if (s) {
895 try = receive_first_packet(tconn, s); 908 try = receive_first_packet(tconn, s);
896 drbd_socket_okay(&tconn->data.socket); 909 drbd_socket_okay(&sock.socket);
897 drbd_socket_okay(&tconn->meta.socket); 910 drbd_socket_okay(&msock.socket);
898 switch (try) { 911 switch (try) {
899 case P_INITIAL_DATA: 912 case P_INITIAL_DATA:
900 if (tconn->data.socket) { 913 if (sock.socket) {
901 conn_warn(tconn, "initial packet S crossed\n"); 914 conn_warn(tconn, "initial packet S crossed\n");
902 sock_release(tconn->data.socket); 915 sock_release(sock.socket);
903 } 916 }
904 tconn->data.socket = s; 917 sock.socket = s;
905 break; 918 break;
906 case P_INITIAL_META: 919 case P_INITIAL_META:
907 if (tconn->meta.socket) { 920 if (msock.socket) {
908 conn_warn(tconn, "initial packet M crossed\n"); 921 conn_warn(tconn, "initial packet M crossed\n");
909 sock_release(tconn->meta.socket); 922 sock_release(msock.socket);
910 } 923 }
911 tconn->meta.socket = s; 924 msock.socket = s;
912 set_bit(DISCARD_CONCURRENT, &tconn->flags); 925 set_bit(DISCARD_CONCURRENT, &tconn->flags);
913 break; 926 break;
914 default: 927 default:
@@ -928,49 +941,48 @@ retry:
928 goto out_release_sockets; 941 goto out_release_sockets;
929 } 942 }
930 943
931 if (tconn->data.socket && &tconn->meta.socket) { 944 if (sock.socket && &msock.socket) {
932 ok = drbd_socket_okay(&tconn->data.socket); 945 ok = drbd_socket_okay(&sock.socket);
933 ok = drbd_socket_okay(&tconn->meta.socket) && ok; 946 ok = drbd_socket_okay(&msock.socket) && ok;
934 if (ok) 947 if (ok)
935 break; 948 break;
936 } 949 }
937 } while (1); 950 } while (1);
938 951
939 sock = tconn->data.socket; 952 sock.socket->sk->sk_reuse = 1; /* SO_REUSEADDR */
940 msock = tconn->meta.socket; 953 msock.socket->sk->sk_reuse = 1; /* SO_REUSEADDR */
941 954
942 msock->sk->sk_reuse = 1; /* SO_REUSEADDR */ 955 sock.socket->sk->sk_allocation = GFP_NOIO;
943 sock->sk->sk_reuse = 1; /* SO_REUSEADDR */ 956 msock.socket->sk->sk_allocation = GFP_NOIO;
944 957
945 sock->sk->sk_allocation = GFP_NOIO; 958 sock.socket->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
946 msock->sk->sk_allocation = GFP_NOIO; 959 msock.socket->sk->sk_priority = TC_PRIO_INTERACTIVE;
947
948 sock->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
949 msock->sk->sk_priority = TC_PRIO_INTERACTIVE;
950 960
951 /* NOT YET ... 961 /* NOT YET ...
952 * sock->sk->sk_sndtimeo = tconn->net_conf->timeout*HZ/10; 962 * sock.socket->sk->sk_sndtimeo = tconn->net_conf->timeout*HZ/10;
953 * sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; 963 * sock.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
954 * first set it to the P_CONNECTION_FEATURES timeout, 964 * first set it to the P_CONNECTION_FEATURES timeout,
955 * which we set to 4x the configured ping_timeout. */ 965 * which we set to 4x the configured ping_timeout. */
956 rcu_read_lock(); 966 rcu_read_lock();
957 nc = rcu_dereference(tconn->net_conf); 967 nc = rcu_dereference(tconn->net_conf);
958 968
959 sock->sk->sk_sndtimeo = 969 sock.socket->sk->sk_sndtimeo =
960 sock->sk->sk_rcvtimeo = nc->ping_timeo*4*HZ/10; 970 sock.socket->sk->sk_rcvtimeo = nc->ping_timeo*4*HZ/10;
961 971
962 msock->sk->sk_rcvtimeo = nc->ping_int*HZ; 972 msock.socket->sk->sk_rcvtimeo = nc->ping_int*HZ;
963 timeout = nc->timeout * HZ / 10; 973 timeout = nc->timeout * HZ / 10;
964 discard_my_data = nc->discard_my_data; 974 discard_my_data = nc->discard_my_data;
965 rcu_read_unlock(); 975 rcu_read_unlock();
966 976
967 msock->sk->sk_sndtimeo = timeout; 977 msock.socket->sk->sk_sndtimeo = timeout;
968 978
969 /* we don't want delays. 979 /* we don't want delays.
970 * we use TCP_CORK where appropriate, though */ 980 * we use TCP_CORK where appropriate, though */
971 drbd_tcp_nodelay(sock); 981 drbd_tcp_nodelay(sock.socket);
972 drbd_tcp_nodelay(msock); 982 drbd_tcp_nodelay(msock.socket);
973 983
984 tconn->data.socket = sock.socket;
985 tconn->meta.socket = msock.socket;
974 tconn->last_received = jiffies; 986 tconn->last_received = jiffies;
975 987
976 h = drbd_do_features(tconn); 988 h = drbd_do_features(tconn);
@@ -989,8 +1001,8 @@ retry:
989 } 1001 }
990 } 1002 }
991 1003
992 sock->sk->sk_sndtimeo = timeout; 1004 tconn->data.socket->sk->sk_sndtimeo = timeout;
993 sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; 1005 tconn->data.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
994 1006
995 if (drbd_send_protocol(tconn) == -EOPNOTSUPP) 1007 if (drbd_send_protocol(tconn) == -EOPNOTSUPP)
996 return -1; 1008 return -1;
@@ -1027,14 +1039,10 @@ retry:
1027 return h; 1039 return h;
1028 1040
1029out_release_sockets: 1041out_release_sockets:
1030 if (tconn->data.socket) { 1042 if (sock.socket)
1031 sock_release(tconn->data.socket); 1043 sock_release(sock.socket);
1032 tconn->data.socket = NULL; 1044 if (msock.socket)
1033 } 1045 sock_release(msock.socket);
1034 if (tconn->meta.socket) {
1035 sock_release(tconn->meta.socket);
1036 tconn->meta.socket = NULL;
1037 }
1038 return -1; 1046 return -1;
1039} 1047}
1040 1048