Commit a83b576c authored by Jens Axboe's avatar Jens Axboe

block: fix stacked driver stats init and free

If a driver allocates a queue for stacked usage, then it does
not currently get stats allocated. This causes the later init
of, eg, writeback throttling to blow up. Move the init to the
queue allocation instead.

Additionally, allow a NULL callback unregistration. This avoids
having the caller check for that, fixing another oops on
removal of a block device that doesn't have poll stats allocated.

Fixes: 34dbad5d ("blk-stat: convert to callback-based statistics reporting")
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 34dbad5d
...@@ -720,6 +720,10 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) ...@@ -720,6 +720,10 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
if (!q->backing_dev_info) if (!q->backing_dev_info)
goto fail_split; goto fail_split;
q->stats = blk_alloc_queue_stats();
if (!q->stats)
goto fail_stats;
q->backing_dev_info->ra_pages = q->backing_dev_info->ra_pages =
(VM_MAX_READAHEAD * 1024) / PAGE_SIZE; (VM_MAX_READAHEAD * 1024) / PAGE_SIZE;
q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK; q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK;
...@@ -776,6 +780,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) ...@@ -776,6 +780,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
fail_ref: fail_ref:
percpu_ref_exit(&q->q_usage_counter); percpu_ref_exit(&q->q_usage_counter);
fail_bdi: fail_bdi:
blk_free_queue_stats(q->stats);
fail_stats:
bdi_put(q->backing_dev_info); bdi_put(q->backing_dev_info);
fail_split: fail_split:
bioset_free(q->bio_split); bioset_free(q->bio_split);
...@@ -852,10 +858,6 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio); ...@@ -852,10 +858,6 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio);
int blk_init_allocated_queue(struct request_queue *q) int blk_init_allocated_queue(struct request_queue *q)
{ {
q->stats = blk_alloc_queue_stats();
if (!q->stats)
return -ENOMEM;
q->fq = blk_alloc_flush_queue(q, NUMA_NO_NODE, q->cmd_size); q->fq = blk_alloc_flush_queue(q, NUMA_NO_NODE, q->cmd_size);
if (!q->fq) if (!q->fq)
return -ENOMEM; return -ENOMEM;
......
...@@ -210,7 +210,8 @@ static void blk_stat_free_callback_rcu(struct rcu_head *head) ...@@ -210,7 +210,8 @@ static void blk_stat_free_callback_rcu(struct rcu_head *head)
void blk_stat_free_callback(struct blk_stat_callback *cb) void blk_stat_free_callback(struct blk_stat_callback *cb)
{ {
call_rcu(&cb->rcu, blk_stat_free_callback_rcu); if (cb)
call_rcu(&cb->rcu, blk_stat_free_callback_rcu);
} }
EXPORT_SYMBOL_GPL(blk_stat_free_callback); EXPORT_SYMBOL_GPL(blk_stat_free_callback);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment