Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion cmd/cgctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func main() {
newCommand,
delCommand,
listCommand,
listControllersCommand,
statCommand,
}
app.Before = func(clix *cli.Context) error {
Expand Down Expand Up @@ -76,7 +77,7 @@ var newCommand = cli.Command{
return err
}
if clix.Bool("enable") {
controllers, err := c.ListControllers()
controllers, err := c.RootControllers()
if err != nil {
return err
}
Expand Down Expand Up @@ -121,6 +122,26 @@ var listCommand = cli.Command{
},
}

var listControllersCommand = cli.Command{
Name: "list-controllers",
Usage: "list controllers in a cgroup",
Action: func(clix *cli.Context) error {
path := clix.Args().First()
c, err := v2.LoadManager(clix.GlobalString("mountpoint"), path)
if err != nil {
return err
}
controllers, err := c.Controllers()
if err != nil {
return err
}
for _, c := range controllers {
fmt.Println(c)
}
return nil
},
}

var statCommand = cli.Command{
Name: "stat",
Usage: "stat a cgroup",
Expand Down
51 changes: 35 additions & 16 deletions v2/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,25 +168,20 @@ func setResources(path string, resources *Resources) error {
return nil
}

func (c *Manager) ListControllers() ([]string, error) {
f, err := os.Open(filepath.Join(c.path, controllersFile))
func (c *Manager) RootControllers() ([]string, error) {
b, err := ioutil.ReadFile(filepath.Join(c.unifiedMountpoint, controllersFile))
if err != nil {
return nil, err
}
defer f.Close()
return strings.Fields(string(b)), nil
}

var (
out []string
s = bufio.NewScanner(f)
)
s.Split(bufio.ScanWords)
for s.Scan() {
if err := s.Err(); err != nil {
return nil, err
}
out = append(out, s.Text())
func (c *Manager) Controllers() ([]string, error) {
b, err := ioutil.ReadFile(filepath.Join(c.path, controllersFile))
if err != nil {
return nil, err
}
return out, nil
return strings.Fields(string(b)), nil
}

type ControllerToggle int
Expand All @@ -205,7 +200,31 @@ func toggleFunc(controllers []string, prefix string) []string {
}

func (c *Manager) ToggleControllers(controllers []string, t ControllerToggle) error {
f, err := os.OpenFile(filepath.Join(c.path, subtreeControl), os.O_WRONLY, 0)
// when c.path is like /foo/bar/baz, the following files need to be written:
// * /sys/fs/cgroup/cgroup.subtree_control
// * /sys/fs/cgroup/foo/cgroup.subtree_control
// * /sys/fs/cgroup/foo/bar/cgroup.subtree_control
// Note that /sys/fs/cgroup/foo/bar/baz/cgroup.subtree_control does not need to be written.
split := strings.Split(c.path, "/")
var lastErr error
for i, _ := range split {
f := strings.Join(split[:i], "/")
if !strings.HasPrefix(f, c.unifiedMountpoint) || f == c.path {
continue
}
filePath := filepath.Join(f, subtreeControl)
if err := c.writeSubtreeControl(filePath, controllers, t); err != nil {
// When running as rootless, the user may face EPERM on parent groups, but it is neglible when the
// controller is already written.
// So we only return the last error.
lastErr = errors.Wrapf(err, "failed to write subtree controllers %+v to %q", controllers, filePath)
}
}
return lastErr
}

func (c *Manager) writeSubtreeControl(filePath string, controllers []string, t ControllerToggle) error {
f, err := os.OpenFile(filePath, os.O_WRONLY, 0)
if err != nil {
return err
}
Expand Down Expand Up @@ -283,7 +302,7 @@ var singleValueFiles = []string{
}

func (c *Manager) Stat() (*stats.Metrics, error) {
controllers, err := c.ListControllers()
controllers, err := c.Controllers()
if err != nil {
return nil, err
}
Expand Down