Skip to content

Commit

Permalink
block: Move blk_throtl_exit() call to blk_cleanup_queue()
Browse files Browse the repository at this point in the history
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.

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 7ad58c0
        Author: Jens Axboe <[email protected]>
        Date:   Sat Oct 23 20:40:26 2010 +0200

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

This patch reverts above change and does not try to shutdown the
throtl work in blk_sync_queue(). By avoiding call to
throtl_shutdown_timer_wq() from blk_sync_queue(), we should also avoid
the problem reported by Ingo.

blk_sync_queue() seems to be used only by md driver and it seems to be
using it to make sure q->unplug_fn is not called as md registers its
own unplug functions and it is about to free up the data structures
used by unplug_fn(). Block throttle does not call back into unplug_fn()
or into md. So there is no need to cancel blk throttle work.

In fact I think cancelling block throttle work is bad because it might
happen that some bios are throttled and scheduled to be dispatched later
with the help of pending work and if work is cancelled, these bios might
never be dispatched.

Block layer also uses blk_sync_queue() during blk_cleanup_queue() and
blk_release_queue() time. That should be safe as we are also calling
blk_throtl_exit() which should make sure all the throttling related
data structures are cleaned up.

Signed-off-by: Vivek Goyal <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
rhvgoyal authored and Jens Axboe committed Mar 3, 2011
1 parent cd25f54 commit da52777
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 8 deletions.
7 changes: 6 additions & 1 deletion block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,13 +380,16 @@ EXPORT_SYMBOL(blk_stop_queue);
* that its ->make_request_fn will not re-add plugging prior to calling
* this function.
*
* This function does not cancel any asynchronous activity arising
* out of elevator or throttling code. That would require elevaotor_exit()
* and blk_throtl_exit() to be called with queue lock initialized.
*
*/
void blk_sync_queue(struct request_queue *q)
{
del_timer_sync(&q->unplug_timer);
del_timer_sync(&q->timeout);
cancel_work_sync(&q->unplug_work);
throtl_shutdown_timer_wq(q);
}
EXPORT_SYMBOL(blk_sync_queue);

Expand Down Expand Up @@ -469,6 +472,8 @@ void blk_cleanup_queue(struct request_queue *q)
if (q->elevator)
elevator_exit(q->elevator);

blk_throtl_exit(q);

blk_put_queue(q);
}
EXPORT_SYMBOL(blk_cleanup_queue);
Expand Down
2 changes: 0 additions & 2 deletions block/blk-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,6 @@ static void blk_release_queue(struct kobject *kobj)

blk_sync_queue(q);

blk_throtl_exit(q);

if (rl->rq_pool)
mempool_destroy(rl->rq_pool);

Expand Down
6 changes: 3 additions & 3 deletions block/blk-throttle.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ static void throtl_update_blkio_group_write_iops(void *key,
throtl_schedule_delayed_work(td->queue, 0);
}

void throtl_shutdown_timer_wq(struct request_queue *q)
static void throtl_shutdown_wq(struct request_queue *q)
{
struct throtl_data *td = q->td;

Expand Down Expand Up @@ -1099,7 +1099,7 @@ void blk_throtl_exit(struct request_queue *q)

BUG_ON(!td);

throtl_shutdown_timer_wq(q);
throtl_shutdown_wq(q);

spin_lock_irq(q->queue_lock);
throtl_release_tgs(td);
Expand Down Expand Up @@ -1129,7 +1129,7 @@ void blk_throtl_exit(struct request_queue *q)
* update limits through cgroup and another work got queued, cancel
* it.
*/
throtl_shutdown_timer_wq(q);
throtl_shutdown_wq(q);
throtl_td_free(td);
}

Expand Down
2 changes: 0 additions & 2 deletions include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,6 @@ extern int blk_throtl_init(struct request_queue *q);
extern void blk_throtl_exit(struct request_queue *q);
extern int blk_throtl_bio(struct request_queue *q, struct bio **bio);
extern void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay);
extern void throtl_shutdown_timer_wq(struct request_queue *q);
#else /* CONFIG_BLK_DEV_THROTTLING */
static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio)
{
Expand All @@ -1154,7 +1153,6 @@ static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio)
static inline int blk_throtl_init(struct request_queue *q) { return 0; }
static inline int blk_throtl_exit(struct request_queue *q) { return 0; }
static inline void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay) {}
static inline void throtl_shutdown_timer_wq(struct request_queue *q) {}
#endif /* CONFIG_BLK_DEV_THROTTLING */

#define MODULE_ALIAS_BLOCKDEV(major,minor) \
Expand Down

0 comments on commit da52777

Please sign in to comment.