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>
This commit is contained in:
parent
ddf343f635
commit
47be03a28c
|
@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave)
|
|||
struct netpoll *np;
|
||||
int err = 0;
|
||||
|
||||
np = kzalloc(sizeof(*np), GFP_KERNEL);
|
||||
np = kzalloc(sizeof(*np), GFP_ATOMIC);
|
||||
err = -ENOMEM;
|
||||
if (!np)
|
||||
goto out;
|
||||
|
||||
err = __netpoll_setup(np, slave->dev);
|
||||
err = __netpoll_setup(np, slave->dev, GFP_ATOMIC);
|
||||
if (err) {
|
||||
kfree(np);
|
||||
goto out;
|
||||
|
@ -1292,7 +1292,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
|
|||
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 slave *slave;
|
||||
|
|
|
@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port)
|
|||
}
|
||||
|
||||
#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;
|
||||
int err;
|
||||
|
||||
np = kzalloc(sizeof(*np), GFP_KERNEL);
|
||||
np = kzalloc(sizeof(*np), gfp);
|
||||
if (!np)
|
||||
return -ENOMEM;
|
||||
|
||||
err = __netpoll_setup(np, port->dev);
|
||||
err = __netpoll_setup(np, port->dev, gfp);
|
||||
if (err) {
|
||||
kfree(np);
|
||||
return err;
|
||||
|
@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team)
|
|||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
|
|||
}
|
||||
|
||||
if (team_netpoll_info(team)) {
|
||||
err = team_port_enable_netpoll(team, port);
|
||||
err = team_port_enable_netpoll(team, port, GFP_KERNEL);
|
||||
if (err) {
|
||||
netdev_err(dev, "Failed to enable netpoll on device %s\n",
|
||||
portname);
|
||||
|
@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(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_port *port;
|
||||
|
@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev,
|
|||
|
||||
mutex_lock(&team->lock);
|
||||
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) {
|
||||
__team_netpoll_cleanup(team);
|
||||
break;
|
||||
|
|
|
@ -953,7 +953,8 @@ struct net_device_ops {
|
|||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
void (*ndo_poll_controller)(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);
|
||||
#endif
|
||||
int (*ndo_set_vf_mac)(struct net_device *dev,
|
||||
|
|
|
@ -43,7 +43,7 @@ struct netpoll_info {
|
|||
void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
|
||||
void netpoll_print_options(struct netpoll *np);
|
||||
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_trap(void);
|
||||
void netpoll_set_trap(int trap);
|
||||
|
|
|
@ -669,19 +669,20 @@ static void vlan_dev_poll_controller(struct net_device *dev)
|
|||
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 net_device *real_dev = info->real_dev;
|
||||
struct netpoll *netpoll;
|
||||
int err = 0;
|
||||
|
||||
netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL);
|
||||
netpoll = kzalloc(sizeof(*netpoll), gfp);
|
||||
err = -ENOMEM;
|
||||
if (!netpoll)
|
||||
goto out;
|
||||
|
||||
err = __netpoll_setup(netpoll, real_dev);
|
||||
err = __netpoll_setup(netpoll, real_dev, gfp);
|
||||
if (err) {
|
||||
kfree(netpoll);
|
||||
goto out;
|
||||
|
|
|
@ -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_port *p, *n;
|
||||
|
@ -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) {
|
||||
if (!p->dev)
|
||||
continue;
|
||||
|
||||
err = br_netpoll_enable(p);
|
||||
err = br_netpoll_enable(p, gfp);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -236,17 +236,17 @@ fail:
|
|||
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;
|
||||
int err = 0;
|
||||
|
||||
np = kzalloc(sizeof(*p->np), GFP_KERNEL);
|
||||
np = kzalloc(sizeof(*p->np), gfp);
|
||||
err = -ENOMEM;
|
||||
if (!np)
|
||||
goto out;
|
||||
|
||||
err = __netpoll_setup(np, p->dev);
|
||||
err = __netpoll_setup(np, p->dev, gfp);
|
||||
if (err) {
|
||||
kfree(np);
|
||||
goto out;
|
||||
|
|
|
@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
|||
if (err)
|
||||
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;
|
||||
|
||||
err = netdev_set_master(dev, br->dev);
|
||||
|
|
|
@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p,
|
|||
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);
|
||||
#else
|
||||
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,
|
|||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -715,7 +715,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
|
|||
}
|
||||
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;
|
||||
const struct net_device_ops *ops;
|
||||
|
@ -734,7 +734,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
|
|||
}
|
||||
|
||||
if (!ndev->npinfo) {
|
||||
npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
|
||||
npinfo = kmalloc(sizeof(*npinfo), gfp);
|
||||
if (!npinfo) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -752,7 +752,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
|
|||
|
||||
ops = np->dev->netdev_ops;
|
||||
if (ops->ndo_netpoll_setup) {
|
||||
err = ops->ndo_netpoll_setup(ndev, npinfo);
|
||||
err = ops->ndo_netpoll_setup(ndev, npinfo, gfp);
|
||||
if (err)
|
||||
goto free_npinfo;
|
||||
}
|
||||
|
@ -857,7 +857,7 @@ int netpoll_setup(struct netpoll *np)
|
|||
refill_skbs();
|
||||
|
||||
rtnl_lock();
|
||||
err = __netpoll_setup(np, ndev);
|
||||
err = __netpoll_setup(np, ndev, GFP_KERNEL);
|
||||
rtnl_unlock();
|
||||
|
||||
if (err)
|
||||
|
|
Loading…
Reference in New Issue