public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
		Ingo Molnar <mingo@elte.hu>, Jim Keniston <jkenisto@us.ibm.com>,
		LKML <linux-kernel@vger.kernel.org>,
		systemtap-ml <systemtap@sources.redhat.com>
Subject: Re: [RFC][PATCH -tip 8/9] kprobes: support respawn probes for 	module probing
Date: Sat, 21 Mar 2009 01:32:00 -0000	[thread overview]
Message-ID: <20090321000844.GD6044@nowhere> (raw)
In-Reply-To: <49C31206.3060806@redhat.com>

On Thu, Mar 19, 2009 at 11:48:22PM -0400, Masami Hiramatsu wrote:
> Frederic Weisbecker wrote:
> >> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> >> index 5016bfb..f16a54e 100644
> >> --- a/kernel/kprobes.c
> >> +++ b/kernel/kprobes.c
> >> @@ -1416,6 +1416,256 @@ static int __kprobes debugfs_kprobe_init(void)
> >>  late_initcall(debugfs_kprobe_init);
> >>  #endif /* CONFIG_DEBUG_FS */
> >>
> >> +/* Kprobes module respawn support */
> >> +enum probe_type {
> >> +	PROBE_TYPE_KPROBE,
> >> +	PROBE_TYPE_KRETPROBE,
> >> +	PROBE_TYPE_JPROBE,
> >> +};
> >> +
> >> +struct module_probe_client {
> >> +	struct list_head list;
> >> +	const char *module;	/* including symbol name */
> >> +	int active;
> >> +	void *data;
> >> +	probe_activate_handler_t handler;
> >> +	enum probe_type type;
> >> +	union {
> >> +		struct kprobe *kp;
> >> +		struct kretprobe *rp;
> >> +		struct jprobe *jp;
> >> +	};
> >> +};
> >> +
> >> +static DEFINE_MUTEX(module_probe_mutex);
> >> +static LIST_HEAD(module_probe_list);
> >> +
> >> +static int activate_module_probe(struct module_probe_client *pc)
> >> +{
> >> +	int ret = 0;
> >> +	if (pc->active)
> >> +		return 0;
> >> +	switch (pc->type) {
> >> +	case PROBE_TYPE_KPROBE:
> >> +		ret = register_kprobe(pc->kp);
> >> +		break;
> >> +	case PROBE_TYPE_KRETPROBE:
> >> +		ret = register_kretprobe(pc->rp);
> >> +		break;
> >> +	case PROBE_TYPE_JPROBE:
> >> +		ret = register_jprobe(pc->jp);
> >> +		break;
> >> +	default:
> >> +		WARN_ON(1);
> >> +		break;
> >> +	}
> >> +	if (!ret)
> >> +		pc->active = 1;
> >> +	return ret;
> >> +}
> >> +
> >> +static void deactivate_module_probe(struct module_probe_client *pc)
> >> +{
> >> +	if (!pc->active)
> >> +		return;
> >> +	switch (pc->type) {
> >> +	case PROBE_TYPE_KPROBE:
> >> +		unregister_kprobe(pc->kp);
> >> +		break;
> >> +	case PROBE_TYPE_KRETPROBE:
> >> +		unregister_kretprobe(pc->rp);
> >> +		break;
> >> +	case PROBE_TYPE_JPROBE:
> >> +		unregister_jprobe(pc->jp);
> >> +		break;
> >> +	default:
> >> +		WARN_ON(1);
> >> +		break;
> >> +	}
> >> +	pc->active = 0;
> >> +}
> >> +
> >> +static const char *probed_module_name(struct kprobe *kp)
> >> +{
> >> +	if ((kp->symbol_name) && strchr(kp->symbol_name, ':'))
> >> +		return kp->symbol_name;
> >> +	return NULL;
> >> +}
> >> +
> >> +static int module_is_exist(const char *module)
> >> +{
> >> +	char buf[MODULE_NAME_LEN + 8];
> >> +	snprintf(buf, MODULE_NAME_LEN + 8, "%s:__stext", module);
> >> +	return module_kallsyms_lookup_name(buf) ? 1 : 0;
> >> +}
> >> +
> >> +static int add_module_probe(const char *module, void *p, enum probe_type type,
> >> +			    probe_activate_handler_t handler, void *data)
> >> +{
> >> +	struct module_probe_client *pc;
> >> +	int ret = 0;
> >> +
> >> +	if (!handler)
> >> +		return -EINVAL;
> >> +
> >> +	pc = kzalloc(sizeof(struct module_probe_client), GFP_KERNEL);
> >> +	pc->kp = p;
> >> +	pc->type = type;
> >> +	pc->module = module;
> >> +	pc->handler = handler;
> >> +	pc->data = data;
> >> +	INIT_LIST_HEAD(&pc->list);
> >> +
> >> +	mutex_lock(&module_probe_mutex);
> >> +	if (module_is_exist(module))
> >> +		ret = activate_module_probe(pc);
> >> +	if (ret)
> >> +		kfree(pc);
> >> +	else
> >> +		list_add_tail(&pc->list, &module_probe_list);
> >> +	mutex_unlock(&module_probe_mutex);
> >> +	return ret;
> >> +}
> >> +
> >> +static void __del_module_probe(struct module_probe_client *pc)
> >> +{
> >> +	list_del(&pc->list);
> >> +	deactivate_module_probe(pc);
> >> +	kfree(pc);
> >> +}
> >> +
> >> +static int del_module_probe(void *p)
> >> +{
> >> +	struct module_probe_client *pc;
> >> +	int ret;
> >> +
> >> +	mutex_lock(&module_probe_mutex);
> >> +	list_for_each_entry(pc, &module_probe_list, list)
> >> +		if (pc->kp == p) {
> >> +			/* don't need safe loop, we exit soon */
> >> +			__del_module_probe(pc);
> >> +			goto found;
> >> +		}
> >> +	ret = -ENOENT;
> >> +found:
> >> +	mutex_unlock(&module_probe_mutex);
> >> +	return ret;
> >> +}
> >> +
> >> +int __kprobes
> >> +register_module_kprobe(struct kprobe *kp,
> >> +		       probe_activate_handler_t handler, void *data)
> >> +{
> >> +	const char *module;
> >> +	module = probed_module_name(kp);
> >> +	if (!module)
> >> +		return register_kprobe(kp);
> >> +	return add_module_probe(module, kp, PROBE_TYPE_KPROBE,
> >> +				handler, data);
> >> +}
> >> +EXPORT_SYMBOL_GPL(register_module_kprobe);
> >> +
> >> +int __kprobes
> >> +register_module_kretprobe(struct kretprobe *rp,
> >> +			  probe_activate_handler_t handler, void *data)
> >> +{
> >> +	const char *module;
> >> +	module = probed_module_name(&rp->kp);
> >> +	if (!module)
> >> +		return register_kretprobe(rp);
> >> +	return add_module_probe(module, rp, PROBE_TYPE_KRETPROBE,
> >> +				handler, data);
> >> +}
> >> +EXPORT_SYMBOL_GPL(register_module_kretprobe);
> >> +
> >> +int __kprobes
> >> +register_module_jprobe(struct jprobe *jp,
> >> +		       probe_activate_handler_t handler, void *data)
> >> +{
> >> +	const char *module;
> >> +	module = probed_module_name(&jp->kp);
> >> +	if (!module)
> >> +		return register_jprobe(jp);
> >> +	return add_module_probe(module, jp, PROBE_TYPE_JPROBE,
> >> +				handler, data);
> >> +}
> >> +EXPORT_SYMBOL_GPL(register_module_jprobe);
> >> +
> >> +void __kprobes unregister_module_kprobe(struct kprobe *kp)
> >> +{
> >> +	const char *module;
> >> +	module = probed_module_name(kp);
> >> +	if (!module)
> >> +		unregister_kprobe(kp);
> >> +	else
> >> +		del_module_probe(kp);
> >> +}
> >> +EXPORT_SYMBOL_GPL(unregister_module_kprobe);
> >> +
> >> +void __kprobes unregister_module_kretprobe(struct kretprobe *rp)
> >> +{
> >> +	const char *module;
> >> +	module = probed_module_name(&rp->kp);
> >> +	if (!module)
> >> +		unregister_kretprobe(rp);
> >> +	else
> >> +		del_module_probe(rp);
> >> +}
> >> +EXPORT_SYMBOL_GPL(unregister_module_kretprobe);
> >> +
> >> +void __kprobes unregister_module_jprobe(struct jprobe *jp)
> >> +{
> >> +	const char *module;
> >> +	module = probed_module_name(&jp->kp);
> >> +	if (!module)
> >> +		unregister_jprobe(jp);
> >> +	else
> >> +		del_module_probe(jp);
> >> +}
> >> +EXPORT_SYMBOL_GPL(unregister_module_jprobe);
> >> +
> >> +static int module_is_probed(const char *mod, const char *sym)
> >> +{
> >> +	int len = strlen(mod);
> >> +	return strncmp(mod, sym, len) == 0 && sym[len] == ':';
> >> +}
> >> +
> >> +static int module_probe_callback(struct notifier_block *nb,
> >> +				 unsigned long state, void *module)
> >> +{
> >> +	struct module_probe_client *pc;
> >> +	struct module *mod = module;
> >> +	if (state == MODULE_STATE_LIVE)
> >> +		return NOTIFY_DONE;
> >> +
> >> +	mutex_lock(&module_probe_mutex);
> >> +	list_for_each_entry(pc, &module_probe_list, list) {
> >> +		if (!module_is_probed(mod->name, pc->module))
> >> +			continue;
> >> +		if (state == MODULE_STATE_COMING &&
> >> +		    pc->handler(pc->data, module)) {
> > 
> > 
> > I don't see a place where you check if pc->handler != NULL
> > May be you could attach a stub in such cases.
> 
> Please see add_module_probe(), handler == NULL case returns -EINVAL,
> and module_probe_list is internal list. So, pc->handler never be NULL.


Ah ok, I missed it.
And indeed if the users don't care about giving a handler, they just
have to use the usual kprobe functions.

 
> Thank you,
> 
> -- 
> Masami Hiramatsu
> 
> Software Engineer
> Hitachi Computer Products (America) Inc.
> Software Solutions Division
> 
> e-mail: mhiramat@redhat.com
> 

      reply	other threads:[~2009-03-21  0:08 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-20  0:08 Masami Hiramatsu
2009-03-20  1:55 ` Frederic Weisbecker
2009-03-20  5:43   ` Masami Hiramatsu
2009-03-20  3:03 ` Frederic Weisbecker
2009-03-20  4:41   ` Masami Hiramatsu
2009-03-21  1:32     ` Frederic Weisbecker [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090321000844.GD6044@nowhere \
    --to=fweisbec@gmail.com \
    --cc=ananth@in.ibm.com \
    --cc=jkenisto@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhiramat@redhat.com \
    --cc=mingo@elte.hu \
    --cc=systemtap@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).