[Devel] [PATCH vz10] cgroup-v2: Fix error handling in cgroup_controllers_hidden_write
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Dec 12 16:29:26 MSK 2025
Add proper rollback mechanism for hidden_ss_mask when cgroup_apply_hidden()
fails. Track successfully applied controllers and restore mask only for
failed ones. This prevents inconsistent state when partial failures occur.
https://virtuozzo.atlassian.net/browse/VSTOR-119803
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
kernel/cgroup/cgroup.c | 57 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 51 insertions(+), 6 deletions(-)
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 753721edb642a..f99f1672bde8c 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -3896,10 +3896,28 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
return ret ?: nbytes;
}
-static int cgroup_apply_hidden(struct cgroup *cgrp)
+/**
+ * cgroup_apply_hidden - apply hidden mask changes to cgroup filesystem
+ * @cgrp: target cgroup
+ * @track_mask: mask of controllers to track (0 to track all)
+ * @applied_mask: output parameter for mask of successfully applied controllers
+ *
+ * Applies the hidden_ss_mask to the cgroup filesystem. On partial failure,
+ * @applied_mask contains the mask of controllers from @track_mask that were
+ * successfully processed before the error occurred. If @track_mask is 0,
+ * all controllers are tracked.
+ *
+ * Returns 0 on success, -errno on failure.
+ */
+static int cgroup_apply_hidden(struct cgroup *cgrp, u16 track_mask,
+ u16 *applied_mask)
{
struct cgroup_subsys *ss;
int ssid;
+ int ret = 0;
+
+ if (applied_mask)
+ *applied_mask = 0;
for_each_subsys(ss, ssid) {
struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
@@ -3910,17 +3928,24 @@ static int cgroup_apply_hidden(struct cgroup *cgrp)
if (!css)
continue;
- if (css_visible(css)) {
- int ret;
+ /* Check if we should track this controller */
+ bool should_track = !track_mask || (track_mask & (1 << ss->id));
+ if (css_visible(css)) {
ret = css_populate_dir(css);
- if (ret)
+ if (ret) {
+ /* Error occurred on this controller - don't mark as applied */
return ret;
+ }
} else {
css_clear_dir(css);
if (ss->css_reset)
ss->css_reset(css);
}
+
+ /* Mark this controller as successfully applied if tracking */
+ if (applied_mask && should_track)
+ *applied_mask |= 1 << ss->id;
}
return 0;
@@ -3934,6 +3959,9 @@ static ssize_t cgroup_controllers_hidden_write(struct kernfs_open_file *of,
struct cgroup_subsys *ss;
u16 hide = 0, show = 0;
struct cgroup *cgrp;
+ u16 old_hidden_ss_mask;
+ u16 change_mask = 0;
+ u16 applied_mask = 0;
int ssid, ret;
char *tok;
@@ -3988,12 +4016,29 @@ static ssize_t cgroup_controllers_hidden_write(struct kernfs_open_file *of,
goto out_unlock;
}
+ old_hidden_ss_mask = cgrp->hidden_ss_mask;
+ change_mask = hide | show;
cgrp->hidden_ss_mask |= hide;
cgrp->hidden_ss_mask &= ~show;
- ret = cgroup_apply_hidden(cgrp);
- if (ret)
+ ret = cgroup_apply_hidden(cgrp, change_mask, &applied_mask);
+ if (ret) {
+ /* Calculate which controllers from change_mask were successfully applied */
+ u16 successfully_applied = applied_mask & change_mask;
+ u16 failed_mask = change_mask & ~successfully_applied;
+
+ /* Restore mask for failed controllers */
+ if (failed_mask & hide) {
+ /* Failed to hide - restore to shown state */
+ cgrp->hidden_ss_mask &= ~(failed_mask & hide);
+ }
+ if (failed_mask & show) {
+ /* Failed to show - restore to hidden state */
+ cgrp->hidden_ss_mask |= (failed_mask & show);
+ }
+
goto out_unlock;
+ }
kernfs_activate(cgrp->kn);
out_unlock:
--
2.43.0
More information about the Devel
mailing list