Skip to content

Commit 4905294

Browse files
Guillaume Naultdavem330
authored andcommitted
netns: Remove __peernet2id_alloc()
__peernet2id_alloc() was used for both plain lookups and for netns ID allocations (depending the value of '*alloc'). Let's separate lookups from allocations instead. That is, integrate the lookup code into __peernet2id() and make peernet2id_alloc() responsible for allocating new netns IDs when necessary. This makes it clear that __peernet2id() doesn't modify the idr and prepares the code for lockless lookups. Also, mark the 'net' argument of __peernet2id() as 'const', since we're modifying this line. Signed-off-by: Guillaume Nault <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6214003 commit 4905294

File tree

1 file changed

+23
-32
lines changed

1 file changed

+23
-32
lines changed

net/core/net_namespace.c

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -211,67 +211,58 @@ static int net_eq_idr(int id, void *net, void *peer)
211211
return 0;
212212
}
213213

214-
/* Should be called with nsid_lock held. If a new id is assigned, the bool alloc
215-
* is set to true, thus the caller knows that the new id must be notified via
216-
* rtnl.
217-
*/
218-
static int __peernet2id_alloc(struct net *net, struct net *peer, bool *alloc)
214+
/* Should be called with nsid_lock held. */
215+
static int __peernet2id(const struct net *net, struct net *peer)
219216
{
220217
int id = idr_for_each(&net->netns_ids, net_eq_idr, peer);
221-
bool alloc_it = *alloc;
222-
223-
*alloc = false;
224218

225219
/* Magic value for id 0. */
226220
if (id == NET_ID_ZERO)
227221
return 0;
228222
if (id > 0)
229223
return id;
230224

231-
if (alloc_it) {
232-
id = alloc_netid(net, peer, -1);
233-
*alloc = true;
234-
return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED;
235-
}
236-
237225
return NETNSA_NSID_NOT_ASSIGNED;
238226
}
239227

240-
/* should be called with nsid_lock held */
241-
static int __peernet2id(struct net *net, struct net *peer)
242-
{
243-
bool no = false;
244-
245-
return __peernet2id_alloc(net, peer, &no);
246-
}
247-
248228
static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
249229
struct nlmsghdr *nlh, gfp_t gfp);
250230
/* This function returns the id of a peer netns. If no id is assigned, one will
251231
* be allocated and returned.
252232
*/
253233
int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp)
254234
{
255-
bool alloc = false, alive = false;
256235
int id;
257236

258237
if (refcount_read(&net->count) == 0)
259238
return NETNSA_NSID_NOT_ASSIGNED;
239+
260240
spin_lock_bh(&net->nsid_lock);
261-
/*
262-
* When peer is obtained from RCU lists, we may race with
241+
id = __peernet2id(net, peer);
242+
if (id >= 0) {
243+
spin_unlock_bh(&net->nsid_lock);
244+
return id;
245+
}
246+
247+
/* When peer is obtained from RCU lists, we may race with
263248
* its cleanup. Check whether it's alive, and this guarantees
264249
* we never hash a peer back to net->netns_ids, after it has
265250
* just been idr_remove()'d from there in cleanup_net().
266251
*/
267-
if (maybe_get_net(peer))
268-
alive = alloc = true;
269-
id = __peernet2id_alloc(net, peer, &alloc);
252+
if (!maybe_get_net(peer)) {
253+
spin_unlock_bh(&net->nsid_lock);
254+
return NETNSA_NSID_NOT_ASSIGNED;
255+
}
256+
257+
id = alloc_netid(net, peer, -1);
270258
spin_unlock_bh(&net->nsid_lock);
271-
if (alloc && id >= 0)
272-
rtnl_net_notifyid(net, RTM_NEWNSID, id, 0, NULL, gfp);
273-
if (alive)
274-
put_net(peer);
259+
260+
put_net(peer);
261+
if (id < 0)
262+
return NETNSA_NSID_NOT_ASSIGNED;
263+
264+
rtnl_net_notifyid(net, RTM_NEWNSID, id, 0, NULL, gfp);
265+
275266
return id;
276267
}
277268
EXPORT_SYMBOL_GPL(peernet2id_alloc);

0 commit comments

Comments
 (0)