Commit 92705460 authored by Masami Hiramatsu (Google)'s avatar Masami Hiramatsu (Google)
Browse files

tracing/kprobes: Simplify __trace_kprobe_create() by removing gotos

parent 7dcc3520
Loading
Loading
Loading
Loading
+49 −48
Original line number Diff line number Diff line
@@ -836,7 +836,8 @@ static int validate_probe_symbol(char *symbol)
static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
				      struct pt_regs *regs);

static int __trace_kprobe_create(int argc, const char *argv[])
static int trace_kprobe_create_internal(int argc, const char *argv[],
					struct traceprobe_parse_context *ctx)
{
	/*
	 * Argument syntax:
@@ -877,7 +878,6 @@ static int __trace_kprobe_create(int argc, const char *argv[])
	char gbuf[MAX_EVENT_NAME_LEN];
	char abuf[MAX_BTF_ARGS_LEN];
	char *dbuf __free(kfree) = NULL;
	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };

	switch (argv[0][0]) {
	case 'r':
@@ -891,8 +891,6 @@ static int __trace_kprobe_create(int argc, const char *argv[])
	if (argc < 2)
		return -ECANCELED;

	trace_probe_log_init("trace_kprobe", argc, argv);

	event = strchr(&argv[0][1], ':');
	if (event)
		event++;
@@ -900,7 +898,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
	if (isdigit(argv[0][1])) {
		if (!is_return) {
			trace_probe_log_err(1, BAD_MAXACT_TYPE);
			goto parse_error;
			return -EINVAL;
		}
		if (event)
			len = event - &argv[0][1] - 1;
@@ -908,21 +906,21 @@ static int __trace_kprobe_create(int argc, const char *argv[])
			len = strlen(&argv[0][1]);
		if (len > MAX_EVENT_NAME_LEN - 1) {
			trace_probe_log_err(1, BAD_MAXACT);
			goto parse_error;
			return -EINVAL;
		}
		memcpy(buf, &argv[0][1], len);
		buf[len] = '\0';
		ret = kstrtouint(buf, 0, &maxactive);
		if (ret || !maxactive) {
			trace_probe_log_err(1, BAD_MAXACT);
			goto parse_error;
			return -EINVAL;
		}
		/* kretprobes instances are iterated over via a list. The
		 * maximum should stay reasonable.
		 */
		if (maxactive > KRETPROBE_MAXACTIVE_MAX) {
			trace_probe_log_err(1, MAXACT_TOO_BIG);
			goto parse_error;
			return -EINVAL;
		}
	}

@@ -931,16 +929,13 @@ static int __trace_kprobe_create(int argc, const char *argv[])
	if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
		trace_probe_log_set_index(1);
		/* Check whether uprobe event specified */
		if (strchr(argv[1], '/') && strchr(argv[1], ':')) {
			ret = -ECANCELED;
			goto out;
		}
		if (strchr(argv[1], '/') && strchr(argv[1], ':'))
			return -ECANCELED;

		/* a symbol specified */
		symbol = kstrdup(argv[1], GFP_KERNEL);
		if (!symbol) {
			ret = -ENOMEM;
			goto out;
		}
		if (!symbol)
			return -ENOMEM;

		tmp = strchr(symbol, '%');
		if (tmp) {
@@ -949,7 +944,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
				is_return = true;
			} else {
				trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX);
				goto parse_error;
				return -EINVAL;
			}
		}

