Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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;
+9 −7
Original line number Diff line number Diff line
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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);
+4 −3
Original line number Diff line number Diff line
@@ -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;
Loading