diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index 5ef841c85526..7dedf4867e7b 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -36,6 +36,7 @@ static unsigned int bareudp_net_id; struct bareudp_net { struct list_head bareudp_list; + struct mutex lock; }; struct bareudp_conf { @@ -636,10 +637,15 @@ static struct bareudp_dev *bareudp_find_dev(struct bareudp_net *bn, { struct bareudp_dev *bareudp, *t = NULL; + mutex_lock(&bn->lock); + list_for_each_entry(bareudp, &bn->bareudp_list, next) { if (conf->port == bareudp->port) t = bareudp; } + + mutex_unlock(&bn->lock); + return t; } @@ -675,7 +681,10 @@ static int bareudp_configure(struct net *net, struct net_device *dev, if (err) return err; + mutex_lock(&bn->lock); list_add(&bareudp->next, &bn->bareudp_list); + mutex_unlock(&bn->lock); + return 0; } @@ -692,7 +701,7 @@ static int bareudp_link_config(struct net_device *dev, return 0; } -static void bareudp_dellink(struct net_device *dev, struct list_head *head) +static void __bareudp_dellink(struct net_device *dev, struct list_head *head) { struct bareudp_dev *bareudp = netdev_priv(dev); @@ -700,6 +709,18 @@ static void bareudp_dellink(struct net_device *dev, struct list_head *head) unregister_netdevice_queue(dev, head); } +static void bareudp_dellink(struct net_device *dev, struct list_head *head) +{ + struct bareudp_dev *bareudp = netdev_priv(dev); + struct bareudp_net *bn; + + bn = net_generic(bareudp->net, bareudp_net_id); + + mutex_lock(&bn->lock); + __bareudp_dellink(dev, head); + mutex_unlock(&bn->lock); +} + static int bareudp_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) @@ -776,6 +797,8 @@ static __net_init int bareudp_init_net(struct net *net) struct bareudp_net *bn = net_generic(net, bareudp_net_id); INIT_LIST_HEAD(&bn->bareudp_list); + mutex_init(&bn->lock); + return 0; } @@ -785,8 +808,12 @@ static void __net_exit bareudp_exit_rtnl_net(struct net *net, struct bareudp_net *bn = net_generic(net, bareudp_net_id); struct bareudp_dev *bareudp, *next; + mutex_lock(&bn->lock); + list_for_each_entry_safe(bareudp, next, &bn->bareudp_list, next) - bareudp_dellink(bareudp->dev, dev_kill_list); + __bareudp_dellink(bareudp->dev, dev_kill_list); + + mutex_unlock(&bn->lock); } static struct pernet_operations bareudp_net_ops = {