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 <[email protected]>
---
 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

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to