aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2017-04-04 14:46:56 -0400
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2017-04-20 22:06:42 -0400
commite16b35ddb840788e023fac2482b61c0b6bf98057 (patch)
tree482b09e069be85d7f9adcea28b79e0ed3a18cd9e
parent1a48df0041c2756194e700affb0e2ff084092e28 (diff)
ftrace: Add helper function ftrace_hash_move_and_update_ops()
The processes of updating a ops filter_hash is a bit complex, and requires setting up an old hash to perform the update. This is done exactly the same in two locations for the same reasons. Create a helper function that does it in one place. Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
-rw-r--r--kernel/trace/ftrace.c105
1 files changed, 53 insertions, 52 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f7fcab8f3aa1..5c8d8eea9e7c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3674,6 +3674,56 @@ ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
3674 return match_records(hash, buff, len, NULL); 3674 return match_records(hash, buff, len, NULL);
3675} 3675}
3676 3676
3677static void ftrace_ops_update_code(struct ftrace_ops *ops,
3678 struct ftrace_ops_hash *old_hash)
3679{
3680 struct ftrace_ops *op;
3681
3682 if (!ftrace_enabled)
3683 return;
3684
3685 if (ops->flags & FTRACE_OPS_FL_ENABLED) {
3686 ftrace_run_modify_code(ops, FTRACE_UPDATE_CALLS, old_hash);
3687 return;
3688 }
3689
3690 /*
3691 * If this is the shared global_ops filter, then we need to
3692 * check if there is another ops that shares it, is enabled.
3693 * If so, we still need to run the modify code.
3694 */
3695 if (ops->func_hash != &global_ops.local_hash)
3696 return;
3697
3698 do_for_each_ftrace_op(op, ftrace_ops_list) {
3699 if (op->func_hash == &global_ops.local_hash &&
3700 op->flags & FTRACE_OPS_FL_ENABLED) {
3701 ftrace_run_modify_code(op, FTRACE_UPDATE_CALLS, old_hash);
3702 /* Only need to do this once */
3703 return;
3704 }
3705 } while_for_each_ftrace_op(op);
3706}
3707
3708static int ftrace_hash_move_and_update_ops(struct ftrace_ops *ops,
3709 struct ftrace_hash **orig_hash,
3710 struct ftrace_hash *hash,
3711 int enable)
3712{
3713 struct ftrace_ops_hash old_hash_ops;
3714 struct ftrace_hash *old_hash;
3715 int ret;
3716
3717 old_hash = *orig_hash;
3718 old_hash_ops.filter_hash = ops->func_hash->filter_hash;
3719 old_hash_ops.notrace_hash = ops->func_hash->notrace_hash;
3720 ret = ftrace_hash_move(ops, enable, orig_hash, hash);
3721 if (!ret) {
3722 ftrace_ops_update_code(ops, &old_hash_ops);
3723 free_ftrace_hash_rcu(old_hash);
3724 }
3725 return ret;
3726}
3677 3727
3678/* 3728/*
3679 * We register the module command as a template to show others how 3729 * We register the module command as a template to show others how
@@ -4306,44 +4356,11 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
4306 return add_hash_entry(hash, ip); 4356 return add_hash_entry(hash, ip);
4307} 4357}
4308 4358
4309static void ftrace_ops_update_code(struct ftrace_ops *ops,
4310 struct ftrace_ops_hash *old_hash)
4311{
4312 struct ftrace_ops *op;
4313
4314 if (!ftrace_enabled)
4315 return;
4316
4317 if (ops->flags & FTRACE_OPS_FL_ENABLED) {
4318 ftrace_run_modify_code(ops, FTRACE_UPDATE_CALLS, old_hash);
4319 return;
4320 }
4321
4322 /*
4323 * If this is the shared global_ops filter, then we need to
4324 * check if there is another ops that shares it, is enabled.
4325 * If so, we still need to run the modify code.
4326 */
4327 if (ops->func_hash != &global_ops.local_hash)
4328 return;
4329
4330 do_for_each_ftrace_op(op, ftrace_ops_list) {
4331 if (op->func_hash == &global_ops.local_hash &&
4332 op->flags & FTRACE_OPS_FL_ENABLED) {
4333 ftrace_run_modify_code(op, FTRACE_UPDATE_CALLS, old_hash);
4334 /* Only need to do this once */
4335 return;
4336 }
4337 } while_for_each_ftrace_op(op);
4338}
4339
4340static int 4359static int
4341ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, 4360ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
4342 unsigned long ip, int remove, int reset, int enable) 4361 unsigned long ip, int remove, int reset, int enable)
4343{ 4362{
4344 struct ftrace_hash **orig_hash; 4363 struct ftrace_hash **orig_hash;
4345 struct ftrace_ops_hash old_hash_ops;
4346 struct ftrace_hash *old_hash;
4347 struct ftrace_hash *hash; 4364 struct ftrace_hash *hash;
4348 int ret; 4365 int ret;
4349 4366
@@ -4378,14 +4395,7 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
4378 } 4395 }
4379 4396
4380 mutex_lock(&ftrace_lock); 4397 mutex_lock(&ftrace_lock);
4381 old_hash = *orig_hash; 4398 ret = ftrace_hash_move_and_update_ops(ops, orig_hash, hash, enable);
4382 old_hash_ops.filter_hash = ops->func_hash->filter_hash;
4383 old_hash_ops.notrace_hash = ops->func_hash->notrace_hash;
4384 ret = ftrace_hash_move(ops, enable, orig_hash, hash);
4385 if (!ret) {
4386 ftrace_ops_update_code(ops, &old_hash_ops);
4387 free_ftrace_hash_rcu(old_hash);
4388 }
4389 mutex_unlock(&ftrace_lock); 4399 mutex_unlock(&ftrace_lock);
4390 4400
4391 out_regex_unlock: 4401 out_regex_unlock:
@@ -4624,10 +4634,8 @@ static void __init set_ftrace_early_filters(void)
4624int ftrace_regex_release(struct inode *inode, struct file *file) 4634int ftrace_regex_release(struct inode *inode, struct file *file)
4625{ 4635{
4626 struct seq_file *m = (struct seq_file *)file->private_data; 4636 struct seq_file *m = (struct seq_file *)file->private_data;
4627 struct ftrace_ops_hash old_hash_ops;
4628 struct ftrace_iterator *iter; 4637 struct ftrace_iterator *iter;
4629 struct ftrace_hash **orig_hash; 4638 struct ftrace_hash **orig_hash;
4630 struct ftrace_hash *old_hash;
4631 struct trace_parser *parser; 4639 struct trace_parser *parser;
4632 int filter_hash; 4640 int filter_hash;
4633 int ret; 4641 int ret;
@@ -4657,15 +4665,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
4657 orig_hash = &iter->ops->func_hash->notrace_hash; 4665 orig_hash = &iter->ops->func_hash->notrace_hash;
4658 4666
4659 mutex_lock(&ftrace_lock); 4667 mutex_lock(&ftrace_lock);
4660 old_hash = *orig_hash; 4668 ret = ftrace_hash_move_and_update_ops(iter->ops, orig_hash,
4661 old_hash_ops.filter_hash = iter->ops->func_hash->filter_hash; 4669 iter->hash, filter_hash);
4662 old_hash_ops.notrace_hash = iter->ops->func_hash->notrace_hash;
4663 ret = ftrace_hash_move(iter->ops, filter_hash,
4664 orig_hash, iter->hash);
4665 if (!ret) {
4666 ftrace_ops_update_code(iter->ops, &old_hash_ops);
4667 free_ftrace_hash_rcu(old_hash);
4668 }
4669 mutex_unlock(&ftrace_lock); 4670 mutex_unlock(&ftrace_lock);
4670 } else { 4671 } else {
4671 /* For read only, the hash is the ops hash */ 4672 /* For read only, the hash is the ops hash */