X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fcore%2Frtnetlink.c;h=e652d8fbaa60cb6f8d26ea3a5cd37b354c818544;hb=b4e5fe4ac713ec66470b6fc3eeb828603b8ed76a;hp=e0b5e89c863de55266c6674143cefa89880d02de;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e0b5e89c8..e652d8fba 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -56,10 +56,12 @@ DECLARE_MUTEX(rtnl_sem); void rtnl_lock(void) { rtnl_shlock(); + rtnl_exlock(); } void rtnl_unlock(void) { + rtnl_exunlock(); rtnl_shunlock(); netdev_run_todo(); @@ -335,6 +337,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) struct rtnetlink_link *link_tab; struct rtattr *rta[RTATTR_MAX]; + int exclusive = 0; int sz_idx, kind; int min_len; int family; @@ -401,6 +404,14 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) return -1; } + if (kind != 2) { + if (rtnl_exlock_nowait()) { + *errp = 0; + return -1; + } + exclusive = 1; + } + memset(&rta, 0, sizeof(rta)); min_len = rtm_min[sz_idx]; @@ -428,10 +439,14 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) goto err_inval; err = link->doit(skb, nlh, (void *)&rta); + if (exclusive) + rtnl_exunlock(); *errp = err; return err; err_inval: + if (exclusive) + rtnl_exunlock(); *errp = -EINVAL; return -1; }