|
@@ -1608,3 +1608,59 @@ cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) {
|
|
|
*/
|
|
|
static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
|
|
|
bool add_front)
|
|
|
+{
|
|
|
+ struct rb_node **p, *parent;
|
|
|
+ struct cfq_queue *__cfqq;
|
|
|
+ unsigned long rb_key;
|
|
|
+ struct cfq_rb_root *service_tree;
|
|
|
+ int left;
|
|
|
+ int new_cfqq = 1;
|
|
|
+
|
|
|
+ service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq),
|
|
|
+ cfqq_type(cfqq));
|
|
|
+ if (cfq_class_idle(cfqq)) {
|
|
|
+ rb_key = CFQ_IDLE_DELAY;
|
|
|
+ parent = rb_last(&service_tree->rb);
|
|
|
+ if (parent && parent != &cfqq->rb_node) {
|
|
|
+ __cfqq = rb_entry(parent, struct cfq_queue, rb_node);
|
|
|
+ rb_key += __cfqq->rb_key;
|
|
|
+ } else
|
|
|
+ rb_key += jiffies;
|
|
|
+ } else if (!add_front) {
|
|
|
+ /*
|
|
|
+ * Get our rb key offset. Subtract any residual slice
|
|
|
+ * value carried from last service. A negative resid
|
|
|
+ * count indicates slice overrun, and this should position
|
|
|
+ * the next service time further away in the tree.
|
|
|
+ */
|
|
|
+ rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies;
|
|
|
+ rb_key -= cfqq->slice_resid;
|
|
|
+ cfqq->slice_resid = 0;
|
|
|
+ } else {
|
|
|
+ rb_key = -HZ;
|
|
|
+ __cfqq = cfq_rb_first(service_tree);
|
|
|
+ rb_key += __cfqq ? __cfqq->rb_key : jiffies;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!RB_EMPTY_NODE(&cfqq->rb_node)) {
|
|
|
+ new_cfqq = 0;
|
|
|
+ /*
|
|
|
+ * same position, nothing more to do
|
|
|
+ */
|
|
|
+ if (rb_key == cfqq->rb_key &&
|
|
|
+ cfqq->service_tree == service_tree)
|
|
|
+ return;
|
|
|
+
|
|
|
+ cfq_rb_erase(&cfqq->rb_node, cfqq->service_tree);
|
|
|
+ cfqq->service_tree = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ left = 1;
|
|
|
+ parent = NULL;
|
|
|
+ cfqq->service_tree = service_tree;
|
|
|
+ p = &service_tree->rb.rb_node;
|
|
|
+ while (*p) {
|
|
|
+ struct rb_node **n;
|
|
|
+
|
|
|
+ parent = *p;
|
|
|
+ __cfqq = rb_entry(parent, struct cfq_queue, rb_node);
|