Skip to content

Commit 0af3fed

Browse files
Yu Kuaiaxboe
authored andcommitted
blk-cgroup: delay freeing policy data after rcu grace period
Currently blkcg_print_blkgs() must hold RCU to iterate blkgs from a blkcg, and prfill() must hold queue_lock to prevent policy data from being freed by policy deactivation. As a consequence, queue_lock has to be nested under RCU from blkcg_print_blkgs(). Delay freeing policy data until after an RCU grace period so prfill() can be protected by RCU alone. Signed-off-by: Yu Kuai <yukuai@fygo.io> Link: https://patch.msgid.link/e20e5d984b41a026d61851966bed35eb094c4bff.1780621988.git.yukuai@fygo.io Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 2565630 commit 0af3fed

5 files changed

Lines changed: 42 additions & 6 deletions

File tree

block/bfq-cgroup.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,13 +550,20 @@ static void bfq_pd_init(struct blkg_policy_data *pd)
550550
bfqg->rq_pos_tree = RB_ROOT;
551551
}
552552

553-
static void bfq_pd_free(struct blkg_policy_data *pd)
553+
static void bfqg_release(struct rcu_head *rcu)
554554
{
555+
struct blkg_policy_data *pd =
556+
container_of(rcu, struct blkg_policy_data, rcu_head);
555557
struct bfq_group *bfqg = pd_to_bfqg(pd);
556558

557559
bfqg_put(bfqg);
558560
}
559561

562+
static void bfq_pd_free(struct blkg_policy_data *pd)
563+
{
564+
call_rcu(&pd->rcu_head, bfqg_release);
565+
}
566+
560567
static void bfq_pd_reset_stats(struct blkg_policy_data *pd)
561568
{
562569
struct bfq_group *bfqg = pd_to_bfqg(pd);

block/blk-cgroup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ struct blkg_policy_data {
140140
struct blkcg_gq *blkg;
141141
int plid;
142142
bool online;
143+
144+
struct rcu_head rcu_head;
143145
};
144146

145147
/*

block/blk-iocost.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3050,6 +3050,16 @@ static void ioc_pd_init(struct blkg_policy_data *pd)
30503050
spin_unlock_irqrestore(&ioc->lock, flags);
30513051
}
30523052

3053+
static void iocg_release(struct rcu_head *rcu)
3054+
{
3055+
struct blkg_policy_data *pd =
3056+
container_of(rcu, struct blkg_policy_data, rcu_head);
3057+
struct ioc_gq *iocg = pd_to_iocg(pd);
3058+
3059+
free_percpu(iocg->pcpu_stat);
3060+
kfree(iocg);
3061+
}
3062+
30533063
static void ioc_pd_free(struct blkg_policy_data *pd)
30543064
{
30553065
struct ioc_gq *iocg = pd_to_iocg(pd);
@@ -3074,8 +3084,8 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
30743084

30753085
hrtimer_cancel(&iocg->waitq_timer);
30763086
}
3077-
free_percpu(iocg->pcpu_stat);
3078-
kfree(iocg);
3087+
3088+
call_rcu(&pd->rcu_head, iocg_release);
30793089
}
30803090

30813091
static void ioc_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)

block/blk-iolatency.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,13 +1031,21 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd)
10311031
iolatency_clear_scaling(blkg);
10321032
}
10331033

1034-
static void iolatency_pd_free(struct blkg_policy_data *pd)
1034+
static void iolat_release(struct rcu_head *rcu)
10351035
{
1036+
struct blkg_policy_data *pd =
1037+
container_of(rcu, struct blkg_policy_data, rcu_head);
10361038
struct iolatency_grp *iolat = pd_to_lat(pd);
1039+
10371040
free_percpu(iolat->stats);
10381041
kfree(iolat);
10391042
}
10401043

1044+
static void iolatency_pd_free(struct blkg_policy_data *pd)
1045+
{
1046+
call_rcu(&pd->rcu_head, iolat_release);
1047+
}
1048+
10411049
static struct cftype iolatency_files[] = {
10421050
{
10431051
.name = "latency",

block/blk-throttle.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,16 +353,25 @@ static void throtl_pd_online(struct blkg_policy_data *pd)
353353
tg_update_has_rules(tg);
354354
}
355355

356-
static void throtl_pd_free(struct blkg_policy_data *pd)
356+
static void tg_release(struct rcu_head *rcu)
357357
{
358+
struct blkg_policy_data *pd =
359+
container_of(rcu, struct blkg_policy_data, rcu_head);
358360
struct throtl_grp *tg = pd_to_tg(pd);
359361

360-
timer_delete_sync(&tg->service_queue.pending_timer);
361362
blkg_rwstat_exit(&tg->stat_bytes);
362363
blkg_rwstat_exit(&tg->stat_ios);
363364
kfree(tg);
364365
}
365366

367+
static void throtl_pd_free(struct blkg_policy_data *pd)
368+
{
369+
struct throtl_grp *tg = pd_to_tg(pd);
370+
371+
timer_delete_sync(&tg->service_queue.pending_timer);
372+
call_rcu(&pd->rcu_head, tg_release);
373+
}
374+
366375
static struct throtl_grp *
367376
throtl_rb_first(struct throtl_service_queue *parent_sq)
368377
{

0 commit comments

Comments
 (0)