• Kirill Tkhai's avatar
    net: Move net:netns_ids destruction out of rtnl_lock() and document locking scheme · fb07a820
    Kirill Tkhai authored
    Currently, we unhash a dying net from netns_ids lists
    under rtnl_lock(). It's a leftover from the time when
    net::netns_ids was introduced. There was no net::nsid_lock,
    and rtnl_lock() was mostly need to order modification
    of alive nets nsid idr, i.e. for:
    	for_each_net(tmp) {
    		...
    		id = __peernet2id(tmp, net);
    		idr_remove(&tmp->netns_ids, id);
    		...
    	}
    
    Since we have net::nsid_lock, the modifications are
    protected by this local lock, and now we may introduce
    better scheme of netns_ids destruction.
    
    Let's look at the functions peernet2id_alloc() and
    get_net_ns_by_id(). Previous commits taught these
    functions to work well with dying net acquired from
    rtnl unlocked lists. And they are the only functions
    which can hash a net to netns_ids or obtain from there.
    And as easy to check, other netns_ids operating functions
    works with id, not with net pointers. So, we do not
    need rtnl_lock to synchronize cleanup_net() with all them.
    
    The another property, which is used in the patch,
    is that net is unhashed from net_namespace_list
    in the only place and by the only process. So,
    we avoid excess rcu_read_lock() or rtnl_lock(),
    when we'are iterating over the list in unhash_nsid().
    
    All the above makes possible to keep rtnl_lock() locked
    only for net->list deletion, and completely avoid it
    for netns_ids unhashing and destruction. As these two
    doings may take long time (e.g., memory allocation
    to send skb), the patch should positively act on
    the scalability and signify decrease the time, which
    rtnl_lock() is held in cleanup_net().
    Signed-off-by: default avatarKirill Tkhai <ktkhai@virtuozzo.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    fb07a820
net_namespace.c 26.7 KB