@@ -957,7 +952,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
		ret = traceprobe_split_symbol_offset(symbol, &offset);
		if (ret || offset < 0 || offset > UINT_MAX) {
			trace_probe_log_err(0, BAD_PROBE_ADDR);
			goto parse_error;
			return -EINVAL;
		}
		ret = validate_probe_symbol(symbol);
		if (ret) {
@@ -965,17 +960,17 @@ static int __trace_kprobe_create(int argc, const char *argv[])
				trace_probe_log_err(0, NON_UNIQ_SYMBOL);
			else
				trace_probe_log_err(0, BAD_PROBE_ADDR);
			goto parse_error;
			return -EINVAL;
		}
		if (is_return)
			ctx.flags |= TPARG_FL_RETURN;
			ctx->flags |= TPARG_FL_RETURN;
		ret = kprobe_on_func_entry(NULL, symbol, offset);
		if (ret == 0 && !is_return)
			ctx.flags |= TPARG_FL_FENTRY;
			ctx->flags |= TPARG_FL_FENTRY;
		/* Defer the ENOENT case until register kprobe */
		if (ret == -EINVAL && is_return) {
			trace_probe_log_err(0, BAD_RETPROBE);
			goto parse_error;
			return -EINVAL;
		}
	}

@@ -984,7 +979,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
		ret = traceprobe_parse_event_name(&event, &group, gbuf,
						  event - argv[0]);
		if (ret)
			goto parse_error;
			return ret;
	}

	if (!event) {
@@ -1000,26 +995,24 @@ static int __trace_kprobe_create(int argc, const char *argv[])
	}

	argc -= 2; argv += 2;
	ctx.funcname = symbol;
	ctx->funcname = symbol;
	new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,
					       abuf, MAX_BTF_ARGS_LEN, &ctx);
					       abuf, MAX_BTF_ARGS_LEN, ctx);
	if (IS_ERR(new_argv)) {
		ret = PTR_ERR(new_argv);
		new_argv = NULL;
		goto out;
		return ret;
	}
	if (new_argv) {
		argc = new_argc;
		argv = new_argv;
	}
	if (argc > MAX_TRACE_ARGS) {
		ret = -E2BIG;
		goto out;
	}
	if (argc > MAX_TRACE_ARGS)
		return -E2BIG;

	ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
	if (ret)
		goto out;
		return ret;

	/* setup a probe */
	tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
@@ -1028,16 +1021,16 @@ static int __trace_kprobe_create(int argc, const char *argv[])
		ret = PTR_ERR(tk);
		/* This must return -ENOMEM, else there is a bug */
		WARN_ON_ONCE(ret != -ENOMEM);
		goto out;	/* We know tk is not allocated */
		return ret;	/* We know tk is not allocated */
	}

	/* parse arguments */
	for (i = 0; i < argc; i++) {
		trace_probe_log_set_index(i + 2);
		ctx.offset = 0;
		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);
		ctx->offset = 0;
		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], ctx);
		if (ret)
			goto out;	/* This can be -ENOMEM */
			return ret;	/* This can be -ENOMEM */
	}
	/* entry handler for kretprobe */
	if (is_return && tk->tp.entry_arg) {
@@ -1048,7 +1041,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
	ptype = is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
	ret = traceprobe_set_print_fmt(&tk->tp, ptype);
	if (ret < 0)
		goto out;
		return ret;

	ret = register_trace_kprobe(tk);
	if (ret) {
@@ -1059,26 +1052,34 @@ static int __trace_kprobe_create(int argc, const char *argv[])
			trace_probe_log_err(0, BAD_PROBE_ADDR);
		else if (ret != -ENOMEM && ret != -EEXIST)
			trace_probe_log_err(0, FAIL_REG_PROBE);
	} else
		return ret;
	}
	/*
	 * Here, 'tk' has been registered to the list successfully,
	 * so we don't need to free it.
	 */
	tk = NULL;

out:
	return 0;
}

static int trace_kprobe_create_cb(int argc, const char *argv[])
{
	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
	int ret;

	trace_probe_log_init("trace_kprobe", argc, argv);

	ret = trace_kprobe_create_internal(argc, argv, &ctx);

	traceprobe_finish_parse(&ctx);
	trace_probe_log_clear();
	return ret;

parse_error:
	ret = -EINVAL;
	goto out;
}

static int trace_kprobe_create(const char *raw_command)
{
	return trace_probe_create(raw_command, __trace_kprobe_create);
	return trace_probe_create(raw_command, trace_kprobe_create_cb);
}

static int create_or_delete_trace_kprobe(const char *raw_command)