extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
 extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int dl_bw_alloc(int cpu, u64 dl_bw);
+extern void dl_bw_free(int cpu, u64 dl_bw);
 #ifdef CONFIG_SMP
 extern void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask);
 extern int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask);
 
 
                if (unlikely(cpu >= nr_cpu_ids))
                        return -EINVAL;
-               ret = dl_cpu_busy(cpu, p);
+               ret = dl_bw_alloc(cpu, p->dl.dl_bw);
        }
 
 out:
 static int cpuset_cpu_inactive(unsigned int cpu)
 {
        if (!cpuhp_tasks_frozen) {
-               int ret = dl_cpu_busy(cpu, NULL);
+               int ret = dl_bw_check_overflow(cpu);
 
                if (ret)
                        return ret;
 
        return ret;
 }
 
-int dl_cpu_busy(int cpu, struct task_struct *p)
+enum dl_bw_request {
+       dl_bw_req_check_overflow = 0,
+       dl_bw_req_alloc,
+       dl_bw_req_free
+};
+
+static int dl_bw_manage(enum dl_bw_request req, int cpu, u64 dl_bw)
 {
-       unsigned long flags, cap;
+       unsigned long flags;
        struct dl_bw *dl_b;
-       bool overflow;
+       bool overflow = 0;
 
        rcu_read_lock_sched();
        dl_b = dl_bw_of(cpu);
        raw_spin_lock_irqsave(&dl_b->lock, flags);
-       cap = dl_bw_capacity(cpu);
-       overflow = __dl_overflow(dl_b, cap, 0, p ? p->dl.dl_bw : 0);
 
-       if (!overflow && p) {
-               /*
-                * We reserve space for this task in the destination
-                * root_domain, as we can't fail after this point.
-                * We will free resources in the source root_domain
-                * later on (see set_cpus_allowed_dl()).
-                */
-               __dl_add(dl_b, p->dl.dl_bw, dl_bw_cpus(cpu));
+       if (req == dl_bw_req_free) {
+               __dl_sub(dl_b, dl_bw, dl_bw_cpus(cpu));
+       } else {
+               unsigned long cap = dl_bw_capacity(cpu);
+
+               overflow = __dl_overflow(dl_b, cap, 0, dl_bw);
+
+               if (req == dl_bw_req_alloc && !overflow) {
+                       /*
+                        * We reserve space in the destination
+                        * root_domain, as we can't fail after this point.
+                        * We will free resources in the source root_domain
+                        * later on (see set_cpus_allowed_dl()).
+                        */
+                       __dl_add(dl_b, dl_bw, dl_bw_cpus(cpu));
+               }
        }
 
        raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
        return overflow ? -EBUSY : 0;
 }
+
+int dl_bw_check_overflow(int cpu)
+{
+       return dl_bw_manage(dl_bw_req_check_overflow, cpu, 0);
+}
+
+int dl_bw_alloc(int cpu, u64 dl_bw)
+{
+       return dl_bw_manage(dl_bw_req_alloc, cpu, dl_bw);
+}
+
+void dl_bw_free(int cpu, u64 dl_bw)
+{
+       dl_bw_manage(dl_bw_req_free, cpu, dl_bw);
+}
 #endif
 
 #ifdef CONFIG_SCHED_DEBUG
 
 extern bool __checkparam_dl(const struct sched_attr *attr);
 extern bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr);
 extern int  dl_cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int  dl_cpu_busy(int cpu, struct task_struct *p);
+extern int  dl_bw_check_overflow(int cpu);
 
 #ifdef CONFIG_CGROUP_SCHED