Commit 9ff01255 authored by Liu Bo's avatar Liu Bo Committed by Jens Axboe

Blk-throttle: update to use rbtree with leftmost node cached

As rbtree has native support of caching leftmost node,
i.e. rb_root_cached, no need to do the caching by ourselves.
Signed-off-by: default avatarLiu Bo <bo.liu@linux.alibaba.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 576ed913
...@@ -84,8 +84,7 @@ struct throtl_service_queue { ...@@ -84,8 +84,7 @@ struct throtl_service_queue {
* RB tree of active children throtl_grp's, which are sorted by * RB tree of active children throtl_grp's, which are sorted by
* their ->disptime. * their ->disptime.
*/ */
struct rb_root pending_tree; /* RB tree of active tgs */ struct rb_root_cached pending_tree; /* RB tree of active tgs */
struct rb_node *first_pending; /* first node in the tree */
unsigned int nr_pending; /* # queued in the tree */ unsigned int nr_pending; /* # queued in the tree */
unsigned long first_pending_disptime; /* disptime of the first tg */ unsigned long first_pending_disptime; /* disptime of the first tg */
struct timer_list pending_timer; /* fires on first_pending_disptime */ struct timer_list pending_timer; /* fires on first_pending_disptime */
...@@ -475,7 +474,7 @@ static void throtl_service_queue_init(struct throtl_service_queue *sq) ...@@ -475,7 +474,7 @@ static void throtl_service_queue_init(struct throtl_service_queue *sq)
{ {
INIT_LIST_HEAD(&sq->queued[0]); INIT_LIST_HEAD(&sq->queued[0]);
INIT_LIST_HEAD(&sq->queued[1]); INIT_LIST_HEAD(&sq->queued[1]);
sq->pending_tree = RB_ROOT; sq->pending_tree = RB_ROOT_CACHED;
timer_setup(&sq->pending_timer, throtl_pending_timer_fn, 0); timer_setup(&sq->pending_timer, throtl_pending_timer_fn, 0);
} }
...@@ -616,31 +615,23 @@ static void throtl_pd_free(struct blkg_policy_data *pd) ...@@ -616,31 +615,23 @@ static void throtl_pd_free(struct blkg_policy_data *pd)
static struct throtl_grp * static struct throtl_grp *
throtl_rb_first(struct throtl_service_queue *parent_sq) throtl_rb_first(struct throtl_service_queue *parent_sq)
{ {
struct rb_node *n;
/* Service tree is empty */ /* Service tree is empty */
if (!parent_sq->nr_pending) if (!parent_sq->nr_pending)
return NULL; return NULL;
if (!parent_sq->first_pending) n = rb_first_cached(&parent_sq->pending_tree);
parent_sq->first_pending = rb_first(&parent_sq->pending_tree); WARN_ON_ONCE(!n);
if (!n)
if (parent_sq->first_pending) return NULL;
return rb_entry_tg(parent_sq->first_pending); return rb_entry_tg(n);
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 throtl_rb_erase(struct rb_node *n, static void throtl_rb_erase(struct rb_node *n,
struct throtl_service_queue *parent_sq) struct throtl_service_queue *parent_sq)
{ {
if (parent_sq->first_pending == n) rb_erase_cached(n, &parent_sq->pending_tree);
parent_sq->first_pending = NULL; RB_CLEAR_NODE(n);
rb_erase_init(n, &parent_sq->pending_tree);
--parent_sq->nr_pending; --parent_sq->nr_pending;
} }
...@@ -658,11 +649,11 @@ static void update_min_dispatch_time(struct throtl_service_queue *parent_sq) ...@@ -658,11 +649,11 @@ static void update_min_dispatch_time(struct throtl_service_queue *parent_sq)
static void tg_service_queue_add(struct throtl_grp *tg) static void tg_service_queue_add(struct throtl_grp *tg)
{ {
struct throtl_service_queue *parent_sq = tg->service_queue.parent_sq; struct throtl_service_queue *parent_sq = tg->service_queue.parent_sq;
struct rb_node **node = &parent_sq->pending_tree.rb_node; struct rb_node **node = &parent_sq->pending_tree.rb_root.rb_node;
struct rb_node *parent = NULL; struct rb_node *parent = NULL;
struct throtl_grp *__tg; struct throtl_grp *__tg;
unsigned long key = tg->disptime; unsigned long key = tg->disptime;
int left = 1; bool leftmost = true;
while (*node != NULL) { while (*node != NULL) {
parent = *node; parent = *node;
...@@ -672,15 +663,13 @@ static void tg_service_queue_add(struct throtl_grp *tg) ...@@ -672,15 +663,13 @@ static void tg_service_queue_add(struct throtl_grp *tg)
node = &parent->rb_left; node = &parent->rb_left;
else { else {
node = &parent->rb_right; node = &parent->rb_right;
left = 0; leftmost = false;
} }
} }
if (left)
parent_sq->first_pending = &tg->rb_node;
rb_link_node(&tg->rb_node, parent, node); rb_link_node(&tg->rb_node, parent, node);
rb_insert_color(&tg->rb_node, &parent_sq->pending_tree); rb_insert_color_cached(&tg->rb_node, &parent_sq->pending_tree,
leftmost);
} }
static void __throtl_enqueue_tg(struct throtl_grp *tg) static void __throtl_enqueue_tg(struct throtl_grp *tg)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment