Merge tag 'v3.10.103' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / block / cfq-iosched.c
index d5cd3131c57a36645bcf049e28ab9a46ab5ea559..69111c5c352ce7f874aed1a769197563d6d96011 100644 (file)
@@ -1275,12 +1275,16 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
 static void
 cfq_update_group_weight(struct cfq_group *cfqg)
 {
-       BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
-
        if (cfqg->new_weight) {
                cfqg->weight = cfqg->new_weight;
                cfqg->new_weight = 0;
        }
+}
+
+static void
+cfq_update_group_leaf_weight(struct cfq_group *cfqg)
+{
+       BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
 
        if (cfqg->new_leaf_weight) {
                cfqg->leaf_weight = cfqg->new_leaf_weight;
@@ -1299,7 +1303,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
        /* add to the service tree */
        BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
 
-       cfq_update_group_weight(cfqg);
+       cfq_update_group_leaf_weight(cfqg);
        __cfq_group_service_tree_add(st, cfqg);
 
        /*
@@ -1323,6 +1327,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
         */
        while ((parent = cfqg_parent(pos))) {
                if (propagate) {
+                       cfq_update_group_weight(pos);
                        propagate = !parent->nr_active++;
                        parent->children_weight += pos->weight;
                }
@@ -1803,7 +1808,7 @@ static u64 cfqg_prfill_avg_queue_size(struct seq_file *sf,
 
        if (samples) {
                v = blkg_stat_read(&cfqg->stats.avg_queue_size_sum);
-               do_div(v, samples);
+               v = div64_u64(v, samples);
        }
        __blkg_prfill_u64(sf, pd, v);
        return 0;
@@ -3570,6 +3575,11 @@ retry:
 
        blkcg = bio_blkcg(bio);
        cfqg = cfq_lookup_create_cfqg(cfqd, blkcg);
+       if (!cfqg) {
+               cfqq = &cfqd->oom_cfqq;
+               goto out;
+       }
+
        cfqq = cic_to_cfqq(cic, is_sync);
 
        /*
@@ -3606,7 +3616,7 @@ retry:
                } else
                        cfqq = &cfqd->oom_cfqq;
        }
-
+out:
        if (new_cfqq)
                kmem_cache_free(cfq_pool, new_cfqq);
 
@@ -3636,12 +3646,17 @@ static struct cfq_queue *
 cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic,
              struct bio *bio, gfp_t gfp_mask)
 {
-       const int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio);
-       const int ioprio = IOPRIO_PRIO_DATA(cic->ioprio);
+       int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio);
+       int ioprio = IOPRIO_PRIO_DATA(cic->ioprio);
        struct cfq_queue **async_cfqq = NULL;
        struct cfq_queue *cfqq = NULL;
 
        if (!is_sync) {
+               if (!ioprio_valid(cic->ioprio)) {
+                       struct task_struct *tsk = current;
+                       ioprio = task_nice_ioprio(tsk);
+                       ioprio_class = task_nice_ioclass(tsk);
+               }
                async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio);
                cfqq = *async_cfqq;
        }
@@ -4347,18 +4362,28 @@ static void cfq_exit_queue(struct elevator_queue *e)
        kfree(cfqd);
 }
 
-static int cfq_init_queue(struct request_queue *q)
+static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
 {
        struct cfq_data *cfqd;
        struct blkcg_gq *blkg __maybe_unused;
        int i, ret;
+       struct elevator_queue *eq;
+
+       eq = elevator_alloc(q, e);
+       if (!eq)
+               return -ENOMEM;
 
        cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
-       if (!cfqd)
+       if (!cfqd) {
+               kobject_put(&eq->kobj);
                return -ENOMEM;
+       }
+       eq->elevator_data = cfqd;
 
        cfqd->queue = q;
-       q->elevator->elevator_data = cfqd;
+       spin_lock_irq(q->queue_lock);
+       q->elevator = eq;
+       spin_unlock_irq(q->queue_lock);
 
        /* Init root service tree */
        cfqd->grp_service_tree = CFQ_RB_ROOT;
@@ -4433,6 +4458,7 @@ static int cfq_init_queue(struct request_queue *q)
 
 out_free:
        kfree(cfqd);
+       kobject_put(&eq->kobj);
        return ret;
 }