OSDN Git Service

Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[uclinux-h8/linux.git] / block / bfq-iosched.c
index 36a66e9..29d2635 100644 (file)
@@ -774,7 +774,7 @@ bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq)
        if (!bfqq->next_rq)
                return;
 
-       bfqq->pos_root = &bfq_bfqq_to_bfqg(bfqq)->rq_pos_tree;
+       bfqq->pos_root = &bfqq_group(bfqq)->rq_pos_tree;
        __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root,
                        blk_rq_pos(bfqq->next_rq), &parent, &p);
        if (!__bfqq) {
@@ -2153,7 +2153,7 @@ static void bfq_check_waker(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                bfqq->waker_detection_started = now_ns;
                bfq_bfqq_name(bfqq->tentative_waker_bfqq, waker_name,
                              MAX_BFQQ_NAME_LENGTH);
-               bfq_log_bfqq(bfqd, bfqq, "set tenative waker %s", waker_name);
+               bfq_log_bfqq(bfqd, bfqq, "set tentative waker %s", waker_name);
        } else /* Same tentative waker queue detected again */
                bfqq->num_waker_detections++;
 
@@ -2669,7 +2669,7 @@ static struct bfq_queue *bfqq_find_close(struct bfq_data *bfqd,
                                         struct bfq_queue *bfqq,
                                         sector_t sector)
 {
-       struct rb_root *root = &bfq_bfqq_to_bfqg(bfqq)->rq_pos_tree;
+       struct rb_root *root = &bfqq_group(bfqq)->rq_pos_tree;
        struct rb_node *parent, *node;
        struct bfq_queue *__bfqq;
 
@@ -2782,6 +2782,15 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
         * are likely to increase the throughput.
         */
        bfqq->new_bfqq = new_bfqq;
+       /*
+        * The above assignment schedules the following redirections:
+        * each time some I/O for bfqq arrives, the process that
+        * generated that I/O is disassociated from bfqq and
+        * associated with new_bfqq. Here we increases new_bfqq->ref
+        * in advance, adding the number of processes that are
+        * expected to be associated with new_bfqq as they happen to
+        * issue I/O.
+        */
        new_bfqq->ref += process_refs;
        return new_bfqq;
 }
@@ -2844,6 +2853,10 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 {
        struct bfq_queue *in_service_bfqq, *new_bfqq;
 
+       /* if a merge has already been setup, then proceed with that first */
+       if (bfqq->new_bfqq)
+               return bfqq->new_bfqq;
+
        /*
         * Check delayed stable merge for rotational or non-queueing
         * devs. For this branch to be executed, bfqq must not be
@@ -2945,9 +2958,6 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
        if (bfq_too_late_for_merging(bfqq))
                return NULL;
 
-       if (bfqq->new_bfqq)
-               return bfqq->new_bfqq;
-
        if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq))
                return NULL;
 
@@ -5181,7 +5191,7 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
        struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
        struct request *rq;
        struct bfq_queue *in_serv_queue;
-       bool waiting_rq, idle_timer_disabled;
+       bool waiting_rq, idle_timer_disabled = false;
 
        spin_lock_irq(&bfqd->lock);
 
@@ -5189,14 +5199,15 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
        waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
 
        rq = __bfq_dispatch_request(hctx);
-
-       idle_timer_disabled =
-               waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
+       if (in_serv_queue == bfqd->in_service_queue) {
+               idle_timer_disabled =
+                       waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
+       }
 
        spin_unlock_irq(&bfqd->lock);
-
-       bfq_update_dispatch_stats(hctx->queue, rq, in_serv_queue,
-                                 idle_timer_disabled);
+       bfq_update_dispatch_stats(hctx->queue, rq,
+                       idle_timer_disabled ? in_serv_queue : NULL,
+                               idle_timer_disabled);
 
        return rq;
 }