rcu.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage
@ 2019-02-21  5:49 Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 1/5] net: rtnetlink: Fix incorrect RCU API usage Joel Fernandes (Google)
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Joel Fernandes (Google) @ 2019-02-21  5:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Joel Fernandes (Google),
	Alexei Starovoitov, Christian Brauner, Daniel Borkmann,
	David Ahern, David S. Miller, Ido Schimmel, Ingo Molnar,
	moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
	Jeff Kirsher, Jesper Dangaard Brouer, John Fastabend,
	Josh Triplett, keescook, Lai Jiangshan, Martin KaFai Lau,
	Mathieu Desnoyers, netdev, Paul E. McKenney, Peter Zijlstra, rcu,
	Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

These patches fix various RCU API usage issues found due to sparse errors as a
result of the recent check to add rcu_check_sparse() to rcu_assign_pointer().
The errors in many cases seem to indicate either an incorrect API usage, or
missing annotations. The annotations added can also help avoid future incorrect
usages and bugs so it is a good idea to do in any case.

These are only build/boot tested and I request for feedback from maintainers
and developers in the various areas the patches touch. Thanks for any feedback!

(There are still errors in rbtree.h but I have kept those for a later time
since fixing them is a bit more involved).

Joel Fernandes (Google) (5):
net: rtnetlink: Fix incorrect RCU API usage
ixgbe: Fix incorrect RCU API usage
sched/cpufreq: Fix incorrect RCU API usage
sched/topology: Annonate RCU pointers properly
rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE

drivers/net/ethernet/intel/ixgbe/ixgbe.h      |  4 ++--
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 17 ++++++++++++-----
include/linux/rcuwait.h                       |  2 +-
kernel/sched/cpufreq.c                        |  8 ++++++--
kernel/sched/sched.h                          | 14 +++++++-------
kernel/sched/topology.c                       | 12 ++++++------
net/core/rtnetlink.c                          |  4 ++--
7 files changed, 36 insertions(+), 25 deletions(-)

--
2.21.0.rc0.258.g878e2cd30e-goog


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH RFC 1/5] net: rtnetlink: Fix incorrect RCU API usage
  2019-02-21  5:49 [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage Joel Fernandes (Google)
@ 2019-02-21  5:49 ` Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 2/5] ixgbe: " Joel Fernandes (Google)
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Joel Fernandes (Google) @ 2019-02-21  5:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Joel Fernandes (Google),
	Alexei Starovoitov, Christian Brauner, Daniel Borkmann,
	David Ahern, David S. Miller, Ido Schimmel, Ingo Molnar,
	moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
	Jeff Kirsher, Jesper Dangaard Brouer, John Fastabend,
	Josh Triplett, keescook, Lai Jiangshan, Martin KaFai Lau,
	Mathieu Desnoyers, netdev, Paul E. McKenney, Peter Zijlstra, rcu,
	Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

rtnl_register_internal() and rtnl_unregister_all tries to directly
dereference an RCU protected pointed outside RCU read side section.
While this is Ok to do since a lock is held, let us use the correct
API to avoid programmer bugs in the future.

This also fixes sparse warnings arising from not using RCU API.

net/core/rtnetlink.c:332:13: warning: incorrect type in assignment
(different address spaces) net/core/rtnetlink.c:332:13:    expected
struct rtnl_link **tab net/core/rtnetlink.c:332:13:    got struct
rtnl_link *[noderef] <asn:4>*<noident>

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 net/core/rtnetlink.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 5ea1bed08ede..98be4b4818a9 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -188,7 +188,7 @@ static int rtnl_register_internal(struct module *owner,
 	msgindex = rtm_msgindex(msgtype);
 
 	rtnl_lock();
-	tab = rtnl_msg_handlers[protocol];
+	tab = rtnl_dereference(rtnl_msg_handlers[protocol]);
 	if (tab == NULL) {
 		tab = kcalloc(RTM_NR_MSGTYPES, sizeof(void *), GFP_KERNEL);
 		if (!tab)
@@ -329,7 +329,7 @@ void rtnl_unregister_all(int protocol)
 	BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);
 
 	rtnl_lock();
-	tab = rtnl_msg_handlers[protocol];
+	tab = rtnl_dereference(rtnl_msg_handlers[protocol]);
 	if (!tab) {
 		rtnl_unlock();
 		return;
-- 
2.21.0.rc0.258.g878e2cd30e-goog


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH RFC 2/5] ixgbe: Fix incorrect RCU API usage
  2019-02-21  5:49 [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 1/5] net: rtnetlink: Fix incorrect RCU API usage Joel Fernandes (Google)
@ 2019-02-21  5:49 ` Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 3/5] sched/cpufreq: " Joel Fernandes (Google)
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Joel Fernandes (Google) @ 2019-02-21  5:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Joel Fernandes (Google),
	Alexei Starovoitov, Christian Brauner, Daniel Borkmann,
	David Ahern, David S. Miller, Ido Schimmel, Ingo Molnar,
	moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
	Jeff Kirsher, Jesper Dangaard Brouer, John Fastabend,
	Josh Triplett, keescook, Lai Jiangshan, Martin KaFai Lau,
	Mathieu Desnoyers, netdev, Paul E. McKenney, Peter Zijlstra, rcu,
	Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

Recently, I added an RCU annotation check in rcu_assign_pointer. This
caused a sparse error to be reported by the ixgbe driver.

Further looking, it seems the adapter->xdp_prog pointer is not annotated
with __rcu. Annonating it fixed the error, but caused a bunch of other
warnings.

