aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-28 03:02:49 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-28 03:02:49 -0500
commit4387d6d6b8a74722bf1f6fc3e29dd2a84cc1d1c2 (patch)
treeaaaff8ca13625da1823204e1fee29774117f7bc7
parentf701d354075914296474d062f18fc8ee681a2318 (diff)
parentda74ff0f9b31ed97104c22c278bf2b41bcf8f33c (diff)
Merge branch 'tracing/ftrace' into tracing/core
-rw-r--r--kernel/trace/trace.c368
1 files changed, 333 insertions, 35 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index bdaf60d3d337..5db7485158df 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1684,23 +1684,20 @@ static struct seq_operations tracer_seq_ops = {
1684}; 1684};
1685 1685
1686static struct trace_iterator * 1686static struct trace_iterator *
1687__tracing_open(struct inode *inode, struct file *file, int *ret) 1687__tracing_open(struct inode *inode, struct file *file)
1688{ 1688{
1689 long cpu_file = (long) inode->i_private; 1689 long cpu_file = (long) inode->i_private;
1690 void *fail_ret = ERR_PTR(-ENOMEM);
1690 struct trace_iterator *iter; 1691 struct trace_iterator *iter;
1691 struct seq_file *m; 1692 struct seq_file *m;
1692 int cpu; 1693 int cpu, ret;
1693 1694
1694 if (tracing_disabled) { 1695 if (tracing_disabled)
1695 *ret = -ENODEV; 1696 return ERR_PTR(-ENODEV);
1696 return NULL;
1697 }
1698 1697
1699 iter = kzalloc(sizeof(*iter), GFP_KERNEL); 1698 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
1700 if (!iter) { 1699 if (!iter)
1701 *ret = -ENOMEM; 1700 return ERR_PTR(-ENOMEM);
1702 goto out;
1703 }
1704 1701
1705 /* 1702 /*
1706 * We make a copy of the current tracer to avoid concurrent 1703 * We make a copy of the current tracer to avoid concurrent
@@ -1708,10 +1705,9 @@ __tracing_open(struct inode *inode, struct file *file, int *ret)
1708 */ 1705 */
1709 mutex_lock(&trace_types_lock); 1706 mutex_lock(&trace_types_lock);
1710 iter->trace = kzalloc(sizeof(*iter->trace), GFP_KERNEL); 1707 iter->trace = kzalloc(sizeof(*iter->trace), GFP_KERNEL);
1711 if (!iter->trace) { 1708 if (!iter->trace)
1712 *ret = -ENOMEM;
1713 goto fail; 1709 goto fail;
1714 } 1710
1715 if (current_trace) 1711 if (current_trace)
1716 *iter->trace = *current_trace; 1712 *iter->trace = *current_trace;
1717 1713
@@ -1750,9 +1746,11 @@ __tracing_open(struct inode *inode, struct file *file, int *ret)
1750 } 1746 }
1751 1747
1752 /* TODO stop tracer */ 1748 /* TODO stop tracer */
1753 *ret = seq_open(file, &tracer_seq_ops); 1749 ret = seq_open(file, &tracer_seq_ops);
1754 if (*ret) 1750 if (ret < 0) {
1751 fail_ret = ERR_PTR(ret);
1755 goto fail_buffer; 1752 goto fail_buffer;
1753 }
1756 1754
1757 m = file->private_data; 1755 m = file->private_data;
1758 m->private = iter; 1756 m->private = iter;
@@ -1762,7 +1760,6 @@ __tracing_open(struct inode *inode, struct file *file, int *ret)
1762 1760
1763 mutex_unlock(&trace_types_lock); 1761 mutex_unlock(&trace_types_lock);
1764 1762
1765 out:
1766 return iter; 1763 return iter;
1767 1764
1768 fail_buffer: 1765 fail_buffer:
@@ -1775,7 +1772,7 @@ __tracing_open(struct inode *inode, struct file *file, int *ret)
1775 kfree(iter->trace); 1772 kfree(iter->trace);
1776 kfree(iter); 1773 kfree(iter);
1777 1774
1778 return ERR_PTR(-ENOMEM); 1775 return fail_ret;
1779} 1776}
1780 1777
1781int tracing_open_generic(struct inode *inode, struct file *filp) 1778int tracing_open_generic(struct inode *inode, struct file *filp)
@@ -1815,9 +1812,12 @@ static int tracing_release(struct inode *inode, struct file *file)
1815 1812
1816static int tracing_open(struct inode *inode, struct file *file) 1813static int tracing_open(struct inode *inode, struct file *file)
1817{ 1814{
1818 int ret; 1815 struct trace_iterator *iter;
1816 int ret = 0;
1819 1817
1820 __tracing_open(inode, file, &ret); 1818 iter = __tracing_open(inode, file);
1819 if (IS_ERR(iter))
1820 ret = PTR_ERR(iter);
1821 1821
1822 return ret; 1822 return ret;
1823} 1823}
@@ -1825,11 +1825,13 @@ static int tracing_open(struct inode *inode, struct file *file)
1825static int tracing_lt_open(struct inode *inode, struct file *file) 1825static int tracing_lt_open(struct inode *inode, struct file *file)
1826{ 1826{
1827 struct trace_iterator *iter; 1827 struct trace_iterator *iter;
1828 int ret; 1828 int ret = 0;
1829 1829
1830 iter = __tracing_open(inode, file, &ret); 1830 iter = __tracing_open(inode, file);
1831 1831
1832 if (!ret) 1832 if (IS_ERR(iter))
1833 ret = PTR_ERR(iter);
1834 else
1833 iter->iter_flags |= TRACE_FILE_LAT_FMT; 1835 iter->iter_flags |= TRACE_FILE_LAT_FMT;
1834 1836
1835 return ret; 1837 return ret;
@@ -2024,57 +2026,62 @@ static ssize_t
2024tracing_trace_options_read(struct file *filp, char __user *ubuf, 2026tracing_trace_options_read(struct file *filp, char __user *ubuf,
2025 size_t cnt, loff_t *ppos) 2027 size_t cnt, loff_t *ppos)
2026{ 2028{
2027 int i; 2029 struct tracer_opt *trace_opts;
2030 u32 tracer_flags;
2031 int len = 0;
2028 char *buf; 2032 char *buf;
2029 int r = 0; 2033 int r = 0;
2030 int len = 0; 2034 int i;
2031 u32 tracer_flags = current_trace->flags->val;
2032 struct tracer_opt *trace_opts = current_trace->flags->opts;
2033 2035
2034 2036
2035 /* calculate max size */ 2037 /* calculate max size */
2036 for (i = 0; trace_options[i]; i++) { 2038 for (i = 0; trace_options[i]; i++) {
2037 len += strlen(trace_options[i]); 2039 len += strlen(trace_options[i]);
2038 len += 3; /* "no" and space */ 2040 len += 3; /* "no" and newline */
2039 } 2041 }
2040 2042
2043 mutex_lock(&trace_types_lock);
2044 tracer_flags = current_trace->flags->val;
2045 trace_opts = current_trace->flags->opts;
2046
2041 /* 2047 /*
2042 * Increase the size with names of options specific 2048 * Increase the size with names of options specific
2043 * of the current tracer. 2049 * of the current tracer.
2044 */ 2050 */
2045 for (i = 0; trace_opts[i].name; i++) { 2051 for (i = 0; trace_opts[i].name; i++) {
2046 len += strlen(trace_opts[i].name); 2052 len += strlen(trace_opts[i].name);
2047 len += 3; /* "no" and space */ 2053 len += 3; /* "no" and newline */
2048 } 2054 }
2049 2055
2050 /* +2 for \n and \0 */ 2056 /* +2 for \n and \0 */
2051 buf = kmalloc(len + 2, GFP_KERNEL); 2057 buf = kmalloc(len + 2, GFP_KERNEL);
2052 if (!buf) 2058 if (!buf) {
2059 mutex_unlock(&trace_types_lock);
2053 return -ENOMEM; 2060 return -ENOMEM;
2061 }
2054 2062
2055 for (i = 0; trace_options[i]; i++) { 2063 for (i = 0; trace_options[i]; i++) {
2056 if (trace_flags & (1 << i)) 2064 if (trace_flags & (1 << i))
2057 r += sprintf(buf + r, "%s ", trace_options[i]); 2065 r += sprintf(buf + r, "%s\n", trace_options[i]);
2058 else 2066 else
2059 r += sprintf(buf + r, "no%s ", trace_options[i]); 2067 r += sprintf(buf + r, "no%s\n", trace_options[i]);
2060 } 2068 }
2061 2069
2062 for (i = 0; trace_opts[i].name; i++) { 2070 for (i = 0; trace_opts[i].name; i++) {
2063 if (tracer_flags & trace_opts[i].bit) 2071 if (tracer_flags & trace_opts[i].bit)
2064 r += sprintf(buf + r, "%s ", 2072 r += sprintf(buf + r, "%s\n",
2065 trace_opts[i].name); 2073 trace_opts[i].name);
2066 else 2074 else
2067 r += sprintf(buf + r, "no%s ", 2075 r += sprintf(buf + r, "no%s\n",
2068 trace_opts[i].name); 2076 trace_opts[i].name);
2069 } 2077 }
2078 mutex_unlock(&trace_types_lock);
2070 2079
2071 r += sprintf(buf + r, "\n");
2072 WARN_ON(r >= len + 2); 2080 WARN_ON(r >= len + 2);
2073 2081
2074 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 2082 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2075 2083
2076 kfree(buf); 2084 kfree(buf);
2077
2078 return r; 2085 return r;
2079} 2086}
2080 2087
@@ -2149,7 +2156,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2149 2156
2150 /* If no option could be set, test the specific tracer options */ 2157 /* If no option could be set, test the specific tracer options */
2151 if (!trace_options[i]) { 2158 if (!trace_options[i]) {
2159 mutex_lock(&trace_types_lock);
2152 ret = set_tracer_option(current_trace, cmp, neg); 2160 ret = set_tracer_option(current_trace, cmp, neg);
2161 mutex_unlock(&trace_types_lock);
2153 if (ret) 2162 if (ret)
2154 return ret; 2163 return ret;
2155 } 2164 }
@@ -2275,8 +2284,17 @@ int tracer_init(struct tracer *t, struct trace_array *tr)
2275 return t->init(tr); 2284 return t->init(tr);
2276} 2285}
2277 2286
2287struct trace_option_dentry;
2288
2289static struct trace_option_dentry *
2290create_trace_option_files(struct tracer *tracer);
2291
2292static void
2293destroy_trace_option_files(struct trace_option_dentry *topts);
2294
2278static int tracing_set_tracer(const char *buf) 2295static int tracing_set_tracer(const char *buf)
2279{ 2296{
2297 static struct trace_option_dentry *topts;
2280 struct trace_array *tr = &global_trace; 2298 struct trace_array *tr = &global_trace;
2281 struct tracer *t; 2299 struct tracer *t;
2282 int ret = 0; 2300 int ret = 0;
@@ -2297,7 +2315,12 @@ static int tracing_set_tracer(const char *buf)
2297 if (current_trace && current_trace->reset) 2315 if (current_trace && current_trace->reset)
2298 current_trace->reset(tr); 2316 current_trace->reset(tr);
2299 2317
2318 destroy_trace_option_files(topts);
2319
2300 current_trace = t; 2320 current_trace = t;
2321
2322 topts = create_trace_option_files(current_trace);
2323
2301 if (t->init) { 2324 if (t->init) {
2302 ret = tracer_init(t, tr); 2325 ret = tracer_init(t, tr);
2303 if (ret) 2326 if (ret)
@@ -3093,6 +3116,279 @@ static void tracing_init_debugfs_percpu(long cpu)
3093#include "trace_selftest.c" 3116#include "trace_selftest.c"
3094#endif 3117#endif
3095 3118
3119struct trace_option_dentry {
3120 struct tracer_opt *opt;
3121 struct tracer_flags *flags;
3122 struct dentry *entry;
3123};
3124
3125static ssize_t
3126trace_options_read(struct file *filp, char __user *ubuf, size_t cnt,
3127 loff_t *ppos)
3128{
3129 struct trace_option_dentry *topt = filp->private_data;
3130 char *buf;
3131
3132 if (topt->flags->val & topt->opt->bit)
3133 buf = "1\n";
3134 else
3135 buf = "0\n";
3136
3137 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
3138}
3139
3140static ssize_t
3141trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
3142 loff_t *ppos)
3143{
3144 struct trace_option_dentry *topt = filp->private_data;
3145 unsigned long val;
3146 char buf[64];
3147 int ret;
3148
3149 if (cnt >= sizeof(buf))
3150 return -EINVAL;
3151
3152 if (copy_from_user(&buf, ubuf, cnt))
3153 return -EFAULT;
3154
3155 buf[cnt] = 0;
3156
3157 ret = strict_strtoul(buf, 10, &val);
3158 if (ret < 0)
3159 return ret;
3160
3161 ret = 0;
3162 switch (val) {
3163 case 0:
3164 /* do nothing if already cleared */
3165 if (!(topt->flags->val & topt->opt->bit))
3166 break;
3167
3168 mutex_lock(&trace_types_lock);
3169 if (current_trace->set_flag)
3170 ret = current_trace->set_flag(topt->flags->val,
3171 topt->opt->bit, 0);
3172 mutex_unlock(&trace_types_lock);
3173 if (ret)
3174 return ret;
3175 topt->flags->val &= ~topt->opt->bit;
3176 break;
3177 case 1:
3178 /* do nothing if already set */
3179 if (topt->flags->val & topt->opt->bit)
3180 break;
3181
3182 mutex_lock(&trace_types_lock);
3183 if (current_trace->set_flag)
3184 ret = current_trace->set_flag(topt->flags->val,
3185 topt->opt->bit, 1);
3186 mutex_unlock(&trace_types_lock);
3187 if (ret)
3188 return ret;
3189 topt->flags->val |= topt->opt->bit;
3190 break;
3191
3192 default:
3193 return -EINVAL;
3194 }
3195
3196 *ppos += cnt;
3197
3198 return cnt;
3199}
3200
3201
3202static const struct file_operations trace_options_fops = {
3203 .open = tracing_open_generic,
3204 .read = trace_options_read,
3205 .write = trace_options_write,
3206};
3207
3208static ssize_t
3209trace_options_core_read(struct file *filp, char __user *ubuf, size_t cnt,
3210 loff_t *ppos)
3211{
3212 long index = (long)filp->private_data;
3213 char *buf;
3214
3215 if (trace_flags & (1 << index))
3216 buf = "1\n";
3217 else
3218 buf = "0\n";
3219
3220 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
3221}
3222
3223static ssize_t
3224trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
3225 loff_t *ppos)
3226{
3227 long index = (long)filp->private_data;
3228 char buf[64];
3229 unsigned long val;
3230 int ret;
3231
3232 if (cnt >= sizeof(buf))
3233 return -EINVAL;
3234
3235 if (copy_from_user(&buf, ubuf, cnt))
3236 return -EFAULT;
3237
3238 buf[cnt] = 0;
3239
3240 ret = strict_strtoul(buf, 10, &val);
3241 if (ret < 0)
3242 return ret;
3243
3244 switch (val) {
3245 case 0:
3246 trace_flags &= ~(1 << index);
3247 break;
3248 case 1:
3249 trace_flags |= 1 << index;
3250 break;
3251
3252 default:
3253 return -EINVAL;
3254 }
3255
3256 *ppos += cnt;
3257
3258 return cnt;
3259}
3260
3261static const struct file_operations trace_options_core_fops = {
3262 .open = tracing_open_generic,
3263 .read = trace_options_core_read,
3264 .write = trace_options_core_write,
3265};
3266
3267static struct dentry *trace_options_init_dentry(void)
3268{
3269 struct dentry *d_tracer;
3270 static struct dentry *t_options;
3271
3272 if (t_options)
3273 return t_options;
3274
3275 d_tracer = tracing_init_dentry();
3276 if (!d_tracer)
3277 return NULL;
3278
3279 t_options = debugfs_create_dir("options", d_tracer);
3280 if (!t_options) {
3281 pr_warning("Could not create debugfs directory 'options'\n");
3282 return NULL;
3283 }
3284
3285 return t_options;
3286}
3287
3288static void
3289create_trace_option_file(struct trace_option_dentry *topt,
3290 struct tracer_flags *flags,
3291 struct tracer_opt *opt)
3292{
3293 struct dentry *t_options;
3294 struct dentry *entry;
3295
3296 t_options = trace_options_init_dentry();
3297 if (!t_options)
3298 return;
3299
3300 topt->flags = flags;
3301 topt->opt = opt;
3302
3303 entry = debugfs_create_file(opt->name, 0644, t_options, topt,
3304 &trace_options_fops);
3305
3306 topt->entry = entry;
3307
3308}
3309
3310static struct trace_option_dentry *
3311create_trace_option_files(struct tracer *tracer)
3312{
3313 struct trace_option_dentry *topts;
3314 struct tracer_flags *flags;
3315 struct tracer_opt *opts;
3316 int cnt;
3317
3318 if (!tracer)
3319 return NULL;
3320
3321 flags = tracer->flags;
3322
3323 if (!flags || !flags->opts)
3324 return NULL;
3325
3326 opts = flags->opts;
3327
3328 for (cnt = 0; opts[cnt].name; cnt++)
3329 ;
3330
3331 topts = kzalloc(sizeof(*topts) * (cnt + 1), GFP_KERNEL);
3332 if (!topts)
3333 return NULL;
3334
3335 for (cnt = 0; opts[cnt].name; cnt++)
3336 create_trace_option_file(&topts[cnt], flags,
3337 &opts[cnt]);
3338
3339 return topts;
3340}
3341
3342static void
3343destroy_trace_option_files(struct trace_option_dentry *topts)
3344{
3345 int cnt;
3346
3347 if (!topts)
3348 return;
3349
3350 for (cnt = 0; topts[cnt].opt; cnt++) {
3351 if (topts[cnt].entry)
3352 debugfs_remove(topts[cnt].entry);
3353 }
3354
3355 kfree(topts);
3356}
3357
3358static struct dentry *
3359create_trace_option_core_file(const char *option, long index)
3360{
3361 struct dentry *t_options;
3362 struct dentry *entry;
3363
3364 t_options = trace_options_init_dentry();
3365 if (!t_options)
3366 return NULL;
3367
3368 entry = debugfs_create_file(option, 0644, t_options, (void *)index,
3369 &trace_options_core_fops);
3370
3371 return entry;
3372}
3373
3374static __init void create_trace_options_dir(void)
3375{
3376 struct dentry *t_options;
3377 struct dentry *entry;
3378 int i;
3379
3380 t_options = trace_options_init_dentry();
3381 if (!t_options)
3382 return;
3383
3384 for (i = 0; trace_options[i]; i++) {
3385 entry = create_trace_option_core_file(trace_options[i], i);
3386 if (!entry)
3387 pr_warning("Could not create debugfs %s entry\n",
3388 trace_options[i]);
3389 }
3390}
3391
3096static __init int tracer_init_debugfs(void) 3392static __init int tracer_init_debugfs(void)
3097{ 3393{
3098 struct dentry *d_tracer; 3394 struct dentry *d_tracer;
@@ -3111,6 +3407,8 @@ static __init int tracer_init_debugfs(void)
3111 if (!entry) 3407 if (!entry)
3112 pr_warning("Could not create debugfs 'trace_options' entry\n"); 3408 pr_warning("Could not create debugfs 'trace_options' entry\n");
3113 3409
3410 create_trace_options_dir();
3411
3114 entry = debugfs_create_file("tracing_cpumask", 0644, d_tracer, 3412 entry = debugfs_create_file("tracing_cpumask", 0644, d_tracer,
3115 NULL, &tracing_cpumask_fops); 3413 NULL, &tracing_cpumask_fops);
3116 if (!entry) 3414 if (!entry)