From: Jiri Olsa <olsajiri@gmail.com>
To: Andrii Nakryiko <andrii@kernel.org>
Cc: linux-trace-kernel@vger.kernel.org, peterz@infradead.org,
oleg@redhat.com, rostedt@goodmis.org, mhiramat@kernel.org,
bpf@vger.kernel.org, linux-kernel@vger.kernel.org,
paulmck@kernel.org
Subject: Re: [PATCH 2/8] uprobes: revamp uprobe refcounting and lifetime management
Date: Thu, 1 Aug 2024 13:09:47 +0200 [thread overview]
Message-ID: <Zqts-5hac4_H-lrC@krava> (raw)
In-Reply-To: <20240731214256.3588718-3-andrii@kernel.org>
On Wed, Jul 31, 2024 at 02:42:50PM -0700, Andrii Nakryiko wrote:
SNIP
> static void put_uprobe(struct uprobe *uprobe)
> {
> - if (refcount_dec_and_test(&uprobe->ref)) {
> - /*
> - * If application munmap(exec_vma) before uprobe_unregister()
> - * gets called, we don't get a chance to remove uprobe from
> - * delayed_uprobe_list from remove_breakpoint(). Do it here.
> - */
> - mutex_lock(&delayed_uprobe_lock);
> - delayed_uprobe_remove(uprobe, NULL);
> - mutex_unlock(&delayed_uprobe_lock);
> - kfree(uprobe);
> - }
> + if (!refcount_dec_and_test(&uprobe->ref))
> + return;
> +
> + write_lock(&uprobes_treelock);
> +
> + if (uprobe_is_active(uprobe))
> + rb_erase(&uprobe->rb_node, &uprobes_tree);
> +
> + write_unlock(&uprobes_treelock);
> +
> + /*
> + * If application munmap(exec_vma) before uprobe_unregister()
> + * gets called, we don't get a chance to remove uprobe from
> + * delayed_uprobe_list from remove_breakpoint(). Do it here.
> + */
> + mutex_lock(&delayed_uprobe_lock);
> + delayed_uprobe_remove(uprobe, NULL);
> + mutex_unlock(&delayed_uprobe_lock);
we should do kfree(uprobe) in here, right?
I think this is fixed later on when uprobe_free_rcu is introduced
SNIP
> @@ -1159,27 +1180,16 @@ struct uprobe *uprobe_register(struct inode *inode,
> if (!IS_ALIGNED(ref_ctr_offset, sizeof(short)))
> return ERR_PTR(-EINVAL);
>
> - retry:
> uprobe = alloc_uprobe(inode, offset, ref_ctr_offset);
> if (IS_ERR(uprobe))
> return uprobe;
>
> - /*
> - * We can race with uprobe_unregister()->delete_uprobe().
> - * Check uprobe_is_active() and retry if it is false.
> - */
> down_write(&uprobe->register_rwsem);
> - ret = -EAGAIN;
> - if (likely(uprobe_is_active(uprobe))) {
> - consumer_add(uprobe, uc);
> - ret = register_for_each_vma(uprobe, uc);
> - }
> + consumer_add(uprobe, uc);
> + ret = register_for_each_vma(uprobe, uc);
> up_write(&uprobe->register_rwsem);
> - put_uprobe(uprobe);
>
> if (ret) {
> - if (unlikely(ret == -EAGAIN))
> - goto retry;
nice, I like getting rid of this.. so far lgtm ;-)
jirka
> uprobe_unregister(uprobe, uc);
> return ERR_PTR(ret);
> }
> @@ -1286,15 +1296,19 @@ static void build_probe_list(struct inode *inode,
> u = rb_entry(t, struct uprobe, rb_node);
> if (u->inode != inode || u->offset < min)
> break;
> + u = try_get_uprobe(u);
> + if (!u) /* uprobe already went away, safe to ignore */
> + continue;
> list_add(&u->pending_list, head);
> - get_uprobe(u);
> }
> for (t = n; (t = rb_next(t)); ) {
> u = rb_entry(t, struct uprobe, rb_node);
> if (u->inode != inode || u->offset > max)
> break;
> + u = try_get_uprobe(u);
> + if (!u) /* uprobe already went away, safe to ignore */
> + continue;
> list_add(&u->pending_list, head);
> - get_uprobe(u);
> }
> }
> read_unlock(&uprobes_treelock);
> @@ -1752,6 +1766,12 @@ static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask)
> return -ENOMEM;
>
> *n = *o;
> + /*
> + * uprobe's refcnt has to be positive at this point, kept by
> + * utask->return_instances items; return_instances can't be
> + * removed right now, as task is blocked due to duping; so
> + * get_uprobe() is safe to use here.
> + */
> get_uprobe(n->uprobe);
> n->next = NULL;
>
> @@ -1894,7 +1914,10 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
> }
> orig_ret_vaddr = utask->return_instances->orig_ret_vaddr;
> }
> -
> + /*
> + * uprobe's refcnt is positive, held by caller, so it's safe to
> + * unconditionally bump it one more time here
> + */
> ri->uprobe = get_uprobe(uprobe);
> ri->func = instruction_pointer(regs);
> ri->stack = user_stack_pointer(regs);
> --
> 2.43.0
>
next prev parent reply other threads:[~2024-08-01 11:09 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-31 21:42 [PATCH 0/8] uprobes: RCU-protected hot path optimizations Andrii Nakryiko
2024-07-31 21:42 ` [PATCH 1/8] rbtree: provide rb_find_rcu() / rb_find_add_rcu() Andrii Nakryiko
2024-07-31 21:42 ` [PATCH 2/8] uprobes: revamp uprobe refcounting and lifetime management Andrii Nakryiko
2024-08-01 11:09 ` Jiri Olsa [this message]
2024-08-01 16:49 ` Andrii Nakryiko
2024-08-01 22:07 ` Andrii Nakryiko
2024-08-02 8:50 ` Oleg Nesterov
2024-08-02 14:58 ` Andrii Nakryiko
2024-08-02 22:19 ` Oleg Nesterov
2024-08-02 11:11 ` Jiri Olsa
2024-08-02 15:03 ` Andrii Nakryiko
2024-08-05 13:44 ` Oleg Nesterov
2024-08-05 17:29 ` Andrii Nakryiko
2024-08-06 10:45 ` Oleg Nesterov
2024-07-31 21:42 ` [PATCH 3/8] uprobes: protected uprobe lifetime with SRCU Andrii Nakryiko
2024-08-01 12:23 ` Liao, Chang
2024-08-01 16:49 ` Andrii Nakryiko
2024-08-02 1:30 ` Liao, Chang
2024-08-05 14:51 ` Oleg Nesterov
2024-08-05 17:31 ` Andrii Nakryiko
2024-07-31 21:42 ` [PATCH 4/8] uprobes: get rid of enum uprobe_filter_ctx in uprobe filter callbacks Andrii Nakryiko
2024-07-31 21:42 ` [PATCH 5/8] uprobes: travers uprobe's consumer list locklessly under SRCU protection Andrii Nakryiko
2024-08-01 14:27 ` Jiri Olsa
2024-08-01 16:49 ` Andrii Nakryiko
2024-08-05 15:59 ` Oleg Nesterov
2024-08-05 17:31 ` Andrii Nakryiko
2024-08-06 10:54 ` Oleg Nesterov
2024-07-31 21:42 ` [PATCH 6/8] perf/uprobe: split uprobe_unregister() Andrii Nakryiko
2024-08-02 2:41 ` Liao, Chang
2024-08-02 15:05 ` Andrii Nakryiko
2024-08-05 20:01 ` Andrii Nakryiko
2024-08-06 1:50 ` Liao, Chang
2024-08-07 13:17 ` Oleg Nesterov
2024-08-07 15:24 ` Andrii Nakryiko
2024-07-31 21:42 ` [PATCH 7/8] uprobes: perform lockless SRCU-protected uprobes_tree lookup Andrii Nakryiko
2024-08-07 17:14 ` Andrii Nakryiko
2024-08-08 10:04 ` Oleg Nesterov
2024-08-08 14:29 ` Oleg Nesterov
2024-08-08 17:00 ` Andrii Nakryiko
2024-08-08 13:40 ` Oleg Nesterov
2024-08-10 14:00 ` Oleg Nesterov
2024-07-31 21:42 ` [PATCH 8/8] uprobes: switch to RCU Tasks Trace flavor for better performance Andrii Nakryiko
2024-08-01 9:35 ` Peter Zijlstra
2024-08-01 16:49 ` Andrii Nakryiko
2024-08-01 18:05 ` Paul E. McKenney
2024-08-07 13:29 ` [PATCH 0/8] uprobes: RCU-protected hot path optimizations Oleg Nesterov
2024-08-07 15:24 ` Andrii Nakryiko
2024-08-07 17:11 ` Oleg Nesterov
2024-08-07 17:31 ` Andrii Nakryiko
2024-08-07 18:24 ` Oleg Nesterov
2024-08-08 7:51 ` Liao, Chang
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=Zqts-5hac4_H-lrC@krava \
--to=olsajiri@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=oleg@redhat.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.