On Tue, Jul 02, 2024 at 01:54:47PM +0200, Peter Zijlstra wrote: > @@ -668,12 +677,25 @@ static struct uprobe *__find_uprobe(struct inode > *inode, loff_t offset) > static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) > { > struct uprobe *uprobe; > + unsigned seq; > > + guard(rcu)(); > > + do { > + seq = read_seqcount_begin(&uprobes_seqcount); > + uprobes = __find_uprobe(inode, offset); > + if (uprobes) { > + /* > + * Lockless RB-tree lookups are prone to > false-negatives. > + * If they find something, it's good. If they do not > find, > + * it needs to be validated. > + */ > + return uprobes; > + } > + } while (read_seqcount_retry(&uprobes_seqcount, seq)); > + > + /* Really didn't find anything. */ > + return NULL; > } > > static struct uprobe *__insert_uprobe(struct uprobe *uprobe) > @@ -702,7 +724,9 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe) > struct uprobe *u; > > write_lock(&uprobes_treelock); > + write_seqcount_begin(&uprobes_seqcount); > u = __insert_uprobe(uprobe); > + write_seqcount_end(&uprobes_seqcount); > write_unlock(&uprobes_treelock); > > return u;
Strictly speaking I suppose we should add rb_find_rcu() and rc_find_add_rcu() that sprinkle some rcu_dereference_raw() and rb_link_node_rcu() around. See the examples in __lt_find() and __lt_insert().