aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2013-05-09 01:44:21 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-05-09 20:11:48 -0400
commit3f2367ba7cbf13ec0f3f1e93b833a7eacd1ab4b8 (patch)
tree81bac89b0b20458cb8505a3bdef4b9189ff4057e /kernel
parentf04f24fb7e48d446bd89a01c6056571f25972511 (diff)
ftrace: Cleanup regex_lock and ftrace_lock around hash updating
Cleanup regex_lock and ftrace_lock locking points around ftrace_ops hash update code. The new rule is that regex_lock protects ops->*_hash read-update-write code for each ftrace_ops. Usually, hash update is done by following sequence. 1. allocate a new local hash and copy the original hash. 2. update the local hash. 3. move(actually, copy) back the local hash to ftrace_ops. 4. update ftrace entries if needed. 5. release the local hash. This makes regex_lock protect #1-#4, and ftrace_lock to protect #3, #4 and adding and removing ftrace_ops from the ftrace_ops_list. The ftrace_lock protects #3 as well because the move functions update the entries too. Link: http://lkml.kernel.org/r/20130509054421.30398.83411.stgit@mhiramat-M0-7522 Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Tom Zanussi <tom.zanussi@intel.com> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ftrace.c59
1 files changed, 32 insertions, 27 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 827f2fe7bc3f..cacf0856191e 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2656,28 +2656,26 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
2656 return -ENOMEM; 2656 return -ENOMEM;
2657 } 2657 }
2658 2658
2659 iter->ops = ops;
2660 iter->flags = flag;
2661
2662 mutex_lock(&ops->regex_lock);
2663
2659 if (flag & FTRACE_ITER_NOTRACE) 2664 if (flag & FTRACE_ITER_NOTRACE)
2660 hash = ops->notrace_hash; 2665 hash = ops->notrace_hash;
2661 else 2666 else
2662 hash = ops->filter_hash; 2667 hash = ops->filter_hash;
2663 2668
2664 iter->ops = ops;
2665 iter->flags = flag;
2666
2667 if (file->f_mode & FMODE_WRITE) { 2669 if (file->f_mode & FMODE_WRITE) {
2668 mutex_lock(&ftrace_lock);
2669 iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); 2670 iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
2670 mutex_unlock(&ftrace_lock);
2671
2672 if (!iter->hash) { 2671 if (!iter->hash) {
2673 trace_parser_put(&iter->parser); 2672 trace_parser_put(&iter->parser);
2674 kfree(iter); 2673 kfree(iter);
2675 return -ENOMEM; 2674 ret = -ENOMEM;
2675 goto out_unlock;
2676 } 2676 }
2677 } 2677 }
2678 2678
2679 mutex_lock(&ops->regex_lock);
2680
2681 if ((file->f_mode & FMODE_WRITE) && 2679 if ((file->f_mode & FMODE_WRITE) &&
2682 (file->f_flags & O_TRUNC)) 2680 (file->f_flags & O_TRUNC))
2683 ftrace_filter_reset(iter->hash); 2681 ftrace_filter_reset(iter->hash);
@@ -2697,6 +2695,8 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
2697 } 2695 }
2698 } else 2696 } else
2699 file->private_data = iter; 2697 file->private_data = iter;
2698
2699 out_unlock:
2700 mutex_unlock(&ops->regex_lock); 2700 mutex_unlock(&ops->regex_lock);
2701 2701
2702 return ret; 2702 return ret;
@@ -3012,7 +3012,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3012 if (WARN_ON(not)) 3012 if (WARN_ON(not))
3013 return -EINVAL; 3013 return -EINVAL;
3014 3014
3015 mutex_lock(&ftrace_lock); 3015 mutex_lock(&trace_probe_ops.regex_lock);
3016 3016
3017 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 3017 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3018 if (!hash) { 3018 if (!hash) {
@@ -3070,14 +3070,16 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3070 3070
3071 } while_for_each_ftrace_rec(); 3071 } while_for_each_ftrace_rec();
3072 3072
3073 mutex_lock(&ftrace_lock);
3073 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash); 3074 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3074 if (ret < 0) 3075 if (ret < 0)
3075 count = ret; 3076 count = ret;
3076 3077
3077 __enable_ftrace_function_probe(); 3078 __enable_ftrace_function_probe();
3079 mutex_unlock(&ftrace_lock);
3078 3080
3079 out_unlock: 3081 out_unlock:
3080 mutex_unlock(&ftrace_lock); 3082 mutex_unlock(&trace_probe_ops.regex_lock);
3081 free_ftrace_hash(hash); 3083 free_ftrace_hash(hash);
3082 3084
3083 return count; 3085 return count;
@@ -3117,7 +3119,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3117 return; 3119 return;
3118 } 3120 }
3119 3121
3120 mutex_lock(&ftrace_lock); 3122 mutex_lock(&trace_probe_ops.regex_lock);
3121 3123
3122 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 3124 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3123 if (!hash) 3125 if (!hash)
@@ -3155,6 +3157,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3155 list_add(&entry->free_list, &free_list); 3157 list_add(&entry->free_list, &free_list);
3156 } 3158 }
3157 } 3159 }
3160 mutex_lock(&ftrace_lock);
3158 __disable_ftrace_function_probe(); 3161 __disable_ftrace_function_probe();
3159 /* 3162 /*
3160 * Remove after the disable is called. Otherwise, if the last 3163 * Remove after the disable is called. Otherwise, if the last
@@ -3166,9 +3169,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3166 list_del(&entry->free_list); 3169 list_del(&entry->free_list);
3167 ftrace_free_entry(entry); 3170 ftrace_free_entry(entry);
3168 } 3171 }
3172 mutex_unlock(&ftrace_lock);
3169 3173
3170 out_unlock: 3174 out_unlock:
3171 mutex_unlock(&ftrace_lock); 3175 mutex_unlock(&trace_probe_ops.regex_lock);
3172 free_ftrace_hash(hash); 3176 free_ftrace_hash(hash);
3173} 3177}
3174 3178
@@ -3284,11 +3288,10 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
3284 } else 3288 } else
3285 iter = file->private_data; 3289 iter = file->private_data;
3286 3290
3287 mutex_lock(&iter->ops->regex_lock);
3288
3289 ret = -ENODEV;
3290 if (unlikely(ftrace_disabled)) 3291 if (unlikely(ftrace_disabled))
3291 goto out_unlock; 3292 return -ENODEV;
3293
3294 /* iter->hash is a local copy, so we don't need regex_lock */
3292 3295
3293 parser = &iter->parser; 3296 parser = &iter->parser;
3294 read = trace_get_user(parser, ubuf, cnt, ppos); 3297 read = trace_get_user(parser, ubuf, cnt, ppos);
@@ -3299,13 +3302,11 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
3299 parser->idx, enable); 3302 parser->idx, enable);
3300 trace_parser_clear(parser); 3303 trace_parser_clear(parser);
3301 if (ret < 0) 3304 if (ret < 0)
3302 goto out_unlock; 3305 goto out;
3303 } 3306 }
3304 3307
3305 ret = read; 3308 ret = read;
3306out_unlock: 3309 out:
3307 mutex_unlock(&iter->ops->regex_lock);
3308
3309 return ret; 3310 return ret;
3310} 3311}
3311 3312
@@ -3357,16 +3358,19 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
3357 if (unlikely(ftrace_disabled)) 3358 if (unlikely(ftrace_disabled))
3358 return -ENODEV; 3359 return -ENODEV;
3359 3360
3361 mutex_lock(&ops->regex_lock);
3362
3360 if (enable) 3363 if (enable)
3361 orig_hash = &ops->filter_hash; 3364 orig_hash = &ops->filter_hash;
3362 else 3365 else
3363 orig_hash = &ops->notrace_hash; 3366 orig_hash = &ops->notrace_hash;
3364 3367
3365 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 3368 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3366 if (!hash) 3369 if (!hash) {
3367 return -ENOMEM; 3370 ret = -ENOMEM;
3371 goto out_regex_unlock;
3372 }
3368 3373
3369 mutex_lock(&ops->regex_lock);
3370 if (reset) 3374 if (reset)
3371 ftrace_filter_reset(hash); 3375 ftrace_filter_reset(hash);
3372 if (buf && !ftrace_match_records(hash, buf, len)) { 3376 if (buf && !ftrace_match_records(hash, buf, len)) {
@@ -3584,8 +3588,6 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
3584 } else 3588 } else
3585 iter = file->private_data; 3589 iter = file->private_data;
3586 3590
3587 mutex_lock(&iter->ops->regex_lock);
3588
3589 parser = &iter->parser; 3591 parser = &iter->parser;
3590 if (trace_parser_loaded(parser)) { 3592 if (trace_parser_loaded(parser)) {
3591 parser->buffer[parser->idx] = 0; 3593 parser->buffer[parser->idx] = 0;
@@ -3594,6 +3596,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
3594 3596
3595 trace_parser_put(parser); 3597 trace_parser_put(parser);
3596 3598
3599 mutex_lock(&iter->ops->regex_lock);
3600
3597 if (file->f_mode & FMODE_WRITE) { 3601 if (file->f_mode & FMODE_WRITE) {
3598 filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); 3602 filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
3599 3603
@@ -3611,10 +3615,11 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
3611 3615
3612 mutex_unlock(&ftrace_lock); 3616 mutex_unlock(&ftrace_lock);
3613 } 3617 }
3618
3619 mutex_unlock(&iter->ops->regex_lock);
3614 free_ftrace_hash(iter->hash); 3620 free_ftrace_hash(iter->hash);
3615 kfree(iter); 3621 kfree(iter);
3616 3622
3617 mutex_unlock(&iter->ops->regex_lock);
3618 return 0; 3623 return 0;
3619} 3624}
3620 3625