6
6
"strconv"
7
7
"strings"
8
8
9
+ "github.com/hashicorp/go-multierror"
9
10
"github.com/spf13/afero"
10
11
"golang.org/x/xerrors"
11
12
"tailscale.com/types/ptr"
@@ -15,11 +16,10 @@ import (
15
16
// Ref: https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt
16
17
const (
17
18
// CPU usage of all tasks in cgroup in nanoseconds.
18
- cgroupV1CPUAcctUsage = "/sys/fs/cgroup/cpu/cpuacct.usage"
19
- // Alternate path
20
- cgroupV1CPUAcctUsageAlt = "/sys/fs/cgroup/cpu,cpuacct/cpuacct.usage"
19
+ cgroupV1CPUAcctUsage = "/sys/fs/cgroup/cpu,cpuacct/cpuacct.usage"
21
20
// CFS quota and period for cgroup in MICROseconds
22
- cgroupV1CFSQuotaUs = "/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us"
21
+ cgroupV1CFSQuotaUs = "/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us"
22
+ // CFS period for cgroup in MICROseconds
23
23
cgroupV1CFSPeriodUs = "/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us"
24
24
// Maximum memory usable by cgroup in bytes
25
25
cgroupV1MemoryMaxUsageBytes = "/sys/fs/cgroup/memory/memory.max_usage_in_bytes"
@@ -153,12 +153,26 @@ func (s *Statter) cGroupV2CPUTotal() (total float64, err error) {
153
153
func (s * Statter ) cGroupV1CPUTotal () (float64 , error ) {
154
154
periodUs , err := readInt64 (s .fs , cgroupV1CFSPeriodUs )
155
155
if err != nil {
156
- return 0 , xerrors .Errorf ("read cpu period: %w" , err )
156
+ // Try alternate path under /sys/fs/cpu
157
+ var merr error
158
+ merr = multierror .Append (merr , xerrors .Errorf ("get cpu period: %w" , err ))
159
+ periodUs , err = readInt64 (s .fs , strings .Replace (cgroupV1CFSPeriodUs , "cpu,cpuacct" , "cpu" , 1 ))
160
+ if err != nil {
161
+ merr = multierror .Append (merr , xerrors .Errorf ("get cpu period: %w" , err ))
162
+ return 0 , merr
163
+ }
157
164
}
158
165
159
166
quotaUs , err := readInt64 (s .fs , cgroupV1CFSQuotaUs )
160
167
if err != nil {
161
- return 0 , xerrors .Errorf ("read cpu quota: %w" , err )
168
+ // Try alternate path under /sys/fs/cpu
169
+ var merr error
170
+ merr = multierror .Append (merr , xerrors .Errorf ("get cpu quota: %w" , err ))
171
+ quotaUs , err = readInt64 (s .fs , strings .Replace (cgroupV1CFSQuotaUs , "cpu,cpuacct" , "cpu" , 1 ))
172
+ if err != nil {
173
+ merr = multierror .Append (merr , xerrors .Errorf ("get cpu quota: %w" , err ))
174
+ return 0 , merr
175
+ }
162
176
}
163
177
164
178
if quotaUs < 0 {
@@ -171,18 +185,28 @@ func (s *Statter) cGroupV1CPUTotal() (float64, error) {
171
185
func (s * Statter ) cGroupV1CPUUsed () (float64 , error ) {
172
186
usageNs , err := readInt64 (s .fs , cgroupV1CPUAcctUsage )
173
187
if err != nil {
174
- // try alternate path
175
- usageNs , err = readInt64 (s .fs , cgroupV1CPUAcctUsageAlt )
188
+ // Try alternate path under /sys/fs/cgroup/cpuacct
189
+ var merr error
190
+ merr = multierror .Append (merr , xerrors .Errorf ("read cpu used: %w" , err ))
191
+ usageNs , err = readInt64 (s .fs , strings .Replace (cgroupV1CPUAcctUsage , "cpu,cpuacct" , "cpuacct" , 1 ))
176
192
if err != nil {
177
- return 0 , xerrors .Errorf ("read cpu used: %w" , err )
193
+ merr = multierror .Append (merr , xerrors .Errorf ("read cpu used: %w" , err ))
194
+ return 0 , merr
178
195
}
179
196
}
180
197
181
198
// usage is in ns, convert to us
182
199
usageNs /= 1000
183
200
periodUs , err := readInt64 (s .fs , cgroupV1CFSPeriodUs )
184
201
if err != nil {
185
- return 0 , xerrors .Errorf ("get cpu period: %w" , err )
202
+ // Try alternate path under /sys/fs/cpu
203
+ var merr error
204
+ merr = multierror .Append (merr , xerrors .Errorf ("get cpu period: %w" , err ))
205
+ periodUs , err = readInt64 (s .fs , strings .Replace (cgroupV1CFSPeriodUs , "cpu,cpuacct" , "cpu" , 1 ))
206
+ if err != nil {
207
+ merr = multierror .Append (merr , xerrors .Errorf ("get cpu period: %w" , err ))
208
+ return 0 , merr
209
+ }
186
210
}
187
211
188
212
return float64 (usageNs ) / float64 (periodUs ), nil
0 commit comments