The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Alexey Dobriyan <adobriyan@gmail.com>
To: Roland McGrath <roland@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/2] utrace core
Date: Wed, 27 Aug 2008 02:55:19 +0400	[thread overview]
Message-ID: <20080826225519.GC27724@x200.localdomain> (raw)
In-Reply-To: <20080826220157.397C7154233@magilla.localdomain>

On Tue, Aug 26, 2008 at 03:01:57PM -0700, Roland McGrath wrote:
> This adds the utrace facility, a new modular interface in the kernel for
> implementing user thread tracing and debugging.  This fits on top of the
> tracehook_* layer, so the new code is well-isolated.

I'll says this again: tracehook_* is pointless abstraction because
there will be no second generic tracing facility. The author of second
one will be asked what is bad in utrace with very high odds.

> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1196,6 +1196,11 @@ struct task_struct {
>  #endif
>  	seccomp_t seccomp;
>  
> +#ifdef CONFIG_UTRACE
> +	struct utrace *utrace;
> +	unsigned long utrace_flags;
> +#endif

Again, embed struct utrace directly into task_struct. task_struct
lifetime rules are way more tested than struct utrace ones.

Add simple spinlock guarding all accesses (OK, I haven't looked very
closely if it's possible)

Nobody needs hundred-line utrace_attach with CPU barriers.

Nobody needs RCU.

Nobody needs restart logic.

Reminder: that struct utrace double-free was P_I_T_A to debug.

I'll check last utrace oops we talked is still there and bogus patch was applied
(sorry, haven't slept night at all). And run to confirm that attach/detach/exec
program still crashes it. There is PREEMPT_RCU now so it will be even more not
funny.

> --- /dev/null
> +++ b/kernel/utrace.c

> +/*
> + * Make sure target->utrace is allocated, and return with it locked on
> + * success.  This function mediates startup races.  The creating parent
> + * task has priority, and other callers will delay here to let its call
> + * succeed and take the new utrace lock first.
> + */
> +static struct utrace *utrace_first_engine(struct task_struct *target,
> +					  struct utrace_attached_engine *engine)
> +	__acquires(utrace->lock)
> +{
> +	struct utrace *utrace;
> +
> +	/*
> +	 * If this is a newborn thread and we are not the creator,
> +	 * we have to wait for it.  The creator gets the first chance
> +	 * to attach.  The PF_STARTING flag is cleared after its
> +	 * report_clone hook has had a chance to run.
> +	 */
> +	if (target->flags & PF_STARTING) {
> +		utrace = current->utrace;
> +		if (utrace == NULL || utrace->u.live.cloning != target) {
> +			yield();
> +			if (signal_pending(current))
> +				return ERR_PTR(-ERESTARTNOINTR);
> +			return NULL;
> +		}
> +	}
> +
> +	utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL);
> +	if (unlikely(utrace == NULL))
> +		return ERR_PTR(-ENOMEM);
> +
> +	INIT_LIST_HEAD(&utrace->attached);
> +	INIT_LIST_HEAD(&utrace->attaching);
> +	list_add(&engine->entry, &utrace->attached);
> +	spin_lock_init(&utrace->lock);
> +	CHECK_INIT(utrace);
> +
> +	spin_lock(&utrace->lock);
> +	task_lock(target);
> +	if (likely(target->utrace == NULL)) {
> +		rcu_assign_pointer(target->utrace, utrace);
> +
> +		/*
> +		 * The task_lock protects us against another thread doing
> +		 * the same thing.  We might still be racing against
> +		 * tracehook_release_task.  It's called with ->exit_state
> +		 * set to EXIT_DEAD and then checks ->utrace with an
> +		 * smp_mb() in between.  If EXIT_DEAD is set, then
> +		 * release_task might have checked ->utrace already and saw
> +		 * it NULL; we can't attach.  If we see EXIT_DEAD not yet
> +		 * set after our barrier, then we know release_task will
> +		 * see our target->utrace pointer.
> +		 */
> +		smp_mb();
> +		if (likely(target->exit_state != EXIT_DEAD)) {
> +			task_unlock(target);
> +			return utrace;
> +		}
> +
> +		/*
> +		 * The target has already been through release_task.
> +		 * Our caller will restart and notice it's too late now.
> +		 */
> +		target->utrace = NULL;
> +	}
> +
> +	/*
> +	 * Another engine attached first, so there is a struct already.
> +	 * A null return says to restart looking for the existing one.
> +	 */
> +	task_unlock(target);
> +	spin_unlock(&utrace->lock);
> +	kmem_cache_free(utrace_cachep, utrace);
> +
> +	return NULL;
> +}

All this junk will dissapear. I even posted proff-of-concept patch.

> +/*
> + * Called with utrace locked.  Clean it up and free it via RCU.
> + */
> +static void rcu_utrace_free(struct utrace *utrace)
> +	__releases(utrace->lock)
> +{
> +	CHECK_DEAD(utrace);
> +	spin_unlock(&utrace->lock);
> +	INIT_RCU_HEAD(&utrace->u.dead);
> +	call_rcu(&utrace->u.dead, utrace_free);

INIT_RCU_HEAD is not needed, call_rcu() will overwrite rcu head unconditionally.


  reply	other threads:[~2008-08-26 22:53 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-26 22:01 [PATCH 0/2] utrace Roland McGrath
2008-08-26 22:01 ` [PATCH 1/2] utrace core Roland McGrath
2008-08-26 22:55   ` Alexey Dobriyan [this message]
2008-08-27 21:32     ` Alexey Dobriyan
2008-08-27 21:46       ` Alexey Dobriyan
2008-08-27 22:00         ` Alexey Dobriyan
2008-08-30 13:45     ` Christoph Hellwig
2008-09-03 12:11     ` Roland McGrath
2008-09-03 17:01       ` Alexey Dobriyan
2008-08-27 20:04   ` Alexey Dobriyan
2008-09-03 12:11     ` Roland McGrath
2008-09-03 18:44       ` Christoph Hellwig
2008-08-30 15:05   ` Alexey Dobriyan
2008-09-03 12:58   ` Petr Tesarik
2008-09-03 18:08     ` Roland McGrath
2008-09-03 18:46       ` Christoph Hellwig
2008-09-04  9:03         ` Petr Tesarik
2008-08-26 22:02 ` [PATCH 2/2] utrace: ptrace cooperation Roland McGrath
2008-08-30 13:38   ` Christoph Hellwig
2008-09-03 12:10     ` Roland McGrath
2008-09-03 18:41       ` Christoph Hellwig
2008-08-26 22:34 ` [PATCH 0/2] utrace Alexey Dobriyan
2008-08-26 22:39   ` Christoph Hellwig
2008-08-27  0:17   ` Frank Ch. Eigler
2008-08-27 13:54     ` Christoph Hellwig
2008-08-27 16:40       ` Ananth N Mavinakayanahalli
2008-08-30 13:40         ` Christoph Hellwig
2008-09-03 12:09           ` Roland McGrath
2008-09-03 18:37             ` Christoph Hellwig
2008-08-27 15:34     ` Alexey Dobriyan
2008-08-29 19:04       ` Frank Ch. Eigler
2008-08-30 13:43       ` Christoph Hellwig
2008-08-27 18:50   ` Alexey Dobriyan
2008-08-27  2:03 ` Peter Zijlstra
2008-10-06 20:47 ` Peter Zijlstra

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=20080826225519.GC27724@x200.localdomain \
    --to=adobriyan@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=roland@redhat.com \
    --cc=torvalds@linux-foundation.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox