apply_raw.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package fs
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "strconv"
  8. "github.com/dotcloud/docker/pkg/libcontainer/cgroups"
  9. )
  10. var (
  11. subsystems = map[string]subsystem{
  12. "devices": &devicesGroup{},
  13. "memory": &memoryGroup{},
  14. "cpu": &cpuGroup{},
  15. "cpuset": &cpusetGroup{},
  16. "cpuacct": &cpuacctGroup{},
  17. "blkio": &blkioGroup{},
  18. "perf_event": &perfEventGroup{},
  19. "freezer": &freezerGroup{},
  20. }
  21. )
  22. type subsystem interface {
  23. Set(*data) error
  24. Remove(*data) error
  25. Stats(*data) (map[string]int64, error)
  26. }
  27. type data struct {
  28. root string
  29. cgroup string
  30. c *cgroups.Cgroup
  31. pid int
  32. }
  33. func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
  34. // We have two implementation of cgroups support, one is based on
  35. // systemd and the dbus api, and one is based on raw cgroup fs operations
  36. // following the pre-single-writer model docs at:
  37. // http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups/
  38. //
  39. // we can pick any subsystem to find the root
  40. cgroupRoot, err := cgroups.FindCgroupMountpoint("cpu")
  41. if err != nil {
  42. return nil, err
  43. }
  44. cgroupRoot = filepath.Dir(cgroupRoot)
  45. if _, err := os.Stat(cgroupRoot); err != nil {
  46. return nil, fmt.Errorf("cgroups fs not found")
  47. }
  48. cgroup := c.Name
  49. if c.Parent != "" {
  50. cgroup = filepath.Join(c.Parent, cgroup)
  51. }
  52. d := &data{
  53. root: cgroupRoot,
  54. cgroup: cgroup,
  55. c: c,
  56. pid: pid,
  57. }
  58. for _, sys := range subsystems {
  59. if err := sys.Set(d); err != nil {
  60. d.Cleanup()
  61. return nil, err
  62. }
  63. }
  64. return d, nil
  65. }
  66. func GetStats(c *cgroups.Cgroup, subsystem string, pid int) (map[string]int64, error) {
  67. cgroupRoot, err := cgroups.FindCgroupMountpoint("cpu")
  68. if err != nil {
  69. return nil, err
  70. }
  71. cgroupRoot = filepath.Dir(cgroupRoot)
  72. if _, err := os.Stat(cgroupRoot); err != nil {
  73. return nil, fmt.Errorf("cgroups fs not found")
  74. }
  75. cgroup := c.Name
  76. if c.Parent != "" {
  77. cgroup = filepath.Join(c.Parent, cgroup)
  78. }
  79. d := &data{
  80. root: cgroupRoot,
  81. cgroup: cgroup,
  82. c: c,
  83. pid: pid,
  84. }
  85. sys, exists := subsystems[subsystem]
  86. if !exists {
  87. return nil, fmt.Errorf("subsystem %s does not exist", subsystem)
  88. }
  89. return sys.Stats(d)
  90. }
  91. func GetPids(c *cgroups.Cgroup) ([]int, error) {
  92. cgroupRoot, err := cgroups.FindCgroupMountpoint("cpu")
  93. if err != nil {
  94. return nil, err
  95. }
  96. cgroupRoot = filepath.Dir(cgroupRoot)
  97. if _, err := os.Stat(cgroupRoot); err != nil {
  98. return nil, fmt.Errorf("cgroup root %s not found", cgroupRoot)
  99. }
  100. cgroup := c.Name
  101. if c.Parent != "" {
  102. cgroup = filepath.Join(c.Parent, cgroup)
  103. }
  104. d := &data{
  105. root: cgroupRoot,
  106. cgroup: cgroup,
  107. c: c,
  108. }
  109. dir, err := d.path("devices")
  110. if err != nil {
  111. return nil, err
  112. }
  113. return cgroups.ReadProcsFile(dir)
  114. }
  115. func (raw *data) parent(subsystem string) (string, error) {
  116. initPath, err := cgroups.GetInitCgroupDir(subsystem)
  117. if err != nil {
  118. return "", err
  119. }
  120. return filepath.Join(raw.root, subsystem, initPath), nil
  121. }
  122. func (raw *data) path(subsystem string) (string, error) {
  123. parent, err := raw.parent(subsystem)
  124. if err != nil {
  125. return "", err
  126. }
  127. return filepath.Join(parent, raw.cgroup), nil
  128. }
  129. func (raw *data) join(subsystem string) (string, error) {
  130. path, err := raw.path(subsystem)
  131. if err != nil {
  132. return "", err
  133. }
  134. if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
  135. return "", err
  136. }
  137. if err := writeFile(path, "cgroup.procs", strconv.Itoa(raw.pid)); err != nil {
  138. return "", err
  139. }
  140. return path, nil
  141. }
  142. func (raw *data) Cleanup() error {
  143. for _, sys := range subsystems {
  144. sys.Remove(raw)
  145. }
  146. return nil
  147. }
  148. func writeFile(dir, file, data string) error {
  149. return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
  150. }
  151. func removePath(p string, err error) error {
  152. if err != nil {
  153. return err
  154. }
  155. if p != "" {
  156. return os.RemoveAll(p)
  157. }
  158. return nil
  159. }