Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 79309
b: refs/heads/master
c: af30151
h: refs/heads/master
i:
  79307: e96a98c
v: v3
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jan 28, 2008
1 parent d1a457d commit baeea87
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 64 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: acc5efbcd2a023c8801f2bba39971cf93812ce7c
refs/heads/master: af30151709bcace1ca844d4bb8b7e2e392ff81eb
1 change: 1 addition & 0 deletions trunk/include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));

struct vlan_group {
int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
unsigned int nr_vlans;
struct hlist_node hlist; /* linked list */
struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
struct rcu_head rcu;
Expand Down
76 changes: 20 additions & 56 deletions trunk/net/8021q/vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,33 +132,17 @@ static void vlan_rcu_free(struct rcu_head *rcu)
vlan_group_free(container_of(rcu, struct vlan_group, rcu));
}


/* This returns 0 if everything went fine.
* It will return 1 if the group was killed as a result.
* A negative return indicates failure.
*
* The RTNL lock must be held.
*/
static int unregister_vlan_dev(struct net_device *real_dev,
unsigned short vlan_id)
void unregister_vlan_dev(struct net_device *dev)
{
struct net_device *dev;
int real_dev_ifindex = real_dev->ifindex;
struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
struct net_device *real_dev = vlan->real_dev;
struct vlan_group *grp;
unsigned int i;
int ret;

if (vlan_id >= VLAN_VID_MASK)
return -EINVAL;
unsigned short vlan_id = vlan->vlan_id;

ASSERT_RTNL();
grp = __vlan_find_group(real_dev_ifindex);
if (!grp)
return -ENOENT;

dev = vlan_group_get_device(grp, vlan_id);
if (!dev)
return -ENOENT;
grp = __vlan_find_group(real_dev->ifindex);
BUG_ON(!grp);

vlan_proc_rem_dev(dev);

Expand All @@ -169,44 +153,25 @@ static int unregister_vlan_dev(struct net_device *real_dev,
real_dev->vlan_rx_kill_vid(real_dev, vlan_id);

vlan_group_set_device(grp, vlan_id, NULL);
synchronize_net();
grp->nr_vlans--;

/* Caller unregisters (and if necessary, puts) VLAN device, but we
* get rid of the reference to real_dev here.
*/
dev_put(real_dev);
synchronize_net();

/* If the group is now empty, kill off the group. */
ret = 0;
for (i = 0; i < VLAN_VID_MASK; i++)
if (vlan_group_get_device(grp, i))
break;

if (i == VLAN_VID_MASK) {
if (grp->nr_vlans == 0) {
if (real_dev->features & NETIF_F_HW_VLAN_RX)
real_dev->vlan_rx_register(real_dev, NULL);

hlist_del_rcu(&grp->hlist);

/* Free the group, after all cpu's are done. */
call_rcu(&grp->rcu, vlan_rcu_free);
ret = 1;
}

return ret;
}

int unregister_vlan_device(struct net_device *dev)
{
int ret;
/* Get rid of the vlan's reference to real_dev */
dev_put(real_dev);

ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
VLAN_DEV_INFO(dev)->vlan_id);
unregister_netdevice(dev);

if (ret == 1)
ret = 0;
return ret;
}

static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
Expand Down Expand Up @@ -291,6 +256,8 @@ int register_vlan_dev(struct net_device *dev)
* it into our local structure.
*/
vlan_group_set_device(grp, vlan_id, dev);
grp->nr_vlans++;

if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
real_dev->vlan_rx_register(real_dev, ngrp);
if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
Expand Down Expand Up @@ -479,20 +446,16 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
case NETDEV_UNREGISTER:
/* Delete all VLANs for this dev. */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
int ret;

vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;

ret = unregister_vlan_dev(dev,
VLAN_DEV_INFO(vlandev)->vlan_id);

unregister_netdevice(vlandev);
/* unregistration of last vlan destroys group, abort
* afterwards */
if (grp->nr_vlans == 1)
i = VLAN_GROUP_ARRAY_LEN;

/* Group was destroyed? */
if (ret == 1)
break;
unregister_vlan_dev(vlandev);
}
break;
}
Expand Down Expand Up @@ -598,7 +561,8 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
err = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
err = unregister_vlan_device(dev);
unregister_vlan_dev(dev);
err = 0;
break;

case GET_VLAN_REALDEV_NAME_CMD:
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/8021q/vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
void vlan_setup(struct net_device *dev);
int register_vlan_dev(struct net_device *dev);
int unregister_vlan_device(struct net_device *dev);
void unregister_vlan_dev(struct net_device *dev);

int vlan_netlink_init(void);
void vlan_netlink_fini(void);
Expand Down
7 changes: 1 addition & 6 deletions trunk/net/8021q/vlan_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,6 @@ static int vlan_newlink(struct net_device *dev,
return register_vlan_dev(dev);
}

static void vlan_dellink(struct net_device *dev)
{
unregister_vlan_device(dev);
}

static inline size_t vlan_qos_map_size(unsigned int n)
{
if (n == 0)
Expand Down Expand Up @@ -226,7 +221,7 @@ struct rtnl_link_ops vlan_link_ops __read_mostly = {
.validate = vlan_validate,
.newlink = vlan_newlink,
.changelink = vlan_changelink,
.dellink = vlan_dellink,
.dellink = unregister_vlan_dev,
.get_size = vlan_get_size,
.fill_info = vlan_fill_info,
};
Expand Down

0 comments on commit baeea87

Please sign in to comment.