Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'trace-fixes-v3.10-rc3-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fixes from Steven Rostedt:
"This contains 4 fixes.

The first two fix the case where full RCU debugging is enabled,
enabling function tracing causes a live lock of the system. This is
due to the added debug checks in rcu_dereference_raw() that is used by
the function tracer. These checks are also traced by the function
tracer as well as cause enough overhead to the function tracer to slow
down the system enough that the time to finish an interrupt can take
longer than when the next interrupt is triggered, causing a live lock
from the timer interrupt.

Talking this over with Paul McKenney, we came up with a fix that adds
a new rcu_dereference_raw_notrace() that does not perform these added
checks, and let the function tracer use that.

The third commit fixes a failed compile when branch tracing is
enabled, due to the conversion of the trace_test_buffer() selftest
that the branch trace wasn't converted for.

The forth patch fixes a bug caught by the RCU lockdep code where a
rcu_read_lock() is performed when rcu is disabled (either going to or
from idle, or user space). This happened on the irqsoff tracer as it
calls task_uid(). The fix here was to use current_uid() when possible
that doesn't use rcu locking. Which luckily, is always used when
irqsoff calls this code."

* tag 'trace-fixes-v3.10-rc3-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
tracing: Use current_uid() for critical time tracing
tracing: Fix bad parameter passed in branch selftest
ftrace: Use the rcu _notrace variants for rcu_dereference_raw() and friends
rcu: Add _notrace variation of rcu_dereference_raw() and hlist_for_each_entry_rcu()

