diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 79 |
1 files changed, 59 insertions, 20 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 4c97947650ae..0c1dc1850858 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -45,6 +45,12 @@ unsigned long __read_mostly tracing_max_latency; | |||
45 | unsigned long __read_mostly tracing_thresh; | 45 | unsigned long __read_mostly tracing_thresh; |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * On boot up, the ring buffer is set to the minimum size, so that | ||
49 | * we do not waste memory on systems that are not using tracing. | ||
50 | */ | ||
51 | static int ring_buffer_expanded; | ||
52 | |||
53 | /* | ||
48 | * We need to change this state when a selftest is running. | 54 | * We need to change this state when a selftest is running. |
49 | * A selftest will lurk into the ring-buffer to count the | 55 | * A selftest will lurk into the ring-buffer to count the |
50 | * entries inserted during the selftest although some concurrent | 56 | * entries inserted during the selftest although some concurrent |
@@ -128,6 +134,8 @@ static int __init set_ftrace(char *str) | |||
128 | { | 134 | { |
129 | strncpy(bootup_tracer_buf, str, BOOTUP_TRACER_SIZE); | 135 | strncpy(bootup_tracer_buf, str, BOOTUP_TRACER_SIZE); |
130 | default_bootup_tracer = bootup_tracer_buf; | 136 | default_bootup_tracer = bootup_tracer_buf; |
137 | /* We are using ftrace early, expand it */ | ||
138 | ring_buffer_expanded = 1; | ||
131 | return 1; | 139 | return 1; |
132 | } | 140 | } |
133 | __setup("ftrace=", set_ftrace); | 141 | __setup("ftrace=", set_ftrace); |
@@ -2315,6 +2323,40 @@ int tracer_init(struct tracer *t, struct trace_array *tr) | |||
2315 | return t->init(tr); | 2323 | return t->init(tr); |
2316 | } | 2324 | } |
2317 | 2325 | ||
2326 | static int tracing_resize_ring_buffer(unsigned long size) | ||
2327 | { | ||
2328 | int ret; | ||
2329 | |||
2330 | /* | ||
2331 | * If kernel or user changes the size of the ring buffer | ||
2332 | * it get completed. | ||
2333 | */ | ||
2334 | ring_buffer_expanded = 1; | ||
2335 | |||
2336 | ret = ring_buffer_resize(global_trace.buffer, size); | ||
2337 | if (ret < 0) | ||
2338 | return ret; | ||
2339 | |||
2340 | ret = ring_buffer_resize(max_tr.buffer, size); | ||
2341 | if (ret < 0) { | ||
2342 | int r; | ||
2343 | |||
2344 | r = ring_buffer_resize(global_trace.buffer, | ||
2345 | global_trace.entries); | ||
2346 | if (r < 0) { | ||
2347 | /* AARGH! We are left with different | ||
2348 | * size max buffer!!!! */ | ||
2349 | WARN_ON(1); | ||
2350 | tracing_disabled = 1; | ||
2351 | } | ||
2352 | return ret; | ||
2353 | } | ||
2354 | |||
2355 | global_trace.entries = size; | ||
2356 | |||
2357 | return ret; | ||
2358 | } | ||
2359 | |||
2318 | struct trace_option_dentry; | 2360 | struct trace_option_dentry; |
2319 | 2361 | ||
2320 | static struct trace_option_dentry * | 2362 | static struct trace_option_dentry * |
@@ -2330,6 +2372,13 @@ static int tracing_set_tracer(const char *buf) | |||
2330 | struct tracer *t; | 2372 | struct tracer *t; |
2331 | int ret = 0; | 2373 | int ret = 0; |
2332 | 2374 | ||
2375 | if (!ring_buffer_expanded) { | ||
2376 | ret = tracing_resize_ring_buffer(trace_buf_size); | ||
2377 | if (ret < 0) | ||
2378 | return ret; | ||
2379 | ret = 0; | ||
2380 | } | ||
2381 | |||
2333 | mutex_lock(&trace_types_lock); | 2382 | mutex_lock(&trace_types_lock); |
2334 | for (t = trace_types; t; t = t->next) { | 2383 | for (t = trace_types; t; t = t->next) { |
2335 | if (strcmp(t->name, buf) == 0) | 2384 | if (strcmp(t->name, buf) == 0) |
@@ -2903,28 +2952,11 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2903 | val <<= 10; | 2952 | val <<= 10; |
2904 | 2953 | ||
2905 | if (val != global_trace.entries) { | 2954 | if (val != global_trace.entries) { |
2906 | ret = ring_buffer_resize(global_trace.buffer, val); | 2955 | ret = tracing_resize_ring_buffer(val); |
2907 | if (ret < 0) { | 2956 | if (ret < 0) { |
2908 | cnt = ret; | 2957 | cnt = ret; |
2909 | goto out; | 2958 | goto out; |
2910 | } | 2959 | } |
2911 | |||
2912 | ret = ring_buffer_resize(max_tr.buffer, val); | ||
2913 | if (ret < 0) { | ||
2914 | int r; | ||
2915 | cnt = ret; | ||
2916 | r = ring_buffer_resize(global_trace.buffer, | ||
2917 | global_trace.entries); | ||
2918 | if (r < 0) { | ||
2919 | /* AARGH! We are left with different | ||
2920 | * size max buffer!!!! */ | ||
2921 | WARN_ON(1); | ||
2922 | tracing_disabled = 1; | ||
2923 | } | ||
2924 | goto out; | ||
2925 | } | ||
2926 | |||
2927 | global_trace.entries = val; | ||
2928 | } | 2960 | } |
2929 | 2961 | ||
2930 | filp->f_pos += cnt; | 2962 | filp->f_pos += cnt; |
@@ -3916,6 +3948,7 @@ void ftrace_dump(void) | |||
3916 | __init static int tracer_alloc_buffers(void) | 3948 | __init static int tracer_alloc_buffers(void) |
3917 | { | 3949 | { |
3918 | struct trace_array_cpu *data; | 3950 | struct trace_array_cpu *data; |
3951 | int ring_buf_size; | ||
3919 | int i; | 3952 | int i; |
3920 | int ret = -ENOMEM; | 3953 | int ret = -ENOMEM; |
3921 | 3954 | ||
@@ -3928,12 +3961,18 @@ __init static int tracer_alloc_buffers(void) | |||
3928 | if (!alloc_cpumask_var(&tracing_reader_cpumask, GFP_KERNEL)) | 3961 | if (!alloc_cpumask_var(&tracing_reader_cpumask, GFP_KERNEL)) |
3929 | goto out_free_tracing_cpumask; | 3962 | goto out_free_tracing_cpumask; |
3930 | 3963 | ||
3964 | /* To save memory, keep the ring buffer size to its minimum */ | ||
3965 | if (ring_buffer_expanded) | ||
3966 | ring_buf_size = trace_buf_size; | ||
3967 | else | ||
3968 | ring_buf_size = 1; | ||
3969 | |||
3931 | cpumask_copy(tracing_buffer_mask, cpu_possible_mask); | 3970 | cpumask_copy(tracing_buffer_mask, cpu_possible_mask); |
3932 | cpumask_copy(tracing_cpumask, cpu_all_mask); | 3971 | cpumask_copy(tracing_cpumask, cpu_all_mask); |
3933 | cpumask_clear(tracing_reader_cpumask); | 3972 | cpumask_clear(tracing_reader_cpumask); |
3934 | 3973 | ||
3935 | /* TODO: make the number of buffers hot pluggable with CPUS */ | 3974 | /* TODO: make the number of buffers hot pluggable with CPUS */ |
3936 | global_trace.buffer = ring_buffer_alloc(trace_buf_size, | 3975 | global_trace.buffer = ring_buffer_alloc(ring_buf_size, |
3937 | TRACE_BUFFER_FLAGS); | 3976 | TRACE_BUFFER_FLAGS); |
3938 | if (!global_trace.buffer) { | 3977 | if (!global_trace.buffer) { |
3939 | printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); | 3978 | printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); |
@@ -3944,7 +3983,7 @@ __init static int tracer_alloc_buffers(void) | |||
3944 | 3983 | ||
3945 | 3984 | ||
3946 | #ifdef CONFIG_TRACER_MAX_TRACE | 3985 | #ifdef CONFIG_TRACER_MAX_TRACE |
3947 | max_tr.buffer = ring_buffer_alloc(trace_buf_size, | 3986 | max_tr.buffer = ring_buffer_alloc(ring_buf_size, |
3948 | TRACE_BUFFER_FLAGS); | 3987 | TRACE_BUFFER_FLAGS); |
3949 | if (!max_tr.buffer) { | 3988 | if (!max_tr.buffer) { |
3950 | printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n"); | 3989 | printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n"); |