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
