OSDN Git Service

block: Make blk_get_backing_dev_info() safe without open bdev
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / block / blk-core.c
index 3115494..56652cd 100644 (file)
@@ -87,7 +87,7 @@ static void blk_clear_congested(struct request_list *rl, int sync)
         * flip its congestion state for events on other blkcgs.
         */
        if (rl == &rl->q->root_rl)
-               clear_wb_congested(rl->q->backing_dev_info.wb.congested, sync);
+               clear_wb_congested(rl->q->backing_dev_info->wb.congested, sync);
 #endif
 }
 
@@ -98,7 +98,7 @@ static void blk_set_congested(struct request_list *rl, int sync)
 #else
        /* see blk_clear_congested() */
        if (rl == &rl->q->root_rl)
-               set_wb_congested(rl->q->backing_dev_info.wb.congested, sync);
+               set_wb_congested(rl->q->backing_dev_info->wb.congested, sync);
 #endif
 }
 
@@ -122,14 +122,12 @@ void blk_queue_congestion_threshold(struct request_queue *q)
  * @bdev:      device
  *
  * Locates the passed device's request queue and returns the address of its
- * backing_dev_info.  This function can only be called if @bdev is opened
- * and the return value is never NULL.
+ * backing_dev_info. The return value is never NULL however we may return
+ * &noop_backing_dev_info if the bdev is not currently open.
  */
 struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
 {
-       struct request_queue *q = bdev_get_queue(bdev);
-
-       return &q->backing_dev_info;
+       return bdev->bd_bdi;
 }
 EXPORT_SYMBOL(blk_get_backing_dev_info);
 
@@ -247,7 +245,7 @@ EXPORT_SYMBOL(blk_start_queue_async);
  **/
 void blk_start_queue(struct request_queue *q)
 {
-       WARN_ON(!irqs_disabled());
+       WARN_ON(!in_interrupt() && !irqs_disabled());
 
        queue_flag_clear(QUEUE_FLAG_STOPPED, q);
        __blk_run_queue(q);
@@ -597,7 +595,7 @@ void blk_cleanup_queue(struct request_queue *q)
        blk_flush_integrity();
 
        /* @q won't process any more request, flush async actions */
-       del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+       del_timer_sync(&q->backing_dev_info->laptop_mode_wb_timer);
        blk_sync_queue(q);
 
        if (q->mq_ops)
@@ -697,7 +695,6 @@ static void blk_queue_usage_counter_release(struct percpu_ref *ref)
 struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 {
        struct request_queue *q;
-       int err;
 
        q = kmem_cache_alloc_node(blk_requestq_cachep,
                                gfp_mask | __GFP_ZERO, node_id);
@@ -712,17 +709,17 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        if (!q->bio_split)
                goto fail_id;
 
-       q->backing_dev_info.ra_pages =
+       q->backing_dev_info = bdi_alloc_node(gfp_mask, node_id);
+       if (!q->backing_dev_info)
+               goto fail_split;
+
+       q->backing_dev_info->ra_pages =
                        (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
-       q->backing_dev_info.capabilities = BDI_CAP_CGROUP_WRITEBACK;
-       q->backing_dev_info.name = "block";
+       q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK;
+       q->backing_dev_info->name = "block";
        q->node = node_id;
 
-       err = bdi_init(&q->backing_dev_info);
-       if (err)
-               goto fail_split;
-
-       setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
+       setup_timer(&q->backing_dev_info->laptop_mode_wb_timer,
                    laptop_mode_timer_fn, (unsigned long) q);
        setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
        INIT_LIST_HEAD(&q->queue_head);
@@ -772,7 +769,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 fail_ref:
        percpu_ref_exit(&q->q_usage_counter);
 fail_bdi:
-       bdi_destroy(&q->backing_dev_info);
+       bdi_put(q->backing_dev_info);
 fail_split:
        bioset_free(q->bio_split);
 fail_id:
@@ -1195,7 +1192,7 @@ fail_elvpriv:
         * disturb iosched and blkcg but weird is bettern than dead.
         */
        printk_ratelimited(KERN_WARNING "%s: dev %s: request aux data allocation failed, iosched may be disturbed\n",
-                          __func__, dev_name(q->backing_dev_info.dev));
+                          __func__, dev_name(q->backing_dev_info->dev));
 
        rq->cmd_flags &= ~REQ_ELVPRIV;
        rq->elv.icq = NULL;
@@ -3251,7 +3248,7 @@ void blk_finish_request(struct request *req, int error)
        BUG_ON(blk_queued_rq(req));
 
        if (unlikely(laptop_mode) && req->cmd_type == REQ_TYPE_FS)
-               laptop_io_completion(&req->q->backing_dev_info);
+               laptop_io_completion(req->q->backing_dev_info);
 
        blk_delete_timer(req);