aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/core/net_namespace.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2c2eb1b629b1..10608dd1489f 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -213,14 +213,13 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id);
213 */ 213 */
214int peernet2id_alloc(struct net *net, struct net *peer) 214int peernet2id_alloc(struct net *net, struct net *peer)
215{ 215{
216 unsigned long flags;
217 bool alloc; 216 bool alloc;
218 int id; 217 int id;
219 218
220 spin_lock_irqsave(&net->nsid_lock, flags); 219 spin_lock_bh(&net->nsid_lock);
221 alloc = atomic_read(&peer->count) == 0 ? false : true; 220 alloc = atomic_read(&peer->count) == 0 ? false : true;
222 id = __peernet2id_alloc(net, peer, &alloc); 221 id = __peernet2id_alloc(net, peer, &alloc);
223 spin_unlock_irqrestore(&net->nsid_lock, flags); 222 spin_unlock_bh(&net->nsid_lock);
224 if (alloc && id >= 0) 223 if (alloc && id >= 0)
225 rtnl_net_notifyid(net, RTM_NEWNSID, id); 224 rtnl_net_notifyid(net, RTM_NEWNSID, id);
226 return id; 225 return id;
@@ -230,12 +229,11 @@ EXPORT_SYMBOL(peernet2id_alloc);
230/* This function returns, if assigned, the id of a peer netns. */ 229/* This function returns, if assigned, the id of a peer netns. */
231int peernet2id(struct net *net, struct net *peer) 230int peernet2id(struct net *net, struct net *peer)
232{ 231{
233 unsigned long flags;
234 int id; 232 int id;
235 233
236 spin_lock_irqsave(&net->nsid_lock, flags); 234 spin_lock_bh(&net->nsid_lock);
237 id = __peernet2id(net, peer); 235 id = __peernet2id(net, peer);
238 spin_unlock_irqrestore(&net->nsid_lock, flags); 236 spin_unlock_bh(&net->nsid_lock);
239 return id; 237 return id;
240} 238}
241 239
@@ -249,18 +247,17 @@ bool peernet_has_id(struct net *net, struct net *peer)
249 247
250struct net *get_net_ns_by_id(struct net *net, int id) 248struct net *get_net_ns_by_id(struct net *net, int id)
251{ 249{
252 unsigned long flags;
253 struct net *peer; 250 struct net *peer;
254 251
255 if (id < 0) 252 if (id < 0)
256 return NULL; 253 return NULL;
257 254
258 rcu_read_lock(); 255 rcu_read_lock();
259 spin_lock_irqsave(&net->nsid_lock, flags); 256 spin_lock_bh(&net->nsid_lock);
260 peer = idr_find(&net->netns_ids, id); 257 peer = idr_find(&net->netns_ids, id);
261 if (peer) 258 if (peer)
262 get_net(peer); 259 get_net(peer);
263 spin_unlock_irqrestore(&net->nsid_lock, flags); 260 spin_unlock_bh(&net->nsid_lock);
264 rcu_read_unlock(); 261 rcu_read_unlock();
265 262
266 return peer; 263 return peer;
@@ -404,17 +401,17 @@ static void cleanup_net(struct work_struct *work)
404 for_each_net(tmp) { 401 for_each_net(tmp) {
405 int id; 402 int id;
406 403
407 spin_lock_irq(&tmp->nsid_lock); 404 spin_lock_bh(&tmp->nsid_lock);
408 id = __peernet2id(tmp, net); 405 id = __peernet2id(tmp, net);
409 if (id >= 0) 406 if (id >= 0)
410 idr_remove(&tmp->netns_ids, id); 407 idr_remove(&tmp->netns_ids, id);
411 spin_unlock_irq(&tmp->nsid_lock); 408 spin_unlock_bh(&tmp->nsid_lock);
412 if (id >= 0) 409 if (id >= 0)
413 rtnl_net_notifyid(tmp, RTM_DELNSID, id); 410 rtnl_net_notifyid(tmp, RTM_DELNSID, id);
414 } 411 }
415 spin_lock_irq(&net->nsid_lock); 412 spin_lock_bh(&net->nsid_lock);
416 idr_destroy(&net->netns_ids); 413 idr_destroy(&net->netns_ids);
417 spin_unlock_irq(&net->nsid_lock); 414 spin_unlock_bh(&net->nsid_lock);
418 415
419 } 416 }
420 rtnl_unlock(); 417 rtnl_unlock();
@@ -542,7 +539,6 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
542{ 539{
543 struct net *net = sock_net(skb->sk); 540 struct net *net = sock_net(skb->sk);
544 struct nlattr *tb[NETNSA_MAX + 1]; 541 struct nlattr *tb[NETNSA_MAX + 1];
545 unsigned long flags;
546 struct net *peer; 542 struct net *peer;
547 int nsid, err; 543 int nsid, err;
548 544
@@ -563,15 +559,15 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
563 if (IS_ERR(peer)) 559 if (IS_ERR(peer))
564 return PTR_ERR(peer); 560 return PTR_ERR(peer);
565 561
566 spin_lock_irqsave(&net->nsid_lock, flags); 562 spin_lock_bh(&net->nsid_lock);
567 if (__peernet2id(net, peer) >= 0) { 563 if (__peernet2id(net, peer) >= 0) {
568 spin_unlock_irqrestore(&net->nsid_lock, flags); 564 spin_unlock_bh(&net->nsid_lock);
569 err = -EEXIST; 565 err = -EEXIST;
570 goto out; 566 goto out;
571 } 567 }
572 568
573 err = alloc_netid(net, peer, nsid); 569 err = alloc_netid(net, peer, nsid);
574 spin_unlock_irqrestore(&net->nsid_lock, flags); 570 spin_unlock_bh(&net->nsid_lock);
575 if (err >= 0) { 571 if (err >= 0) {
576 rtnl_net_notifyid(net, RTM_NEWNSID, err); 572 rtnl_net_notifyid(net, RTM_NEWNSID, err);
577 err = 0; 573 err = 0;
@@ -693,11 +689,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
693 .idx = 0, 689 .idx = 0,
694 .s_idx = cb->args[0], 690 .s_idx = cb->args[0],
695 }; 691 };
696 unsigned long flags;
697 692
698 spin_lock_irqsave(&net->nsid_lock, flags); 693 spin_lock_bh(&net->nsid_lock);
699 idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); 694 idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
700 spin_unlock_irqrestore(&net->nsid_lock, flags); 695 spin_unlock_bh(&net->nsid_lock);
701 696
702 cb->args[0] = net_cb.idx; 697 cb->args[0] = net_cb.idx;
703 return skb->len; 698 return skb->len;