[Devel] [PATCH RHEL10 COMMIT] cgroup-v2: Fix error handling in cgroup_controllers_hidden_write()

Konstantin Khorenko khorenko at virtuozzo.com
Tue Dec 16 23:56:12 MSK 2025


The commit is pushed to "branch-rh10-6.12.0-55.13.1.3.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-55.13.1.3.25.vz10
------>
commit a05a668cf1c9f8c7bff5e89a4a6bbcd43271593a
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date:   Mon Dec 15 19:21:56 2025 +0800

    cgroup-v2: Fix error handling in cgroup_controllers_hidden_write()
    
    Currently if there is a population error, we can end up with partially
    applied mask, which is not what we want, let's do a proper cleanup.
    
    Split cgroup_apply_hidden() into two separate helpers for showing and
    hiding: cgroup_unhide() and cgroup_hide(). As cgroup_hide() never fails
    we can easily use it for both hiding on success path and cleanup on
    error path of cgroup_unhide() with restored old mask.
    
    While on it let's add small comments to those helpers.
    
    https://virtuozzo.atlassian.net/browse/VSTOR-119803
    Fixes: fbc4461a215c ("cgroup-v2: Add a new API to hide cgroup files per controller")
    Co-developed-by: Konstantin Khorenko <khorenko at virtuozzo.com>
    Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
    
    Feature: ve: ve generic structures
---
 kernel/cgroup/cgroup.c | 52 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 46 insertions(+), 6 deletions(-)

diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index eb2b64f7da37b..92abecb000b19 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -3896,7 +3896,11 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
 	return ret ?: nbytes;
 }
 
-static int cgroup_apply_hidden(struct cgroup *cgrp)
+/*
+ * cgroup_unhide() - Apply cleared bits in hidden_ss_mask to the cgroup
+ * directory by populating files for visible controllers.
+ */
+static int cgroup_unhide(struct cgroup *cgrp)
 {
 	struct cgroup_subsys *ss;
 	int ssid;
@@ -3916,14 +3920,36 @@ static int cgroup_apply_hidden(struct cgroup *cgrp)
 			ret = css_populate_dir(css);
 			if (ret)
 				return ret;
-		} else {
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * cgroup_hide() - Apply set bits in hidden_ss_mask to the cgroup
+ * directory by clearing files for hidden controllers.
+ */
+static void cgroup_hide(struct cgroup *cgrp)
+{
+	struct cgroup_subsys *ss;
+	int ssid;
+
+	for_each_subsys(ss, ssid) {
+		struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
+
+		if (!(cgroup_ss_mask(cgrp) & (1 << ss->id)))
+			continue;
+
+		if (!css)
+			continue;
+
+		if (!css_visible(css)) {
 			css_clear_dir(css);
 			if (ss->css_reset)
 				ss->css_reset(css);
 		}
 	}
-
-	return 0;
 }
 
 /* change the hidden controllers for a cgroup in the default hierarchy */
@@ -3933,6 +3959,7 @@ static ssize_t cgroup_controllers_hidden_write(struct kernfs_open_file *of,
 {
 	struct cgroup_subsys *ss;
 	u16 hide = 0, show = 0;
+	u16 old_hidden_ss_mask;
 	struct cgroup *cgrp;
 	int ssid, ret;
 	char *tok;
@@ -3988,10 +4015,23 @@ static ssize_t cgroup_controllers_hidden_write(struct kernfs_open_file *of,
 		goto out_unlock;
 	}
 
-	cgrp->hidden_ss_mask |= hide;
+	/*
+	 * This is similar to cgroup_apply_control_enable(). We first try to
+	 * populate dirs for controllers being shown, and on success, hide the
+	 * controllers being hidden. On error we restore the old mask and hide
+	 * any dirs that might have been populated in cgroup_unhide().
+	 */
+	old_hidden_ss_mask = cgroup_hidden_ss_mask(cgrp);
 	cgrp->hidden_ss_mask &= ~show;
 
-	ret = cgroup_apply_hidden(cgrp);
+	ret = cgroup_unhide(cgrp);
+	if (ret)
+		/* Restore old mask on failure */
+		cgrp->hidden_ss_mask = old_hidden_ss_mask;
+	else
+		cgrp->hidden_ss_mask |= hide;
+
+	cgroup_hide(cgrp);
 	if (ret)
 		goto out_unlock;
 


More information about the Devel mailing list