aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c79
1 files changed, 34 insertions, 45 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 5d59155adf2a..9bb8f87c4cda 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1409,14 +1409,34 @@ EXPORT_SYMBOL(register_netdevice_notifier);
1409 * register_netdevice_notifier(). The notifier is unlinked into the 1409 * register_netdevice_notifier(). The notifier is unlinked into the
1410 * kernel structures and may then be reused. A negative errno code 1410 * kernel structures and may then be reused. A negative errno code
1411 * is returned on a failure. 1411 * is returned on a failure.
1412 *
1413 * After unregistering unregister and down device events are synthesized
1414 * for all devices on the device list to the removed notifier to remove
1415 * the need for special case cleanup code.
1412 */ 1416 */
1413 1417
1414int unregister_netdevice_notifier(struct notifier_block *nb) 1418int unregister_netdevice_notifier(struct notifier_block *nb)
1415{ 1419{
1420 struct net_device *dev;
1421 struct net *net;
1416 int err; 1422 int err;
1417 1423
1418 rtnl_lock(); 1424 rtnl_lock();
1419 err = raw_notifier_chain_unregister(&netdev_chain, nb); 1425 err = raw_notifier_chain_unregister(&netdev_chain, nb);
1426 if (err)
1427 goto unlock;
1428
1429 for_each_net(net) {
1430 for_each_netdev(net, dev) {
1431 if (dev->flags & IFF_UP) {
1432 nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
1433 nb->notifier_call(nb, NETDEV_DOWN, dev);
1434 }
1435 nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
1436 nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
1437 }
1438 }
1439unlock:
1420 rtnl_unlock(); 1440 rtnl_unlock();
1421 return err; 1441 return err;
1422} 1442}
@@ -1596,6 +1616,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1596 kfree_skb(skb); 1616 kfree_skb(skb);
1597 return NET_RX_DROP; 1617 return NET_RX_DROP;
1598 } 1618 }
1619 skb->skb_iif = 0;
1599 skb_set_dev(skb, dev); 1620 skb_set_dev(skb, dev);
1600 skb->tstamp.tv64 = 0; 1621 skb->tstamp.tv64 = 0;
1601 skb->pkt_type = PACKET_HOST; 1622 skb->pkt_type = PACKET_HOST;
@@ -4027,54 +4048,41 @@ static int dev_ifconf(struct net *net, char __user *arg)
4027 4048
4028#ifdef CONFIG_PROC_FS 4049#ifdef CONFIG_PROC_FS
4029 4050
4030#define BUCKET_SPACE (32 - NETDEV_HASHBITS) 4051#define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1)
4031
4032struct dev_iter_state {
4033 struct seq_net_private p;
4034 unsigned int pos; /* bucket << BUCKET_SPACE + offset */
4035};
4036 4052
4037#define get_bucket(x) ((x) >> BUCKET_SPACE) 4053#define get_bucket(x) ((x) >> BUCKET_SPACE)
4038#define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1)) 4054#define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1))
4039#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) 4055#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
4040 4056
4041static inline struct net_device *dev_from_same_bucket(struct seq_file *seq) 4057static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos)
4042{ 4058{
4043 struct dev_iter_state *state = seq->private;
4044 struct net *net = seq_file_net(seq); 4059 struct net *net = seq_file_net(seq);
4045 struct net_device *dev; 4060 struct net_device *dev;
4046 struct hlist_node *p; 4061 struct hlist_node *p;
4047 struct hlist_head *h; 4062 struct hlist_head *h;
4048 unsigned int count, bucket, offset; 4063 unsigned int count = 0, offset = get_offset(*pos);
4049 4064
4050 bucket = get_bucket(state->pos); 4065 h = &net->dev_name_head[get_bucket(*pos)];
4051 offset = get_offset(state->pos);
4052 h = &net->dev_name_head[bucket];
4053 count = 0;
4054 hlist_for_each_entry_rcu(dev, p, h, name_hlist) { 4066 hlist_for_each_entry_rcu(dev, p, h, name_hlist) {
4055 if (count++ == offset) { 4067 if (++count == offset)
4056 state->pos = set_bucket_offset(bucket, count);
4057 return dev; 4068 return dev;
4058 }
4059 } 4069 }
4060 4070
4061 return NULL; 4071 return NULL;
4062} 4072}
4063 4073
4064static inline struct net_device *dev_from_new_bucket(struct seq_file *seq) 4074static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos)
4065{ 4075{
4066 struct dev_iter_state *state = seq->private;
4067 struct net_device *dev; 4076 struct net_device *dev;
4068 unsigned int bucket; 4077 unsigned int bucket;
4069 4078
4070 bucket = get_bucket(state->pos);
4071 do { 4079 do {
4072 dev = dev_from_same_bucket(seq); 4080 dev = dev_from_same_bucket(seq, pos);
4073 if (dev) 4081 if (dev)
4074 return dev; 4082 return dev;
4075 4083
4076 bucket++; 4084 bucket = get_bucket(*pos) + 1;
4077 state->pos = set_bucket_offset(bucket, 0); 4085 *pos = set_bucket_offset(bucket, 1);
4078 } while (bucket < NETDEV_HASHENTRIES); 4086 } while (bucket < NETDEV_HASHENTRIES);
4079 4087
4080 return NULL; 4088 return NULL;
@@ -4087,33 +4095,20 @@ static inline struct net_device *dev_from_new_bucket(struct seq_file *seq)
4087void *dev_seq_start(struct seq_file *seq, loff_t *pos) 4095void *dev_seq_start(struct seq_file *seq, loff_t *pos)
4088 __acquires(RCU) 4096 __acquires(RCU)
4089{ 4097{
4090 struct dev_iter_state *state = seq->private;
4091
4092 rcu_read_lock(); 4098 rcu_read_lock();
4093 if (!*pos) 4099 if (!*pos)
4094 return SEQ_START_TOKEN; 4100 return SEQ_START_TOKEN;
4095 4101
4096 /* check for end of the hash */ 4102 if (get_bucket(*pos) >= NETDEV_HASHENTRIES)
4097 if (state->pos == 0 && *pos > 1)
4098 return NULL; 4103 return NULL;
4099 4104
4100 return dev_from_new_bucket(seq); 4105 return dev_from_bucket(seq, pos);
4101} 4106}
4102 4107
4103void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 4108void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
4104{ 4109{
4105 struct net_device *dev;
4106
4107 ++*pos; 4110 ++*pos;
4108 4111 return dev_from_bucket(seq, pos);
4109 if (v == SEQ_START_TOKEN)
4110 return dev_from_new_bucket(seq);
4111
4112 dev = dev_from_same_bucket(seq);
4113 if (dev)
4114 return dev;
4115
4116 return dev_from_new_bucket(seq);
4117} 4112}
4118 4113
4119void dev_seq_stop(struct seq_file *seq, void *v) 4114void dev_seq_stop(struct seq_file *seq, void *v)
@@ -4212,13 +4207,7 @@ static const struct seq_operations dev_seq_ops = {
4212static int dev_seq_open(struct inode *inode, struct file *file) 4207static int dev_seq_open(struct inode *inode, struct file *file)
4213{ 4208{
4214 return seq_open_net(inode, file, &dev_seq_ops, 4209 return seq_open_net(inode, file, &dev_seq_ops,
4215 sizeof(struct dev_iter_state)); 4210 sizeof(struct seq_net_private));
4216}
4217
4218int dev_seq_open_ops(struct inode *inode, struct file *file,
4219 const struct seq_operations *ops)
4220{
4221 return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
4222} 4211}
4223 4212
4224static const struct file_operations dev_seq_fops = { 4213static const struct file_operations dev_seq_fops = {