(controllers []string, t ControllerToggle)
| 331 | } |
| 332 | |
| 333 | func (c *Manager) ToggleControllers(controllers []string, t ControllerToggle) error { |
| 334 | // when c.path is like /foo/bar/baz, the following files need to be written: |
| 335 | // * /sys/fs/cgroup/cgroup.subtree_control |
| 336 | // * /sys/fs/cgroup/foo/cgroup.subtree_control |
| 337 | // * /sys/fs/cgroup/foo/bar/cgroup.subtree_control |
| 338 | // Note that /sys/fs/cgroup/foo/bar/baz/cgroup.subtree_control does not need to be written. |
| 339 | split := strings.Split(c.path, "/") |
| 340 | var lastErr error |
| 341 | for i := range split { |
| 342 | f := strings.Join(split[:i], "/") |
| 343 | if !strings.HasPrefix(f, c.unifiedMountpoint) || f == c.path { |
| 344 | continue |
| 345 | } |
| 346 | filePath := filepath.Join(f, subtreeControl) |
| 347 | if err := c.writeSubtreeControl(filePath, controllers, t); err != nil { |
| 348 | // When running as rootless, the user may face EPERM on parent groups, but it is negligible when the |
| 349 | // controller is already written. |
| 350 | // So we only return the last error. |
| 351 | lastErr = fmt.Errorf("failed to write subtree controllers %+v to %q: %w", controllers, filePath, err) |
| 352 | } else { |
| 353 | lastErr = nil |
| 354 | } |
| 355 | } |
| 356 | return lastErr |
| 357 | } |
| 358 | |
| 359 | func (c *Manager) writeSubtreeControl(filePath string, controllers []string, t ControllerToggle) error { |
| 360 | f, err := os.OpenFile(filePath, os.O_WRONLY, 0) |
no test coverage detected