Skip to content

Commit 289141b

Browse files
Josef Bacikdavem330
authored andcommitted
inet: split inet_csk_get_port into two functions
inet_csk_get_port does two different things, it either scans for an open port, or it tries to see if the specified port is available for use. Since these two operations have different rules and are basically independent lets split them into two different functions to make them both more readable. Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 6cd6661 commit 289141b

File tree

1 file changed

+44
-22
lines changed

1 file changed

+44
-22
lines changed

net/ipv4/inet_connection_sock.c

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -156,33 +156,21 @@ static int inet_csk_bind_conflict(const struct sock *sk,
156156
return sk2 != NULL;
157157
}
158158

159-
/* Obtain a reference to a local port for the given sock,
160-
* if snum is zero it means select any available local port.
161-
* We try to allocate an odd port (and leave even ports for connect())
159+
/*
160+
* Find an open port number for the socket. Returns with the
161+
* inet_bind_hashbucket lock held.
162162
*/
163-
int inet_csk_get_port(struct sock *sk, unsigned short snum)
163+
static struct inet_bind_hashbucket *
164+
inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *port_ret)
164165
{
165-
bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
166166
struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
167-
int ret = 1, port = snum;
167+
int port = 0;
168168
struct inet_bind_hashbucket *head;
169169
struct net *net = sock_net(sk);
170170
int i, low, high, attempt_half;
171171
struct inet_bind_bucket *tb;
172-
kuid_t uid = sock_i_uid(sk);
173172
u32 remaining, offset;
174-
bool reuseport_ok = !!snum;
175173

176-
if (port) {
177-
head = &hinfo->bhash[inet_bhashfn(net, port,
178-
hinfo->bhash_size)];
179-
spin_lock_bh(&head->lock);
180-
inet_bind_bucket_for_each(tb, &head->chain)
181-
if (net_eq(ib_net(tb), net) && tb->port == port)
182-
goto tb_found;
183-
184-
goto tb_not_found;
185-
}
186174
attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
187175
other_half_scan:
188176
inet_get_local_port_range(net, &low, &high);
@@ -219,11 +207,12 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
219207
spin_lock_bh(&head->lock);
220208
inet_bind_bucket_for_each(tb, &head->chain)
221209
if (net_eq(ib_net(tb), net) && tb->port == port) {
222-
if (!inet_csk_bind_conflict(sk, tb, false, reuseport_ok))
210+
if (!inet_csk_bind_conflict(sk, tb, false, false))
223211
goto success;
224212
goto next_port;
225213
}
226-
goto tb_not_found;
214+
tb = NULL;
215+
goto success;
227216
next_port:
228217
spin_unlock_bh(&head->lock);
229218
cond_resched();
@@ -238,8 +227,41 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
238227
attempt_half = 2;
239228
goto other_half_scan;
240229
}
241-
return ret;
230+
return NULL;
231+
success:
232+
*port_ret = port;
233+
*tb_ret = tb;
234+
return head;
235+
}
236+
237+
/* Obtain a reference to a local port for the given sock,
238+
* if snum is zero it means select any available local port.
239+
* We try to allocate an odd port (and leave even ports for connect())
240+
*/
241+
int inet_csk_get_port(struct sock *sk, unsigned short snum)
242+
{
243+
bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
244+
struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
245+
int ret = 1, port = snum;
246+
struct inet_bind_hashbucket *head;
247+
struct net *net = sock_net(sk);
248+
struct inet_bind_bucket *tb = NULL;
249+
kuid_t uid = sock_i_uid(sk);
242250

251+
if (!port) {
252+
head = inet_csk_find_open_port(sk, &tb, &port);
253+
if (!head)
254+
return ret;
255+
if (!tb)
256+
goto tb_not_found;
257+
goto success;
258+
}
259+
head = &hinfo->bhash[inet_bhashfn(net, port,
260+
hinfo->bhash_size)];
261+
spin_lock_bh(&head->lock);
262+
inet_bind_bucket_for_each(tb, &head->chain)
263+
if (net_eq(ib_net(tb), net) && tb->port == port)
264+
goto tb_found;
243265
tb_not_found:
244266
tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
245267
net, head, port);
@@ -255,7 +277,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
255277
!rcu_access_pointer(sk->sk_reuseport_cb) &&
256278
sk->sk_reuseport && uid_eq(tb->fastuid, uid)))
257279
goto success;
258-
if (inet_csk_bind_conflict(sk, tb, true, reuseport_ok))
280+
if (inet_csk_bind_conflict(sk, tb, true, true))
259281
goto fail_unlock;
260282
}
261283
success:

0 commit comments

Comments
 (0)