aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/cluster/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/cluster/tcp.c')
-rw-r--r--fs/ocfs2/cluster/tcp.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index c6b90e670389..681691bc233a 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -108,7 +108,7 @@ static struct rb_root o2net_handler_tree = RB_ROOT;
108static struct o2net_node o2net_nodes[O2NM_MAX_NODES]; 108static struct o2net_node o2net_nodes[O2NM_MAX_NODES];
109 109
110/* XXX someday we'll need better accounting */ 110/* XXX someday we'll need better accounting */
111static struct socket *o2net_listen_sock = NULL; 111static struct socket *o2net_listen_sock;
112 112
113/* 113/*
114 * listen work is only queued by the listening socket callbacks on the 114 * listen work is only queued by the listening socket callbacks on the
@@ -1799,7 +1799,7 @@ int o2net_register_hb_callbacks(void)
1799 1799
1800/* ------------------------------------------------------------ */ 1800/* ------------------------------------------------------------ */
1801 1801
1802static int o2net_accept_one(struct socket *sock) 1802static int o2net_accept_one(struct socket *sock, int *more)
1803{ 1803{
1804 int ret, slen; 1804 int ret, slen;
1805 struct sockaddr_in sin; 1805 struct sockaddr_in sin;
@@ -1810,6 +1810,7 @@ static int o2net_accept_one(struct socket *sock)
1810 struct o2net_node *nn; 1810 struct o2net_node *nn;
1811 1811
1812 BUG_ON(sock == NULL); 1812 BUG_ON(sock == NULL);
1813 *more = 0;
1813 ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, 1814 ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type,
1814 sock->sk->sk_protocol, &new_sock); 1815 sock->sk->sk_protocol, &new_sock);
1815 if (ret) 1816 if (ret)
@@ -1821,6 +1822,7 @@ static int o2net_accept_one(struct socket *sock)
1821 if (ret < 0) 1822 if (ret < 0)
1822 goto out; 1823 goto out;
1823 1824
1825 *more = 1;
1824 new_sock->sk->sk_allocation = GFP_ATOMIC; 1826 new_sock->sk->sk_allocation = GFP_ATOMIC;
1825 1827
1826 ret = o2net_set_nodelay(new_sock); 1828 ret = o2net_set_nodelay(new_sock);
@@ -1919,11 +1921,36 @@ out:
1919 return ret; 1921 return ret;
1920} 1922}
1921 1923
1924/*
1925 * This function is invoked in response to one or more
1926 * pending accepts at softIRQ level. We must drain the
1927 * entire que before returning.
1928 */
1929
1922static void o2net_accept_many(struct work_struct *work) 1930static void o2net_accept_many(struct work_struct *work)
1923{ 1931{
1924 struct socket *sock = o2net_listen_sock; 1932 struct socket *sock = o2net_listen_sock;
1925 while (o2net_accept_one(sock) == 0) 1933 int more;
1934 int err;
1935
1936 /*
1937 * It is critical to note that due to interrupt moderation
1938 * at the network driver level, we can't assume to get a
1939 * softIRQ for every single conn since tcp SYN packets
1940 * can arrive back-to-back, and therefore many pending
1941 * accepts may result in just 1 softIRQ. If we terminate
1942 * the o2net_accept_one() loop upon seeing an err, what happens
1943 * to the rest of the conns in the queue? If no new SYN
1944 * arrives for hours, no softIRQ will be delivered,
1945 * and the connections will just sit in the queue.
1946 */
1947
1948 for (;;) {
1949 err = o2net_accept_one(sock, &more);
1950 if (!more)
1951 break;
1926 cond_resched(); 1952 cond_resched();
1953 }
1927} 1954}
1928 1955
1929static void o2net_listen_data_ready(struct sock *sk) 1956static void o2net_listen_data_ready(struct sock *sk)