|
@@ -983,3 +983,137 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2,
|
|
#define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */
|
|
#define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */
|
|
#define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */
|
|
#define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */
|
|
unsigned wrap = 0; /* bit mask: requests behind the disk head? */
|
|
unsigned wrap = 0; /* bit mask: requests behind the disk head? */
|
|
|
|
+
|
|
|
|
+ if (rq1 == NULL || rq1 == rq2)
|
|
|
|
+ return rq2;
|
|
|
|
+ if (rq2 == NULL)
|
|
|
|
+ return rq1;
|
|
|
|
+
|
|
|
|
+ if (rq_is_sync(rq1) != rq_is_sync(rq2))
|
|
|
|
+ return rq_is_sync(rq1) ? rq1 : rq2;
|
|
|
|
+
|
|
|
|
+ if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_PRIO)
|
|
|
|
+ return rq1->cmd_flags & REQ_PRIO ? rq1 : rq2;
|
|
|
|
+
|
|
|
|
+ s1 = blk_rq_pos(rq1);
|
|
|
|
+ s2 = blk_rq_pos(rq2);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * by definition, 1KiB is 2 sectors
|
|
|
|
+ */
|
|
|
|
+ back_max = cfqd->cfq_back_max * 2;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Strict one way elevator _except_ in the case where we allow
|
|
|
|
+ * short backward seeks which are biased as twice the cost of a
|
|
|
|
+ * similar forward seek.
|
|
|
|
+ */
|
|
|
|
+ if (s1 >= last)
|
|
|
|
+ d1 = s1 - last;
|
|
|
|
+ else if (s1 + back_max >= last)
|
|
|
|
+ d1 = (last - s1) * cfqd->cfq_back_penalty;
|
|
|
|
+ else
|
|
|
|
+ wrap |= CFQ_RQ1_WRAP;
|
|
|
|
+
|
|
|
|
+ if (s2 >= last)
|
|
|
|
+ d2 = s2 - last;
|
|
|
|
+ else if (s2 + back_max >= last)
|
|
|
|
+ d2 = (last - s2) * cfqd->cfq_back_penalty;
|
|
|
|
+ else
|
|
|
|
+ wrap |= CFQ_RQ2_WRAP;
|
|
|
|
+
|
|
|
|
+ /* Found required data */
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * By doing switch() on the bit mask "wrap" we avoid having to
|
|
|
|
+ * check two variables for all permutations: --> faster!
|
|
|
|
+ */
|
|
|
|
+ switch (wrap) {
|
|
|
|
+ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */
|
|
|
|
+ if (d1 < d2)
|
|
|
|
+ return rq1;
|
|
|
|
+ else if (d2 < d1)
|
|
|
|
+ return rq2;
|
|
|
|
+ else {
|
|
|
|
+ if (s1 >= s2)
|
|
|
|
+ return rq1;
|
|
|
|
+ else
|
|
|
|
+ return rq2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case CFQ_RQ2_WRAP:
|
|
|
|
+ return rq1;
|
|
|
|
+ case CFQ_RQ1_WRAP:
|
|
|
|
+ return rq2;
|
|
|
|
+ case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both rqs wrapped */
|
|
|
|
+ default:
|
|
|
|
+ /*
|
|
|
|
+ * Since both rqs are wrapped,
|
|
|
|
+ * start with the one that's further behind head
|
|
|
|
+ * (--> only *one* back seek required),
|
|
|
|
+ * since back seek takes more time than forward.
|
|
|
|
+ */
|
|
|
|
+ if (s1 <= s2)
|
|
|
|
+ return rq1;
|
|
|
|
+ else
|
|
|
|
+ return rq2;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * The below is leftmost cache rbtree addon
|
|
|
|
+ */
|
|
|
|
+static struct cfq_queue *cfq_rb_first(struct cfq_rb_root *root)
|
|
|
|
+{
|
|
|
|
+ /* Service tree is empty */
|
|
|
|
+ if (!root->count)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ if (!root->left)
|
|
|
|
+ root->left = rb_first(&root->rb);
|
|
|
|
+
|
|
|
|
+ if (root->left)
|
|
|
|
+ return rb_entry(root->left, struct cfq_queue, rb_node);
|
|
|
|
+
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct cfq_group *cfq_rb_first_group(struct cfq_rb_root *root)
|
|
|
|
+{
|
|
|
|
+ if (!root->left)
|
|
|
|
+ root->left = rb_first(&root->rb);
|
|
|
|
+
|
|
|
|
+ if (root->left)
|
|
|
|
+ return rb_entry_cfqg(root->left);
|
|
|
|
+
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void rb_erase_init(struct rb_node *n, struct rb_root *root)
|
|
|
|
+{
|
|
|
|
+ rb_erase(n, root);
|
|
|
|
+ RB_CLEAR_NODE(n);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root)
|
|
|
|
+{
|
|
|
|
+ if (root->left == n)
|
|
|
|
+ root->left = NULL;
|
|
|
|
+ rb_erase_init(n, &root->rb);
|
|
|
|
+ --root->count;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * would be nice to take fifo expire time into account as well
|
|
|
|
+ */
|
|
|
|
+static struct request *
|
|
|
|
+cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
|
|
|
|
+ struct request *last)
|
|
|
|
+{
|
|
|
|
+ struct rb_node *rbnext = rb_next(&last->rb_node);
|
|
|
|
+ struct rb_node *rbprev = rb_prev(&last->rb_node);
|
|
|
|
+ struct request *next = NULL, *prev = NULL;
|
|
|
|
+
|
|
|
|
+ BUG_ON(RB_EMPTY_NODE(&last->rb_node));
|
|
|
|
+
|
|
|
|
+ if (rbprev)
|