Commit 47be03a2 authored by Amerigo Wang's avatar Amerigo Wang Committed by David S. Miller

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: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarCong Wang <amwang@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ddf343f6
...@@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave) ...@@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave)
struct netpoll *np; struct netpoll *np;
int err = 0; int err = 0;
np = kzalloc(sizeof(*np), GFP_KERNEL); np = kzalloc(sizeof(*np), GFP_ATOMIC);
err = -ENOMEM; err = -ENOMEM;
if (!np) if (!np)
goto out; goto out;
err = __netpoll_setup(np, slave->dev); err = __netpoll_setup(np, slave->dev, GFP_ATOMIC);
if (err) { if (err) {
kfree(np); kfree(np);
goto out; goto out;
...@@ -1292,7 +1292,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) ...@@ -1292,7 +1292,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
read_unlock(&bond->lock); read_unlock(&bond->lock);
} }
static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp)
{ {
struct bonding *bond = netdev_priv(dev); struct bonding *bond = netdev_priv(dev);
struct slave *slave; struct slave *slave;
......
...@@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port) ...@@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port)
} }
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static int team_port_enable_netpoll(struct team *team, struct team_port *port) static int team_port_enable_netpoll(struct team *team, struct team_port *port,
gfp_t gfp)
{ {
struct netpoll *np; struct netpoll *np;
int err; int err;
np = kzalloc(sizeof(*np), GFP_KERNEL); np = kzalloc(sizeof(*np), gfp);
if (!np) if (!np)
return -ENOMEM; return -ENOMEM;
err = __netpoll_setup(np, port->dev); err = __netpoll_setup(np, port->dev, gfp);
if (err) { if (err) {
kfree(np); kfree(np);
return err; return err;
...@@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team) ...@@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team)
} }
#else #else
static int team_port_enable_netpoll(struct team *team, struct team_port *port) static int team_port_enable_netpoll(struct team *team, struct team_port *port,
gfp_t gfp)
{ {
return 0; return 0;
} }
...@@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) ...@@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
} }
if (team_netpoll_info(team)) { if (team_netpoll_info(team)) {
err = team_port_enable_netpoll(team, port); err = team_port_enable_netpoll(team, port, GFP_KERNEL);
if (err) { if (err) {
netdev_err(dev, "Failed to enable netpoll on device %s\n", netdev_err(dev, "Failed to enable netpoll on device %s\n",
portname); portname);
...@@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(struct net_device *dev) ...@@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(struct net_device *dev)
} }
static int team_netpoll_setup(struct net_device *dev, static int team_netpoll_setup(struct net_device *dev,
struct netpoll_info *npifo) struct netpoll_info *npifo, gfp_t gfp)
{ {
struct team *team = netdev_priv(dev); struct team *team = netdev_priv(dev);
struct team_port *port; struct team_port *port;
...@@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev, ...@@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev,
mutex_lock(&team->lock); mutex_lock(&team->lock);
list_for_each_entry(port, &team->port_list, list) { list_for_each_entry(port, &team->port_list, list) {
err = team_port_enable_netpoll(team, port); err = team_port_enable_netpoll(team, port, gfp);
if (err) { if (err) {
__team_netpoll_cleanup(team); __team_netpoll_cleanup(team);
break; break;
......
...@@ -953,7 +953,8 @@ struct net_device_ops { ...@@ -953,7 +953,8 @@ struct net_device_ops {
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
void (*ndo_poll_controller)(struct net_device *dev); void (*ndo_poll_controller)(struct net_device *dev);
int (*ndo_netpoll_setup)(struct net_device *dev, int (*ndo_netpoll_setup)(struct net_device *dev,
struct netpoll_info *info); struct netpoll_info *info,
gfp_t gfp);
void (*ndo_netpoll_cleanup)(struct net_device *dev); void (*ndo_netpoll_cleanup)(struct net_device *dev);
#endif #endif
int (*ndo_set_vf_mac)(struct net_device *dev, int (*ndo_set_vf_mac)(struct net_device *dev,
......
...@@ -43,7 +43,7 @@ struct netpoll_info { ...@@ -43,7 +43,7 @@ struct netpoll_info {
void netpoll_send_udp(struct netpoll *np, const char *msg, int len); void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
void netpoll_print_options(struct netpoll *np); void netpoll_print_options(struct netpoll *np);
int netpoll_parse_options(struct netpoll *np, char *opt); int netpoll_parse_options(struct netpoll *np, char *opt);
int __netpoll_setup(struct netpoll *np, struct net_device *ndev); int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp);
int netpoll_setup(struct netpoll *np); int netpoll_setup(struct netpoll *np);
int netpoll_trap(void); int netpoll_trap(void);
void netpoll_set_trap(int trap); void netpoll_set_trap(int trap);
......
...@@ -669,19 +669,20 @@ static void vlan_dev_poll_controller(struct net_device *dev) ...@@ -669,19 +669,20 @@ static void vlan_dev_poll_controller(struct net_device *dev)
return; return;
} }
static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo,
gfp_t gfp)
{ {
struct vlan_dev_priv *info = vlan_dev_priv(dev); struct vlan_dev_priv *info = vlan_dev_priv(dev);
struct net_device *real_dev = info->real_dev; struct net_device *real_dev = info->real_dev;
struct netpoll *netpoll; struct netpoll *netpoll;
int err = 0; int err = 0;
netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); netpoll = kzalloc(sizeof(*netpoll), gfp);
err = -ENOMEM; err = -ENOMEM;
if (!netpoll) if (!netpoll)
goto out; goto out;
err = __netpoll_setup(netpoll, real_dev); err = __netpoll_setup(netpoll, real_dev, gfp);
if (err) { if (err) {
kfree(netpoll); kfree(netpoll);
goto out; goto out;
......
...@@ -213,7 +213,8 @@ static void br_netpoll_cleanup(struct net_device *dev) ...@@ -213,7 +213,8 @@ static void br_netpoll_cleanup(struct net_device *dev)
} }
} }
static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
gfp_t gfp)
{ {
struct net_bridge *br = netdev_priv(dev); struct net_bridge *br = netdev_priv(dev);
struct net_bridge_port *p, *n; struct net_bridge_port *p, *n;
...@@ -222,8 +223,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) ...@@ -222,8 +223,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
list_for_each_entry_safe(p, n, &br->port_list, list) { list_for_each_entry_safe(p, n, &br->port_list, list) {
if (!p->dev) if (!p->dev)
continue; continue;
err = br_netpoll_enable(p, gfp);
err = br_netpoll_enable(p);
if (err) if (err)
goto fail; goto fail;
} }
...@@ -236,17 +236,17 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) ...@@ -236,17 +236,17 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
goto out; goto out;
} }
int br_netpoll_enable(struct net_bridge_port *p) int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
{ {
struct netpoll *np; struct netpoll *np;
int err = 0; int err = 0;
np = kzalloc(sizeof(*p->np), GFP_KERNEL); np = kzalloc(sizeof(*p->np), gfp);
err = -ENOMEM; err = -ENOMEM;
if (!np) if (!np)
goto out; goto out;
err = __netpoll_setup(np, p->dev); err = __netpoll_setup(np, p->dev, gfp);
if (err) { if (err) {
kfree(np); kfree(np);
goto out; goto out;
......
...@@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (err) if (err)
goto err2; goto err2;
if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL))))
goto err3; goto err3;
err = netdev_set_master(dev, br->dev); err = netdev_set_master(dev, br->dev);
......
...@@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, ...@@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
netpoll_send_skb(np, skb); netpoll_send_skb(np, skb);
} }
extern int br_netpoll_enable(struct net_bridge_port *p); extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp);
extern void br_netpoll_disable(struct net_bridge_port *p); extern void br_netpoll_disable(struct net_bridge_port *p);
#else #else
static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br)
...@@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, ...@@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
{ {
} }
static inline int br_netpoll_enable(struct net_bridge_port *p) static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
{ {
return 0; return 0;
} }
......
...@@ -715,7 +715,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) ...@@ -715,7 +715,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
} }
EXPORT_SYMBOL(netpoll_parse_options); EXPORT_SYMBOL(netpoll_parse_options);
int __netpoll_setup(struct netpoll *np, struct net_device *ndev) int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
{ {
struct netpoll_info *npinfo; struct netpoll_info *npinfo;
const struct net_device_ops *ops; const struct net_device_ops *ops;
...@@ -734,7 +734,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev) ...@@ -734,7 +734,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
} }
if (!ndev->npinfo) { if (!ndev->npinfo) {
npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); npinfo = kmalloc(sizeof(*npinfo), gfp);
if (!npinfo) { if (!npinfo) {
err = -ENOMEM; err = -ENOMEM;
goto out; goto out;
...@@ -752,7 +752,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev) ...@@ -752,7 +752,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
ops = np->dev->netdev_ops; ops = np->dev->netdev_ops;
if (ops->ndo_netpoll_setup) { if (ops->ndo_netpoll_setup) {
err = ops->ndo_netpoll_setup(ndev, npinfo); err = ops->ndo_netpoll_setup(ndev, npinfo, gfp);
if (err) if (err)
goto free_npinfo; goto free_npinfo;
} }
...@@ -857,7 +857,7 @@ int netpoll_setup(struct netpoll *np) ...@@ -857,7 +857,7 @@ int netpoll_setup(struct netpoll *np)
refill_skbs(); refill_skbs();
rtnl_lock(); rtnl_lock();
err = __netpoll_setup(np, ndev); err = __netpoll_setup(np, ndev, GFP_KERNEL);
rtnl_unlock(); rtnl_unlock();
if (err) if (err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment