Skip to content

Commit 1b23cdb

Browse files
committed
net: protect netdev->napi_list with netdev_lock()
Hold netdev->lock when NAPIs are getting added or removed. This will allow safe access to NAPI instances of a net_device without rtnl_lock. Create a family of helpers which assume the lock is already taken. Switch iavf to them, as it makes extensive use of netdev->lock, already. Reviewed-by: Joe Damato <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Reviewed-by: Kuniyuki Iwashima <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 5112457 commit 1b23cdb

File tree

3 files changed

+60
-15
lines changed

3 files changed

+60
-15
lines changed

drivers/net/ethernet/intel/iavf/iavf_main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,8 +1800,8 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter)
18001800
q_vector->v_idx = q_idx;
18011801
q_vector->reg_idx = q_idx;
18021802
cpumask_copy(&q_vector->affinity_mask, cpu_possible_mask);
1803-
netif_napi_add(adapter->netdev, &q_vector->napi,
1804-
iavf_napi_poll);
1803+
netif_napi_add_locked(adapter->netdev, &q_vector->napi,
1804+
iavf_napi_poll);
18051805
}
18061806

18071807
return 0;
@@ -1827,7 +1827,7 @@ static void iavf_free_q_vectors(struct iavf_adapter *adapter)
18271827
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
18281828
struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
18291829

1830-
netif_napi_del(&q_vector->napi);
1830+
netif_napi_del_locked(&q_vector->napi);
18311831
}
18321832
kfree(adapter->q_vectors);
18331833
adapter->q_vectors = NULL;

include/linux/netdevice.h

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,7 +2456,7 @@ struct net_device {
24562456
* Drivers are free to use it for other protection.
24572457
*
24582458
* Protects:
2459-
* @net_shaper_hierarchy, @reg_state
2459+
* @napi_list, @net_shaper_hierarchy, @reg_state
24602460
*
24612461
* Partially protects (writers must hold both @lock and rtnl_lock):
24622462
* @up
@@ -2712,8 +2712,19 @@ static inline void netif_napi_set_irq(struct napi_struct *napi, int irq)
27122712
*/
27132713
#define NAPI_POLL_WEIGHT 64
27142714

2715-
void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
2716-
int (*poll)(struct napi_struct *, int), int weight);
2715+
void netif_napi_add_weight_locked(struct net_device *dev,
2716+
struct napi_struct *napi,
2717+
int (*poll)(struct napi_struct *, int),
2718+
int weight);
2719+
2720+
static inline void
2721+
netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
2722+
int (*poll)(struct napi_struct *, int), int weight)
2723+
{
2724+
netdev_lock(dev);
2725+
netif_napi_add_weight_locked(dev, napi, poll, weight);
2726+
netdev_unlock(dev);
2727+
}
27172728

