diff options
Diffstat (limited to 'kernel/trace/trace_uprobe.c')
| -rw-r--r-- | kernel/trace/trace_uprobe.c | 57 | 
1 files changed, 41 insertions, 16 deletions
| diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 32494fb0ee6..272261b5f94 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -70,7 +70,7 @@ struct trace_uprobe {  	(sizeof(struct probe_arg) * (n)))  static int register_uprobe_event(struct trace_uprobe *tu); -static void unregister_uprobe_event(struct trace_uprobe *tu); +static int unregister_uprobe_event(struct trace_uprobe *tu);  static DEFINE_MUTEX(uprobe_lock);  static LIST_HEAD(uprobe_list); @@ -164,11 +164,17 @@ static struct trace_uprobe *find_probe_event(const char *event, const char *grou  }  /* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */ -static void unregister_trace_uprobe(struct trace_uprobe *tu) +static int unregister_trace_uprobe(struct trace_uprobe *tu)  { +	int ret; + +	ret = unregister_uprobe_event(tu); +	if (ret) +		return ret; +  	list_del(&tu->list); -	unregister_uprobe_event(tu);  	free_trace_uprobe(tu); +	return 0;  }  /* Register a trace_uprobe and probe_event */ @@ -181,9 +187,12 @@ static int register_trace_uprobe(struct trace_uprobe *tu)  	/* register as an event */  	old_tp = find_probe_event(tu->call.name, tu->call.class->system); -	if (old_tp) +	if (old_tp) {  		/* delete old event */ -		unregister_trace_uprobe(old_tp); +		ret = unregister_trace_uprobe(old_tp); +		if (ret) +			goto end; +	}  	ret = register_uprobe_event(tu);  	if (ret) { @@ -256,6 +265,8 @@ static int create_trace_uprobe(int argc, char **argv)  		group = UPROBE_EVENT_SYSTEM;  	if (is_delete) { +		int ret; +  		if (!event) {  			pr_info("Delete command needs an event name.\n");  			return -EINVAL; @@ -269,9 +280,9 @@ static int create_trace_uprobe(int argc, char **argv)  			return -ENOENT;  		}  		/* delete an event */ -		unregister_trace_uprobe(tu); +		ret = unregister_trace_uprobe(tu);  		mutex_unlock(&uprobe_lock); -		return 0; +		return ret;  	}  	if (argc < 2) { @@ -283,8 +294,10 @@ static int create_trace_uprobe(int argc, char **argv)  		return -EINVAL;  	}  	arg = strchr(argv[1], ':'); -	if (!arg) +	if (!arg) { +		ret = -EINVAL;  		goto fail_address_parse; +	}  	*arg++ = '\0';  	filename = argv[1]; @@ -406,16 +419,20 @@ fail_address_parse:  	return ret;  } -static void cleanup_all_probes(void) +static int cleanup_all_probes(void)  {  	struct trace_uprobe *tu; +	int ret = 0;  	mutex_lock(&uprobe_lock);  	while (!list_empty(&uprobe_list)) {  		tu = list_entry(uprobe_list.next, struct trace_uprobe, list); -		unregister_trace_uprobe(tu); +		ret = unregister_trace_uprobe(tu); +		if (ret) +			break;  	}  	mutex_unlock(&uprobe_lock); +	return ret;  }  /* Probes listing interfaces */ @@ -460,8 +477,13 @@ static const struct seq_operations probes_seq_op = {  static int probes_open(struct inode *inode, struct file *file)  { -	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) -		cleanup_all_probes(); +	int ret; + +	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { +		ret = cleanup_all_probes(); +		if (ret) +			return ret; +	}  	return seq_open(file, &probes_seq_op);  } @@ -816,8 +838,6 @@ static void uprobe_perf_print(struct trace_uprobe *tu,  	size = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));  	size = ALIGN(size + tu->size + sizeof(u32), sizeof(u64)) - sizeof(u32); -	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough")) -		return;  	preempt_disable();  	head = this_cpu_ptr(call->perf_events); @@ -968,12 +988,17 @@ static int register_uprobe_event(struct trace_uprobe *tu)  	return ret;  } -static void unregister_uprobe_event(struct trace_uprobe *tu) +static int unregister_uprobe_event(struct trace_uprobe *tu)  { +	int ret; +  	/* tu->event is unregistered in trace_remove_event_call() */ -	trace_remove_event_call(&tu->call); +	ret = trace_remove_event_call(&tu->call); +	if (ret) +		return ret;  	kfree(tu->call.print_fmt);  	tu->call.print_fmt = NULL; +	return 0;  }  /* Make a trace interface for controling probe points */ | 
