--- /dev/null
+From 4d38a87fbb77fb9ff2ff4e914162a8ae6453eff5 Mon Sep 17 00:00:00 2001
+From: Paolo Valente <paolo.valente@linaro.org>
+Date: Sat, 21 Mar 2020 10:45:21 +0100
+Subject: block, bfq: invoke flush_idle_tree after reparent_active_queues in pd_offline
+
+From: Paolo Valente <paolo.valente@linaro.org>
+
+commit 4d38a87fbb77fb9ff2ff4e914162a8ae6453eff5 upstream.
+
+In bfq_pd_offline(), the function bfq_flush_idle_tree() is invoked to
+flush the rb tree that contains all idle entities belonging to the pd
+(cgroup) being destroyed. In particular, bfq_flush_idle_tree() is
+invoked before bfq_reparent_active_queues(). Yet the latter may happen
+to add some entities to the idle tree. It happens if, in some of the
+calls to bfq_bfqq_move() performed by bfq_reparent_active_queues(),
+the queue to move is empty and gets expired.
+
+This commit simply reverses the invocation order between
+bfq_flush_idle_tree() and bfq_reparent_active_queues().
+
+Tested-by: cki-project@redhat.com
+Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/bfq-cgroup.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+--- a/block/bfq-cgroup.c
++++ b/block/bfq-cgroup.c
+@@ -894,13 +894,6 @@ static void bfq_pd_offline(struct blkg_p
+ 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
+- * cgroup from the one being destroyed now.
+- */
+- bfq_flush_idle_tree(st);
+-
+- /*
+ * It may happen that some queues are still active
+ * (busy) upon group destruction (if the corresponding
+ * processes have been forced to terminate). We move
+@@ -913,6 +906,19 @@ static void bfq_pd_offline(struct blkg_p
+ * scheduler has taken no reference.
+ */
+ bfq_reparent_active_queues(bfqd, bfqg, st, i);
++
++ /*
++ * The idle tree may still contain bfq_queues
++ * belonging to exited task because they never
++ * migrated to a different cgroup from the one being
++ * destroyed now. In addition, even
++ * bfq_reparent_active_queues() may happen to add some
++ * entities to the idle tree. It happens if, in some
++ * of the calls to bfq_bfqq_move() performed by
++ * bfq_reparent_active_queues(), the queue to move is
++ * empty and gets expired.
++ */
++ bfq_flush_idle_tree(st);
+ }
+
+ __bfq_deactivate_entity(entity, false);
--- /dev/null
+From 576682fa52cbd95deb3773449566274f206acc58 Mon Sep 17 00:00:00 2001
+From: Paolo Valente <paolo.valente@linaro.org>
+Date: Sat, 21 Mar 2020 10:45:20 +0100
+Subject: block, bfq: make reparent_leaf_entity actually work only on leaf entities
+
+From: Paolo Valente <paolo.valente@linaro.org>
+
+commit 576682fa52cbd95deb3773449566274f206acc58 upstream.
+
+bfq_reparent_leaf_entity() reparents the input leaf entity (a leaf
+entity represents just a bfq_queue in an entity tree). Yet, the input
+entity is guaranteed to always be a leaf entity only in two-level
+entity trees. In this respect, because of the error fixed by
+commit 14afc5936197 ("block, bfq: fix overwrite of bfq_group pointer
+in bfq_find_set_group()"), all (wrongly collapsed) entity trees happened
+to actually have only two levels. After the latter commit, this does not
+hold any longer.
+
+This commit fixes this problem by modifying
+bfq_reparent_leaf_entity(), so that it searches an active leaf entity
+down the path that stems from the input entity. Such a leaf entity is
+guaranteed to exist when bfq_reparent_leaf_entity() is invoked.
+
+Tested-by: cki-project@redhat.com
+Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/bfq-cgroup.c | 48 +++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 31 insertions(+), 17 deletions(-)
+
+--- a/block/bfq-cgroup.c
++++ b/block/bfq-cgroup.c
+@@ -815,39 +815,53 @@ static void bfq_flush_idle_tree(struct b
+ /**
+ * bfq_reparent_leaf_entity - move leaf entity to the root_group.
+ * @bfqd: the device data structure with the root group.
+- * @entity: the entity to move.
++ * @entity: the entity to move, if entity is a leaf; or the parent entity
++ * of an active leaf entity to move, if entity is not a leaf.
+ */
+ static void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
+- struct bfq_entity *entity)
++ struct bfq_entity *entity,
++ int ioprio_class)
+ {
+- struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
++ struct bfq_queue *bfqq;
++ struct bfq_entity *child_entity = entity;
+
++ while (child_entity->my_sched_data) { /* leaf not reached yet */
++ struct bfq_sched_data *child_sd = child_entity->my_sched_data;
++ struct bfq_service_tree *child_st = child_sd->service_tree +
++ ioprio_class;
++ struct rb_root *child_active = &child_st->active;
++
++ child_entity = bfq_entity_of(rb_first(child_active));
++
++ if (!child_entity)
++ child_entity = child_sd->in_service_entity;
++ }
++
++ bfqq = bfq_entity_to_bfqq(child_entity);
+ bfq_bfqq_move(bfqd, bfqq, bfqd->root_group);
+ }
+
+ /**
+- * bfq_reparent_active_entities - move to the root group all active
+- * entities.
++ * bfq_reparent_active_queues - move to the root group all active queues.
+ * @bfqd: the device data structure with the root group.
+ * @bfqg: the group to move from.
+- * @st: the service tree with the entities.
++ * @st: the service tree to start the search from.
+ */
+-static void bfq_reparent_active_entities(struct bfq_data *bfqd,
+- struct bfq_group *bfqg,
+- struct bfq_service_tree *st)
++static void bfq_reparent_active_queues(struct bfq_data *bfqd,
++ struct bfq_group *bfqg,
++ struct bfq_service_tree *st,
++ int ioprio_class)
+ {
+ struct rb_root *active = &st->active;
+- struct bfq_entity *entity = NULL;
+-
+- if (!RB_EMPTY_ROOT(&st->active))
+- entity = bfq_entity_of(rb_first(active));
++ struct bfq_entity *entity;
+
+- for (; entity ; entity = bfq_entity_of(rb_first(active)))
+- bfq_reparent_leaf_entity(bfqd, entity);
++ while ((entity = bfq_entity_of(rb_first(active))))
++ bfq_reparent_leaf_entity(bfqd, entity, ioprio_class);
+
+ if (bfqg->sched_data.in_service_entity)
+ bfq_reparent_leaf_entity(bfqd,
+- bfqg->sched_data.in_service_entity);
++ bfqg->sched_data.in_service_entity,
++ ioprio_class);
+ }
+
+ /**
+@@ -898,7 +912,7 @@ static void bfq_pd_offline(struct blkg_p
+ * There is no need to put the sync queues, as the
+ * scheduler has taken no reference.
+ */
+- bfq_reparent_active_entities(bfqd, bfqg, st);
++ bfq_reparent_active_queues(bfqd, bfqg, st, i);
+ }
+
+ __bfq_deactivate_entity(entity, false);
--- /dev/null
+From c8997736650060594845e42c5d01d3118aec8d25 Mon Sep 17 00:00:00 2001
+From: Paolo Valente <paolo.valente@linaro.org>
+Date: Sat, 21 Mar 2020 10:45:19 +0100
+Subject: block, bfq: turn put_queue into release_process_ref in __bfq_bic_change_cgroup
+
+From: Paolo Valente <paolo.valente@linaro.org>
+
+commit c8997736650060594845e42c5d01d3118aec8d25 upstream.
+
+A bfq_put_queue() may be invoked in __bfq_bic_change_cgroup(). The
+goal of this put is to release a process reference to a bfq_queue. But
+process-reference releases may trigger also some extra operation, and,
+to this goal, are handled through bfq_release_process_ref(). So, turn
+the invocation of bfq_put_queue() into an invocation of
+bfq_release_process_ref().
+
+Tested-by: cki-project@redhat.com
+Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/bfq-cgroup.c | 5 +----
+ block/bfq-iosched.c | 2 --
+ block/bfq-iosched.h | 1 +
+ 3 files changed, 2 insertions(+), 6 deletions(-)
+
+--- a/block/bfq-cgroup.c
++++ b/block/bfq-cgroup.c
+@@ -714,10 +714,7 @@ static struct bfq_group *__bfq_bic_chang
+
+ if (entity->sched_data != &bfqg->sched_data) {
+ bic_set_bfqq(bic, NULL, 0);
+- bfq_log_bfqq(bfqd, async_bfqq,
+- "bic_change_group: %p %d",
+- async_bfqq, async_bfqq->ref);
+- bfq_put_queue(async_bfqq);
++ bfq_release_process_ref(bfqd, async_bfqq);
+ }
+ }
+
+--- a/block/bfq-iosched.c
++++ b/block/bfq-iosched.c
+@@ -2716,8 +2716,6 @@ static void bfq_bfqq_save_state(struct b
+ }
+ }
+
+-
+-static
+ void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+ {
+ /*
+--- a/block/bfq-iosched.h
++++ b/block/bfq-iosched.h
+@@ -955,6 +955,7 @@ void bfq_bfqq_expire(struct bfq_data *bf
+ bool compensate, enum bfqq_expiration reason);
+ void bfq_put_queue(struct bfq_queue *bfqq);
+ void bfq_end_wr_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
++void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq);
+ void bfq_schedule_dispatch(struct bfq_data *bfqd);
+ void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
+
afs-fix-rename-operation-status-delivery.patch
afs-fix-afs_d_validate-to-set-the-right-directory-version.patch
afs-fix-race-between-post-modification-dir-edit-and-readdir-d_revalidate.patch
+block-bfq-turn-put_queue-into-release_process_ref-in-__bfq_bic_change_cgroup.patch
+block-bfq-make-reparent_leaf_entity-actually-work-only-on-leaf-entities.patch
+block-bfq-invoke-flush_idle_tree-after-reparent_active_queues-in-pd_offline.patch