public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Matthieu Fertré" <matthieu.fertre@kerlabs.com>
To: Darren Hart <dvhart@linux.intel.com>
Cc: lkml <linux-kernel@vger.kernel.org>,
	Louis Rilling <louis.rilling@kerlabs.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@elte.hu>,
	Eric Dumazet <eric.dumazet@gmail.com>,
	John Kacur <jkacur@redhat.com>,
	Rusty Russell <rusty@rustcorp.com.au>
Subject: Re: [PATCH] futex: fix errors in nested key ref-counting
Date: Tue, 19 Oct 2010 10:55:39 +0200	[thread overview]
Message-ID: <4CBD5D0B.8010309@kerlabs.com> (raw)
In-Reply-To: <4CBB17A8.70401@linux.intel.com>

Hi,

the patch fixes the bug on my side. Without it, on 2.6.36-rc8, I get a
general protection error at second run of the test I have previously sent.

Thanks,

Matthieu


Le 17/10/2010 17:35, Darren Hart a écrit :
> The following patch should address the ref counting issue reported by
> Mattieu and Louis as well as one with futex_wait_requeue_pi. I have only
> been able to test on a single socket dual core i7 system, I'd like to
> see some additional testing.
> 
> I have another pair of patches which push the ref-counting out of
> unqueue_me() and futex_wait_setup(), but they're exhibiting some
> unexpected behavior. I didn't want to hold up this fix on those
> cleanups.
> 
> 
> 
> From 7b0ff7743691c07ef9283d63388d9cfc0de736ef Mon Sep 17 00:00:00 2001
> From: Darren Hart <dvhart@linux.intel.com>
> Date: Fri, 15 Oct 2010 13:18:46 -0700
> Subject: [PATCH] futex: fix errors in nested key ref-counting
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> futex_wait() was leaking key references due to futex_wait_setup() acquiring an
> additional reference via the queue_lock() routine. The nested key ref-counting
> has been masking bugs and complicating code analysis. queue_lock() is only
> called with a previously ref-counted key, so remove the additional ref-counting
> from the queue_(un)lock() functions.
> 
> futex_wait_requeue_pi() drops one key reference too many in unqueue_me_pi().
> Remove the key reference handling from unqueue_me_pi(). This was paired with a
> queue_lock() in futex_lock_pi(), so the count remains unchanged.
> 
> Document remaining nested key ref-counting sites.
> 
> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
> Reported-by: Matthieu Fertré<matthieu.fertre@kerlabs.com>
> Reported-by: Louis Rilling<louis.rilling@kerlabs.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Ingo Molnar <mingo@elte.hu>
> CC: Eric Dumazet <eric.dumazet@gmail.com>
> CC: John Kacur <jkacur@redhat.com>
> CC: Rusty Russell <rusty@rustcorp.com.au>
> ---
>  kernel/futex.c |   31 ++++++++++++++++---------------
>  1 files changed, 16 insertions(+), 15 deletions(-)
> 
> diff --git a/kernel/futex.c b/kernel/futex.c
> index 6a3a5fa..abaafd0 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -1363,7 +1363,6 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
>  {
>  	struct futex_hash_bucket *hb;
>  
> -	get_futex_key_refs(&q->key);
>  	hb = hash_futex(&q->key);
>  	q->lock_ptr = &hb->lock;
>  
> @@ -1375,7 +1374,6 @@ static inline void
>  queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
>  {
>  	spin_unlock(&hb->lock);
> -	drop_futex_key_refs(&q->key);
>  }
>  
>  /**
> @@ -1480,8 +1478,6 @@ static void unqueue_me_pi(struct futex_q *q)
>  	q->pi_state = NULL;
>  
>  	spin_unlock(q->lock_ptr);
> -
> -	drop_futex_key_refs(&q->key);
>  }
>  
>  /*
> @@ -1812,7 +1808,10 @@ static int futex_wait(u32 __user *uaddr, int fshared,
>  	}
>  
>  retry:
> -	/* Prepare to wait on uaddr. */
> +	/*
> +	 * Prepare to wait on uaddr. On success, holds hb lock and increments
> +	 * q.key refs.
> +	 */
>  	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
>  	if (ret)
>  		goto out;
> @@ -1822,24 +1821,23 @@ retry:
>  
>  	/* If we were woken (and unqueued), we succeeded, whatever. */
>  	ret = 0;
> +	/* unqueue_me() drops q.key ref */
>  	if (!unqueue_me(&q))
> -		goto out_put_key;
> +		goto out;
>  	ret = -ETIMEDOUT;
>  	if (to && !to->task)
> -		goto out_put_key;
> +		goto out;
>  
>  	/*
>  	 * We expect signal_pending(current), but we might be the
>  	 * victim of a spurious wakeup as well.
>  	 */
> -	if (!signal_pending(current)) {
> -		put_futex_key(fshared, &q.key);
> +	if (!signal_pending(current))
>  		goto retry;
> -	}
>  
>  	ret = -ERESTARTSYS;
>  	if (!abs_time)
> -		goto out_put_key;
> +		goto out;
>  
>  	restart = &current_thread_info()->restart_block;
>  	restart->fn = futex_wait_restart;
> @@ -1856,8 +1854,6 @@ retry:
>  
>  	ret = -ERESTART_RESTARTBLOCK;
>  
> -out_put_key:
> -	put_futex_key(fshared, &q.key);
>  out:
>  	if (to) {
>  		hrtimer_cancel(&to->timer);
> @@ -2236,7 +2232,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
>  	q.rt_waiter = &rt_waiter;
>  	q.requeue_pi_key = &key2;
>  
> -	/* Prepare to wait on uaddr. */
> +	/* 
> +	 * Prepare to wait on uaddr. On success, increments q.key (key1) ref
> +	 * count.
> +	 */
>  	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
>  	if (ret)
>  		goto out_key2;
> @@ -2254,7 +2253,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
>  	 * In order for us to be here, we know our q.key == key2, and since
>  	 * we took the hb->lock above, we also know that futex_requeue() has
>  	 * completed and we no longer have to concern ourselves with a wakeup
> -	 * race with the atomic proxy lock acquition by the requeue code.
> +	 * race with the atomic proxy lock acquition by the requeue code. The
> +	 * futex_requeue dropped our key1 reference and incremented our key2
> +	 * reference count.
>  	 */
>  
>  	/* Check if the requeue code acquired the second futex for us. */


      reply	other threads:[~2010-10-19  8:55 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-17 15:35 [PATCH] futex: fix errors in nested key ref-counting Darren Hart
2010-10-19  8:55 ` Matthieu Fertré [this message]

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=4CBD5D0B.8010309@kerlabs.com \
    --to=matthieu.fertre@kerlabs.com \
    --cc=dvhart@linux.intel.com \
    --cc=eric.dumazet@gmail.com \
    --cc=jkacur@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=louis.rilling@kerlabs.com \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    --cc=rusty@rustcorp.com.au \
    --cc=tglx@linutronix.de \
    /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