diff options
author | Tariq Saeed <tariq.x.saeed@oracle.com> | 2014-06-10 18:18:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-10 18:34:46 -0400 |
commit | 79deb3c148e0ed0ac3dab9e953777b096d58b443 (patch) | |
tree | 566a713482b2537015b88fe3ef76f295fcac4b24 | |
parent | 1d21b1bf53f81256002f93387ec80ca13e3c5a8f (diff) |
ocfs2/o2net: incorrect to terminate accepting connections loop upon rejecting an invalid one
When o2net-accept-one() rejects an illegal connection, it terminates the
loop picking up the remaining queued connections. This fix will
continue accepting connections till the queue is emtpy.
Addresses Orabug 17489469.
Signed-off-by: Tariq Saseed <tariq.x.saeed@oracle.com>
Signed-off-by: Srinivas Eeda <srinivas.eeda@oracle.com>
Reviewed-by: Mark Fasheh <mfasheh@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ocfs2/cluster/tcp.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index a68e07a9bd46..681691bc233a 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -1799,7 +1799,7 @@ int o2net_register_hb_callbacks(void) | |||
1799 | 1799 | ||
1800 | /* ------------------------------------------------------------ */ | 1800 | /* ------------------------------------------------------------ */ |
1801 | 1801 | ||
1802 | static int o2net_accept_one(struct socket *sock) | 1802 | static 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 | |||
1922 | static void o2net_accept_many(struct work_struct *work) | 1930 | static 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 | ||
1929 | static void o2net_listen_data_ready(struct sock *sk) | 1956 | static void o2net_listen_data_ready(struct sock *sk) |