This is the mail archive of the systemtap@sources.redhat.com mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Design + prototype: Multiple kprobes at an address - take2


Jim Keniston wrote:
On Wed, 2005-04-06 at 07:48, Ananth N Mavinakayanahalli wrote:

Hi Jim,


Thanks for the review comments!

I missed take 1.  Sorry if these comments have already been addressed,
but here goes...

...

+
+static void copy_kprobe(struct kprobe *src, struct kprobe *dst)
+{
+	dst->opcode = src->opcode;
+	memcpy(&dst->ainsn, &src->ainsn, sizeof(struct arch_specific_insn));
+}


x86_64 stores the copy of the instruction on a different (executable)
page.  (See arch_prepare_kprobe().)  It's not clear to me that you take
this into account.

struct arch_specific_insn on x86_64 is just kprobe_opcode_t *insn. So I think we should be ok here.

+
+struct aggr_probe *register_aggr_probe(struct kprobe *old_p)
+{
+	struct aggr_probe *ap;
+
+	ap = kcalloc(1, sizeof(struct aggr_probe), GFP_ATOMIC);


I understand why you have to use GFP_ATOMIC here (lock held), but
consider that there may be many probepoints where there are multiple
kprobes.  (E.g., Hien is thinking of re-implementing retprobes using
your multiple-kprobes feature, to allow register/unregister of a
retprobe to be independent of the entry probe.  Think about those two
probes at the entry for every system call.)  Anyway, it's probably best
to avoid eating up GFP_ATOMIC memory.

Instead, why not pre-allocate this memory early in register_kprobe(),
before you acquire the lock?  If you don't need it (the usual case), you
can just free it.

Hmm, some cases to think of if kmalloc/kcalloc fails in this case:


- if this is the only probe at the address, the registration should
still go on.
- if this is one of many, the registration should fail.

I think this is doable.

...

int register_kprobe(struct kprobe *p)
{
	int ret = 0;
	unsigned long flags = 0;
+	struct aggr_probe *ap;
+	struct kprobe *old_p;

	if ((ret = arch_prepare_kprobe(p)) != 0) {
		goto rm_kprobe;
	}
+	
	spin_lock_irqsave(&kprobe_lock, flags);
	INIT_HLIST_NODE(&p->hlist);
-	if (get_kprobe(p->addr)) {
-		ret = -EEXIST;
+	old_p = get_kprobe(p->addr);
+	if (old_p) {
+		if (old_p->break_handler) {


Seems like you could change this to
		if (old_p->break_handler || p->break_handler)
and remove the two checks below.

Yes, you are right. Guess I can't get dumber :-)


....


void unregister_kprobe(struct kprobe *p)
{
unsigned long flags;
- arch_remove_kprobe(p);
+ struct kprobe *kp;
+ struct aggr_probe *ap;
+
spin_lock_irqsave(&kprobe_lock, flags);
+ kp = get_kprobe(p->addr);
+ if (kp && (kp->pre_handler == aggr_pre_handler)) {
+
+ /* this is one of the possibly many kprobes at the address */
+ ap = container_of(kp, struct aggr_probe, kp);
+ list_del(&p->list);
+
+ /* + * if we just unregistered the last probe at the address,
+ * its time to cleanup
+ */ + if (list_empty(&ap->kprobes)) {
+ arch_remove_kprobe(p);


Unfortunately, on x86_64, arch_remove_kprobe() can sleep, so you can't
call it holding a lock.

...

Hmm OK. Will have to rearrange the code a bit.


Thanks,
Ananth


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]