|
@@ -330,26 +330,19 @@ static struct bio *throtl_pop_queued(struct list_head *queued,
|
|
|
}
|
|
|
|
|
|
/* init a service_queue, assumes the caller zeroed it */
|
|
|
-static void throtl_service_queue_init(struct throtl_service_queue *sq,
|
|
|
- struct throtl_service_queue *parent_sq)
|
|
|
+static void throtl_service_queue_init(struct throtl_service_queue *sq)
|
|
|
{
|
|
|
INIT_LIST_HEAD(&sq->queued[0]);
|
|
|
INIT_LIST_HEAD(&sq->queued[1]);
|
|
|
sq->pending_tree = RB_ROOT;
|
|
|
- sq->parent_sq = parent_sq;
|
|
|
setup_timer(&sq->pending_timer, throtl_pending_timer_fn,
|
|
|
(unsigned long)sq);
|
|
|
}
|
|
|
|
|
|
-static void throtl_service_queue_exit(struct throtl_service_queue *sq)
|
|
|
-{
|
|
|
- del_timer_sync(&sq->pending_timer);
|
|
|
-}
|
|
|
-
|
|
|
static struct blkg_policy_data *throtl_pd_alloc(gfp_t gfp, int node)
|
|
|
{
|
|
|
struct throtl_grp *tg;
|
|
|
- int cpu;
|
|
|
+ int rw, cpu;
|
|
|
|
|
|
tg = kzalloc_node(sizeof(*tg), gfp, node);
|
|
|
if (!tg)
|
|
@@ -361,6 +354,19 @@ static struct blkg_policy_data *throtl_pd_alloc(gfp_t gfp, int node)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+ throtl_service_queue_init(&tg->service_queue);
|
|
|
+
|
|
|
+ for (rw = READ; rw <= WRITE; rw++) {
|
|
|
+ throtl_qnode_init(&tg->qnode_on_self[rw], tg);
|
|
|
+ throtl_qnode_init(&tg->qnode_on_parent[rw], tg);
|
|
|
+ }
|
|
|
+
|
|
|
+ RB_CLEAR_NODE(&tg->rb_node);
|
|
|
+ tg->bps[READ] = -1;
|
|
|
+ tg->bps[WRITE] = -1;
|
|
|
+ tg->iops[READ] = -1;
|
|
|
+ tg->iops[WRITE] = -1;
|
|
|
+
|
|
|
for_each_possible_cpu(cpu) {
|
|
|
struct tg_stats_cpu *stats_cpu = per_cpu_ptr(tg->stats_cpu, cpu);
|
|
|
|
|
@@ -375,8 +381,7 @@ static void throtl_pd_init(struct blkcg_gq *blkg)
|
|
|
{
|
|
|
struct throtl_grp *tg = blkg_to_tg(blkg);
|
|
|
struct throtl_data *td = blkg->q->td;
|
|
|
- struct throtl_service_queue *parent_sq;
|
|
|
- int rw;
|
|
|
+ struct throtl_service_queue *sq = &tg->service_queue;
|
|
|
|
|
|
/*
|
|
|
* If on the default hierarchy, we switch to properly hierarchical
|
|
@@ -391,25 +396,10 @@ static void throtl_pd_init(struct blkcg_gq *blkg)
|
|
|
* Limits of a group don't interact with limits of other groups
|
|
|
* regardless of the position of the group in the hierarchy.
|
|
|
*/
|
|
|
- parent_sq = &td->service_queue;
|
|
|
-
|
|
|
+ sq->parent_sq = &td->service_queue;
|
|
|
if (cgroup_on_dfl(blkg->blkcg->css.cgroup) && blkg->parent)
|
|
|
- parent_sq = &blkg_to_tg(blkg->parent)->service_queue;
|
|
|
-
|
|
|
- throtl_service_queue_init(&tg->service_queue, parent_sq);
|
|
|
-
|
|
|
- for (rw = READ; rw <= WRITE; rw++) {
|
|
|
- throtl_qnode_init(&tg->qnode_on_self[rw], tg);
|
|
|
- throtl_qnode_init(&tg->qnode_on_parent[rw], tg);
|
|
|
- }
|
|
|
-
|
|
|
- RB_CLEAR_NODE(&tg->rb_node);
|
|
|
+ sq->parent_sq = &blkg_to_tg(blkg->parent)->service_queue;
|
|
|
tg->td = td;
|
|
|
-
|
|
|
- tg->bps[READ] = -1;
|
|
|
- tg->bps[WRITE] = -1;
|
|
|
- tg->iops[READ] = -1;
|
|
|
- tg->iops[WRITE] = -1;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -436,17 +426,11 @@ static void throtl_pd_online(struct blkcg_gq *blkg)
|
|
|
tg_update_has_rules(blkg_to_tg(blkg));
|
|
|
}
|
|
|
|
|
|
-static void throtl_pd_exit(struct blkcg_gq *blkg)
|
|
|
-{
|
|
|
- struct throtl_grp *tg = blkg_to_tg(blkg);
|
|
|
-
|
|
|
- throtl_service_queue_exit(&tg->service_queue);
|
|
|
-}
|
|
|
-
|
|
|
static void throtl_pd_free(struct blkg_policy_data *pd)
|
|
|
{
|
|
|
struct throtl_grp *tg = pd_to_tg(pd);
|
|
|
|
|
|
+ del_timer_sync(&tg->service_queue.pending_timer);
|
|
|
free_percpu(tg->stats_cpu);
|
|
|
kfree(tg);
|
|
|
}
|
|
@@ -1421,7 +1405,6 @@ static struct blkcg_policy blkcg_policy_throtl = {
|
|
|
.pd_alloc_fn = throtl_pd_alloc,
|
|
|
.pd_init_fn = throtl_pd_init,
|
|
|
.pd_online_fn = throtl_pd_online,
|
|
|
- .pd_exit_fn = throtl_pd_exit,
|
|
|
.pd_free_fn = throtl_pd_free,
|
|
|
.pd_reset_stats_fn = throtl_pd_reset_stats,
|
|
|
};
|
|
@@ -1616,7 +1599,7 @@ int blk_throtl_init(struct request_queue *q)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
INIT_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn);
|
|
|
- throtl_service_queue_init(&td->service_queue, NULL);
|
|
|
+ throtl_service_queue_init(&td->service_queue);
|
|
|
|
|
|
q->td = td;
|
|
|
td->queue = q;
|