summaryrefslogtreecommitdiff
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/drbd/drbd_receiver.c')
-rw-r--r--drivers/block/drbd/drbd_receiver.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 96ab2ff..46c5579 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -666,12 +666,11 @@ out:
return sock;
}
-static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn)
+static struct socket *prepare_listen_socket(struct drbd_tconn *tconn)
{
- int timeo, err, my_addr_len;
- int sndbuf_size, rcvbuf_size, connect_int;
- struct socket *s_estab = NULL, *s_listen;
+ int err, sndbuf_size, rcvbuf_size, my_addr_len;
struct sockaddr_in6 my_addr;
+ struct socket *s_listen;
struct net_conf *nc;
const char *what;
@@ -683,7 +682,6 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn)
}
sndbuf_size = nc->sndbuf_size;
rcvbuf_size = nc->rcvbuf_size;
- connect_int = nc->connect_int;
rcu_read_unlock();
my_addr_len = min_t(int, tconn->my_addr_len, sizeof(struct sockaddr_in6));
@@ -691,18 +689,13 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn)
what = "sock_create_kern";
err = sock_create_kern(((struct sockaddr *)&my_addr)->sa_family,
- SOCK_STREAM, IPPROTO_TCP, &s_listen);
+ SOCK_STREAM, IPPROTO_TCP, &s_listen);
if (err) {
s_listen = NULL;
goto out;
}
- timeo = connect_int * HZ;
- timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */
-
- s_listen->sk->sk_reuse = 1; /* SO_REUSEADDR */
- s_listen->sk->sk_rcvtimeo = timeo;
- s_listen->sk->sk_sndtimeo = timeo;
+ s_listen->sk->sk_reuse = 1; /* SO_REUSEADDR */
drbd_setbufsize(s_listen, sndbuf_size, rcvbuf_size);
what = "bind before listen";
@@ -715,7 +708,46 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn)
if (err < 0)
goto out;
- what = "accept";
+ return s_listen;
+out:
+ if (s_listen)
+ sock_release(s_listen);
+ if (err < 0) {
+ if (err != -EAGAIN && err != -EINTR && err != -ERESTARTSYS) {
+ conn_err(tconn, "%s failed, err = %d\n", what, err);
+ conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+ }
+ }
+
+ return NULL;
+}
+
+static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn)
+{
+ int timeo, connect_int, err = 0;
+ struct socket *s_estab = NULL;
+ struct socket *s_listen;
+ struct net_conf *nc;
+
+ rcu_read_lock();
+ nc = rcu_dereference(tconn->net_conf);
+ if (!nc) {
+ rcu_read_unlock();
+ return NULL;
+ }
+ connect_int = nc->connect_int;
+ rcu_read_unlock();
+
+ timeo = connect_int * HZ;
+ timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */
+
+ s_listen = prepare_listen_socket(tconn);
+ if (!s_listen)
+ goto out;
+
+ s_listen->sk->sk_rcvtimeo = timeo;
+ s_listen->sk->sk_sndtimeo = timeo;
+
err = kernel_accept(s_listen, &s_estab, 0);
out:
@@ -723,7 +755,7 @@ out:
sock_release(s_listen);
if (err < 0) {
if (err != -EAGAIN && err != -EINTR && err != -ERESTARTSYS) {
- conn_err(tconn, "%s failed, err = %d\n", what, err);
+ conn_err(tconn, "accept failed, err = %d\n", err);
conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
}
}