[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