All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vivek Goyal <vgoyal@redhat.com>
To: NeilBrown <neilb@suse.de>
Cc: Jens Axboe <jaxboe@fusionio.com>, linux-kernel@vger.kernel.org
Subject: Re: blk_throtl_exit  taking q->queue_lock is problematic
Date: Wed, 16 Feb 2011 10:53:05 -0500	[thread overview]
Message-ID: <20110216155305.GC14653@redhat.com> (raw)
In-Reply-To: <20110216183114.26a3613b@notabene.brown>

On Wed, Feb 16, 2011 at 06:31:14PM +1100, NeilBrown wrote:
> 
> 
> Hi,
> 
>  I recently discovered that blk_throtl_exit takes ->queue_lock when a blockdev
> is finally released.
> 
> This is a problem for because by that time the queue_lock doesn't exist any
> more.  It is in a separate data structure controlled by the RAID personality
> and by the time that the block device is being destroyed the raid personality
> has shutdown and the data structure containing the lock has been freed.
> 
> This has not been a problem before.  Nothing else takes queue_lock after
> blk_cleanup_queue.

I agree that this is a problem. blk_throtl_exit() needs queue lock to
avoid other races with cgroup code and for avoiding races for its
lists etc.

> 
> I could of course set queue_lock to point to __queue_lock and initialise that,
> but it seems untidy and probably violates some locking requirements.
> 
> Is there some way you could use some other lock - maybe a global lock, or
> maybe used __queue_lock directly ???

Initially I had put blk_throtl_exit() in blk_cleanup_queue() where it is
known that ->queue_lock is still around. Due to a bug, Jens moved it
to blk_release_queue(). I still think that blk_cleanup_queue() is a better
place to call blk_throtl_exit().

I think following patch should solve the issue. This patch is also not
completely race free. I was thinking that can we get rid of
throtl_shutdown_timer_wq() call in blk_sync_queue(). IOW, in what
circumstances blk_sync_queue() is used.

Thanks
Vivek


o Move blk_throtl_exit() in blk_cleanup_queue() as blk_throtl_exit() is
  written in such a way that it needs queue lock. In blk_release_queue()
  there is no gurantee that ->queue_lock is still around.

o Initially blk_throtl_exit() was in blk_cleanup_queue() but Ingo reported
  one problem.

  https://lkml.org/lkml/2010/10/23/86

  And a quick fix moved blk_throtl_exit() to blk_release_queue().

	commit 7ad58c028652753814054f4e3ac58f925e7343f4
	Author: Jens Axboe <jaxboe@fusionio.com>
	Date:   Sat Oct 23 20:40:26 2010 +0200

    	block: fix use-after-free bug in blk throttle code

o This patch reverts above change and instead checks for q->td in
  throtl_shutdown_timer_wq(). 

o This is also not completely race free as check for q->td is without
  spinlock and we can't take spinlock here as it is called from
  blk_release_queue->blk_sync_queue() where ->queue_lock might have gone
  away.

o So the question is should we really call throtl_shutdown_timer_wq() from
  blk_sync_queue(). It might not make much sense because there might
  be queued bios in throttling logic. The only way to cleanup all bios
  and cancel all async activity is blk_throtl_exit(). 

  I also don't see it being called to cancel async activity for CFQ. Who
  makes sure that async activity is cancelled. IOW, I am wondering in
  what circumstances blk_sync_queue() is called and is it required to
  call throtl_shutdown_timer_wq() from blk_sync_queue(). If we can get
  rid of it, then we have taken care of all the races, AFAIK.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 block/blk-core.c     |    2 ++
 block/blk-sysfs.c    |    2 --
 block/blk-throttle.c |    6 ++++++
 3 files changed, 8 insertions(+), 2 deletions(-)

Index: linux-2.6/block/blk-core.c
===================================================================
--- linux-2.6.orig/block/blk-core.c	2011-02-14 17:43:06.000000000 -0500
+++ linux-2.6/block/blk-core.c	2011-02-16 10:11:58.910022185 -0500
@@ -474,6 +474,8 @@ void blk_cleanup_queue(struct request_qu
 	if (q->elevator)
 		elevator_exit(q->elevator);
 
+	blk_throtl_exit(q);
+
 	blk_put_queue(q);
 }
 EXPORT_SYMBOL(blk_cleanup_queue);
Index: linux-2.6/block/blk-sysfs.c
===================================================================
--- linux-2.6.orig/block/blk-sysfs.c	2011-02-11 09:25:16.000000000 -0500
+++ linux-2.6/block/blk-sysfs.c	2011-02-16 10:12:16.379762988 -0500
@@ -471,8 +471,6 @@ static void blk_release_queue(struct kob
 
 	blk_sync_queue(q);
 
-	blk_throtl_exit(q);
-
 	if (rl->rq_pool)
 		mempool_destroy(rl->rq_pool);
 
Index: linux-2.6/block/blk-throttle.c
===================================================================
--- linux-2.6.orig/block/blk-throttle.c	2011-02-16 10:08:12.000000000 -0500
+++ linux-2.6/block/blk-throttle.c	2011-02-16 10:45:18.006119406 -0500
@@ -961,6 +961,9 @@ void throtl_shutdown_timer_wq(struct req
 {
 	struct throtl_data *td = q->td;
 
+	if (!td)
+		return;
+
 	cancel_delayed_work_sync(&td->throtl_work);
 }
 
@@ -1122,6 +1125,9 @@ void blk_throtl_exit(struct request_queu
 	 * it.
 	 */
 	throtl_shutdown_timer_wq(q);
+
+	/* Decouple throtl data from queue. */
+	q->td = NULL;
 	throtl_td_free(td);
 }
 

  reply	other threads:[~2011-02-16 15:53 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-16  7:31 blk_throtl_exit taking q->queue_lock is problematic NeilBrown
2011-02-16 15:53 ` Vivek Goyal [this message]
2011-02-17  0:35   ` NeilBrown
2011-02-17  1:10     ` Vivek Goyal
2011-02-17  5:55       ` NeilBrown
2011-02-17 15:01         ` Vivek Goyal
2011-02-17 16:59         ` Vivek Goyal
2011-02-18  2:40           ` NeilBrown
2011-02-18  3:19             ` Mike Snitzer
2011-02-18  3:33               ` NeilBrown
2011-02-18 14:04                 ` Mike Snitzer
2011-02-18 15:04                 ` Vivek Goyal
2011-02-21  7:24                   ` NeilBrown
2011-02-21 14:42                     ` Vivek Goyal
2011-02-18 15:05             ` Vivek Goyal
2011-02-17 20:00 ` Vivek Goyal
2011-02-18  1:57   ` NeilBrown

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=20110216155305.GC14653@redhat.com \
    --to=vgoyal@redhat.com \
    --cc=jaxboe@fusionio.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=neilb@suse.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 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.