From 064e4c9e660d248088f6d40184482abd3435fbb5 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 7 Feb 2020 11:10:37 -0500 Subject: [PATCH] fixes for 4.14 Signed-off-by: Sasha Levin --- ...nt-to-why-rcu_dereference_sched-is-o.patch | 53 +++++++ ...t-ftrace_graph_hash-with-ftrace_sync.patch | 71 +++++++++ .../padata-remove-broken-queue-flushing.patch | 144 ++++++++++++++++++ queue-4.14/series | 5 + ...-ftrace_graph_hash-pointer-with-__rc.patch | 77 ++++++++++ ...-ftrace_graph_notrace_hash-pointer-w.patch | 72 +++++++++ 6 files changed, 422 insertions(+) create mode 100644 queue-4.14/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch create mode 100644 queue-4.14/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch create mode 100644 queue-4.14/padata-remove-broken-queue-flushing.patch create mode 100644 queue-4.14/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch create mode 100644 queue-4.14/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch diff --git a/queue-4.14/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch b/queue-4.14/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch new file mode 100644 index 00000000000..699a07dcb18 --- /dev/null +++ b/queue-4.14/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch @@ -0,0 +1,53 @@ +From 21ccac67ac9ab65faad677e9f247dbe5294c857d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2020 02:17:57 -0500 +Subject: ftrace: Add comment to why rcu_dereference_sched() is open coded + +From: Steven Rostedt (VMware) + +[ Upstream commit 16052dd5bdfa16dbe18d8c1d4cde2ddab9d23177 ] + +Because the function graph tracer can execute in sections where RCU is not +"watching", the rcu_dereference_sched() for the has needs to be open coded. +This is fine because the RCU "flavor" of the ftrace hash is protected by +its own RCU handling (it does its own little synchronization on every CPU +and does not rely on RCU sched). + +Acked-by: Joel Fernandes (Google) +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 757bb1bffed99..99af95e294d8d 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -879,6 +879,11 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + + preempt_disable_notrace(); + ++ /* ++ * Have to open code "rcu_dereference_sched()" because the ++ * function graph tracer can be called when RCU is not ++ * "watching". ++ */ + hash = rcu_dereference_protected(ftrace_graph_hash, !preemptible()); + + if (ftrace_hash_empty(hash)) { +@@ -926,6 +931,11 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr) + + preempt_disable_notrace(); + ++ /* ++ * Have to open code "rcu_dereference_sched()" because the ++ * function graph tracer can be called when RCU is not ++ * "watching". ++ */ + notrace_hash = rcu_dereference_protected(ftrace_graph_notrace_hash, + !preemptible()); + +-- +2.20.1 + diff --git a/queue-4.14/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch b/queue-4.14/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch new file mode 100644 index 00000000000..0f49e9c92e8 --- /dev/null +++ b/queue-4.14/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch @@ -0,0 +1,71 @@ +From ad59a417aff22bb3fe5824463c6a05761c480b3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2020 09:20:32 -0500 +Subject: ftrace: Protect ftrace_graph_hash with ftrace_sync + +From: Steven Rostedt (VMware) + +[ Upstream commit 54a16ff6f2e50775145b210bcd94d62c3c2af117 ] + +As function_graph tracer can run when RCU is not "watching", it can not be +protected by synchronize_rcu() it requires running a task on each CPU before +it can be freed. Calling schedule_on_each_cpu(ftrace_sync) needs to be used. + +Link: https://lore.kernel.org/r/20200205131110.GT2935@paulmck-ThinkPad-P72 + +Cc: stable@vger.kernel.org +Fixes: b9b0c831bed26 ("ftrace: Convert graph filter to use hash tables") +Reported-by: "Paul E. McKenney" +Reviewed-by: Joel Fernandes (Google) +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/ftrace.c | 11 +++++++++-- + kernel/trace/trace.h | 2 ++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index dd9fdb52e24ad..8974ecbcca3cb 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -5419,8 +5419,15 @@ ftrace_graph_release(struct inode *inode, struct file *file) + + mutex_unlock(&graph_lock); + +- /* Wait till all users are no longer using the old hash */ +- synchronize_sched(); ++ /* ++ * We need to do a hard force of sched synchronization. ++ * This is because we use preempt_disable() to do RCU, but ++ * the function tracers can be called where RCU is not watching ++ * (like before user_exit()). We can not rely on the RCU ++ * infrastructure to do the synchronization, thus we must do it ++ * ourselves. ++ */ ++ schedule_on_each_cpu(ftrace_sync); + + free_ftrace_hash(old_hash); + } +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 99af95e294d8d..c4c61ebb8d054 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -883,6 +883,7 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + * Have to open code "rcu_dereference_sched()" because the + * function graph tracer can be called when RCU is not + * "watching". ++ * Protected with schedule_on_each_cpu(ftrace_sync) + */ + hash = rcu_dereference_protected(ftrace_graph_hash, !preemptible()); + +@@ -935,6 +936,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr) + * Have to open code "rcu_dereference_sched()" because the + * function graph tracer can be called when RCU is not + * "watching". ++ * Protected with schedule_on_each_cpu(ftrace_sync) + */ + notrace_hash = rcu_dereference_protected(ftrace_graph_notrace_hash, + !preemptible()); +-- +2.20.1 + diff --git a/queue-4.14/padata-remove-broken-queue-flushing.patch b/queue-4.14/padata-remove-broken-queue-flushing.patch new file mode 100644 index 00000000000..99ae55a54ac --- /dev/null +++ b/queue-4.14/padata-remove-broken-queue-flushing.patch @@ -0,0 +1,144 @@ +From b382112579378624c4dff73beef511ca530d8326 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Nov 2019 13:17:31 +0800 +Subject: padata: Remove broken queue flushing + +From: Herbert Xu + +[ Upstream commit 07928d9bfc81640bab36f5190e8725894d93b659 ] + +The function padata_flush_queues is fundamentally broken because +it cannot force padata users to complete the request that is +underway. IOW padata has to passively wait for the completion +of any outstanding work. + +As it stands flushing is used in two places. Its use in padata_stop +is simply unnecessary because nothing depends on the queues to +be flushed afterwards. + +The other use in padata_replace is more substantial as we depend +on it to free the old pd structure. This patch instead uses the +pd->refcnt to dynamically free the pd structure once all requests +are complete. + +Fixes: 2b73b07ab8a4 ("padata: Flush the padata queues actively") +Cc: +Signed-off-by: Herbert Xu +Reviewed-by: Daniel Jordan +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + kernel/padata.c | 46 ++++++++++++---------------------------------- + 1 file changed, 12 insertions(+), 34 deletions(-) + +diff --git a/kernel/padata.c b/kernel/padata.c +index 87540ce72aea6..ef4ba3d664dab 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -34,6 +34,8 @@ + + #define MAX_OBJ_NUM 1000 + ++static void padata_free_pd(struct parallel_data *pd); ++ + static int padata_index_to_cpu(struct parallel_data *pd, int cpu_index) + { + int cpu, target_cpu; +@@ -292,6 +294,7 @@ static void padata_serial_worker(struct work_struct *serial_work) + struct padata_serial_queue *squeue; + struct parallel_data *pd; + LIST_HEAD(local_list); ++ int cnt; + + local_bh_disable(); + squeue = container_of(serial_work, struct padata_serial_queue, work); +@@ -301,6 +304,8 @@ static void padata_serial_worker(struct work_struct *serial_work) + list_replace_init(&squeue->serial.list, &local_list); + spin_unlock(&squeue->serial.lock); + ++ cnt = 0; ++ + while (!list_empty(&local_list)) { + struct padata_priv *padata; + +@@ -310,9 +315,12 @@ static void padata_serial_worker(struct work_struct *serial_work) + list_del_init(&padata->list); + + padata->serial(padata); +- atomic_dec(&pd->refcnt); ++ cnt++; + } + local_bh_enable(); ++ ++ if (atomic_sub_and_test(cnt, &pd->refcnt)) ++ padata_free_pd(pd); + } + + /** +@@ -435,8 +443,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst, + setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd); + atomic_set(&pd->seq_nr, -1); + atomic_set(&pd->reorder_objects, 0); +- atomic_set(&pd->refcnt, 0); +- pd->pinst = pinst; ++ atomic_set(&pd->refcnt, 1); + spin_lock_init(&pd->lock); + + return pd; +@@ -460,31 +467,6 @@ static void padata_free_pd(struct parallel_data *pd) + kfree(pd); + } + +-/* Flush all objects out of the padata queues. */ +-static void padata_flush_queues(struct parallel_data *pd) +-{ +- int cpu; +- struct padata_parallel_queue *pqueue; +- struct padata_serial_queue *squeue; +- +- for_each_cpu(cpu, pd->cpumask.pcpu) { +- pqueue = per_cpu_ptr(pd->pqueue, cpu); +- flush_work(&pqueue->work); +- } +- +- del_timer_sync(&pd->timer); +- +- if (atomic_read(&pd->reorder_objects)) +- padata_reorder(pd); +- +- for_each_cpu(cpu, pd->cpumask.cbcpu) { +- squeue = per_cpu_ptr(pd->squeue, cpu); +- flush_work(&squeue->work); +- } +- +- BUG_ON(atomic_read(&pd->refcnt) != 0); +-} +- + static void __padata_start(struct padata_instance *pinst) + { + pinst->flags |= PADATA_INIT; +@@ -498,10 +480,6 @@ static void __padata_stop(struct padata_instance *pinst) + pinst->flags &= ~PADATA_INIT; + + synchronize_rcu(); +- +- get_online_cpus(); +- padata_flush_queues(pinst->pd); +- put_online_cpus(); + } + + /* Replace the internal control structure with a new one. */ +@@ -522,8 +500,8 @@ static void padata_replace(struct padata_instance *pinst, + if (!cpumask_equal(pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu)) + notification_mask |= PADATA_CPU_SERIAL; + +- padata_flush_queues(pd_old); +- padata_free_pd(pd_old); ++ if (atomic_dec_and_test(&pd_old->refcnt)) ++ padata_free_pd(pd_old); + + if (notification_mask) + blocking_notifier_call_chain(&pinst->cpumask_change_notifier, +-- +2.20.1 + diff --git a/queue-4.14/series b/queue-4.14/series index 43d2a91c7c8..f23160d69c2 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -54,3 +54,8 @@ of-add-of_dma_default_coherent-select-it-on-powerpc.patch dm-zoned-support-zone-sizes-smaller-than-128mib.patch dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch dm-crypt-fix-benbi-iv-constructor-crash-if-used-in-authenticated-mode.patch +padata-remove-broken-queue-flushing.patch +tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch +tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch +ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch +ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch diff --git a/queue-4.14/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch b/queue-4.14/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch new file mode 100644 index 00000000000..d53dbb9064b --- /dev/null +++ b/queue-4.14/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch @@ -0,0 +1,77 @@ +From d1f1e884e2214ae1764557f30d0735dfd9e99020 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Feb 2020 12:57:04 +0530 +Subject: tracing: Annotate ftrace_graph_hash pointer with __rcu + +From: Amol Grover + +[ Upstream commit 24a9729f831462b1d9d61dc85ecc91c59037243f ] + +Fix following instances of sparse error +kernel/trace/ftrace.c:5664:29: error: incompatible types in comparison +kernel/trace/ftrace.c:5785:21: error: incompatible types in comparison +kernel/trace/ftrace.c:5864:36: error: incompatible types in comparison +kernel/trace/ftrace.c:5866:25: error: incompatible types in comparison + +Use rcu_dereference_protected to access the __rcu annotated pointer. + +Link: http://lkml.kernel.org/r/20200201072703.17330-1-frextrite@gmail.com + +Reviewed-by: Joel Fernandes (Google) +Signed-off-by: Amol Grover +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/ftrace.c | 2 +- + kernel/trace/trace.h | 9 ++++++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 3864d23414429..6af28692f0f53 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -5146,7 +5146,7 @@ static const struct file_operations ftrace_notrace_fops = { + + static DEFINE_MUTEX(graph_lock); + +-struct ftrace_hash *ftrace_graph_hash = EMPTY_HASH; ++struct ftrace_hash __rcu *ftrace_graph_hash = EMPTY_HASH; + struct ftrace_hash *ftrace_graph_notrace_hash = EMPTY_HASH; + + enum graph_filter_type { +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index dbb212c40a410..17f36488d3c84 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -868,22 +868,25 @@ extern void __trace_graph_return(struct trace_array *tr, + unsigned long flags, int pc); + + #ifdef CONFIG_DYNAMIC_FTRACE +-extern struct ftrace_hash *ftrace_graph_hash; ++extern struct ftrace_hash __rcu *ftrace_graph_hash; + extern struct ftrace_hash *ftrace_graph_notrace_hash; + + static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + { + unsigned long addr = trace->func; + int ret = 0; ++ struct ftrace_hash *hash; + + preempt_disable_notrace(); + +- if (ftrace_hash_empty(ftrace_graph_hash)) { ++ hash = rcu_dereference_protected(ftrace_graph_hash, !preemptible()); ++ ++ if (ftrace_hash_empty(hash)) { + ret = 1; + goto out; + } + +- if (ftrace_lookup_ip(ftrace_graph_hash, addr)) { ++ if (ftrace_lookup_ip(hash, addr)) { + + /* + * This needs to be cleared on the return functions +-- +2.20.1 + diff --git a/queue-4.14/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch b/queue-4.14/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch new file mode 100644 index 00000000000..90559af67b9 --- /dev/null +++ b/queue-4.14/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch @@ -0,0 +1,72 @@ +From f150cce7fb6956762036b60fe498040f69c2f637 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2020 11:27:02 +0530 +Subject: tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu + +From: Amol Grover + +[ Upstream commit fd0e6852c407dd9aefc594f54ddcc21d84803d3b ] + +Fix following instances of sparse error +kernel/trace/ftrace.c:5667:29: error: incompatible types in comparison +kernel/trace/ftrace.c:5813:21: error: incompatible types in comparison +kernel/trace/ftrace.c:5868:36: error: incompatible types in comparison +kernel/trace/ftrace.c:5870:25: error: incompatible types in comparison + +Use rcu_dereference_protected to dereference the newly annotated pointer. + +Link: http://lkml.kernel.org/r/20200205055701.30195-1-frextrite@gmail.com + +Signed-off-by: Amol Grover +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/ftrace.c | 2 +- + kernel/trace/trace.h | 8 ++++++-- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 6af28692f0f53..dd9fdb52e24ad 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -5147,7 +5147,7 @@ static const struct file_operations ftrace_notrace_fops = { + static DEFINE_MUTEX(graph_lock); + + struct ftrace_hash __rcu *ftrace_graph_hash = EMPTY_HASH; +-struct ftrace_hash *ftrace_graph_notrace_hash = EMPTY_HASH; ++struct ftrace_hash __rcu *ftrace_graph_notrace_hash = EMPTY_HASH; + + enum graph_filter_type { + GRAPH_FILTER_NOTRACE = 0, +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 17f36488d3c84..757bb1bffed99 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -869,7 +869,7 @@ extern void __trace_graph_return(struct trace_array *tr, + + #ifdef CONFIG_DYNAMIC_FTRACE + extern struct ftrace_hash __rcu *ftrace_graph_hash; +-extern struct ftrace_hash *ftrace_graph_notrace_hash; ++extern struct ftrace_hash __rcu *ftrace_graph_notrace_hash; + + static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + { +@@ -922,10 +922,14 @@ static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace) + static inline int ftrace_graph_notrace_addr(unsigned long addr) + { + int ret = 0; ++ struct ftrace_hash *notrace_hash; + + preempt_disable_notrace(); + +- if (ftrace_lookup_ip(ftrace_graph_notrace_hash, addr)) ++ notrace_hash = rcu_dereference_protected(ftrace_graph_notrace_hash, ++ !preemptible()); ++ ++ if (ftrace_lookup_ip(notrace_hash, addr)) + ret = 1; + + preempt_enable_notrace(); +-- +2.20.1 + -- 2.47.3