diff options
| author | Amerigo Wang <amwang@redhat.com> | 2012-08-09 21:24:37 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-08-14 17:33:30 -0400 |
| commit | 47be03a28cc6c80e3aa2b3e8ed6d960ff0c5c0af (patch) | |
| tree | ba11046ff60d948cd4db06652e2483537387b3ca | |
| parent | ddf343f635fe4440cad528e12f96f28bd50aa099 (diff) | |
netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
slave_enable_netpoll() and __netpoll_setup() may be called
with read_lock() held, so should use GFP_ATOMIC to allocate
memory. Eric suggested to pass gfp flags to __netpoll_setup().
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 6 | ||||
| -rw-r--r-- | drivers/net/team/team.c | 16 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 3 | ||||
| -rw-r--r-- | include/linux/netpoll.h | 2 | ||||
| -rw-r--r-- | net/8021q/vlan_dev.c | 7 | ||||
| -rw-r--r-- | net/bridge/br_device.c | 12 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 4 | ||||
| -rw-r--r-- | net/core/netpoll.c | 8 |
9 files changed, 32 insertions, 28 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6fae5f3ec7f6..8697136e27c0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave) | |||
| 1235 | struct netpoll *np; | 1235 | struct netpoll *np; |
| 1236 | int err = 0; | 1236 | int err = 0; |
| 1237 | 1237 | ||
| 1238 | np = kzalloc(sizeof(*np), GFP_KERNEL); | 1238 | np = kzalloc(sizeof(*np), GFP_ATOMIC); |
| 1239 | err = -ENOMEM; | 1239 | err = -ENOMEM; |
| 1240 | if (!np) | 1240 | if (!np) |
| 1241 | goto out; | 1241 | goto out; |
| 1242 | 1242 | ||
| 1243 | err = __netpoll_setup(np, slave->dev); | 1243 | err = __netpoll_setup(np, slave->dev, GFP_ATOMIC); |
| 1244 | if (err) { | 1244 | if (err) { |
| 1245 | kfree(np); | 1245 | kfree(np); |
| 1246 | goto out; | 1246 | goto out; |
| @@ -1292,7 +1292,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) | |||
| 1292 | read_unlock(&bond->lock); | 1292 | read_unlock(&bond->lock); |
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) | 1295 | static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) |
| 1296 | { | 1296 | { |
| 1297 | struct bonding *bond = netdev_priv(dev); | 1297 | struct bonding *bond = netdev_priv(dev); |
| 1298 | struct slave *slave; | 1298 | struct slave *slave; |
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 87707ab39430..341b65dbbcd3 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
| @@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port) | |||
| 795 | } | 795 | } |
| 796 | 796 | ||
| 797 | #ifdef CONFIG_NET_POLL_CONTROLLER | 797 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 798 | static int team_port_enable_netpoll(struct team *team, struct team_port *port) | 798 | static int team_port_enable_netpoll(struct team *team, struct team_port *port, |
| 799 | gfp_t gfp) | ||
| 799 | { | 800 | { |
| 800 | struct netpoll *np; | 801 | struct netpoll *np; |
| 801 | int err; | 802 | int err; |
| 802 | 803 | ||
| 803 | np = kzalloc(sizeof(*np), GFP_KERNEL); | 804 | np = kzalloc(sizeof(*np), gfp); |
| 804 | if (!np) | 805 | if (!np) |
| 805 | return -ENOMEM; | 806 | return -ENOMEM; |
| 806 | 807 | ||
| 807 | err = __netpoll_setup(np, port->dev); | 808 | err = __netpoll_setup(np, port->dev, gfp); |
| 808 | if (err) { | 809 | if (err) { |
| 809 | kfree(np); | 810 | kfree(np); |
| 810 | return err; | 811 | return err; |
| @@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team) | |||
| 833 | } | 834 | } |
| 834 | 835 | ||
| 835 | #else | 836 | #else |
| 836 | static int team_port_enable_netpoll(struct team *team, struct team_port *port) | 837 | static int team_port_enable_netpoll(struct team *team, struct team_port *port, |
| 838 | gfp_t gfp) | ||
| 837 | { | 839 | { |
| 838 | return 0; | 840 | return 0; |
| 839 | } | 841 | } |
| @@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) | |||
| 913 | } | 915 | } |
| 914 | 916 | ||
| 915 | if (team_netpoll_info(team)) { | 917 | if (team_netpoll_info(team)) { |
| 916 | err = team_port_enable_netpoll(team, port); | 918 | err = team_port_enable_netpoll(team, port, GFP_KERNEL); |
| 917 | if (err) { | 919 | if (err) { |
| 918 | netdev_err(dev, "Failed to enable netpoll on device %s\n", | 920 | netdev_err(dev, "Failed to enable netpoll on device %s\n", |
| 919 | portname); | 921 | portname); |
| @@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(struct net_device *dev) | |||
| 1443 | } | 1445 | } |
| 1444 | 1446 | ||
| 1445 | static int team_netpoll_setup(struct net_device *dev, | 1447 | static int team_netpoll_setup(struct net_device *dev, |
| 1446 | struct netpoll_info *npifo) | 1448 | struct netpoll_info *npifo, gfp_t gfp) |
| 1447 | { | 1449 | { |
| 1448 | struct team *team = netdev_priv(dev); | 1450 | struct team *team = netdev_priv(dev); |
| 1449 | struct team_port *port; | 1451 | struct team_port *port; |
| @@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev, | |||
| 1451 | 1453 | ||
| 1452 | mutex_lock(&team->lock); | 1454 | mutex_lock(&team->lock); |
| 1453 | list_for_each_entry(port, &team->port_list, list) { | 1455 | list_for_each_entry(port, &team->port_list, list) { |
| 1454 | err = team_port_enable_netpoll(team, port); | 1456 | err = team_port_enable_netpoll(team, port, gfp); |
| 1455 | if (err) { | 1457 | if (err) { |
| 1456 | __team_netpoll_cleanup(team); | 1458 | __team_netpoll_cleanup(team); |
| 1457 | break; | 1459 | break; |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a9db4f33407f..3560d688161e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -953,7 +953,8 @@ struct net_device_ops { | |||
| 953 | #ifdef CONFIG_NET_POLL_CONTROLLER | 953 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 954 | void (*ndo_poll_controller)(struct net_device *dev); | 954 | void (*ndo_poll_controller)(struct net_device *dev); |
| 955 | int (*ndo_netpoll_setup)(struct net_device *dev, | 955 | int (*ndo_netpoll_setup)(struct net_device *dev, |
| 956 | struct netpoll_info *info); | 956 | struct netpoll_info *info, |
| 957 | gfp_t gfp); | ||
| 957 | void (*ndo_netpoll_cleanup)(struct net_device *dev); | 958 | void (*ndo_netpoll_cleanup)(struct net_device *dev); |
| 958 | #endif | 959 | #endif |
| 959 | int (*ndo_set_vf_mac)(struct net_device *dev, | 960 | int (*ndo_set_vf_mac)(struct net_device *dev, |
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 28f5389c924b..bf2d51eec0f3 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h | |||
| @@ -43,7 +43,7 @@ struct netpoll_info { | |||
| 43 | void netpoll_send_udp(struct netpoll *np, const char *msg, int len); | 43 | void netpoll_send_udp(struct netpoll *np, const char *msg, int len); |
| 44 | void netpoll_print_options(struct netpoll *np); | 44 | void netpoll_print_options(struct netpoll *np); |
| 45 | int netpoll_parse_options(struct netpoll *np, char *opt); | 45 | int netpoll_parse_options(struct netpoll *np, char *opt); |
| 46 | int __netpoll_setup(struct netpoll *np, struct net_device *ndev); | 46 | int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp); |
| 47 | int netpoll_setup(struct netpoll *np); | 47 | int netpoll_setup(struct netpoll *np); |
| 48 | int netpoll_trap(void); | 48 | int netpoll_trap(void); |
| 49 | void netpoll_set_trap(int trap); | 49 | void netpoll_set_trap(int trap); |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 73a2a83ee2da..ee4ae0944cef 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -669,19 +669,20 @@ static void vlan_dev_poll_controller(struct net_device *dev) | |||
| 669 | return; | 669 | return; |
| 670 | } | 670 | } |
| 671 | 671 | ||
| 672 | static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) | 672 | static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, |
| 673 | gfp_t gfp) | ||
| 673 | { | 674 | { |
| 674 | struct vlan_dev_priv *info = vlan_dev_priv(dev); | 675 | struct vlan_dev_priv *info = vlan_dev_priv(dev); |
| 675 | struct net_device *real_dev = info->real_dev; | 676 | struct net_device *real_dev = info->real_dev; |
| 676 | struct netpoll *netpoll; | 677 | struct netpoll *netpoll; |
| 677 | int err = 0; | 678 | int err = 0; |
| 678 | 679 | ||
| 679 | netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); | 680 | netpoll = kzalloc(sizeof(*netpoll), gfp); |
| 680 | err = -ENOMEM; | 681 | err = -ENOMEM; |
| 681 | if (!netpoll) | 682 | if (!netpoll) |
| 682 | goto out; | 683 | goto out; |
| 683 | 684 | ||
| 684 | err = __netpoll_setup(netpoll, real_dev); | 685 | err = __netpoll_setup(netpoll, real_dev, gfp); |
| 685 | if (err) { | 686 | if (err) { |
| 686 | kfree(netpoll); | 687 | kfree(netpoll); |
| 687 | goto out; | 688 | goto out; |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 333484537600..ed0e0f9dc788 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -213,7 +213,8 @@ static void br_netpoll_cleanup(struct net_device *dev) | |||
| 213 | } | 213 | } |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) | 216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, |
| 217 | gfp_t gfp) | ||
| 217 | { | 218 | { |
| 218 | struct net_bridge *br = netdev_priv(dev); | 219 | struct net_bridge *br = netdev_priv(dev); |
| 219 | struct net_bridge_port *p, *n; | 220 | struct net_bridge_port *p, *n; |
| @@ -222,8 +223,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) | |||
| 222 | |||
