cgroups.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package cgroups
  2. import (
  3. "bufio"
  4. "errors"
  5. "github.com/dotcloud/docker/pkg/mount"
  6. "io"
  7. "io/ioutil"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. )
  12. var (
  13. ErrNotFound = errors.New("mountpoint not found")
  14. )
  15. type Cgroup struct {
  16. Name string `json:"name,omitempty"`
  17. Parent string `json:"parent,omitempty"`
  18. DeviceAccess bool `json:"device_access,omitempty"` // name of parent cgroup or slice
  19. Memory int64 `json:"memory,omitempty"` // Memory limit (in bytes)
  20. MemorySwap int64 `json:"memory_swap,omitempty"` // Total memory usage (memory + swap); set `-1' to disable swap
  21. CpuShares int64 `json:"cpu_shares,omitempty"` // CPU shares (relative weight vs. other containers)
  22. CpusetCpus string `json:"cpuset_cpus,omitempty"` // CPU to use
  23. UnitProperties [][2]string `json:"unit_properties,omitempty"` // systemd unit properties
  24. }
  25. type ActiveCgroup interface {
  26. Cleanup() error
  27. }
  28. // https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
  29. func FindCgroupMountpoint(subsystem string) (string, error) {
  30. mounts, err := mount.GetMounts()
  31. if err != nil {
  32. return "", err
  33. }
  34. for _, mount := range mounts {
  35. if mount.Fstype == "cgroup" {
  36. for _, opt := range strings.Split(mount.VfsOpts, ",") {
  37. if opt == subsystem {
  38. return mount.Mountpoint, nil
  39. }
  40. }
  41. }
  42. }
  43. return "", ErrNotFound
  44. }
  45. // Returns the relative path to the cgroup docker is running in.
  46. func GetThisCgroupDir(subsystem string) (string, error) {
  47. f, err := os.Open("/proc/self/cgroup")
  48. if err != nil {
  49. return "", err
  50. }
  51. defer f.Close()
  52. return parseCgroupFile(subsystem, f)
  53. }
  54. func GetInitCgroupDir(subsystem string) (string, error) {
  55. f, err := os.Open("/proc/1/cgroup")
  56. if err != nil {
  57. return "", err
  58. }
  59. defer f.Close()
  60. return parseCgroupFile(subsystem, f)
  61. }
  62. func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
  63. s := bufio.NewScanner(r)
  64. for s.Scan() {
  65. if err := s.Err(); err != nil {
  66. return "", err
  67. }
  68. text := s.Text()
  69. parts := strings.Split(text, ":")
  70. for _, subs := range strings.Split(parts[1], ",") {
  71. if subs == subsystem {
  72. return parts[2], nil
  73. }
  74. }
  75. }
  76. return "", ErrNotFound
  77. }
  78. func writeFile(dir, file, data string) error {
  79. return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
  80. }
  81. func (c *Cgroup) Apply(pid int) (ActiveCgroup, error) {
  82. // We have two implementation of cgroups support, one is based on
  83. // systemd and the dbus api, and one is based on raw cgroup fs operations
  84. // following the pre-single-writer model docs at:
  85. // http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups/
  86. if useSystemd() {
  87. return systemdApply(c, pid)
  88. } else {
  89. return rawApply(c, pid)
  90. }
  91. }