This patch tries to fix all warnings by using RCU API properly. This
makes sense to do because not using RCU properly can result in various
hard to find bugs. This is a best effort fix and is only build tested.
The sparse errors and warnings go away with the change. I request
maintainers / developers in this area to test it properly.

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe.h      |  4 ++--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 17 ++++++++++++-----
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 08d85e336bd4..3b14daf27516 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -311,7 +311,7 @@ struct ixgbe_ring {
 	struct ixgbe_ring *next;	/* pointer to next ring in q_vector */
 	struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */
 	struct net_device *netdev;	/* netdev ring belongs to */
-	struct bpf_prog *xdp_prog;
+	struct bpf_prog __rcu *xdp_prog;
 	struct device *dev;		/* device for DMA mapping */
 	void *desc;			/* descriptor ring memory */
 	union {
@@ -560,7 +560,7 @@ struct ixgbe_adapter {
 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	/* OS defined structs */
 	struct net_device *netdev;
-	struct bpf_prog *xdp_prog;
+	struct bpf_prog __rcu *xdp_prog;
 	struct pci_dev *pdev;
 	struct mii_bus *mii_bus;
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index daff8183534b..6aa59bb13a14 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2199,7 +2199,7 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
 	u32 act;
 
 	rcu_read_lock();
-	xdp_prog = READ_ONCE(rx_ring->xdp_prog);
+	xdp_prog = rcu_dereference(rx_ring->xdp_prog);
 
 	if (!xdp_prog)
 		goto xdp_out;
@@ -6547,7 +6547,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
 			     rx_ring->queue_index) < 0)
 		goto err;
 
-	rx_ring->xdp_prog = adapter->xdp_prog;
+	rcu_assign_pointer(rx_ring->xdp_prog, adapter->xdp_prog);
 
 	return 0;
 err:
@@ -10246,7 +10246,10 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
 	if (nr_cpu_ids > MAX_XDP_QUEUES)
 		return -ENOMEM;
 
-	old_prog = xchg(&adapter->xdp_prog, prog);
+	rcu_read_lock();
+	old_prog = rcu_dereference(adapter->xdp_prog);
+	rcu_assign_pointer(adapter->xdp_prog, prog);
+	rcu_read_unlock();
 
 	/* If transitioning XDP modes reconfigure rings */
 	if (!!prog != !!old_prog) {
@@ -10271,13 +10274,17 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
 static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct bpf_prog *prog;
 
 	switch (xdp->command) {
 	case XDP_SETUP_PROG:
 		return ixgbe_xdp_setup(dev, xdp->prog);
 	case XDP_QUERY_PROG:
-		xdp->prog_id = adapter->xdp_prog ?
-			adapter->xdp_prog->aux->id : 0;
+		rcu_read_lock();
+		prog = rcu_dereference(adapter->xdp_prog);
+		xdp->prog_id = prog ? prog->aux->id : 0;
+		rcu_read_unlock();
+
 		return 0;
 	case XDP_QUERY_XSK_UMEM:
 		return ixgbe_xsk_umem_query(adapter, &xdp->xsk.umem,
-- 
2.21.0.rc0.258.g878e2cd30e-goog


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21  5:49 [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 1/5] net: rtnetlink: Fix incorrect RCU API usage Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 2/5] ixgbe: " Joel Fernandes (Google)
@ 2019-02-21  5:49 ` Joel Fernandes (Google)
  2019-02-21  9:18   ` Peter Zijlstra
                     ` (2 more replies)
  2019-02-21  5:49 ` [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly Joel Fernandes (Google)
  2019-02-21  5:49 ` [PATCH RFC 5/5] rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE Joel Fernandes (Google)
  4 siblings, 3 replies; 20+ messages in thread
From: Joel Fernandes (Google) @ 2019-02-21  5:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Joel Fernandes (Google),
	Alexei Starovoitov, Christian Brauner, Daniel Borkmann,
	David Ahern, David S. Miller, Ido Schimmel, Ingo Molnar,
	moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
	Jeff Kirsher, Jesper Dangaard Brouer, John Fastabend,
	Josh Triplett, keescook, Lai Jiangshan, Martin KaFai Lau,
	Mathieu Desnoyers, netdev, Paul E. McKenney, Peter Zijlstra, rcu,
	Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

Recently I added an RCU annotation check to rcu_assign_pointer(). All
pointers assigned to RCU protected data are to be annotated with __rcu
inorder to be able to use rcu_assign_pointer() similar to checks in
other RCU APIs.

This resulted in a sparse error: kernel//sched/cpufreq.c:41:9: sparse:
error: incompatible types in comparison expression (different address
spaces)

Fix this by using the correct APIs for RCU accesses. This will
potentially avoid any future bugs in the code. If it is felt that RCU
protection is not needed here, then the rcu_assign_pointer call can be
dropped and replaced with, say, WRITE_ONCE or smp_store_release. Or, may
be we add a new API to do it. But calls rcu_assign_pointer seems an
abuse of the RCU API unless RCU is being used.

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 kernel/sched/cpufreq.c | 8 ++++++--
 kernel/sched/sched.h   | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c
index 22bd8980f32f..c9aeb3bf5dc2 100644
--- a/kernel/sched/cpufreq.c
+++ b/kernel/sched/cpufreq.c
@@ -7,7 +7,7 @@
  */
 #include "sched.h"
 
-DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
+DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
 
 /**
  * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer.
@@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
 	if (WARN_ON(!data || !func))
 		return;
 
-	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
+	rcu_read_lock();
+	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
+		rcu_read_unlock();
 		return;
+	}
+	rcu_read_unlock();
 
 	data->func = func;
 	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index d04530bf251f..2ab545d40381 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2166,7 +2166,7 @@ static inline u64 irq_time_read(int cpu)
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
 #ifdef CONFIG_CPU_FREQ
-DECLARE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
+DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
 
 /**
  * cpufreq_update_util - Take a note about CPU utilization changes.
-- 
2.21.0.rc0.258.g878e2cd30e-goog


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly
  2019-02-21  5:49 [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage Joel Fernandes (Google)
                   ` (2 preceding siblings ...)
  2019-02-21  5:49 ` [PATCH RFC 3/5] sched/cpufreq: " Joel Fernandes (Google)
@ 2019-02-21  5:49 ` Joel Fernandes (Google)
  2019-02-21  9:19   ` Peter Zijlstra
  2019-02-21  5:49 ` [PATCH RFC 5/5] rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE Joel Fernandes (Google)
  4 siblings, 1 reply; 20+ messages in thread
From: Joel Fernandes (Google) @ 2019-02-21  5:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Joel Fernandes (Google),
	Alexei Starovoitov, Christian Brauner, Daniel Borkmann,
	David Ahern, David S. Miller, Ido Schimmel, Ingo Molnar,
	moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
	Jeff Kirsher, Jesper Dangaard Brouer, John Fastabend,
	Josh Triplett, keescook, Lai Jiangshan, Martin KaFai Lau,
	Mathieu Desnoyers, netdev, Paul E. McKenney, Peter Zijlstra, rcu,
	Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

The scheduler's topology code uses rcu_assign_pointer() to initialize
various pointers.

Let us annotate the pointers correctly which also help avoid future
bugs. This suppresses the new sparse errors caused by an annotation
check I added to rcu_assign_pointer().

Also replace rcu_assign_pointer call on rq->sd with WRITE_ONCE. This
should be sufficient for the rq->sd initialization.

This fixes sparse errors:
kernel//sched/topology.c:378:9: sparse: error: incompatible types in
comparison expression (different address spaces)
kernel//sched/topology.c:387:9: sparse: error: incompatible types in
comparison expression (different address spaces)
kernel//sched/topology.c:612:9: sparse: error: incompatible types in
comparison expression (different address spaces)
kernel//sched/topology.c:615:9: sparse: error: incompatible types in
comparison expression (different address spaces)
kernel//sched/topology.c:618:9: sparse: error: incompatible types in
comparison expression (different address spaces)
kernel//sched/topology.c:621:9: sparse: error: incompatible types in
comparison expression (different address spaces)

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 kernel/sched/sched.h    | 12 ++++++------
 kernel/sched/topology.c | 12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 2ab545d40381..806703afd4b0 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -780,7 +780,7 @@ struct root_domain {
 	 * NULL-terminated list of performance domains intersecting with the
 	 * CPUs of the rd. Protected by RCU.
 	 */
-	struct perf_domain	*pd;
+	struct perf_domain __rcu *pd;
 };
 
 extern struct root_domain def_root_domain;
@@ -1305,13 +1305,13 @@ static inline struct sched_domain *lowest_flag_domain(int cpu, int flag)
 	return sd;
 }
 
-DECLARE_PER_CPU(struct sched_domain *, sd_llc);
+DECLARE_PER_CPU(struct sched_domain __rcu *, sd_llc);
 DECLARE_PER_CPU(int, sd_llc_size);
 DECLARE_PER_CPU(int, sd_llc_id);
-DECLARE_PER_CPU(struct sched_domain_shared *, sd_llc_shared);
-DECLARE_PER_CPU(struct sched_domain *, sd_numa);
-DECLARE_PER_CPU(struct sched_domain *, sd_asym_packing);
-DECLARE_PER_CPU(struct sched_domain *, sd_asym_cpucapacity);
+DECLARE_PER_CPU(struct sched_domain_shared __rcu *, sd_llc_shared);
+DECLARE_PER_CPU(struct sched_domain __rcu *, sd_numa);
+DECLARE_PER_CPU(struct sched_domain __rcu *, sd_asym_packing);
+DECLARE_PER_CPU(struct sched_domain __rcu *, sd_asym_cpucapacity);
 extern struct static_key_false sched_asym_cpucapacity;
 
 struct sched_group_capacity {
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 3f35ba1d8fde..2eab2e16ded5 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -586,13 +586,13 @@ static void destroy_sched_domains(struct sched_domain *sd)
  * the cpumask of the domain), this allows us to quickly tell if
  * two CPUs are in the same cache domain, see cpus_share_cache().
  */
-DEFINE_PER_CPU(struct sched_domain *, sd_llc);
+DEFINE_PER_CPU(struct sched_domain __rcu *, sd_llc);
 DEFINE_PER_CPU(int, sd_llc_size);
 DEFINE_PER_CPU(int, sd_llc_id);
-DEFINE_PER_CPU(struct sched_domain_shared *, sd_llc_shared);
-DEFINE_PER_CPU(struct sched_domain *, sd_numa);
-DEFINE_PER_CPU(struct sched_domain *, sd_asym_packing);
-DEFINE_PER_CPU(struct sched_domain *, sd_asym_cpucapacity);
+DEFINE_PER_CPU(struct sched_domain_shared __rcu *, sd_llc_shared);
+DEFINE_PER_CPU(struct sched_domain __rcu *, sd_numa);
+DEFINE_PER_CPU(struct sched_domain __rcu *, sd_asym_packing);
+DEFINE_PER_CPU(struct sched_domain __rcu *, sd_asym_cpucapacity);
 DEFINE_STATIC_KEY_FALSE(sched_asym_cpucapacity);
 
 static void update_top_cache_domain(int cpu)
@@ -668,7 +668,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
 
 	rq_attach_root(rq, rd);
 	tmp = rq->sd;
-	rcu_assign_pointer(rq->sd, sd);
+	WRITE_ONCE(rq->sd, sd);
 	dirty_sched_domain_sysctl(cpu);
 	destroy_sched_domains(tmp);
 
-- 
2.21.0.rc0.258.g878e2cd30e-goog


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH RFC 5/5] rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE
  2019-02-21  5:49 [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage Joel Fernandes (Google)
                   ` (3 preceding siblings ...)
  2019-02-21  5:49 ` [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly Joel Fernandes (Google)
@ 2019-02-21  5:49 ` Joel Fernandes (Google)
  2019-02-21  9:20   ` Peter Zijlstra
  4 siblings, 1 reply; 20+ messages in thread
From: Joel Fernandes (Google) @ 2019-02-21  5:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: Joel Fernandes (Google),
	Alexei Starovoitov, Christian Brauner, Daniel Borkmann,
	David Ahern, David S. Miller, Ido Schimmel, Ingo Molnar,
	moderated list:INTEL ETHERNET DRIVERS, Jakub Kicinski,
	Jeff Kirsher, Jesper Dangaard Brouer, John Fastabend,
	Josh Triplett, keescook, Lai Jiangshan, Martin KaFai Lau,
	Mathieu Desnoyers, netdev, Paul E. McKenney, Peter Zijlstra, rcu,
	Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

This suppresses a sparse error generated due to the recently added
rcu_assign_pointer sparse check below. It seems WRITE_ONCE should be
sufficient here.

>> kernel//locking/percpu-rwsem.c:162:9: sparse: error: incompatible
types in comparison expression (different address spaces)

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 include/linux/rcuwait.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/rcuwait.h b/include/linux/rcuwait.h
index 90bfa3279a01..9e5b4760e6c2 100644
--- a/include/linux/rcuwait.h
+++ b/include/linux/rcuwait.h
@@ -44,7 +44,7 @@ extern void rcuwait_wake_up(struct rcuwait *w);
 	 */                                                             \
 	WARN_ON(current->exit_state);                                   \
 									\
-	rcu_assign_pointer((w)->task, current);				\
+	WRITE_ONCE((w)->task, current);					\
 	for (;;) {							\
 		/*							\
 		 * Implicit barrier (A) pairs with (B) in		\
-- 
2.21.0.rc0.258.g878e2cd30e-goog


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21  5:49 ` [PATCH RFC 3/5] sched/cpufreq: " Joel Fernandes (Google)
@ 2019-02-21  9:18   ` Peter Zijlstra
  2019-02-21 15:21     ` Joel Fernandes
  2019-02-21 16:17   ` Steven Rostedt
  2019-02-21 23:05   ` Rafael J. Wysocki
  2 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2019-02-21  9:18 UTC (permalink / raw)
  To: Joel Fernandes (Google)
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
>  	if (WARN_ON(!data || !func))
>  		return;
>  
> -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> +	rcu_read_lock();
> +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> +		rcu_read_unlock();
>  		return;
> +	}
> +	rcu_read_unlock();
>  
>  	data->func = func;
>  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);

This doesn't make any kind of sense to me.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly
  2019-02-21  5:49 ` [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly Joel Fernandes (Google)
@ 2019-02-21  9:19   ` Peter Zijlstra
  2019-02-21 15:10     ` Joel Fernandes
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2019-02-21  9:19 UTC (permalink / raw)
  To: Joel Fernandes (Google)
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 12:49:41AM -0500, Joel Fernandes (Google) wrote:

> Also replace rcu_assign_pointer call on rq->sd with WRITE_ONCE. This
> should be sufficient for the rq->sd initialization.

> @@ -668,7 +668,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
>  
>  	rq_attach_root(rq, rd);
>  	tmp = rq->sd;
> -	rcu_assign_pointer(rq->sd, sd);
> +	WRITE_ONCE(rq->sd, sd);
>  	dirty_sched_domain_sysctl(cpu);
>  	destroy_sched_domains(tmp);

Where did the RELEASE barrier go?

That was a publish operation, now it is not.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 5/5] rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE
  2019-02-21  5:49 ` [PATCH RFC 5/5] rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE Joel Fernandes (Google)
@ 2019-02-21  9:20   ` Peter Zijlstra
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2019-02-21  9:20 UTC (permalink / raw)
  To: Joel Fernandes (Google)
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 12:49:42AM -0500, Joel Fernandes (Google) wrote:
> This suppresses a sparse error generated due to the recently added
> rcu_assign_pointer sparse check below. It seems WRITE_ONCE should be
> sufficient here.
> 
> >> kernel//locking/percpu-rwsem.c:162:9: sparse: error: incompatible
> types in comparison expression (different address spaces)
> 
> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
> ---
>  include/linux/rcuwait.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/rcuwait.h b/include/linux/rcuwait.h
> index 90bfa3279a01..9e5b4760e6c2 100644
> --- a/include/linux/rcuwait.h
> +++ b/include/linux/rcuwait.h
> @@ -44,7 +44,7 @@ extern void rcuwait_wake_up(struct rcuwait *w);
>  	 */                                                             \
>  	WARN_ON(current->exit_state);                                   \
>  									\
> -	rcu_assign_pointer((w)->task, current);				\
> +	WRITE_ONCE((w)->task, current);					\
>  	for (;;) {							\
>  		/*							\
>  		 * Implicit barrier (A) pairs with (B) in		\

Distinct lack of justification for loosing the RELEASE again.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly
  2019-02-21  9:19   ` Peter Zijlstra
@ 2019-02-21 15:10     ` Joel Fernandes
  2019-02-21 15:29       ` Peter Zijlstra
  0 siblings, 1 reply; 20+ messages in thread
From: Joel Fernandes @ 2019-02-21 15:10 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

Hi Peter,

Thanks for taking a look.

On Thu, Feb 21, 2019 at 10:19:44AM +0100, Peter Zijlstra wrote:
> On Thu, Feb 21, 2019 at 12:49:41AM -0500, Joel Fernandes (Google) wrote:
> 
> > Also replace rcu_assign_pointer call on rq->sd with WRITE_ONCE. This
> > should be sufficient for the rq->sd initialization.
> 
> > @@ -668,7 +668,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
> >  
> >  	rq_attach_root(rq, rd);
> >  	tmp = rq->sd;
> > -	rcu_assign_pointer(rq->sd, sd);
> > +	WRITE_ONCE(rq->sd, sd);
> >  	dirty_sched_domain_sysctl(cpu);
> >  	destroy_sched_domains(tmp);
> 
> Where did the RELEASE barrier go?
> 
> That was a publish operation, now it is not.

Funny thing is, initially I had written this patch with smp_store_release()
instead of WRITE_ONCE, but checkpatch complaints with that since it needs a
comment on top of it, and I wasn't sure if RELEASE barrier was the intent of
using rcu_assign_pointer (all the more reason to replace it with something
more explicit).

I will replace it with the following and resubmit it then:

/* Release barrier */
smp_store_release(&rq->sd, sd);

Or do we want to just drop the "Release barrier" comment and live with the
checkpatch warning?

(my same response applies to patch 5/5).

thanks,

 - Joel


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21  9:18   ` Peter Zijlstra
@ 2019-02-21 15:21     ` Joel Fernandes
  2019-02-21 15:31       ` Peter Zijlstra
  0 siblings, 1 reply; 20+ messages in thread
From: Joel Fernandes @ 2019-02-21 15:21 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 10:18:05AM +0100, Peter Zijlstra wrote:
> On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> > @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
> >  	if (WARN_ON(!data || !func))
> >  		return;
> >  
> > -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> > +	rcu_read_lock();
> > +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> > +		rcu_read_unlock();
> >  		return;
> > +	}
> > +	rcu_read_unlock();
> >  
> >  	data->func = func;
> >  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> 
> This doesn't make any kind of sense to me.
> 

As per the rcu_assign_pointer() line, I inferred that
cpufreq_update_util_data is expected to be RCU protected. Reading the pointer
value of RCU pointers generally needs to be done from RCU read section, and
using rcu_dereference() (or using rcu_access()).

In this patch, I changed cpufreq_update_util_data to be __rcu annotated to
avoid the sparse error thrown by rcu_assign_pointer().

Instead of doing that, If your intention here is RELEASE barrier, should I
just replace in this function:
	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
with:
	smp_store_release(per_cpu(cpufreq_update_util_data, cpu), data))
?

It would be nice IMO to be explicit about the intention of release/publish
semantics by using smp_store_release().

thanks,

 - Joel


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly
  2019-02-21 15:10     ` Joel Fernandes
@ 2019-02-21 15:29       ` Peter Zijlstra
  2019-02-21 17:17         ` Joel Fernandes
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2019-02-21 15:29 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 10:10:57AM -0500, Joel Fernandes wrote:
> Hi Peter,
> 
> Thanks for taking a look.
> 
> On Thu, Feb 21, 2019 at 10:19:44AM +0100, Peter Zijlstra wrote:
> > On Thu, Feb 21, 2019 at 12:49:41AM -0500, Joel Fernandes (Google) wrote:
> > 
> > > Also replace rcu_assign_pointer call on rq->sd with WRITE_ONCE. This
> > > should be sufficient for the rq->sd initialization.
> > 
> > > @@ -668,7 +668,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
> > >  
> > >  	rq_attach_root(rq, rd);
> > >  	tmp = rq->sd;
> > > -	rcu_assign_pointer(rq->sd, sd);
> > > +	WRITE_ONCE(rq->sd, sd);
> > >  	dirty_sched_domain_sysctl(cpu);
> > >  	destroy_sched_domains(tmp);
> > 
> > Where did the RELEASE barrier go?
> > 
> > That was a publish operation, now it is not.
> 
> Funny thing is, initially I had written this patch with smp_store_release()
> instead of WRITE_ONCE, but checkpatch complaints with that since it needs a
> comment on top of it, and I wasn't sure if RELEASE barrier was the intent of
> using rcu_assign_pointer (all the more reason to replace it with something
> more explicit).
> 
> I will replace it with the following and resubmit it then:
> 
> /* Release barrier */
> smp_store_release(&rq->sd, sd);
> 
> Or do we want to just drop the "Release barrier" comment and live with the
> checkpatch warning?

How about we keep using rcu_assign_pointer(), the whole sched domain
tree is under rcu; peruse that destroy_sched_domains() function for
instance.

Also check how for_each_domain() uses rcu_dereference().

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21 15:21     ` Joel Fernandes
@ 2019-02-21 15:31       ` Peter Zijlstra
  2019-02-21 15:52         ` Paul E. McKenney
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2019-02-21 15:31 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 10:21:39AM -0500, Joel Fernandes wrote:
> On Thu, Feb 21, 2019 at 10:18:05AM +0100, Peter Zijlstra wrote:
> > On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> > > @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
> > >  	if (WARN_ON(!data || !func))
> > >  		return;
> > >  
> > > -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> > > +	rcu_read_lock();
> > > +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> > > +		rcu_read_unlock();
> > >  		return;
> > > +	}
> > > +	rcu_read_unlock();
> > >  
> > >  	data->func = func;
> > >  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> > 
> > This doesn't make any kind of sense to me.
> > 
> 
> As per the rcu_assign_pointer() line, I inferred that
> cpufreq_update_util_data is expected to be RCU protected. Reading the pointer
> value of RCU pointers generally needs to be done from RCU read section, and
> using rcu_dereference() (or using rcu_access()).
> 
> In this patch, I changed cpufreq_update_util_data to be __rcu annotated to
> avoid the sparse error thrown by rcu_assign_pointer().
> 
> Instead of doing that, If your intention here is RELEASE barrier, should I
> just replace in this function:
> 	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> with:
> 	smp_store_release(per_cpu(cpufreq_update_util_data, cpu), data))
> ?
> 
> It would be nice IMO to be explicit about the intention of release/publish
> semantics by using smp_store_release().

No, it is RCU managed, it should be RCU. The problem is that the hunk
above is utter crap.

All that does is read the pointer, it never actually dereferences it.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21 15:31       ` Peter Zijlstra
@ 2019-02-21 15:52         ` Paul E. McKenney
  2019-02-21 16:11           ` Peter Zijlstra
  0 siblings, 1 reply; 20+ messages in thread
From: Paul E. McKenney @ 2019-02-21 15:52 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Joel Fernandes, linux-kernel, Alexei Starovoitov,
	Christian Brauner, Daniel Borkmann, David Ahern, David S. Miller,
	Ido Schimmel, Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, rcu, Song Liu,
	Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 04:31:17PM +0100, Peter Zijlstra wrote:
> On Thu, Feb 21, 2019 at 10:21:39AM -0500, Joel Fernandes wrote:
> > On Thu, Feb 21, 2019 at 10:18:05AM +0100, Peter Zijlstra wrote:
> > > On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> > > > @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
> > > >  	if (WARN_ON(!data || !func))
> > > >  		return;
> > > >  
> > > > -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> > > > +	rcu_read_lock();
> > > > +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> > > > +		rcu_read_unlock();
> > > >  		return;
> > > > +	}
> > > > +	rcu_read_unlock();
> > > >  
> > > >  	data->func = func;
> > > >  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> > > 
> > > This doesn't make any kind of sense to me.
> > > 
> > 
> > As per the rcu_assign_pointer() line, I inferred that
> > cpufreq_update_util_data is expected to be RCU protected. Reading the pointer
> > value of RCU pointers generally needs to be done from RCU read section, and
> > using rcu_dereference() (or using rcu_access()).
> > 
> > In this patch, I changed cpufreq_update_util_data to be __rcu annotated to
> > avoid the sparse error thrown by rcu_assign_pointer().
> > 
> > Instead of doing that, If your intention here is RELEASE barrier, should I
> > just replace in this function:
> > 	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> > with:
> > 	smp_store_release(per_cpu(cpufreq_update_util_data, cpu), data))
> > ?
> > 
> > It would be nice IMO to be explicit about the intention of release/publish
> > semantics by using smp_store_release().
> 
> No, it is RCU managed, it should be RCU. The problem is that the hunk
> above is utter crap.
> 
> All that does is read the pointer, it never actually dereferences it.

For whatever it is worth, in that case it could use rcu_access_pointer().
And this primitive does not do the lockdep check for being within an RCU
read-side critical section.  As Peter says, if there is no dereferencing,
there can be no use-after-free bug, so the RCU read-side critical is
not needed.

Good eyes, Peter!  ;-)

							Thanx, Paul


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21 15:52         ` Paul E. McKenney
@ 2019-02-21 16:11           ` Peter Zijlstra
  2019-02-21 17:13             ` Joel Fernandes
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2019-02-21 16:11 UTC (permalink / raw)
  To: Paul E. McKenney
  Cc: Joel Fernandes, linux-kernel, Alexei Starovoitov,
	Christian Brauner, Daniel Borkmann, David Ahern, David S. Miller,
	Ido Schimmel, Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, rcu, Song Liu,
	Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 07:52:18AM -0800, Paul E. McKenney wrote:
> On Thu, Feb 21, 2019 at 04:31:17PM +0100, Peter Zijlstra wrote:
> > On Thu, Feb 21, 2019 at 10:21:39AM -0500, Joel Fernandes wrote:
> > > On Thu, Feb 21, 2019 at 10:18:05AM +0100, Peter Zijlstra wrote:
> > > > On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> > > > > @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
> > > > >  	if (WARN_ON(!data || !func))
> > > > >  		return;
> > > > >  
> > > > > -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> > > > > +	rcu_read_lock();
> > > > > +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> > > > > +		rcu_read_unlock();
> > > > >  		return;
> > > > > +	}
> > > > > +	rcu_read_unlock();
> > > > >  
> > > > >  	data->func = func;
> > > > >  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);

> For whatever it is worth, in that case it could use rcu_access_pointer().
> And this primitive does not do the lockdep check for being within an RCU
> read-side critical section.  As Peter says, if there is no dereferencing,
> there can be no use-after-free bug, so the RCU read-side critical is
> not needed.

On top of that, I suspect this is under the write-side lock (we're doing
assignment after all).

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21  5:49 ` [PATCH RFC 3/5] sched/cpufreq: " Joel Fernandes (Google)
  2019-02-21  9:18   ` Peter Zijlstra
@ 2019-02-21 16:17   ` Steven Rostedt
  2019-02-21 23:05   ` Rafael J. Wysocki
  2 siblings, 0 replies; 20+ messages in thread
From: Steven Rostedt @ 2019-02-21 16:17 UTC (permalink / raw)
  To: Joel Fernandes (Google)
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	Peter Zijlstra, rcu, Song Liu, xdp-newbies, Yonghong Song,
	Rafael J. Wysocki

On Thu, 21 Feb 2019 00:49:40 -0500
"Joel Fernandes (Google)" <joel@joelfernandes.org> wrote:

> Recently I added an RCU annotation check to rcu_assign_pointer(). All
> pointers assigned to RCU protected data are to be annotated with __rcu
> inorder to be able to use rcu_assign_pointer() similar to checks in
> other RCU APIs.
> 
> This resulted in a sparse error: kernel//sched/cpufreq.c:41:9: sparse:
> error: incompatible types in comparison expression (different address
> spaces)
> 
> Fix this by using the correct APIs for RCU accesses. This will
> potentially avoid any future bugs in the code. If it is felt that RCU
> protection is not needed here, then the rcu_assign_pointer call can be
> dropped and replaced with, say, WRITE_ONCE or smp_store_release. Or, may
> be we add a new API to do it. But calls rcu_assign_pointer seems an
> abuse of the RCU API unless RCU is being used.

This all looks broken, and this patch is papering over the issue, or
worse, hiding it.

> 
> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
> ---
>  kernel/sched/cpufreq.c | 8 ++++++--
>  kernel/sched/sched.h   | 2 +-
>  2 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c
> index 22bd8980f32f..c9aeb3bf5dc2 100644
> --- a/kernel/sched/cpufreq.c
> +++ b/kernel/sched/cpufreq.c
> @@ -7,7 +7,7 @@
>   */
>  #include "sched.h"
>  
> -DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
> +DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
>  
>  /**
>   * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer.
> @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
>  	if (WARN_ON(!data || !func))
>  		return;
>  
> -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> +	rcu_read_lock();
> +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> +		rcu_read_unlock();
>  		return;
> +	}
> +	rcu_read_unlock();
>  
>  	data->func = func;
>  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);

An rcu_assign_pointer() is to update something that is going to be read
under rcu_read_lock() elsewhere. But updates to an rcu variable are not
protected by rcu_read_lock() (hence the "read" in the name). Adding
rcu_read_lock() above does nothing, but perhaps hides an issue.

Writes usually have something else that protects against races. Thus,
the above shouldn't be switched to using a rcu_dereference(), but
perhaps a rcu_dereference_protected(), with whatever is protecting
updates?

Which doing a bit of investigating, looks to be the rwsem
"policy->rwsem", where policy comes from:

	policy = cpufreq_cpu_get(cpu);

I would say the code as is, is not broken. But this patch isn't helping
anything.

-- Steve


> diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
> index d04530bf251f..2ab545d40381 100644
> --- a/kernel/sched/sched.h
> +++ b/kernel/sched/sched.h
> @@ -2166,7 +2166,7 @@ static inline u64 irq_time_read(int cpu)
>  #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
>  
>  #ifdef CONFIG_CPU_FREQ
> -DECLARE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
> +DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
>  
>  /**
>   * cpufreq_update_util - Take a note about CPU utilization changes.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21 16:11           ` Peter Zijlstra
@ 2019-02-21 17:13             ` Joel Fernandes
  2019-02-21 17:29               ` Paul E. McKenney
  0 siblings, 1 reply; 20+ messages in thread
From: Joel Fernandes @ 2019-02-21 17:13 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Paul E. McKenney, linux-kernel, Alexei Starovoitov,
	Christian Brauner, Daniel Borkmann, David Ahern, David S. Miller,
	Ido Schimmel, Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, rcu, Song Liu,
	Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 05:11:44PM +0100, Peter Zijlstra wrote:
> On Thu, Feb 21, 2019 at 07:52:18AM -0800, Paul E. McKenney wrote:
> > On Thu, Feb 21, 2019 at 04:31:17PM +0100, Peter Zijlstra wrote:
> > > On Thu, Feb 21, 2019 at 10:21:39AM -0500, Joel Fernandes wrote:
> > > > On Thu, Feb 21, 2019 at 10:18:05AM +0100, Peter Zijlstra wrote:
> > > > > On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> > > > > > @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
> > > > > >  	if (WARN_ON(!data || !func))
> > > > > >  		return;
> > > > > >  
> > > > > > -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> > > > > > +	rcu_read_lock();
> > > > > > +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> > > > > > +		rcu_read_unlock();
> > > > > >  		return;
> > > > > > +	}
> > > > > > +	rcu_read_unlock();
> > > > > >  
> > > > > >  	data->func = func;
> > > > > >  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> 
> > For whatever it is worth, in that case it could use rcu_access_pointer().
> > And this primitive does not do the lockdep check for being within an RCU
> > read-side critical section.  As Peter says, if there is no dereferencing,
> > there can be no use-after-free bug, so the RCU read-side critical is
> > not needed.
> 
> On top of that, I suspect this is under the write-side lock (we're doing
> assignment after all).

Yes it is under a policy->rwsem, just confirmed that.

And indeed rcu_read_lock() is not needed here in this patch, thanks for
pointing that out. Sometimes the word "dereference" plays some visual tricks
and in this case tempted me to add an RCU reader section ;-) Assuming you
guys are in agreement with usage of rcu_access_pointer() here to keep sparse
happy, I'll rework the patch accordingly and resubmit with that.

thanks!

 - Joel




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly
  2019-02-21 15:29       ` Peter Zijlstra
@ 2019-02-21 17:17         ` Joel Fernandes
  0 siblings, 0 replies; 20+ messages in thread
From: Joel Fernandes @ 2019-02-21 17:17 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	rcu, Song Liu, Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 04:29:44PM +0100, Peter Zijlstra wrote:
> On Thu, Feb 21, 2019 at 10:10:57AM -0500, Joel Fernandes wrote:
> > Hi Peter,
> > 
> > Thanks for taking a look.
> > 
> > On Thu, Feb 21, 2019 at 10:19:44AM +0100, Peter Zijlstra wrote:
> > > On Thu, Feb 21, 2019 at 12:49:41AM -0500, Joel Fernandes (Google) wrote:
> > > 
> > > > Also replace rcu_assign_pointer call on rq->sd with WRITE_ONCE. This
> > > > should be sufficient for the rq->sd initialization.
> > > 
> > > > @@ -668,7 +668,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
> > > >  
> > > >  	rq_attach_root(rq, rd);
> > > >  	tmp = rq->sd;
> > > > -	rcu_assign_pointer(rq->sd, sd);
> > > > +	WRITE_ONCE(rq->sd, sd);
> > > >  	dirty_sched_domain_sysctl(cpu);
> > > >  	destroy_sched_domains(tmp);
> > > 
> > > Where did the RELEASE barrier go?
> > > 
> > > That was a publish operation, now it is not.
> > 
> > Funny thing is, initially I had written this patch with smp_store_release()
> > instead of WRITE_ONCE, but checkpatch complaints with that since it needs a
> > comment on top of it, and I wasn't sure if RELEASE barrier was the intent of
> > using rcu_assign_pointer (all the more reason to replace it with something
> > more explicit).
> > 
> > I will replace it with the following and resubmit it then:
> > 
> > /* Release barrier */
> > smp_store_release(&rq->sd, sd);
> > 
> > Or do we want to just drop the "Release barrier" comment and live with the
> > checkpatch warning?
> 
> How about we keep using rcu_assign_pointer(), the whole sched domain
> tree is under rcu; peruse that destroy_sched_domains() function for
> instance.
> 
> Also check how for_each_domain() uses rcu_dereference().

May be then, all those pointers should be made __rcu as well. Then we can use
rcu_assign_pointer() here. I will look more into it and study these functions
as you are suggesting.

thanks,

- Joel


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21 17:13             ` Joel Fernandes
@ 2019-02-21 17:29               ` Paul E. McKenney
  0 siblings, 0 replies; 20+ messages in thread
From: Paul E. McKenney @ 2019-02-21 17:29 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: Peter Zijlstra, linux-kernel, Alexei Starovoitov,
	Christian Brauner, Daniel Borkmann, David Ahern, David S. Miller,
	Ido Schimmel, Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, rcu, Song Liu,
	Steven Rostedt, xdp-newbies, Yonghong Song

On Thu, Feb 21, 2019 at 12:13:11PM -0500, Joel Fernandes wrote:
> On Thu, Feb 21, 2019 at 05:11:44PM +0100, Peter Zijlstra wrote:
> > On Thu, Feb 21, 2019 at 07:52:18AM -0800, Paul E. McKenney wrote:
> > > On Thu, Feb 21, 2019 at 04:31:17PM +0100, Peter Zijlstra wrote:
> > > > On Thu, Feb 21, 2019 at 10:21:39AM -0500, Joel Fernandes wrote:
> > > > > On Thu, Feb 21, 2019 at 10:18:05AM +0100, Peter Zijlstra wrote:
> > > > > > On Thu, Feb 21, 2019 at 12:49:40AM -0500, Joel Fernandes (Google) wrote:
> > > > > > > @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
> > > > > > >  	if (WARN_ON(!data || !func))
> > > > > > >  		return;
> > > > > > >  
> > > > > > > -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> > > > > > > +	rcu_read_lock();
> > > > > > > +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> > > > > > > +		rcu_read_unlock();
> > > > > > >  		return;
> > > > > > > +	}
> > > > > > > +	rcu_read_unlock();
> > > > > > >  
> > > > > > >  	data->func = func;
> > > > > > >  	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
> > 
> > > For whatever it is worth, in that case it could use rcu_access_pointer().
> > > And this primitive does not do the lockdep check for being within an RCU
> > > read-side critical section.  As Peter says, if there is no dereferencing,
> > > there can be no use-after-free bug, so the RCU read-side critical is
> > > not needed.
> > 
> > On top of that, I suspect this is under the write-side lock (we're doing
> > assignment after all).
> 
> Yes it is under a policy->rwsem, just confirmed that.
> 
> And indeed rcu_read_lock() is not needed here in this patch, thanks for
> pointing that out. Sometimes the word "dereference" plays some visual tricks
> and in this case tempted me to add an RCU reader section ;-) Assuming you
> guys are in agreement with usage of rcu_access_pointer() here to keep sparse
> happy, I'll rework the patch accordingly and resubmit with that.

