projects
/
cascardo
/
linux.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
netns: notify new nsid outside __peernet2id()
[cascardo/linux.git]
/
net
/
core
/
net_namespace.c
diff --git
a/net/core/net_namespace.c
b/net/core/net_namespace.c
index
78fc04a
..
ee86424
100644
(file)
--- a/
net/core/net_namespace.c
+++ b/
net/core/net_namespace.c
@@
-147,11
+147,9
@@
static void ops_free_list(const struct pernet_operations *ops,
}
}
}
}
-static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd,
- int id);
static int alloc_netid(struct net *net, struct net *peer, int reqid)
{
static int alloc_netid(struct net *net, struct net *peer, int reqid)
{
- int min = 0, max = 0
, id
;
+ int min = 0, max = 0;
ASSERT_RTNL();
ASSERT_RTNL();
@@
-160,11
+158,7
@@
static int alloc_netid(struct net *net, struct net *peer, int reqid)
max = reqid + 1;
}
max = reqid + 1;
}
- id = idr_alloc(&net->netns_ids, peer, min, max, GFP_KERNEL);
- if (id >= 0)
- rtnl_net_notifyid(net, peer, RTM_NEWNSID, id);
-
- return id;
+ return idr_alloc(&net->netns_ids, peer, min, max, GFP_KERNEL);
}
/* This function is used by idr_for_each(). If net is equal to peer, the
}
/* This function is used by idr_for_each(). If net is equal to peer, the
@@
-180,36
+174,52
@@
static int net_eq_idr(int id, void *net, void *peer)
return 0;
}
return 0;
}
-static int __peernet2id
(struct net *net, struct net *peer, bool
alloc)
+static int __peernet2id
_alloc(struct net *net, struct net *peer, bool *
alloc)
{
int id = idr_for_each(&net->netns_ids, net_eq_idr, peer);
{
int id = idr_for_each(&net->netns_ids, net_eq_idr, peer);
+ bool alloc_it = *alloc;
ASSERT_RTNL();
ASSERT_RTNL();
+ *alloc = false;
+
/* Magic value for id 0. */
if (id == NET_ID_ZERO)
return 0;
if (id > 0)
return id;
/* Magic value for id 0. */
if (id == NET_ID_ZERO)
return 0;
if (id > 0)
return id;
- if (alloc)
- return alloc_netid(net, peer, -1);
+ if (alloc_it) {
+ id = alloc_netid(net, peer, -1);
+ *alloc = true;
+ return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED;
+ }
+
+ return NETNSA_NSID_NOT_ASSIGNED;
+}
+
+static int __peernet2id(struct net *net, struct net *peer)
+{
+ bool no = false;
- return
-ENOENT
;
+ return
__peernet2id_alloc(net, peer, &no)
;
}
}
+static void rtnl_net_notifyid(struct net *net, int cmd, int id);
/* This function returns the id of a peer netns. If no id is assigned, one will
* be allocated and returned.
*/
/* This function returns the id of a peer netns. If no id is assigned, one will
* be allocated and returned.
*/
-int peernet2id(struct net *net, struct net *peer)
+int peernet2id
_alloc
(struct net *net, struct net *peer)
{
bool alloc = atomic_read(&peer->count) == 0 ? false : true;
int id;
{
bool alloc = atomic_read(&peer->count) == 0 ? false : true;
int id;
- id = __peernet2id(net, peer, alloc);
- return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED;
+ id = __peernet2id_alloc(net, peer, &alloc);
+ if (alloc && id >= 0)
+ rtnl_net_notifyid(net, RTM_NEWNSID, id);
+ return id;
}
}
-EXPORT_SYMBOL(peernet2id);
+EXPORT_SYMBOL(peernet2id
_alloc
);
struct net *get_net_ns_by_id(struct net *net, int id)
{
struct net *get_net_ns_by_id(struct net *net, int id)
{
@@
-362,10
+372,10
@@
static void cleanup_net(struct work_struct *work)
list_del_rcu(&net->list);
list_add_tail(&net->exit_list, &net_exit_list);
for_each_net(tmp) {
list_del_rcu(&net->list);
list_add_tail(&net->exit_list, &net_exit_list);
for_each_net(tmp) {
- int id = __peernet2id(tmp, net
, false
);
+ int id = __peernet2id(tmp, net);
if (id >= 0) {
if (id >= 0) {
- rtnl_net_notifyid(tmp,
net,
RTM_DELNSID, id);
+ rtnl_net_notifyid(tmp, RTM_DELNSID, id);
idr_remove(&tmp->netns_ids, id);
}
}
idr_remove(&tmp->netns_ids, id);
}
}
@@
-517,14
+527,16
@@
static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
if (IS_ERR(peer))
return PTR_ERR(peer);
if (IS_ERR(peer))
return PTR_ERR(peer);
- if (__peernet2id(net, peer
, false
) >= 0) {
+ if (__peernet2id(net, peer) >= 0) {
err = -EEXIST;
goto out;
}
err = alloc_netid(net, peer, nsid);
err = -EEXIST;
goto out;
}
err = alloc_netid(net, peer, nsid);
- if (err > 0)
+ if (err >= 0) {
+ rtnl_net_notifyid(net, RTM_NEWNSID, err);
err = 0;
err = 0;
+ }
out:
put_net(peer);
return err;
out:
put_net(peer);
return err;
@@
-538,14
+550,10
@@
static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, struct net *net, struct net *peer,
- int nsid)
+ int cmd, struct net *net, int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
- int id;
-
- ASSERT_RTNL();
nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags);
if (!nlh)
nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags);
if (!nlh)
@@
-554,14
+562,7
@@
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;
- if (nsid >= 0) {
- id = nsid;
- } else {
- id = __peernet2id(net, peer, false);
- if (id < 0)
- id = NETNSA_NSID_NOT_ASSIGNED;
- }
- if (nla_put_s32(skb, NETNSA_NSID, id))
+ if (nla_put_s32(skb, NETNSA_NSID, nsid))
goto nla_put_failure;
nlmsg_end(skb, nlh);
goto nla_put_failure;
nlmsg_end(skb, nlh);
@@
-578,7
+579,7
@@
static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh)
struct nlattr *tb[NETNSA_MAX + 1];
struct sk_buff *msg;
struct net *peer;
struct nlattr *tb[NETNSA_MAX + 1];
struct sk_buff *msg;
struct net *peer;
- int err;
+ int err
, id
;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy);
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy);
@@
-600,8
+601,9
@@
static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh)
goto out;
}
goto out;
}
+ id = __peernet2id(net, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_GETNSID, net,
peer, -1
);
+ RTM_GETNSID, net,
id
);
if (err < 0)
goto err_out;
if (err < 0)
goto err_out;
@@
-633,7
+635,7
@@
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, net_cb->net,
peer,
id);
+ RTM_NEWNSID, net_cb->net, id);
if (ret < 0)
return ret;
if (ret < 0)
return ret;
@@
-661,8
+663,7
@@
static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
return skb->len;
}
-static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd,
- int id)
+static void rtnl_net_notifyid(struct net *net, int cmd, int id)
{
struct sk_buff *msg;
int err = -ENOMEM;
{
struct sk_buff *msg;
int err = -ENOMEM;
@@
-671,7
+672,7
@@
static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd,
if (!msg)
goto out;
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, net,
peer,
id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id);
if (err < 0)
goto err_out;
if (err < 0)
goto err_out;