Merge branch 'for-linus' of git://git.kernel.dk/linux-block

Pull block layer fix from Jens Axboe:
 "Just a single fix this week, fixing a regression introduced in this
  release.

  When we put the final reference to the queue, we may need to block.
  Ensure that we can safely do so. From Bart"

* 'for-linus' of git://git.kernel.dk/linux-block:
  block: Fix a blk_exit_rl() regression
This commit is contained in:
Linus Torvalds 2017-06-16 17:26:10 +09:00
commit e78e4626d4
2 changed files with 24 additions and 12 deletions

View File

@ -777,24 +777,25 @@ static void blk_free_queue_rcu(struct rcu_head *rcu_head)
}
/**
* blk_release_queue: - release a &struct request_queue when it is no longer needed
* @kobj: the kobj belonging to the request queue to be released
* __blk_release_queue - release a request queue when it is no longer needed
* @work: pointer to the release_work member of the request queue to be released
*
* Description:
* blk_release_queue is the pair to blk_init_queue() or
* blk_queue_make_request(). It should be called when a request queue is
* being released; typically when a block device is being de-registered.
* Currently, its primary task it to free all the &struct request
* structures that were allocated to the queue and the queue itself.
* blk_release_queue is the counterpart of blk_init_queue(). It should be
* called when a request queue is being released; typically when a block
* device is being de-registered. Its primary task it to free the queue
* itself.
*
* Note:
* Notes:
* The low level driver must have finished any outstanding requests first
* via blk_cleanup_queue().
**/
static void blk_release_queue(struct kobject *kobj)
*
* Although blk_release_queue() may be called with preemption disabled,
* __blk_release_queue() may sleep.
*/
static void __blk_release_queue(struct work_struct *work)
{
struct request_queue *q =
container_of(kobj, struct request_queue, kobj);
struct request_queue *q = container_of(work, typeof(*q), release_work);
if (test_bit(QUEUE_FLAG_POLL_STATS, &q->queue_flags))
blk_stat_remove_callback(q, q->poll_cb);
@ -834,6 +835,15 @@ static void blk_release_queue(struct kobject *kobj)
call_rcu(&q->rcu_head, blk_free_queue_rcu);
}
static void blk_release_queue(struct kobject *kobj)
{
struct request_queue *q =
container_of(kobj, struct request_queue, kobj);
INIT_WORK(&q->release_work, __blk_release_queue);
schedule_work(&q->release_work);
}
static const struct sysfs_ops queue_sysfs_ops = {
.show = queue_attr_show,
.store = queue_attr_store,

View File

@ -586,6 +586,8 @@ struct request_queue {
size_t cmd_size;
void *rq_alloc_data;
struct work_struct release_work;
};
#define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */