[PATCH RFC v3 18/90] cgroup: give the budget of a cell back
From: Josef Bacik
Date: Thu Nov 05 2026 - 10:01:37 EST
The ids of a cell are only lent to it. The cgroups that the cell created
below its budget are owned by those ids. So is the budget itself, once it
has been handed to the root user of the cell.
Add cgroup_cell_budget_put(). It removes everything below the budget,
returns the budget to its previous owner and clears CGRP_CELL_BUDGET. It
reports whether all of that worked, because the ids must not be lent to
another cell if it did not.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
include/linux/cgroup.h | 1 +
kernel/cgroup/cgroup.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 0e45a5a1afea..4d9baf195f1e 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -155,6 +155,7 @@ struct cgroup *cgroup_get_from_fd(int fd);
struct cgroup *cgroup_cell_budget_get(struct file *file, kuid_t *uid, kgid_t *gid);
int cgroup_cell_chown(struct cgroup *cgrp, kuid_t uid, kgid_t gid);
+int cgroup_cell_budget_put(struct cgroup *cgrp, bool handed, kuid_t uid, kgid_t gid);
struct cgroup *cgroup_v1v2_get_from_fd(int fd);
/* Was this controller blocked from v1 hierarchies by cgroup_no_v1= ? */
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index fb2775006087..e5e6761522eb 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -7125,6 +7125,44 @@ struct cgroup *cgroup_cell_budget_get(struct file *file, kuid_t *uid, kgid_t *gi
return cgrp;
}
+/**
+ * cgroup_cell_budget_put - the cell is gone, give its budget back
+ * @cgrp: the budget. The reference is consumed
+ * @handed: the cgroup had been handed to the cell's root
+ * @uid: who owned it before
+ * @gid: likewise
+ *
+ * The cgroup is empty. Whatever the cell made below it is owned by ids that
+ * were only lent to the cell, so it goes, and the cgroup itself returns to its
+ * owner.
+ *
+ * Return: 0, or an error if something is left that is owned by the cell's ids.
+ */
+int cgroup_cell_budget_put(struct cgroup *cgrp, bool handed, kuid_t uid, kgid_t gid)
+{
+ struct cgroup_subsys_state *css;
+ struct cgroup *dsct;
+ int ret = 0;
+
+ cgroup_lock();
+ clear_bit(CGRP_CELL_BUDGET, &cgrp->flags);
+ if (handed && !cgroup_is_dead(cgrp)) {
+ cgroup_for_each_live_descendant_post(dsct, css, cgrp) {
+ if (dsct == cgrp)
+ continue;
+ ret = cgroup_destroy_locked(dsct);
+ if (ret)
+ break;
+ }
+ }
+ cgroup_unlock();
+
+ if (handed && !ret)
+ ret = cgroup_cell_chown(cgrp, uid, gid);
+ cgroup_put(cgrp);
+ return ret;
+}
+
/**
* cgroup_cell_chown - hand a cgroup to somebody
* @cgrp: the cgroup
--
2.55.0