slab.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2020 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package procfs
  14. import (
  15. "bufio"
  16. "bytes"
  17. "fmt"
  18. "regexp"
  19. "strconv"
  20. "strings"
  21. "github.com/prometheus/procfs/internal/util"
  22. )
  23. var (
  24. slabSpace = regexp.MustCompile(`\s+`)
  25. slabVer = regexp.MustCompile(`slabinfo -`)
  26. slabHeader = regexp.MustCompile(`# name`)
  27. )
  28. // Slab represents a slab pool in the kernel.
  29. type Slab struct {
  30. Name string
  31. ObjActive int64
  32. ObjNum int64
  33. ObjSize int64
  34. ObjPerSlab int64
  35. PagesPerSlab int64
  36. // tunables
  37. Limit int64
  38. Batch int64
  39. SharedFactor int64
  40. SlabActive int64
  41. SlabNum int64
  42. SharedAvail int64
  43. }
  44. // SlabInfo represents info for all slabs.
  45. type SlabInfo struct {
  46. Slabs []*Slab
  47. }
  48. func shouldParseSlab(line string) bool {
  49. if slabVer.MatchString(line) {
  50. return false
  51. }
  52. if slabHeader.MatchString(line) {
  53. return false
  54. }
  55. return true
  56. }
  57. // parseV21SlabEntry is used to parse a line from /proc/slabinfo version 2.1.
  58. func parseV21SlabEntry(line string) (*Slab, error) {
  59. // First cleanup whitespace.
  60. l := slabSpace.ReplaceAllString(line, " ")
  61. s := strings.Split(l, " ")
  62. if len(s) != 16 {
  63. return nil, fmt.Errorf("%w: unable to parse: %q", ErrFileParse, line)
  64. }
  65. var err error
  66. i := &Slab{Name: s[0]}
  67. i.ObjActive, err = strconv.ParseInt(s[1], 10, 64)
  68. if err != nil {
  69. return nil, err
  70. }
  71. i.ObjNum, err = strconv.ParseInt(s[2], 10, 64)
  72. if err != nil {
  73. return nil, err
  74. }
  75. i.ObjSize, err = strconv.ParseInt(s[3], 10, 64)
  76. if err != nil {
  77. return nil, err
  78. }
  79. i.ObjPerSlab, err = strconv.ParseInt(s[4], 10, 64)
  80. if err != nil {
  81. return nil, err
  82. }
  83. i.PagesPerSlab, err = strconv.ParseInt(s[5], 10, 64)
  84. if err != nil {
  85. return nil, err
  86. }
  87. i.Limit, err = strconv.ParseInt(s[8], 10, 64)
  88. if err != nil {
  89. return nil, err
  90. }
  91. i.Batch, err = strconv.ParseInt(s[9], 10, 64)
  92. if err != nil {
  93. return nil, err
  94. }
  95. i.SharedFactor, err = strconv.ParseInt(s[10], 10, 64)
  96. if err != nil {
  97. return nil, err
  98. }
  99. i.SlabActive, err = strconv.ParseInt(s[13], 10, 64)
  100. if err != nil {
  101. return nil, err
  102. }
  103. i.SlabNum, err = strconv.ParseInt(s[14], 10, 64)
  104. if err != nil {
  105. return nil, err
  106. }
  107. i.SharedAvail, err = strconv.ParseInt(s[15], 10, 64)
  108. if err != nil {
  109. return nil, err
  110. }
  111. return i, nil
  112. }
  113. // parseSlabInfo21 is used to parse a slabinfo 2.1 file.
  114. func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) {
  115. scanner := bufio.NewScanner(r)
  116. s := SlabInfo{Slabs: []*Slab{}}
  117. for scanner.Scan() {
  118. line := scanner.Text()
  119. if !shouldParseSlab(line) {
  120. continue
  121. }
  122. slab, err := parseV21SlabEntry(line)
  123. if err != nil {
  124. return s, err
  125. }
  126. s.Slabs = append(s.Slabs, slab)
  127. }
  128. return s, nil
  129. }
  130. // SlabInfo reads data from `/proc/slabinfo`.
  131. func (fs FS) SlabInfo() (SlabInfo, error) {
  132. // TODO: Consider passing options to allow for parsing different
  133. // slabinfo versions. However, slabinfo 2.1 has been stable since
  134. // kernel 2.6.10 and later.
  135. data, err := util.ReadFileNoStat(fs.proc.Path("slabinfo"))
  136. if err != nil {
  137. return SlabInfo{}, err
  138. }
  139. return parseSlabInfo21(bytes.NewReader(data))
  140. }