27182729
/**
27192730
* netif_napi_add() - initialize a NAPI context
@@ -2731,6 +2742,13 @@ netif_napi_add(struct net_device *dev, struct napi_struct *napi,
27312742
netif_napi_add_weight(dev, napi, poll, NAPI_POLL_WEIGHT);
27322743
}
27332744

2745+
static inline void
2746+
netif_napi_add_locked(struct net_device *dev, struct napi_struct *napi,
2747+
int (*poll)(struct napi_struct *, int))
2748+
{
2749+
netif_napi_add_weight_locked(dev, napi, poll, NAPI_POLL_WEIGHT);
2750+
}
2751+
27342752
static inline void
27352753
netif_napi_add_tx_weight(struct net_device *dev,
27362754
struct napi_struct *napi,
@@ -2741,6 +2759,15 @@ netif_napi_add_tx_weight(struct net_device *dev,
27412759
netif_napi_add_weight(dev, napi, poll, weight);
27422760
}
27432761

2762+
static inline void
2763+
netif_napi_add_config_locked(struct net_device *dev, struct napi_struct *napi,
2764+
int (*poll)(struct napi_struct *, int), int index)
2765+
{
2766+
napi->index = index;
2767+
napi->config = &dev->napi_config[index];
2768+
netif_napi_add_weight_locked(dev, napi, poll, NAPI_POLL_WEIGHT);
2769+
}
2770+
27442771
/**
27452772
* netif_napi_add_config - initialize a NAPI context with persistent config
27462773
* @dev: network device
@@ -2752,9 +2779,9 @@ static inline void
27522779
netif_napi_add_config(struct net_device *dev, struct napi_struct *napi,
27532780
int (*poll)(struct napi_struct *, int), int index)
27542781
{
2755-
napi->index = index;
2756-
napi->config = &dev->napi_config[index];
2757-
netif_napi_add_weight(dev, napi, poll, NAPI_POLL_WEIGHT);
2782+
netdev_lock(dev);
2783+
netif_napi_add_config_locked(dev, napi, poll, index);
2784+
netdev_unlock(dev);
27582785
}
27592786

27602787
/**
@@ -2774,6 +2801,8 @@ static inline void netif_napi_add_tx(struct net_device *dev,
27742801
netif_napi_add_tx_weight(dev, napi, poll, NAPI_POLL_WEIGHT);
27752802
}
27762803

2804+
void __netif_napi_del_locked(struct napi_struct *napi);
2805+
27772806
/**
27782807
* __netif_napi_del - remove a NAPI context
27792808
* @napi: NAPI context
@@ -2782,7 +2811,18 @@ static inline void netif_napi_add_tx(struct net_device *dev,
27822811
* containing @napi. Drivers might want to call this helper to combine
27832812
* all the needed RCU grace periods into a single one.
27842813
*/
2785-
void __netif_napi_del(struct napi_struct *napi);
2814+
static inline void __netif_napi_del(struct napi_struct *napi)
2815+
{
2816+
netdev_lock(napi->dev);
2817+
__netif_napi_del_locked(napi);
2818+
netdev_unlock(napi->dev);
2819+
}
2820+
2821+
static inline void netif_napi_del_locked(struct napi_struct *napi)
2822+
{
2823+
__netif_napi_del_locked(napi);
2824+
synchronize_net();
2825+
}
27862826

27872827
/**
27882828
* netif_napi_del - remove a NAPI context

net/core/dev.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6910,9 +6910,12 @@ netif_napi_dev_list_add(struct net_device *dev, struct napi_struct *napi)
69106910
list_add_rcu(&napi->dev_list, higher); /* adds after higher */
69116911
}
69126912

6913-
void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
6914-
int (*poll)(struct napi_struct *, int), int weight)
6913+
void netif_napi_add_weight_locked(struct net_device *dev,
6914+
struct napi_struct *napi,
6915+
int (*poll)(struct napi_struct *, int),
6916+
int weight)
69156917
{
6918+
netdev_assert_locked(dev);
69166919
if (WARN_ON(test_and_set_bit(NAPI_STATE_LISTED, &napi->state)))
69176920
return;
69186921

@@ -6953,7 +6956,7 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
69536956
dev->threaded = false;
69546957
netif_napi_set_irq(napi, -1);
69556958
}
6956-
EXPORT_SYMBOL(netif_napi_add_weight);
6959+
EXPORT_SYMBOL(netif_napi_add_weight_locked);
69576960

69586961
void napi_disable(struct napi_struct *n)
69596962
{
@@ -7024,8 +7027,10 @@ static void flush_gro_hash(struct napi_struct *napi)
70247027
}
70257028

70267029
/* Must be called in process context */
7027-
void __netif_napi_del(struct napi_struct *napi)
7030+
void __netif_napi_del_locked(struct napi_struct *napi)
70287031
{
7032+
netdev_assert_locked(napi->dev);
7033+
70297034
if (!test_and_clear_bit(NAPI_STATE_LISTED, &napi->state))
70307035
return;
70317036

@@ -7045,7 +7050,7 @@ void __netif_napi_del(struct napi_struct *napi)
70457050
napi->thread = NULL;
70467051
}
70477052
}
7048-
EXPORT_SYMBOL(__netif_napi_del);
7053+
EXPORT_SYMBOL(__netif_napi_del_locked);
70497054

70507055
static int __napi_poll(struct napi_struct *n, bool *repoll)
70517056
{

0 commit comments

Comments
 (0)