Message ID | 20250207210248.qy4i5Wkl@linutronix.de (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next] xfrm: Use rcuref_t for xfrm_state' reference counting. | expand |
Hi Sebastian, kernel test robot noticed the following build warnings: [auto build test WARNING on net-next/main] url: https://github.com/intel-lab-lkp/linux/commits/Sebastian-Andrzej-Siewior/xfrm-Use-rcuref_t-for-xfrm_state-reference-counting/20250208-050716 base: net-next/main patch link: https://lore.kernel.org/r/20250207210248.qy4i5Wkl%40linutronix.de patch subject: [PATCH net-next] xfrm: Use rcuref_t for xfrm_state' reference counting. config: i386-randconfig-r122-20250209 (https://download.01.org/0day-ci/archive/20250209/202502090827.R1HaLYSt-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250209/202502090827.R1HaLYSt-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202502090827.R1HaLYSt-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) net/xfrm/xfrm_state.c:1866:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1866:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1866:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1866:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1866:17: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct hlist_head *h @@ got struct hlist_head [noderef] __rcu * @@ net/xfrm/xfrm_state.c:1866:17: sparse: expected struct hlist_head *h net/xfrm/xfrm_state.c:1866:17: sparse: got struct hlist_head [noderef] __rcu * net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:1869:17: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct hlist_head *h @@ got struct hlist_head [noderef] __rcu * @@ net/xfrm/xfrm_state.c:1869:17: sparse: expected struct hlist_head *h net/xfrm/xfrm_state.c:1869:17: sparse: got struct hlist_head [noderef] __rcu * net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2479:9: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: cast removes address space '__rcu' of expression net/xfrm/xfrm_state.c:2593:17: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct hlist_head *h @@ got struct hlist_head [noderef] __rcu * @@ net/xfrm/xfrm_state.c:2593:17: sparse: expected struct hlist_head *h net/xfrm/xfrm_state.c:2593:17: sparse: got struct hlist_head [noderef] __rcu * net/xfrm/xfrm_state.c:3253:31: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct hlist_head [noderef] __rcu *state_bydst @@ got struct hlist_head * @@ net/xfrm/xfrm_state.c:3253:31: sparse: expected struct hlist_head [noderef] __rcu *state_bydst net/xfrm/xfrm_state.c:3253:31: sparse: got struct hlist_head * net/xfrm/xfrm_state.c:3256:31: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct hlist_head [noderef] __rcu *state_bysrc @@ got struct hlist_head * @@ net/xfrm/xfrm_state.c:3256:31: sparse: expected struct hlist_head [noderef] __rcu *state_bysrc net/xfrm/xfrm_state.c:3256:31: sparse: got struct hlist_head * net/xfrm/xfrm_state.c:3259:31: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct hlist_head [noderef] __rcu *state_byspi @@ got struct hlist_head * @@ net/xfrm/xfrm_state.c:3259:31: sparse: expected struct hlist_head [noderef] __rcu *state_byspi net/xfrm/xfrm_state.c:3259:31: sparse: got struct hlist_head * net/xfrm/xfrm_state.c:3262:31: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct hlist_head [noderef] __rcu *state_byseq @@ got struct hlist_head * @@ net/xfrm/xfrm_state.c:3262:31: sparse: expected struct hlist_head [noderef] __rcu *state_byseq net/xfrm/xfrm_state.c:3262:31: sparse: got struct hlist_head * net/xfrm/xfrm_state.c:3280:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_byseq @@ net/xfrm/xfrm_state.c:3280:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3280:33: sparse: got struct hlist_head [noderef] __rcu *state_byseq net/xfrm/xfrm_state.c:3282:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_byspi @@ net/xfrm/xfrm_state.c:3282:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3282:33: sparse: got struct hlist_head [noderef] __rcu *state_byspi net/xfrm/xfrm_state.c:3284:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_bysrc @@ net/xfrm/xfrm_state.c:3284:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3284:33: sparse: got struct hlist_head [noderef] __rcu *state_bysrc net/xfrm/xfrm_state.c:3286:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_bydst @@ net/xfrm/xfrm_state.c:3286:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3286:33: sparse: got struct hlist_head [noderef] __rcu *state_bydst net/xfrm/xfrm_state.c:3302:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head const *h @@ got struct hlist_head [noderef] __rcu *state_byseq @@ net/xfrm/xfrm_state.c:3302:9: sparse: expected struct hlist_head const *h net/xfrm/xfrm_state.c:3302:9: sparse: got struct hlist_head [noderef] __rcu *state_byseq net/xfrm/xfrm_state.c:3303:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_byseq @@ net/xfrm/xfrm_state.c:3303:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3303:33: sparse: got struct hlist_head [noderef] __rcu *state_byseq net/xfrm/xfrm_state.c:3304:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head const *h @@ got struct hlist_head [noderef] __rcu *state_byspi @@ net/xfrm/xfrm_state.c:3304:9: sparse: expected struct hlist_head const *h net/xfrm/xfrm_state.c:3304:9: sparse: got struct hlist_head [noderef] __rcu *state_byspi net/xfrm/xfrm_state.c:3305:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_byspi @@ net/xfrm/xfrm_state.c:3305:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3305:33: sparse: got struct hlist_head [noderef] __rcu *state_byspi net/xfrm/xfrm_state.c:3306:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head const *h @@ got struct hlist_head [noderef] __rcu *state_bysrc @@ net/xfrm/xfrm_state.c:3306:9: sparse: expected struct hlist_head const *h net/xfrm/xfrm_state.c:3306:9: sparse: got struct hlist_head [noderef] __rcu *state_bysrc net/xfrm/xfrm_state.c:3307:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_bysrc @@ net/xfrm/xfrm_state.c:3307:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3307:33: sparse: got struct hlist_head [noderef] __rcu *state_bysrc net/xfrm/xfrm_state.c:3308:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head const *h @@ got struct hlist_head [noderef] __rcu *state_bydst @@ net/xfrm/xfrm_state.c:3308:9: sparse: expected struct hlist_head const *h net/xfrm/xfrm_state.c:3308:9: sparse: got struct hlist_head [noderef] __rcu *state_bydst net/xfrm/xfrm_state.c:3309:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct hlist_head *n @@ got struct hlist_head [noderef] __rcu *state_bydst @@ net/xfrm/xfrm_state.c:3309:33: sparse: expected struct hlist_head *n net/xfrm/xfrm_state.c:3309:33: sparse: got struct hlist_head [noderef] __rcu *state_bydst net/xfrm/xfrm_state.c: note: in included file (through include/linux/rbtree.h, include/linux/mm_types.h, include/linux/uio.h, ...): include/linux/rcupdate.h:880:25: sparse: sparse: context imbalance in 'xfrm_register_type' - unexpected unlock include/linux/rcupdate.h:880:25: sparse: sparse: context imbalance in 'xfrm_unregister_type' - unexpected unlock include/linux/rcupdate.h:880:25: sparse: sparse: context imbalance in 'xfrm_get_type' - unexpected unlock include/linux/rcupdate.h:880:25: sparse: sparse: context imbalance in 'xfrm_register_type_offload' - unexpected unlock include/linux/rcupdate.h:880:25: sparse: sparse: context imbalance in 'xfrm_unregister_type_offload' - unexpected unlock include/linux/rcupdate.h:880:25: sparse: sparse: context imbalance in 'xfrm_get_type_offload' - unexpected unlock net/xfrm/xfrm_state.c:942:17: sparse: sparse: dereference of noderef expression net/xfrm/xfrm_state.c:987:17: sparse: sparse: dereference of noderef expression >> net/xfrm/xfrm_state.c:58:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct rcuref_t [usertype] *ref @@ got struct rcuref_t [noderef] __rcu * @@ net/xfrm/xfrm_state.c:58:28: sparse: expected struct rcuref_t [usertype] *ref net/xfrm/xfrm_state.c:58:28: sparse: got struct rcuref_t [noderef] __rcu * >> net/xfrm/xfrm_state.c:58:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct rcuref_t [usertype] *ref @@ got struct rcuref_t [noderef] __rcu * @@ net/xfrm/xfrm_state.c:58:28: sparse: expected struct rcuref_t [usertype] *ref net/xfrm/xfrm_state.c:58:28: sparse: got struct rcuref_t [noderef] __rcu * >> net/xfrm/xfrm_state.c:58:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct rcuref_t [usertype] *ref @@ got struct rcuref_t [noderef] __rcu * @@ net/xfrm/xfrm_state.c:58:28: sparse: expected struct rcuref_t [usertype] *ref net/xfrm/xfrm_state.c:58:28: sparse: got struct rcuref_t [noderef] __rcu * >> net/xfrm/xfrm_state.c:58:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct rcuref_t [usertype] *ref @@ got struct rcuref_t [noderef] __rcu * @@ net/xfrm/xfrm_state.c:58:28: sparse: expected struct rcuref_t [usertype] *ref net/xfrm/xfrm_state.c:58:28: sparse: got struct rcuref_t [noderef] __rcu * >> net/xfrm/xfrm_state.c:58:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct rcuref_t [usertype] *ref @@ got struct rcuref_t [noderef] __rcu * @@ net/xfrm/xfrm_state.c:58:28: sparse: expected struct rcuref_t [usertype] *ref net/xfrm/xfrm_state.c:58:28: sparse: got struct rcuref_t [noderef] __rcu * net/xfrm/xfrm_state.c: note: in included file (through include/linux/smp.h, include/linux/alloc_tag.h, include/linux/percpu.h, ...): include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true net/xfrm/xfrm_state.c:1673:9: sparse: sparse: dereference of noderef expression include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true net/xfrm/xfrm_state.c:1773:9: sparse: sparse: dereference of noderef expression net/xfrm/xfrm_state.c:1809:9: sparse: sparse: dereference of noderef expression include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true net/xfrm/xfrm_state.c:2082:17: sparse: sparse: dereference of noderef expression net/xfrm/xfrm_state.c:2101:17: sparse: sparse: dereference of noderef expression net/xfrm/xfrm_state.c:2288:17: sparse: sparse: dereference of noderef expression include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true net/xfrm/xfrm_state.c: note: in included file: include/net/xfrm.h:1947:16: sparse: sparse: incompatible types in comparison expression (different address spaces): include/net/xfrm.h:1947:16: sparse: struct sock [noderef] __rcu * include/net/xfrm.h:1947:16: sparse: struct sock * vim +58 net/xfrm/xfrm_state.c 55 56 static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x) 57 { > 58 return rcuref_get(&x->ref); 59 } 60
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ed4b83696c77f..3da13b8a5afda 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -14,7 +14,7 @@ #include <linux/mutex.h> #include <linux/audit.h> #include <linux/slab.h> -#include <linux/refcount.h> +#include <linux/rcuref.h> #include <linux/sockptr.h> #include <net/sock.h> @@ -189,7 +189,7 @@ struct xfrm_state { struct hlist_node state_cache; struct hlist_node state_cache_input; - refcount_t refcnt; + rcuref_t ref; spinlock_t lock; u32 pcpu_num; @@ -901,24 +901,24 @@ void __xfrm_state_destroy(struct xfrm_state *, bool); static inline void __xfrm_state_put(struct xfrm_state *x) { - refcount_dec(&x->refcnt); + WARN_ON(rcuref_put(&x->ref)); } static inline void xfrm_state_put(struct xfrm_state *x) { - if (refcount_dec_and_test(&x->refcnt)) + if (rcuref_put(&x->ref)) __xfrm_state_destroy(x, false); } static inline void xfrm_state_put_sync(struct xfrm_state *x) { - if (refcount_dec_and_test(&x->refcnt)) + if (rcuref_put(&x->ref)) __xfrm_state_destroy(x, true); } static inline void xfrm_state_hold(struct xfrm_state *x) { - refcount_inc(&x->refcnt); + WARN_ON(!rcuref_get(&x->ref)); } static inline bool addr_match(const void *token1, const void *token2, diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index ad2202fa82f34..ded79ec53cbdd 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -55,7 +55,7 @@ static HLIST_HEAD(xfrm_state_dev_gc_list); static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x) { - return refcount_inc_not_zero(&x->refcnt); + return rcuref_get(&x->ref); } static inline unsigned int xfrm_dst_hash(struct net *net, @@ -738,7 +738,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net) if (x) { write_pnet(&x->xs_net, net); - refcount_set(&x->refcnt, 1); + rcuref_init(&x->ref, 1); atomic_set(&x->tunnel_users, 0); INIT_LIST_HEAD(&x->km.all); INIT_HLIST_NODE(&x->state_cache);
xfrm_state::ref is used for reference counting of xfrm_state itself. The structure already follows RCU rules for its lifetime. Using rcuref_t instead of refcount_t has the advantage that refcount_inc_not_zero() can be replaced with a regular rcuref_get() which does not suffer from a cmpxchg() loop. The cmpxchg() loop might be repeated several times if there are puts or gets in parallel. Replace xfrm_state's reference counting with rcuref_t. The __xfrm_state_put() and xfrm_state_hold() which should always succeed have a warning in case they don't succeed. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- include/net/xfrm.h | 12 ++++++------ net/xfrm/xfrm_state.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)