Skip to content

Commit fc9c89b

Browse files
committed
Merge branch 'bridge-register-netdev-before-changelink'
Ido Schimmel says: ==================== bridge: Fix kernel oops during bridge creation First patch adds a missing ndo_uninit() in the bridge driver, which is a prerequisite for the second patch that actually fixes the oops. Please consider both patches for 4.4.y, 4.9.y and 4.10.y ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 96a94cc + 5b8d542 commit fc9c89b

File tree

5 files changed

+26
-14
lines changed

5 files changed

+26
-14
lines changed

net/bridge/br_device.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ static int br_dev_init(struct net_device *dev)
119119
return err;
120120
}
121121

122+
static void br_dev_uninit(struct net_device *dev)
123+
{
124+
struct net_bridge *br = netdev_priv(dev);
125+
126+
br_multicast_uninit_stats(br);
127+
br_vlan_flush(br);
128+
free_percpu(br->stats);
129+
}
130+
122131
static int br_dev_open(struct net_device *dev)
123132
{
124133
struct net_bridge *br = netdev_priv(dev);
@@ -332,6 +341,7 @@ static const struct net_device_ops br_netdev_ops = {
332341
.ndo_open = br_dev_open,
333342
.ndo_stop = br_dev_stop,
334343
.ndo_init = br_dev_init,
344+
.ndo_uninit = br_dev_uninit,
335345
.ndo_start_xmit = br_dev_xmit,
336346
.ndo_get_stats64 = br_get_stats64,
337347
.ndo_set_mac_address = br_set_mac_address,
@@ -356,14 +366,6 @@ static const struct net_device_ops br_netdev_ops = {
356366
.ndo_features_check = passthru_features_check,
357367
};
358368

359-
static void br_dev_free(struct net_device *dev)
360-
{
361-
struct net_bridge *br = netdev_priv(dev);
362-
363-
free_percpu(br->stats);
364-
free_netdev(dev);
365-
}
366-
367369
static struct device_type br_type = {
368370
.name = "bridge",
369371
};
@@ -376,7 +378,7 @@ void br_dev_setup(struct net_device *dev)
376378
ether_setup(dev);
377379

378380
dev->netdev_ops = &br_netdev_ops;
379-
dev->destructor = br_dev_free;
381+
dev->destructor = free_netdev;
380382
dev->ethtool_ops = &br_ethtool_ops;
381383
SET_NETDEV_DEVTYPE(dev, &br_type);
382384
dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;

net/bridge/br_if.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,6 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
311311

312312
br_fdb_delete_by_port(br, NULL, 0, 1);
313313

314-
br_vlan_flush(br);
315314
br_multicast_dev_del(br);
316315
cancel_delayed_work_sync(&br->gc_work);
317316

net/bridge/br_multicast.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,8 +2031,6 @@ void br_multicast_dev_del(struct net_bridge *br)
20312031

20322032
out:
20332033
spin_unlock_bh(&br->multicast_lock);
2034-
2035-
free_percpu(br->mcast_stats);
20362034
}
20372035

20382036
int br_multicast_set_router(struct net_bridge *br, unsigned long val)
@@ -2531,6 +2529,11 @@ int br_multicast_init_stats(struct net_bridge *br)
25312529
return 0;
25322530
}
25332531

2532+
void br_multicast_uninit_stats(struct net_bridge *br)
2533+
{
2534+
free_percpu(br->mcast_stats);
2535+
}
2536+
25342537
static void mcast_stats_add_dir(u64 *dst, u64 *src)
25352538
{
25362539
dst[BR_MCAST_DIR_RX] += src[BR_MCAST_DIR_RX];

net/bridge/br_netlink.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,11 +1165,14 @@ static int br_dev_newlink(struct net *src_net, struct net_device *dev,
11651165
spin_unlock_bh(&br->lock);
11661166
}
11671167

1168-
err = br_changelink(dev, tb, data);
1168+
err = register_netdevice(dev);
11691169
if (err)
11701170
return err;
11711171

1172-
return register_netdevice(dev);
1172+
err = br_changelink(dev, tb, data);
1173+
if (err)
1174+
unregister_netdevice(dev);
1175+
return err;
11731176
}
11741177

11751178
static size_t br_get_size(const struct net_device *brdev)

net/bridge/br_private.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
620620
void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
621621
const struct sk_buff *skb, u8 type, u8 dir);
622622
int br_multicast_init_stats(struct net_bridge *br);
623+
void br_multicast_uninit_stats(struct net_bridge *br);
623624
void br_multicast_get_stats(const struct net_bridge *br,
624625
const struct net_bridge_port *p,
625626
struct br_mcast_stats *dest);
@@ -760,6 +761,10 @@ static inline int br_multicast_init_stats(struct net_bridge *br)
760761
return 0;
761762
}
762763

764+
static inline void br_multicast_uninit_stats(struct net_bridge *br)
765+
{
766+
}
767+
763768
static inline int br_multicast_igmp_type(const struct sk_buff *skb)
764769
{
765770
return 0;

0 commit comments

Comments
 (0)