+48 -11
+20
include/linux/rculist.h
··· 461 461 &(pos)->member)), typeof(*(pos)), member)) 462 462 463 463 /** 464 + * hlist_for_each_entry_rcu_notrace - iterate over rcu list of given type (for tracing) 465 + * @pos: the type * to use as a loop cursor. 466 + * @head: the head for your list. 467 + * @member: the name of the hlist_node within the struct. 468 + * 469 + * This list-traversal primitive may safely run concurrently with 470 + * the _rcu list-mutation primitives such as hlist_add_head_rcu() 471 + * as long as the traversal is guarded by rcu_read_lock(). 472 + * 473 + * This is the same as hlist_for_each_entry_rcu() except that it does 474 + * not do any RCU debugging or tracing. 475 + */ 476 + #define hlist_for_each_entry_rcu_notrace(pos, head, member) \ 477 + for (pos = hlist_entry_safe (rcu_dereference_raw_notrace(hlist_first_rcu(head)),\ 478 + typeof(*(pos)), member); \ 479 + pos; \ 480 + pos = hlist_entry_safe(rcu_dereference_raw_notrace(hlist_next_rcu(\ 481 + &(pos)->member)), typeof(*(pos)), member)) 482 + 483 + /** 464 484 * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type 465 485 * @pos: the type * to use as a loop cursor. 466 486 * @head: the head for your list.
+9
include/linux/rcupdate.h
··· 640 640 641 641 #define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/ 642 642 643 + /* 644 + * The tracing infrastructure traces RCU (we want that), but unfortunately 645 + * some of the RCU checks causes tracing to lock up the system. 646 + * 647 + * The tracing version of rcu_dereference_raw() must not call 648 + * rcu_read_lock_held(). 649 + */ 650 + #define rcu_dereference_raw_notrace(p) __rcu_dereference_check((p), 1, __rcu) 651 + 643 652 /** 644 653 * rcu_access_index() - fetch RCU index with no dereferencing 645 654 * @p: The index to read
+9 -9
kernel/trace/ftrace.c
··· 120 120 121 121 /* 122 122 * Traverse the ftrace_global_list, invoking all entries. The reason that we 123 - * can use rcu_dereference_raw() is that elements removed from this list 123 + * can use rcu_dereference_raw_notrace() is that elements removed from this list 124 124 * are simply leaked, so there is no need to interact with a grace-period 125 - * mechanism. The rcu_dereference_raw() calls are needed to handle 125 + * mechanism. The rcu_dereference_raw_notrace() calls are needed to handle 126 126 * concurrent insertions into the ftrace_global_list. 127 127 * 128 128 * Silly Alpha and silly pointer-speculation compiler optimizations! 129 129 */ 130 130 #define do_for_each_ftrace_op(op, list) \ 131 - op = rcu_dereference_raw(list); \ 131 + op = rcu_dereference_raw_notrace(list); \ 132 132 do 133 133 134 134 /* 135 135 * Optimized for just a single item in the list (as that is the normal case). 136 136 */ 137 137 #define while_for_each_ftrace_op(op) \ 138 - while (likely(op = rcu_dereference_raw((op)->next)) && \ 138 + while (likely(op = rcu_dereference_raw_notrace((op)->next)) && \ 139 139 unlikely((op) != &ftrace_list_end)) 140 140 141 141 static inline void ftrace_ops_init(struct ftrace_ops *ops) ··· 779 779 if (hlist_empty(hhd)) 780 780 return NULL; 781 781 782 - hlist_for_each_entry_rcu(rec, hhd, node) { 782 + hlist_for_each_entry_rcu_notrace(rec, hhd, node) { 783 783 if (rec->ip == ip) 784 784 return rec; 785 785 } ··· 1165 1165 1166 1166 hhd = &hash->buckets[key]; 1167 1167 1168 - hlist_for_each_entry_rcu(entry, hhd, hlist) { 1168 + hlist_for_each_entry_rcu_notrace(entry, hhd, hlist) { 1169 1169 if (entry->ip == ip) 1170 1170 return entry; 1171 1171 } ··· 1422 1422 struct ftrace_hash *notrace_hash; 1423 1423 int ret; 1424 1424 1425 - filter_hash = rcu_dereference_raw(ops->filter_hash); 1426 - notrace_hash = rcu_dereference_raw(ops->notrace_hash); 1425 + filter_hash = rcu_dereference_raw_notrace(ops->filter_hash); 1426 + notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash); 1427 1427 1428 1428 if ((ftrace_hash_empty(filter_hash) || 1429 1429 ftrace_lookup_ip(filter_hash, ip)) && ··· 2920 2920 * on the hash. rcu_read_lock is too dangerous here. 2921 2921 */ 2922 2922 preempt_disable_notrace(); 2923 - hlist_for_each_entry_rcu(entry, hhd, node) { 2923 + hlist_for_each_entry_rcu_notrace(entry, hhd, node) { 2924 2924 if (entry->ip == ip) 2925 2925 entry->ops->func(ip, parent_ip, &entry->data); 2926 2926 }
+9 -1
kernel/trace/trace.c
··· 843 843 844 844 memcpy(max_data->comm, tsk->comm, TASK_COMM_LEN); 845 845 max_data->pid = tsk->pid; 846 - max_data->uid = task_uid(tsk); 846 + /* 847 + * If tsk == current, then use current_uid(), as that does not use 848 + * RCU. The irq tracer can be called out of RCU scope. 849 + */ 850 + if (tsk == current) 851 + max_data->uid = current_uid(); 852 + else 853 + max_data->uid = task_uid(tsk); 854 + 847 855 max_data->nice = tsk->static_prio - 20 - MAX_RT_PRIO; 848 856 max_data->policy = tsk->policy; 849 857 max_data->rt_priority = tsk->rt_priority;
+1 -1
kernel/trace/trace_selftest.c
··· 1159 1159 /* stop the tracing. */ 1160 1160 tracing_stop(); 1161 1161 /* check the trace buffer */ 1162 - ret = trace_test_buffer(tr, &count); 1162 + ret = trace_test_buffer(&tr->trace_buffer, &count); 1163 1163 trace->reset(tr); 1164 1164 tracing_start(); 1165 1165