summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/bfq-cgroup.c105
-rw-r--r--block/bfq-iosched.c7
-rw-r--r--block/bfq-sched.c9
-rw-r--r--block/bfq.h8
4 files changed, 53 insertions, 76 deletions
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index 7a6192007..5ee99ecbd 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -161,7 +161,9 @@ static struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg)
static struct bfq_group *blkg_to_bfqg(struct blkcg_gq *blkg)
{
- return pd_to_bfqg(blkg_to_pd(blkg, &blkcg_policy_bfq));
+ struct blkg_policy_data *pd = blkg_to_pd(blkg, &blkcg_policy_bfq);
+ BUG_ON(!pd);
+ return pd_to_bfqg(pd);
}
/*
@@ -396,7 +398,8 @@ static struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, int node)
if (!bfqg)
return NULL;
- if (bfqg_stats_init(&bfqg->stats, gfp)) {
+ if (bfqg_stats_init(&bfqg->stats, gfp) ||
+ bfqg_stats_init(&bfqg->dead_stats, gfp)) {
kfree(bfqg);
return NULL;
}
@@ -404,6 +407,20 @@ static struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, int node)
return &bfqg->pd;
}
+static void bfq_group_set_parent(struct bfq_group *bfqg,
+ struct bfq_group *parent)
+{
+ struct bfq_entity *entity;
+
+ BUG_ON(!parent);
+ BUG_ON(!bfqg);
+ BUG_ON(bfqg == parent);
+
+ entity = &bfqg->entity;
+ entity->parent = parent->my_entity;
+ entity->sched_data = &parent->sched_data;
+}
+
static void bfq_pd_init(struct blkg_policy_data *pd)
{
struct blkcg_gq *blkg = pd_to_blkg(pd);
@@ -421,15 +438,16 @@ static void bfq_pd_init(struct blkg_policy_data *pd)
bfqg->bfqd = bfqd;
bfqg->active_entities = 0;
bfqg->rq_pos_tree = RB_ROOT;
-
- /* if the root_group does not exist, we are handling it right now */
- if (bfqd->root_group && bfqg != bfqd->root_group)
- hlist_add_head(&bfqg->bfqd_node, &bfqd->group_list);
}
static void bfq_pd_free(struct blkg_policy_data *pd)
{
- return kfree(pd_to_bfqg(pd));
+ struct bfq_group *bfqg = pd_to_bfqg(pd);
+
+ bfqg_stats_exit(&bfqg->stats);
+ bfqg_stats_exit(&bfqg->dead_stats);
+
+ return kfree(bfqg);
}
/* offset delta from bfqg->stats to bfqg->dead_stats */
@@ -468,20 +486,6 @@ static void bfq_pd_reset_stats(struct blkg_policy_data *pd)
bfqg_stats_reset(&bfqg->dead_stats);
}
-static void bfq_group_set_parent(struct bfq_group *bfqg,
- struct bfq_group *parent)
-{
- struct bfq_entity *entity;
-
- BUG_ON(!parent);
- BUG_ON(!bfqg);
- BUG_ON(bfqg == parent);
-
- entity = &bfqg->entity;
- entity->parent = parent->my_entity;
- entity->sched_data = &parent->sched_data;
-}
-
static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd,
struct blkcg *blkcg)
{
@@ -721,11 +725,19 @@ static void bfq_reparent_active_entities(struct bfq_data *bfqd,
static void bfq_pd_offline(struct blkg_policy_data *pd)
{
struct bfq_service_tree *st;
- struct bfq_group *bfqg = pd_to_bfqg(pd);
- struct bfq_data *bfqd = bfqg->bfqd;
- struct bfq_entity *entity = bfqg->my_entity;
+ struct bfq_group *bfqg;
+ struct bfq_data *bfqd;
+ struct bfq_entity *entity;
int i;
+ BUG_ON(!pd);
+ bfqg = pd_to_bfqg(pd);
+ BUG_ON(!bfqg);
+ bfqd = bfqg->bfqd;
+ BUG_ON(bfqd && !bfqd->root_group);
+
+ entity = bfqg->my_entity;
+
if (!entity) /* root group */
return;
@@ -734,8 +746,8 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
* deactivating the group itself.
*/
for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) {
+ BUG_ON(!bfqg->sched_data.service_tree);
st = bfqg->sched_data.service_tree + i;
-
/*
* The idle tree may still contain bfq_queues belonging
* to exited task because they never migrated to a different
@@ -763,7 +775,6 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
BUG_ON(bfqg->sched_data.next_in_service);
BUG_ON(bfqg->sched_data.in_service_entity);
- hlist_del(&bfqg->bfqd_node);
__bfq_deactivate_entity(entity, 0);
bfq_put_async_queues(bfqd, bfqg);
BUG_ON(entity->tree);
@@ -773,46 +784,14 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
static void bfq_end_wr_async(struct bfq_data *bfqd)
{
- struct hlist_node *tmp;
- struct bfq_group *bfqg;
-
- hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node)
- bfq_end_wr_async_queues(bfqd, bfqg);
- bfq_end_wr_async_queues(bfqd, bfqd->root_group);
-}
-
-/**
- * bfq_disconnect_groups - disconnect @bfqd from all its groups.
- * @bfqd: the device descriptor being exited.
- *
- * When the device exits we just make sure that no lookup can return
- * the now unused group structures. They will be deallocated on cgroup
- * destruction.
- */
-static void bfq_disconnect_groups(struct bfq_data *bfqd)
-{
- struct hlist_node *tmp;
- struct bfq_group *bfqg;
-
- bfq_log(bfqd, "disconnect_groups beginning");
- hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) {
- hlist_del(&bfqg->bfqd_node);
-
- __bfq_deactivate_entity(bfqg->my_entity, 0);
+ struct blkcg_gq *blkg;
- /*
- * Don't remove from the group hash, just set an
- * invalid key. No lookups can race with the
- * assignment as bfqd is being destroyed; this
- * implies also that new elements cannot be added
- * to the list.
- */
- rcu_assign_pointer(bfqg->bfqd, NULL);
+ list_for_each_entry(blkg, &bfqd->queue->blkg_list, q_node) {
+ struct bfq_group *bfqg = blkg_to_bfqg(blkg);
- bfq_log(bfqd, "disconnect_groups: put async for group %p",
- bfqg);
- bfq_put_async_queues(bfqd, bfqg);
+ bfq_end_wr_async_queues(bfqd, bfqg);
}
+ bfq_end_wr_async_queues(bfqd, bfqd->root_group);
}
static u64 bfqio_cgroup_weight_read(struct cgroup_subsys_state *css,
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index dbce1f83f..d1f648d05 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -3919,7 +3919,6 @@ static void bfq_exit_queue(struct elevator_queue *e)
list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list)
bfq_deactivate_bfqq(bfqd, bfqq, 0);
- bfq_disconnect_groups(bfqd);
spin_unlock_irq(q->queue_lock);
bfq_shutdown_timer_wq(bfqd);
@@ -3930,6 +3929,8 @@ static void bfq_exit_queue(struct elevator_queue *e)
#ifdef CONFIG_BFQ_GROUP_IOSCHED
blkcg_deactivate_policy(q, &blkcg_policy_bfq);
+#else
+ kfree(bfqd->root_group);
#endif
kfree(bfqd);
@@ -4385,7 +4386,7 @@ static int __init bfq_init(void)
if (ret)
goto err_pol_unreg;
- pr_info("BFQ I/O-scheduler: v7r10");
+ pr_info("BFQ I/O-scheduler: v7r11");
return 0;
@@ -4408,5 +4409,5 @@ static void __exit bfq_exit(void)
module_init(bfq_init);
module_exit(bfq_exit);
-MODULE_AUTHOR("Fabio Checconi, Paolo Valente");
+MODULE_AUTHOR("Arianna Avanzini, Fabio Checconi, Paolo Valente");
MODULE_LICENSE("GPL");
diff --git a/block/bfq-sched.c b/block/bfq-sched.c
index 9328a1f09..a64fec119 100644
--- a/block/bfq-sched.c
+++ b/block/bfq-sched.c
@@ -839,13 +839,16 @@ static void bfq_activate_entity(struct bfq_entity *entity)
static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
{
struct bfq_sched_data *sd = entity->sched_data;
- struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- int was_in_service = entity == sd->in_service_entity;
+ struct bfq_service_tree *st;
+ int was_in_service;
int ret = 0;
- if (!entity->on_st)
+ if (sd == NULL || !entity->on_st) /* never activated, or inactive */
return 0;
+ st = bfq_entity_service_tree(entity);
+ was_in_service = entity == sd->in_service_entity;
+
BUG_ON(was_in_service && entity->tree);
if (was_in_service) {
diff --git a/block/bfq.h b/block/bfq.h
index 97a677f8c..32dfceead 100644
--- a/block/bfq.h
+++ b/block/bfq.h
@@ -1,5 +1,5 @@
/*
- * BFQ-v7r10 for 4.4.0: data structures and common functions prototypes.
+ * BFQ-v7r11 for 4.4.0: data structures and common functions prototypes.
*
* Based on ideas and code from CFQ:
* Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
@@ -421,7 +421,6 @@ enum bfq_device_speed {
* @peak_rate_samples: number of samples used to calculate @peak_rate.
* @bfq_max_budget: maximum budget allotted to a bfq_queue before
* rescheduling.
- * @group_list: list of all the bfq_groups active on the device.
* @active_list: list of all the bfq_queues active on the device.
* @idle_list: list of all the bfq_queues idle on the device.
* @bfq_fifo_expire: timeout for async/sync requests; when it expires
@@ -526,7 +525,6 @@ struct bfq_data {
u64 peak_rate;
int bfq_max_budget;
- struct hlist_head group_list;
struct list_head active_list;
struct list_head idle_list;
@@ -702,8 +700,6 @@ struct bfq_group_data {
* @entity: schedulable entity to insert into the parent group sched_data.
* @sched_data: own sched_data, to contain child entities (they may be
* both bfq_queues and bfq_groups).
- * @bfqd_node: node to be inserted into the @bfqd->group_list list
- * of the groups active on the same device; used for cleanup.
* @bfqd: the bfq_data for the device this group acts upon.
* @async_bfqq: array of async queues for all the tasks belonging to
* the group, one queue per ioprio value per ioprio_class,
@@ -737,8 +733,6 @@ struct bfq_group {
struct bfq_entity entity;
struct bfq_sched_data sched_data;
- struct hlist_node bfqd_node;
-
void *bfqd;
struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR];