Commit 6f8191fd authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

block: simplify disk shutdown



Set the queue dying flag and call blk_mq_exit_queue from del_gendisk for
all disks that do not have separately allocated queues, and thus remove
the need to call blk_cleanup_queue for them.

Rename blk_cleanup_disk to blk_mq_destroy_queue to make it clear that
this function is intended only for separately allocated blk-mq queues.

This saves an extra queue freeze for devices without a separately
allocated queue.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Link: https://lore.kernel.org/r/20220619060552.1850436-6-hch@lst.de


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 0e353402
Loading
Loading
Loading
Loading
+0 −37
Original line number Diff line number Diff line
@@ -284,43 +284,6 @@ void blk_queue_start_drain(struct request_queue *q)
	wake_up_all(&q->mq_freeze_wq);
}

/**
 * blk_cleanup_queue - shutdown a request queue
 * @q: request queue to shutdown
 *
 * Mark @q DYING, drain all pending requests, mark @q DEAD, destroy and
 * put it.  All future requests will be failed immediately with -ENODEV.
 *
 * Context: can sleep
 */
void blk_cleanup_queue(struct request_queue *q)
{
	/* cannot be called from atomic context */
	might_sleep();

	WARN_ON_ONCE(blk_queue_registered(q));

	/* mark @q DYING, no new request or merges will be allowed afterwards */
	blk_queue_flag_set(QUEUE_FLAG_DYING, q);
	blk_queue_start_drain(q);

	/*
	 * Drain all requests queued before DYING marking. Set DEAD flag to
	 * prevent that blk_mq_run_hw_queues() accesses the hardware queues
	 * after draining finished.
	 */
	blk_freeze_queue(q);
	blk_sync_queue(q);
	if (queue_is_mq(q)) {
		blk_mq_cancel_work_sync(q);
		blk_mq_exit_queue(q);
	}

	/* @q is and will stay empty, shutdown and put */
	blk_put_queue(q);
}
EXPORT_SYMBOL(blk_cleanup_queue);

/**
 * blk_queue_enter() - try to increase q->q_usage_counter
 * @q: request queue pointer
+41 −2
Original line number Diff line number Diff line
@@ -3902,7 +3902,7 @@ static struct request_queue *blk_mq_init_queue_data(struct blk_mq_tag_set *set,
	q->queuedata = queuedata;
	ret = blk_mq_init_allocated_queue(set, q);
	if (ret) {
		blk_cleanup_queue(q);
		blk_put_queue(q);
		return ERR_PTR(ret);
	}
	return q;
@@ -3914,6 +3914,35 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
}
EXPORT_SYMBOL(blk_mq_init_queue);

/**
 * blk_mq_destroy_queue - shutdown a request queue
 * @q: request queue to shutdown
 *
 * This shuts down a request queue allocated by blk_mq_init_queue() and drops
 * the initial reference.  All future requests will failed with -ENODEV.
 *
 * Context: can sleep
 */
void blk_mq_destroy_queue(struct request_queue *q)
{
	WARN_ON_ONCE(!queue_is_mq(q));
	WARN_ON_ONCE(blk_queue_registered(q));

	might_sleep();

	blk_queue_flag_set(QUEUE_FLAG_DYING, q);
	blk_queue_start_drain(q);
	blk_freeze_queue(q);

	blk_sync_queue(q);
	blk_mq_cancel_work_sync(q);
	blk_mq_exit_queue(q);

	/* @q is and will stay empty, shutdown and put */
	blk_put_queue(q);
}
EXPORT_SYMBOL(blk_mq_destroy_queue);

struct gendisk *__blk_mq_alloc_disk(struct blk_mq_tag_set *set, void *queuedata,
		struct lock_class_key *lkclass)
{
@@ -3926,13 +3955,23 @@ struct gendisk *__blk_mq_alloc_disk(struct blk_mq_tag_set *set, void *queuedata,

	disk = __alloc_disk_node(q, set->numa_node, lkclass);
	if (!disk) {
		blk_cleanup_queue(q);
		blk_put_queue(q);
		return ERR_PTR(-ENOMEM);
	}
	set_bit(GD_OWNS_QUEUE, &disk->state);
	return disk;
}
EXPORT_SYMBOL(__blk_mq_alloc_disk);

struct gendisk *blk_mq_alloc_disk_for_queue(struct request_queue *q,
		struct lock_class_key *lkclass)
{
	if (!blk_get_queue(q))
		return NULL;
	return __alloc_disk_node(q, NUMA_NO_NODE, lkclass);
}
EXPORT_SYMBOL(blk_mq_alloc_disk_for_queue);

static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
		struct blk_mq_tag_set *set, struct request_queue *q,
		int hctx_idx, int node)
+0 −5
Original line number Diff line number Diff line
@@ -755,11 +755,6 @@ static void blk_free_queue_rcu(struct rcu_head *rcu_head)
 * decremented with blk_put_queue(). Once the refcount reaches 0 this function
 * is called.
 *
 * For drivers that have a request_queue on a gendisk and added with
 * __device_add_disk() the refcount to request_queue will reach 0 with
 * the last put_disk() called by the driver. For drivers which don't use
 * __device_add_disk() this happens with blk_cleanup_queue().
 *
 * Drivers exist which depend on the release of the request_queue to be
 * synchronous, it should not be deferred.
 *
+3 −0
Original line number Diff line number Diff line
@@ -424,6 +424,9 @@ int bdev_resize_partition(struct gendisk *disk, int partno, sector_t start,
		sector_t length);
void blk_drop_partitions(struct gendisk *disk);

struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
		struct lock_class_key *lkclass);

int bio_add_hw_page(struct request_queue *q, struct bio *bio,
		struct page *page, unsigned int len, unsigned int offset,
		unsigned int max_sectors, bool *same_page);
+2 −2
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ void bsg_remove_queue(struct request_queue *q)
			container_of(q->tag_set, struct bsg_set, tag_set);

		bsg_unregister_queue(bset->bd);
		blk_cleanup_queue(q);
		blk_mq_destroy_queue(q);
		blk_mq_free_tag_set(&bset->tag_set);
		kfree(bset);
	}
@@ -399,7 +399,7 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,

	return q;
out_cleanup_queue:
	blk_cleanup_queue(q);
	blk_mq_destroy_queue(q);
out_queue:
	blk_mq_free_tag_set(set);
out_tag_set:
Loading