Works for me!

							Thanx, Paul


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH RFC 3/5] sched/cpufreq: Fix incorrect RCU API usage
  2019-02-21  5:49 ` [PATCH RFC 3/5] sched/cpufreq: " Joel Fernandes (Google)
  2019-02-21  9:18   ` Peter Zijlstra
  2019-02-21 16:17   ` Steven Rostedt
@ 2019-02-21 23:05   ` Rafael J. Wysocki
  2 siblings, 0 replies; 20+ messages in thread
From: Rafael J. Wysocki @ 2019-02-21 23:05 UTC (permalink / raw)
  To: Joel Fernandes (Google)
  Cc: linux-kernel, Alexei Starovoitov, Christian Brauner,
	Daniel Borkmann, David Ahern, David S. Miller, Ido Schimmel,
	Ingo Molnar, moderated list:INTEL ETHERNET DRIVERS,
	Jakub Kicinski, Jeff Kirsher, Jesper Dangaard Brouer,
	John Fastabend, Josh Triplett, keescook, Lai Jiangshan,
	Martin KaFai Lau, Mathieu Desnoyers, netdev, Paul E. McKenney,
	Peter Zijlstra, rcu, Song Liu, Steven Rostedt, xdp-newbies,
	Yonghong Song

On Thursday, February 21, 2019 6:49:40 AM CET Joel Fernandes (Google) wrote:
> Recently I added an RCU annotation check to rcu_assign_pointer(). All
> pointers assigned to RCU protected data are to be annotated with __rcu
> inorder to be able to use rcu_assign_pointer() similar to checks in
> other RCU APIs.
> 
> This resulted in a sparse error: kernel//sched/cpufreq.c:41:9: sparse:
> error: incompatible types in comparison expression (different address
> spaces)
> 
> Fix this by using the correct APIs for RCU accesses. This will
> potentially avoid any future bugs in the code. If it is felt that RCU
> protection is not needed here, then the rcu_assign_pointer call can be
> dropped and replaced with, say, WRITE_ONCE or smp_store_release. Or, may
> be we add a new API to do it. But calls rcu_assign_pointer seems an
> abuse of the RCU API unless RCU is being used.
> 
> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
> ---
>  kernel/sched/cpufreq.c | 8 ++++++--
>  kernel/sched/sched.h   | 2 +-
>  2 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c
> index 22bd8980f32f..c9aeb3bf5dc2 100644
> --- a/kernel/sched/cpufreq.c
> +++ b/kernel/sched/cpufreq.c
> @@ -7,7 +7,7 @@
>   */
>  #include "sched.h"
>  
> -DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
> +DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
>  
>  /**
>   * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer.
> @@ -34,8 +34,12 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
>  	if (WARN_ON(!data || !func))
>  		return;
>  
> -	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
> +	rcu_read_lock();
> +	if (WARN_ON(rcu_dereference(per_cpu(cpufreq_update_util_data, cpu)))) {
> +		rcu_read_unlock();
>  		return;
> +	}
> +	rcu_read_unlock();

As Steve said, this is not a read-side critical section, so the rcu_read_lock()
and rcu_read_unlock() don't help.

But rcu_access_pointer() should work here AFAICS.

Cheers,
Rafael


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2019-02-21 23:06 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-21  5:49 [PATCH RFC 0/5] RCU fixes for rcu_assign_pointer() usage Joel Fernandes (Google)
2019-02-21  5:49 ` [PATCH RFC 1/5] net: rtnetlink: Fix incorrect RCU API usage Joel Fernandes (Google)
2019-02-21  5:49 ` [PATCH RFC 2/5] ixgbe: " Joel Fernandes (Google)
2019-02-21  5:49 ` [PATCH RFC 3/5] sched/cpufreq: " Joel Fernandes (Google)
2019-02-21  9:18   ` Peter Zijlstra
2019-02-21 15:21     ` Joel Fernandes
2019-02-21 15:31       ` Peter Zijlstra
2019-02-21 15:52         ` Paul E. McKenney
2019-02-21 16:11           ` Peter Zijlstra
2019-02-21 17:13             ` Joel Fernandes
2019-02-21 17:29               ` Paul E. McKenney
2019-02-21 16:17   ` Steven Rostedt
2019-02-21 23:05   ` Rafael J. Wysocki
2019-02-21  5:49 ` [PATCH RFC 4/5] sched/topology: Annonate RCU pointers properly Joel Fernandes (Google)
2019-02-21  9:19   ` Peter Zijlstra
2019-02-21 15:10     ` Joel Fernandes
2019-02-21 15:29       ` Peter Zijlstra
2019-02-21 17:17         ` Joel Fernandes
2019-02-21  5:49 ` [PATCH RFC 5/5] rcuwait: Replace rcu_assign_pointer() with WRITE_ONCE Joel Fernandes (Google)
2019-02-21  9:20   ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).