blob: 7896fd7242830ab894f3b1191de7089dc65a3f09 [file] [log] [blame]
khenaidoo26721882021-08-11 17:42:52 -04001// 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
14package procfs
15
16import (
17 "bufio"
18 "bytes"
19 "fmt"
20 "regexp"
21 "strconv"
22 "strings"
23
24 "github.com/prometheus/procfs/internal/util"
25)
26
27var (
28 slabSpace = regexp.MustCompile(`\s+`)
29 slabVer = regexp.MustCompile(`slabinfo -`)
30 slabHeader = regexp.MustCompile(`# name`)
31)
32
33// Slab represents a slab pool in the kernel.
34type Slab struct {
35 Name string
36 ObjActive int64
37 ObjNum int64
38 ObjSize int64
39 ObjPerSlab int64
40 PagesPerSlab int64
41 // tunables
42 Limit int64
43 Batch int64
44 SharedFactor int64
45 SlabActive int64
46 SlabNum int64
47 SharedAvail int64
48}
49
50// SlabInfo represents info for all slabs.
51type SlabInfo struct {
52 Slabs []*Slab
53}
54
55func shouldParseSlab(line string) bool {
56 if slabVer.MatchString(line) {
57 return false
58 }
59 if slabHeader.MatchString(line) {
60 return false
61 }
62 return true
63}
64
65// parseV21SlabEntry is used to parse a line from /proc/slabinfo version 2.1.
66func parseV21SlabEntry(line string) (*Slab, error) {
67 // First cleanup whitespace.
68 l := slabSpace.ReplaceAllString(line, " ")
69 s := strings.Split(l, " ")
70 if len(s) != 16 {
71 return nil, fmt.Errorf("unable to parse: %q", line)
72 }
73 var err error
74 i := &Slab{Name: s[0]}
75 i.ObjActive, err = strconv.ParseInt(s[1], 10, 64)
76 if err != nil {
77 return nil, err
78 }
79 i.ObjNum, err = strconv.ParseInt(s[2], 10, 64)
80 if err != nil {
81 return nil, err
82 }
83 i.ObjSize, err = strconv.ParseInt(s[3], 10, 64)
84 if err != nil {
85 return nil, err
86 }
87 i.ObjPerSlab, err = strconv.ParseInt(s[4], 10, 64)
88 if err != nil {
89 return nil, err
90 }
91 i.PagesPerSlab, err = strconv.ParseInt(s[5], 10, 64)
92 if err != nil {
93 return nil, err
94 }
95 i.Limit, err = strconv.ParseInt(s[8], 10, 64)
96 if err != nil {
97 return nil, err
98 }
99 i.Batch, err = strconv.ParseInt(s[9], 10, 64)
100 if err != nil {
101 return nil, err
102 }
103 i.SharedFactor, err = strconv.ParseInt(s[10], 10, 64)
104 if err != nil {
105 return nil, err
106 }
107 i.SlabActive, err = strconv.ParseInt(s[13], 10, 64)
108 if err != nil {
109 return nil, err
110 }
111 i.SlabNum, err = strconv.ParseInt(s[14], 10, 64)
112 if err != nil {
113 return nil, err
114 }
115 i.SharedAvail, err = strconv.ParseInt(s[15], 10, 64)
116 if err != nil {
117 return nil, err
118 }
119 return i, nil
120}
121
122// parseSlabInfo21 is used to parse a slabinfo 2.1 file.
123func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) {
124 scanner := bufio.NewScanner(r)
125 s := SlabInfo{Slabs: []*Slab{}}
126 for scanner.Scan() {
127 line := scanner.Text()
128 if !shouldParseSlab(line) {
129 continue
130 }
131 slab, err := parseV21SlabEntry(line)
132 if err != nil {
133 return s, err
134 }
135 s.Slabs = append(s.Slabs, slab)
136 }
137 return s, nil
138}
139
140// SlabInfo reads data from /proc/slabinfo
141func (fs FS) SlabInfo() (SlabInfo, error) {
142 // TODO: Consider passing options to allow for parsing different
143 // slabinfo versions. However, slabinfo 2.1 has been stable since
144 // kernel 2.6.10 and later.
145 data, err := util.ReadFileNoStat(fs.proc.Path("slabinfo"))
146 if err != nil {
147 return SlabInfo{}, err
148 }
149
150 return parseSlabInfo21(bytes.NewReader(data))
151}