Blame view
net/rds/tcp_listen.c
5.07 KB
70041088e RDS: Add TCP tran... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* * Copyright (c) 2006 Oracle. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ #include <linux/kernel.h> |
5a0e3ad6a include cleanup: ... |
34 |
#include <linux/gfp.h> |
70041088e RDS: Add TCP tran... |
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#include <linux/in.h> #include <net/tcp.h> #include "rds.h" #include "tcp.h" /* * cheesy, but simple.. */ static void rds_tcp_accept_worker(struct work_struct *work); static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker); static struct socket *rds_tcp_listen_sock; static int rds_tcp_accept_one(struct socket *sock) { struct socket *new_sock = NULL; struct rds_connection *conn; int ret; struct inet_sock *inet; ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, sock->sk->sk_protocol, &new_sock); if (ret) goto out; new_sock->type = sock->type; new_sock->ops = sock->ops; ret = sock->ops->accept(sock, new_sock, O_NONBLOCK); if (ret < 0) goto out; rds_tcp_tune(new_sock); inet = inet_sk(new_sock->sk); |
6884b348e net/rds: remove u... |
69 70 71 72 |
rdsdebug("accepted tcp %pI4:%u -> %pI4:%u ", &inet->inet_saddr, ntohs(inet->inet_sport), &inet->inet_daddr, ntohs(inet->inet_dport)); |
70041088e RDS: Add TCP tran... |
73 |
|
c720c7e83 inet: rename some... |
74 75 |
conn = rds_conn_create(inet->inet_saddr, inet->inet_daddr, &rds_tcp_transport, GFP_KERNEL); |
70041088e RDS: Add TCP tran... |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
if (IS_ERR(conn)) { ret = PTR_ERR(conn); goto out; } /* * see the comment above rds_queue_delayed_reconnect() */ if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING)) { if (rds_conn_state(conn) == RDS_CONN_UP) rds_tcp_stats_inc(s_tcp_listen_closed_stale); else rds_tcp_stats_inc(s_tcp_connect_raced); rds_conn_drop(conn); ret = 0; goto out; } rds_tcp_set_callbacks(new_sock, conn); rds_connect_complete(conn); new_sock = NULL; ret = 0; out: if (new_sock) sock_release(new_sock); return ret; } static void rds_tcp_accept_worker(struct work_struct *work) { while (rds_tcp_accept_one(rds_tcp_listen_sock) == 0) cond_resched(); } void rds_tcp_listen_data_ready(struct sock *sk, int bytes) { void (*ready)(struct sock *sk, int bytes); rdsdebug("listen data ready sk %p ", sk); |
f064af1e5 net: fix a lockde... |
117 |
read_lock_bh(&sk->sk_callback_lock); |
70041088e RDS: Add TCP tran... |
118 |
ready = sk->sk_user_data; |
8690bfa17 RDS: cleanup: rem... |
119 |
if (!ready) { /* check for teardown race */ |
70041088e RDS: Add TCP tran... |
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
ready = sk->sk_data_ready; goto out; } /* * ->sk_data_ready is also called for a newly established child socket * before it has been accepted and the accepter has set up their * data_ready.. we only want to queue listen work for our listening * socket */ if (sk->sk_state == TCP_LISTEN) queue_work(rds_wq, &rds_tcp_listen_work); out: |
f064af1e5 net: fix a lockde... |
134 |
read_unlock_bh(&sk->sk_callback_lock); |
70041088e RDS: Add TCP tran... |
135 136 |
ready(sk, bytes); } |
ef87b7ea3 RDS: remove __ini... |
137 |
int rds_tcp_listen_init(void) |
70041088e RDS: Add TCP tran... |
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
{ struct sockaddr_in sin; struct socket *sock = NULL; int ret; ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); if (ret < 0) goto out; sock->sk->sk_reuse = 1; rds_tcp_nonagle(sock); write_lock_bh(&sock->sk->sk_callback_lock); sock->sk->sk_user_data = sock->sk->sk_data_ready; sock->sk->sk_data_ready = rds_tcp_listen_data_ready; write_unlock_bh(&sock->sk->sk_callback_lock); sin.sin_family = PF_INET, sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY); sin.sin_port = (__force u16)htons(RDS_TCP_PORT); ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); if (ret < 0) goto out; ret = sock->ops->listen(sock, 64); if (ret < 0) goto out; rds_tcp_listen_sock = sock; sock = NULL; out: if (sock) sock_release(sock); return ret; } void rds_tcp_listen_stop(void) { struct socket *sock = rds_tcp_listen_sock; struct sock *sk; |
8690bfa17 RDS: cleanup: rem... |
179 |
if (!sock) |
70041088e RDS: Add TCP tran... |
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
return; sk = sock->sk; /* serialize with and prevent further callbacks */ lock_sock(sk); write_lock_bh(&sk->sk_callback_lock); if (sk->sk_user_data) { sk->sk_data_ready = sk->sk_user_data; sk->sk_user_data = NULL; } write_unlock_bh(&sk->sk_callback_lock); release_sock(sk); /* wait for accepts to stop and close the socket */ flush_workqueue(rds_wq); sock_release(sock); rds_tcp_listen_sock = NULL; } |