From: Tim Froidcoeur <tim.froidco...@tessares.net>

[ Upstream commit 62ffc589abb176821662efc4525ee4ac0b9c3894 ]

Refactor the fastreuse update code in inet_csk_get_port into a small
helper function that can be called from other places.

Acked-by: Matthieu Baerts <matthieu.bae...@tessares.net>
Signed-off-by: Tim Froidcoeur <tim.froidco...@tessares.net>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 include/net/inet_connection_sock.h |    4 +
 net/ipv4/inet_connection_sock.c    |   93 ++++++++++++++++++++-----------------
 2 files changed, 55 insertions(+), 42 deletions(-)

--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -321,5 +321,9 @@ int inet_csk_compat_getsockopt(struct so
 int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
                               char __user *optval, unsigned int optlen);
 
+/* update the fast reuse flag when adding a socket */
+void inet_csk_update_fastreuse(struct inet_bind_bucket *tb,
+                              struct sock *sk);
+
 struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
 #endif /* _INET_CONNECTION_SOCK_H */
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -276,51 +276,12 @@ static inline int sk_reuseport_match(str
                                    ipv6_only_sock(sk), true);
 }
 
-/* Obtain a reference to a local port for the given sock,
- * if snum is zero it means select any available local port.
- * We try to allocate an odd port (and leave even ports for connect())
- */
-int inet_csk_get_port(struct sock *sk, unsigned short snum)
+void inet_csk_update_fastreuse(struct inet_bind_bucket *tb,
+                              struct sock *sk)
 {
-       bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
-       struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
-       int ret = 1, port = snum;
-       struct inet_bind_hashbucket *head;
-       struct net *net = sock_net(sk);
-       struct inet_bind_bucket *tb = NULL;
        kuid_t uid = sock_i_uid(sk);
+       bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
 
-       if (!port) {
-               head = inet_csk_find_open_port(sk, &tb, &port);
-               if (!head)
-                       return ret;
-               if (!tb)
-                       goto tb_not_found;
-               goto success;
-       }
-       head = &hinfo->bhash[inet_bhashfn(net, port,
-                                         hinfo->bhash_size)];
-       spin_lock_bh(&head->lock);
-       inet_bind_bucket_for_each(tb, &head->chain)
-               if (net_eq(ib_net(tb), net) && tb->port == port)
-                       goto tb_found;
-tb_not_found:
-       tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
-                                    net, head, port);
-       if (!tb)
-               goto fail_unlock;
-tb_found:
-       if (!hlist_empty(&tb->owners)) {
-               if (sk->sk_reuse == SK_FORCE_REUSE)
-                       goto success;
-
-               if ((tb->fastreuse > 0 && reuse) ||
-                   sk_reuseport_match(tb, sk))
-                       goto success;
-               if (inet_csk_bind_conflict(sk, tb, true, true))
-                       goto fail_unlock;
-       }
-success:
        if (hlist_empty(&tb->owners)) {
                tb->fastreuse = reuse;
                if (sk->sk_reuseport) {
@@ -364,6 +325,54 @@ success:
                        tb->fastreuseport = 0;
                }
        }
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ * We try to allocate an odd port (and leave even ports for connect())
+ */
+int inet_csk_get_port(struct sock *sk, unsigned short snum)
+{
+       bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
+       struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
+       int ret = 1, port = snum;
+       struct inet_bind_hashbucket *head;
+       struct net *net = sock_net(sk);
+       struct inet_bind_bucket *tb = NULL;
+
+       if (!port) {
+               head = inet_csk_find_open_port(sk, &tb, &port);
+               if (!head)
+                       return ret;
+               if (!tb)
+                       goto tb_not_found;
+               goto success;
+       }
+       head = &hinfo->bhash[inet_bhashfn(net, port,
+                                         hinfo->bhash_size)];
+       spin_lock_bh(&head->lock);
+       inet_bind_bucket_for_each(tb, &head->chain)
+               if (net_eq(ib_net(tb), net) && tb->port == port)
+                       goto tb_found;
+tb_not_found:
+       tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
+                                    net, head, port);
+       if (!tb)
+               goto fail_unlock;
+tb_found:
+       if (!hlist_empty(&tb->owners)) {
+               if (sk->sk_reuse == SK_FORCE_REUSE)
+                       goto success;
+
+               if ((tb->fastreuse > 0 && reuse) ||
+                   sk_reuseport_match(tb, sk))
+                       goto success;
+               if (inet_csk_bind_conflict(sk, tb, true, true))
+                       goto fail_unlock;
+       }
+success:
+       inet_csk_update_fastreuse(tb, sk);
+
        if (!inet_csk(sk)->icsk_bind_hash)
                inet_bind_hash(sk, tb, port);
        WARN_ON(inet_csk(sk)->icsk_bind_hash != tb);


Reply via email to