--- y/block/blk-throttle.h +++ b/block/blk-throttle.h @@ -141,6 +141,8 @@ struct throtl_grp { struct blkg_rwstat stat_bytes; struct blkg_rwstat stat_ios; + + struct work_struct free_work; }; extern struct blkcg_policy blkcg_policy_throtl; --- y/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -493,9 +493,9 @@ static void throtl_pd_offline(struct blk throtl_upgrade_state(tg->td); } -static void throtl_pd_free(struct blkg_policy_data *pd) +static void tg_free_workfn(struct work_struct *w) { - struct throtl_grp *tg = pd_to_tg(pd); + struct throtl_grp *tg = container_of(w, struct throtl_grp, free_work); del_timer_sync(&tg->service_queue.pending_timer); blkg_rwstat_exit(&tg->stat_bytes); @@ -503,6 +503,14 @@ static void throtl_pd_free(struct blkg_p kfree(tg); } +static void throtl_pd_free(struct blkg_policy_data *pd) +{ + struct throtl_grp *tg = pd_to_tg(pd); + + INIT_WORK(&tg->free_work, tg_free_workfn); + queue_work(system_unbound_wq, &tg->free_work); +} + static struct throtl_grp * throtl_rb_first(struct throtl_service_queue *parent_sq) {