SUNRPC: Dont run rpcauth_cache_shrinker() when gfp_mask is GFP_NOFS
[safe/jmp/linux-2.6] / net / core / rtnetlink.c
index 020e43b..fe776c9 100644 (file)
@@ -90,6 +90,14 @@ int rtnl_is_locked(void)
 }
 EXPORT_SYMBOL(rtnl_is_locked);
 
+#ifdef CONFIG_PROVE_LOCKING
+int lockdep_rtnl_is_held(void)
+{
+       return lockdep_is_held(&rtnl_mutex);
+}
+EXPORT_SYMBOL(lockdep_rtnl_is_held);
+#endif /* #ifdef CONFIG_PROVE_LOCKING */
+
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -549,6 +557,19 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
        }
 }
 
+static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
+                                          const struct ifinfomsg *ifm)
+{
+       unsigned int flags = ifm->ifi_flags;
+
+       /* bugwards compatibility: ifi_change == 0 is treated as ~0 */
+       if (ifm->ifi_change)
+               flags = (flags & ifm->ifi_change) |
+                       (dev->flags & ~ifm->ifi_change);
+
+       return flags;
+}
+
 static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
                                 const struct net_device_stats *b)
 {
@@ -904,13 +925,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
        }
 
        if (ifm->ifi_flags || ifm->ifi_change) {
-               unsigned int flags = ifm->ifi_flags;
-
-               /* bugwards compatibility: ifi_change == 0 is treated as ~0 */
-               if (ifm->ifi_change)
-                       flags = (flags & ifm->ifi_change) |
-                               (dev->flags & ~ifm->ifi_change);
-               err = dev_change_flags(dev, flags);
+               err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
                if (err < 0)
                        goto errout;
        }
@@ -1053,6 +1068,26 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        return 0;
 }
 
+int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
+{
+       unsigned int old_flags;
+       int err;
+
+       old_flags = dev->flags;
+       if (ifm && (ifm->ifi_flags || ifm->ifi_change)) {
+               err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
+               if (err < 0)
+                       return err;
+       }
+
+       dev->rtnl_link_state = RTNL_LINK_INITIALIZED;
+       rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
+
+       __dev_notify_flags(dev, old_flags);
+       return 0;
+}
+EXPORT_SYMBOL(rtnl_configure_link);
+
 struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
        char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[])
 {
@@ -1074,6 +1109,7 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 
        dev_net_set(dev, net);
        dev->rtnl_link_ops = ops;
+       dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
        dev->real_num_tx_queues = real_num_queues;
 
        if (strchr(dev->name, '%')) {
@@ -1203,7 +1239,7 @@ replay:
                if (!(nlh->nlmsg_flags & NLM_F_CREATE))
                        return -ENODEV;
 
-               if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
+               if (ifm->ifi_index)
                        return -EOPNOTSUPP;
                if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
                        return -EOPNOTSUPP;
@@ -1234,9 +1270,16 @@ replay:
                        err = ops->newlink(net, dev, tb, data);
                else
                        err = register_netdevice(dev);
+
                if (err < 0 && !IS_ERR(dev))
                        free_netdev(dev);
+               if (err < 0)
+                       goto out;
 
+               err = rtnl_configure_link(dev, ifm);
+               if (err < 0)
+                       unregister_netdevice(dev);
+out:
                put_net(dest_net);
                return err;
        }
@@ -1427,8 +1470,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
        switch (event) {
        case NETDEV_UP:
        case NETDEV_DOWN:
-               rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
-               break;
        case NETDEV_PRE_UP:
        case NETDEV_POST_INIT:
        case NETDEV_REGISTER: