Commit f2955b49 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'perf-fixes-for-linus' of...

Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  tracing: t_start: reset FTRACE_ITER_HASH in case of seek/pread
  perf symbols: Fix multiple initialization of symbol system
  perf: Fix CPU hotplug
  perf, trace: Fix module leak
  tracing/kprobe: Fix handling of C-unlike argument names
  tracing/kprobes: Fix handling of argument names
  perf probe: Fix handling of arguments names
  perf probe: Fix return probe support
  tracing/kprobe: Fix a memory leak in error case
  tracing: Do not allow llseek to set_ftrace_filter
parents 3d96406c 9efdda31
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -5761,15 +5761,15 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
{
	unsigned int cpu = (long)hcpu;

	switch (action) {
	switch (action & ~CPU_TASKS_FROZEN) {

	case CPU_UP_PREPARE:
	case CPU_UP_PREPARE_FROZEN:
	case CPU_DOWN_FAILED:
		perf_event_init_cpu(cpu);
		break;

	case CPU_UP_CANCELED:
	case CPU_DOWN_PREPARE:
	case CPU_DOWN_PREPARE_FROZEN:
		perf_event_exit_cpu(cpu);
		break;

+3 −1
Original line number Diff line number Diff line
@@ -1510,6 +1510,8 @@ static void *t_start(struct seq_file *m, loff_t *pos)
		if (*pos > 0)
			return t_hash_start(m, pos);
		iter->flags |= FTRACE_ITER_PRINTALL;
		/* reset in case of seek/pread */
		iter->flags &= ~FTRACE_ITER_HASH;
		return iter;
	}

@@ -2416,7 +2418,7 @@ static const struct file_operations ftrace_filter_fops = {
	.open = ftrace_filter_open,
	.read = seq_read,
	.write = ftrace_filter_write,
	.llseek = ftrace_regex_lseek,
	.llseek = no_llseek,
	.release = ftrace_filter_release,
};

+3 −0
Original line number Diff line number Diff line
@@ -91,6 +91,8 @@ int perf_trace_init(struct perf_event *p_event)
		    tp_event->class && tp_event->class->reg &&
		    try_module_get(tp_event->mod)) {
			ret = perf_trace_event_init(tp_event, p_event);
			if (ret)
				module_put(tp_event->mod);
			break;
		}
	}
@@ -146,6 +148,7 @@ void perf_trace_destroy(struct perf_event *p_event)
		}
	}
out:
	module_put(tp_event->mod);
	mutex_unlock(&event_mutex);
}

+25 −18
Original line number Diff line number Diff line
@@ -514,8 +514,8 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
static int kretprobe_dispatcher(struct kretprobe_instance *ri,
				struct pt_regs *regs);

/* Check the name is good for event/group */
static int check_event_name(const char *name)
/* Check the name is good for event/group/fields */
static int is_good_name(const char *name)
{
	if (!isalpha(*name) && *name != '_')
		return 0;
@@ -557,7 +557,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
	else
		tp->rp.kp.pre_handler = kprobe_dispatcher;

	if (!event || !check_event_name(event)) {
	if (!event || !is_good_name(event)) {
		ret = -EINVAL;
		goto error;
	}
@@ -567,7 +567,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
	if (!tp->call.name)
		goto error;

	if (!group || !check_event_name(group)) {
	if (!group || !is_good_name(group)) {
		ret = -EINVAL;
		goto error;
	}
@@ -883,7 +883,7 @@ static int create_trace_probe(int argc, char **argv)
	int i, ret = 0;
	int is_return = 0, is_delete = 0;
	char *symbol = NULL, *event = NULL, *group = NULL;
	char *arg, *tmp;
	char *arg;
	unsigned long offset = 0;
	void *addr = NULL;
	char buf[MAX_EVENT_NAME_LEN];
@@ -992,26 +992,36 @@ static int create_trace_probe(int argc, char **argv)
	/* parse arguments */
	ret = 0;
	for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
		/* Increment count for freeing args in error case */
		tp->nr_args++;

		/* Parse argument name */
		arg = strchr(argv[i], '=');
		if (arg)
		if (arg) {
			*arg++ = '\0';
		else
			tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
		} else {
			arg = argv[i];
			/* If argument name is omitted, set "argN" */
			snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1);
			tp->args[i].name = kstrdup(buf, GFP_KERNEL);
		}

		tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
		if (!tp->args[i].name) {
			pr_info("Failed to allocate argument%d name '%s'.\n",
				i, argv[i]);
			pr_info("Failed to allocate argument[%d] name.\n", i);
			ret = -ENOMEM;
			goto error;
		}
		tmp = strchr(tp->args[i].name, ':');
		if (tmp)
			*tmp = '_';	/* convert : to _ */

		if (!is_good_name(tp->args[i].name)) {
			pr_info("Invalid argument[%d] name: %s\n",
				i, tp->args[i].name);
			ret = -EINVAL;
			goto error;
		}

		if (conflict_field_name(tp->args[i].name, tp->args, i)) {
			pr_info("Argument%d name '%s' conflicts with "
			pr_info("Argument[%d] name '%s' conflicts with "
				"another field.\n", i, argv[i]);
			ret = -EINVAL;
			goto error;
@@ -1020,12 +1030,9 @@ static int create_trace_probe(int argc, char **argv)
		/* Parse fetch argument */
		ret = parse_probe_arg(arg, tp, &tp->args[i], is_return);
		if (ret) {
			pr_info("Parse error at argument%d. (%d)\n", i, ret);
			kfree(tp->args[i].name);
			pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
			goto error;
		}

		tp->nr_args++;
	}

	ret = register_trace_probe(tp);
+1 −0
Original line number Diff line number Diff line
@@ -1539,6 +1539,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
		goto error;
	}
	tev->point.offset = pev->point.offset;
	tev->point.retprobe = pev->point.retprobe;
	tev->nargs = pev->nargs;
	if (tev->nargs) {
		tev->args = zalloc(sizeof(struct probe_trace_arg)
Loading