forked from mirrors/linux
		
	rtnetlink: Add assertion helpers for per-netns RTNL.
Once an RTNL scope is converted with rtnl_net_lock(), we will replace RTNL helper functions inside the scope with the following per-netns alternatives: ASSERT_RTNL() -> ASSERT_RTNL_NET(net) rcu_dereference_rtnl(p) -> rcu_dereference_rtnl_net(net, p) Note that the per-netns helpers are equivalent to the conventional helpers unless CONFIG_DEBUG_NET_SMALL_RTNL is enabled. Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
		
							parent
							
								
									76aed95319
								
							
						
					
					
						commit
						844e5e7e65
					
				
					 2 changed files with 53 additions and 4 deletions
				
			
		| 
						 | 
					@ -51,6 +51,10 @@ extern atomic_t dev_unreg_count;
 | 
				
			||||||
extern struct rw_semaphore pernet_ops_rwsem;
 | 
					extern struct rw_semaphore pernet_ops_rwsem;
 | 
				
			||||||
extern struct rw_semaphore net_rwsem;
 | 
					extern struct rw_semaphore net_rwsem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ASSERT_RTNL() \
 | 
				
			||||||
 | 
						WARN_ONCE(!rtnl_is_locked(), \
 | 
				
			||||||
 | 
							  "RTNL: assertion failed at %s (%d)\n", __FILE__,  __LINE__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_PROVE_LOCKING
 | 
					#ifdef CONFIG_PROVE_LOCKING
 | 
				
			||||||
extern bool lockdep_rtnl_is_held(void);
 | 
					extern bool lockdep_rtnl_is_held(void);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -98,6 +102,22 @@ void __rtnl_net_unlock(struct net *net);
 | 
				
			||||||
void rtnl_net_lock(struct net *net);
 | 
					void rtnl_net_lock(struct net *net);
 | 
				
			||||||
void rtnl_net_unlock(struct net *net);
 | 
					void rtnl_net_unlock(struct net *net);
 | 
				
			||||||
int rtnl_net_lock_cmp_fn(const struct lockdep_map *a, const struct lockdep_map *b);
 | 
					int rtnl_net_lock_cmp_fn(const struct lockdep_map *a, const struct lockdep_map *b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool rtnl_net_is_locked(struct net *net);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ASSERT_RTNL_NET(net)						\
 | 
				
			||||||
 | 
						WARN_ONCE(!rtnl_net_is_locked(net),				\
 | 
				
			||||||
 | 
							  "RTNL_NET: assertion failed at %s (%d)\n",		\
 | 
				
			||||||
 | 
							  __FILE__,  __LINE__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool lockdep_rtnl_net_is_held(struct net *net);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define rcu_dereference_rtnl_net(net, p)				\
 | 
				
			||||||
 | 
						rcu_dereference_check(p, lockdep_rtnl_net_is_held(net))
 | 
				
			||||||
 | 
					#define rtnl_net_dereference(net, p)					\
 | 
				
			||||||
 | 
						rcu_dereference_protected(p, lockdep_rtnl_net_is_held(net))
 | 
				
			||||||
 | 
					#define rcu_replace_pointer_rtnl_net(net, rp, p)			\
 | 
				
			||||||
 | 
						rcu_replace_pointer(rp, p, lockdep_rtnl_net_is_held(net))
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline void __rtnl_net_lock(struct net *net) {}
 | 
					static inline void __rtnl_net_lock(struct net *net) {}
 | 
				
			||||||
static inline void __rtnl_net_unlock(struct net *net) {}
 | 
					static inline void __rtnl_net_unlock(struct net *net) {}
 | 
				
			||||||
| 
						 | 
					@ -111,6 +131,27 @@ static inline void rtnl_net_unlock(struct net *net)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	rtnl_unlock();
 | 
						rtnl_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void ASSERT_RTNL_NET(struct net *net)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ASSERT_RTNL();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void *rcu_dereference_rtnl_net(struct net *net, void *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return rcu_dereference_rtnl(p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void *rtnl_net_dereference(struct net *net, void *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return rtnl_dereference(p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void *rcu_replace_pointer_rtnl_net(struct net *net,
 | 
				
			||||||
 | 
											 void *rp, void *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return rcu_replace_pointer_rtnl(rp, p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct netdev_queue *dev_ingress_queue(struct net_device *dev)
 | 
					static inline struct netdev_queue *dev_ingress_queue(struct net_device *dev)
 | 
				
			||||||
| 
						 | 
					@ -140,10 +181,6 @@ void rtnetlink_init(void);
 | 
				
			||||||
void __rtnl_unlock(void);
 | 
					void __rtnl_unlock(void);
 | 
				
			||||||
void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail);
 | 
					void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ASSERT_RTNL() \
 | 
					 | 
				
			||||||
	WARN_ONCE(!rtnl_is_locked(), \
 | 
					 | 
				
			||||||
		  "RTNL: assertion failed at %s (%d)\n", __FILE__,  __LINE__)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
 | 
					extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
 | 
				
			||||||
			     struct netlink_callback *cb,
 | 
								     struct netlink_callback *cb,
 | 
				
			||||||
			     struct net_device *dev,
 | 
								     struct net_device *dev,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -235,6 +235,18 @@ int rtnl_net_lock_cmp_fn(const struct lockdep_map *a, const struct lockdep_map *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rtnl_net_cmp_locks(net_a, net_b);
 | 
						return rtnl_net_cmp_locks(net_a, net_b);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool rtnl_net_is_locked(struct net *net)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return rtnl_is_locked() && mutex_is_locked(&net->rtnl_mutex);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(rtnl_net_is_locked);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool lockdep_rtnl_net_is_held(struct net *net)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return lockdep_rtnl_is_held() && lockdep_is_held(&net->rtnl_mutex);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(lockdep_rtnl_net_is_held);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct rtnl_link __rcu *__rcu *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1];
 | 
					static struct rtnl_link __rcu *__rcu *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue