diff options
Diffstat (limited to 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/devmap.c | 31 | 
1 files changed, 31 insertions, 0 deletions
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index c0a48f336997..3867864cdc2f 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -719,6 +719,32 @@ const struct bpf_map_ops dev_map_hash_ops = {  	.map_check_btf = map_check_no_btf,  }; +static void dev_map_hash_remove_netdev(struct bpf_dtab *dtab, +				       struct net_device *netdev) +{ +	unsigned long flags; +	u32 i; + +	spin_lock_irqsave(&dtab->index_lock, flags); +	for (i = 0; i < dtab->n_buckets; i++) { +		struct bpf_dtab_netdev *dev; +		struct hlist_head *head; +		struct hlist_node *next; + +		head = dev_map_index_hash(dtab, i); + +		hlist_for_each_entry_safe(dev, next, head, index_hlist) { +			if (netdev != dev->dev) +				continue; + +			dtab->items--; +			hlist_del_rcu(&dev->index_hlist); +			call_rcu(&dev->rcu, __dev_map_entry_free); +		} +	} +	spin_unlock_irqrestore(&dtab->index_lock, flags); +} +  static int dev_map_notification(struct notifier_block *notifier,  				ulong event, void *ptr)  { @@ -735,6 +761,11 @@ static int dev_map_notification(struct notifier_block *notifier,  		 */  		rcu_read_lock();  		list_for_each_entry_rcu(dtab, &dev_map_list, list) { +			if (dtab->map.map_type == BPF_MAP_TYPE_DEVMAP_HASH) { +				dev_map_hash_remove_netdev(dtab, netdev); +				continue; +			} +  			for (i = 0; i < dtab->map.max_entries; i++) {  				struct bpf_dtab_netdev *dev, *odev;  | 

