Re: [RFC] [PATCH 2.6.37-rc5-tip 4/20] 4: uprobes: Adding andremove a uprobe in a rb tree.

From: Peter Zijlstra
Date: Tue Jan 25 2011 - 07:16:40 EST


On Thu, 2010-12-16 at 15:28 +0530, Srikar Dronamraju wrote:
> +static int match_inode(struct uprobe *uprobe, struct inode *inode,
> + struct rb_node **p)
> +{
> + struct rb_node *n = *p;
> +
> + if (inode < uprobe->inode)
> + *p = n->rb_left;
> + else if (inode > uprobe->inode)
> + *p = n->rb_right;
> + else
> + return 1;
> + return 0;
> +}
> +
> +static int match_offset(struct uprobe *uprobe, unsigned long offset,
> + struct rb_node **p)
> +{
> + struct rb_node *n = *p;
> +
> + if (offset < uprobe->offset)
> + *p = n->rb_left;
> + else if (offset > uprobe->offset)
> + *p = n->rb_right;
> + else
> + return 1;
> + return 0;
> +}
> +
> +/*
> + * Find a uprobe corresponding to a given inode:offset
> + * Acquires treelock
> + */
> +static struct uprobe *find_uprobe(struct inode * inode,
> + unsigned long offset)
> +{
> + struct rb_node *n = uprobes_tree.rb_node;
> + struct uprobe *uprobe, *u = NULL;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&treelock, flags);
> + while (n) {
> + uprobe = rb_entry(n, struct uprobe, rb_node);
> +
> + if (match_inode(uprobe, inode, &n)) {
> + if (match_offset(uprobe, offset, &n)) {
> + if (atomic_inc_not_zero(&uprobe->ref))
> + u = uprobe;
> + break;
> + }
> + }
> + }
> + spin_unlock_irqrestore(&treelock, flags);
> + return u;
> +}
> +
> +/*
> + * Check if a uprobe is already inserted;
> + * If it does; return refcount incremented uprobe
> + * else add the current uprobe and return NULL
> + * Acquires treelock.
> + */
> +static struct uprobe *insert_uprobe_rb_node(struct uprobe *uprobe)
> +{
> + struct rb_node **p = &uprobes_tree.rb_node;
> + struct rb_node *parent = NULL;
> + struct uprobe *u;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&treelock, flags);
> + while (*p) {
> + parent = *p;
> + u = rb_entry(parent, struct uprobe, rb_node);
> + if (u->inode > uprobe->inode)
> + p = &(*p)->rb_left;
> + else if (u->inode < uprobe->inode)
> + p = &(*p)->rb_right;
> + else {
> + if (u->offset > uprobe->offset)
> + p = &(*p)->rb_left;
> + else if (u->offset < uprobe->offset)
> + p = &(*p)->rb_right;
> + else {
> + atomic_inc(&u->ref);

If the lookup can find a 'dead' entry, then why can't we here?

> + goto unlock_return;
> + }
> + }
> + }
> + u = NULL;
> + rb_link_node(&uprobe->rb_node, parent, p);
> + rb_insert_color(&uprobe->rb_node, &uprobes_tree);
> + atomic_set(&uprobe->ref, 2);
> +
> +unlock_return:
> + spin_unlock_irqrestore(&treelock, flags);
> + return u;
> +}

It would be nice if you could merge the find and 'acquire' thing, the
lookup is basically the same in both cases.

Also, I'm not quite sure on the name of that last function, its not a
strict insert and what's the trailing _rb_node about? That lookup isn't
called find_uprobe_rb_node() either is it?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/