blob: f8070e6e2bec7d4385b6e41d3112fa6894a4d61e [file] [log] [blame]
khenaidoo26721882021-08-11 17:42:52 -04001// Copyright 2019 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 "io"
21 "strconv"
22 "strings"
23
24 "github.com/prometheus/procfs/internal/util"
25)
26
27// Fscacheinfo represents fscache statistics.
28type Fscacheinfo struct {
29 // Number of index cookies allocated
30 IndexCookiesAllocated uint64
31 // data storage cookies allocated
32 DataStorageCookiesAllocated uint64
33 // Number of special cookies allocated
34 SpecialCookiesAllocated uint64
35 // Number of objects allocated
36 ObjectsAllocated uint64
37 // Number of object allocation failures
38 ObjectAllocationsFailure uint64
39 // Number of objects that reached the available state
40 ObjectsAvailable uint64
41 // Number of objects that reached the dead state
42 ObjectsDead uint64
43 // Number of objects that didn't have a coherency check
44 ObjectsWithoutCoherencyCheck uint64
45 // Number of objects that passed a coherency check
46 ObjectsWithCoherencyCheck uint64
47 // Number of objects that needed a coherency data update
48 ObjectsNeedCoherencyCheckUpdate uint64
49 // Number of objects that were declared obsolete
50 ObjectsDeclaredObsolete uint64
51 // Number of pages marked as being cached
52 PagesMarkedAsBeingCached uint64
53 // Number of uncache page requests seen
54 UncachePagesRequestSeen uint64
55 // Number of acquire cookie requests seen
56 AcquireCookiesRequestSeen uint64
57 // Number of acq reqs given a NULL parent
58 AcquireRequestsWithNullParent uint64
59 // Number of acq reqs rejected due to no cache available
60 AcquireRequestsRejectedNoCacheAvailable uint64
61 // Number of acq reqs succeeded
62 AcquireRequestsSucceeded uint64
63 // Number of acq reqs rejected due to error
64 AcquireRequestsRejectedDueToError uint64
65 // Number of acq reqs failed on ENOMEM
66 AcquireRequestsFailedDueToEnomem uint64
67 // Number of lookup calls made on cache backends
68 LookupsNumber uint64
69 // Number of negative lookups made
70 LookupsNegative uint64
71 // Number of positive lookups made
72 LookupsPositive uint64
73 // Number of objects created by lookup
74 ObjectsCreatedByLookup uint64
75 // Number of lookups timed out and requeued
76 LookupsTimedOutAndRequed uint64
77 InvalidationsNumber uint64
78 InvalidationsRunning uint64
79 // Number of update cookie requests seen
80 UpdateCookieRequestSeen uint64
81 // Number of upd reqs given a NULL parent
82 UpdateRequestsWithNullParent uint64
83 // Number of upd reqs granted CPU time
84 UpdateRequestsRunning uint64
85 // Number of relinquish cookie requests seen
86 RelinquishCookiesRequestSeen uint64
87 // Number of rlq reqs given a NULL parent
88 RelinquishCookiesWithNullParent uint64
89 // Number of rlq reqs waited on completion of creation
90 RelinquishRequestsWaitingCompleteCreation uint64
91 // Relinqs rtr
92 RelinquishRetries uint64
93 // Number of attribute changed requests seen
94 AttributeChangedRequestsSeen uint64
95 // Number of attr changed requests queued
96 AttributeChangedRequestsQueued uint64
97 // Number of attr changed rejected -ENOBUFS
98 AttributeChangedRejectDueToEnobufs uint64
99 // Number of attr changed failed -ENOMEM
100 AttributeChangedFailedDueToEnomem uint64
101 // Number of attr changed ops given CPU time
102 AttributeChangedOps uint64
103 // Number of allocation requests seen
104 AllocationRequestsSeen uint64
105 // Number of successful alloc reqs
106 AllocationOkRequests uint64
107 // Number of alloc reqs that waited on lookup completion
108 AllocationWaitingOnLookup uint64
109 // Number of alloc reqs rejected -ENOBUFS
110 AllocationsRejectedDueToEnobufs uint64
111 // Number of alloc reqs aborted -ERESTARTSYS
112 AllocationsAbortedDueToErestartsys uint64
113 // Number of alloc reqs submitted
114 AllocationOperationsSubmitted uint64
115 // Number of alloc reqs waited for CPU time
116 AllocationsWaitedForCPU uint64
117 // Number of alloc reqs aborted due to object death
118 AllocationsAbortedDueToObjectDeath uint64
119 // Number of retrieval (read) requests seen
120 RetrievalsReadRequests uint64
121 // Number of successful retr reqs
122 RetrievalsOk uint64
123 // Number of retr reqs that waited on lookup completion
124 RetrievalsWaitingLookupCompletion uint64
125 // Number of retr reqs returned -ENODATA
126 RetrievalsReturnedEnodata uint64
127 // Number of retr reqs rejected -ENOBUFS
128 RetrievalsRejectedDueToEnobufs uint64
129 // Number of retr reqs aborted -ERESTARTSYS
130 RetrievalsAbortedDueToErestartsys uint64
131 // Number of retr reqs failed -ENOMEM
132 RetrievalsFailedDueToEnomem uint64
133 // Number of retr reqs submitted
134 RetrievalsRequests uint64
135 // Number of retr reqs waited for CPU time
136 RetrievalsWaitingCPU uint64
137 // Number of retr reqs aborted due to object death
138 RetrievalsAbortedDueToObjectDeath uint64
139 // Number of storage (write) requests seen
140 StoreWriteRequests uint64
141 // Number of successful store reqs
142 StoreSuccessfulRequests uint64
143 // Number of store reqs on a page already pending storage
144 StoreRequestsOnPendingStorage uint64
145 // Number of store reqs rejected -ENOBUFS
146 StoreRequestsRejectedDueToEnobufs uint64
147 // Number of store reqs failed -ENOMEM
148 StoreRequestsFailedDueToEnomem uint64
149 // Number of store reqs submitted
150 StoreRequestsSubmitted uint64
151 // Number of store reqs granted CPU time
152 StoreRequestsRunning uint64
153 // Number of pages given store req processing time
154 StorePagesWithRequestsProcessing uint64
155 // Number of store reqs deleted from tracking tree
156 StoreRequestsDeleted uint64
157 // Number of store reqs over store limit
158 StoreRequestsOverStoreLimit uint64
159 // Number of release reqs against pages with no pending store
160 ReleaseRequestsAgainstPagesWithNoPendingStorage uint64
161 // Number of release reqs against pages stored by time lock granted
162 ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
163 // Number of release reqs ignored due to in-progress store
164 ReleaseRequestsIgnoredDueToInProgressStore uint64
165 // Number of page stores cancelled due to release req
166 PageStoresCancelledByReleaseRequests uint64
167 VmscanWaiting uint64
168 // Number of times async ops added to pending queues
169 OpsPending uint64
170 // Number of times async ops given CPU time
171 OpsRunning uint64
172 // Number of times async ops queued for processing
173 OpsEnqueued uint64
174 // Number of async ops cancelled
175 OpsCancelled uint64
176 // Number of async ops rejected due to object lookup/create failure
177 OpsRejected uint64
178 // Number of async ops initialised
179 OpsInitialised uint64
180 // Number of async ops queued for deferred release
181 OpsDeferred uint64
182 // Number of async ops released (should equal ini=N when idle)
183 OpsReleased uint64
184 // Number of deferred-release async ops garbage collected
185 OpsGarbageCollected uint64
186 // Number of in-progress alloc_object() cache ops
187 CacheopAllocationsinProgress uint64
188 // Number of in-progress lookup_object() cache ops
189 CacheopLookupObjectInProgress uint64
190 // Number of in-progress lookup_complete() cache ops
191 CacheopLookupCompleteInPorgress uint64
192 // Number of in-progress grab_object() cache ops
193 CacheopGrabObjectInProgress uint64
194 CacheopInvalidations uint64
195 // Number of in-progress update_object() cache ops
196 CacheopUpdateObjectInProgress uint64
197 // Number of in-progress drop_object() cache ops
198 CacheopDropObjectInProgress uint64
199 // Number of in-progress put_object() cache ops
200 CacheopPutObjectInProgress uint64
201 // Number of in-progress attr_changed() cache ops
202 CacheopAttributeChangeInProgress uint64
203 // Number of in-progress sync_cache() cache ops
204 CacheopSyncCacheInProgress uint64
205 // Number of in-progress read_or_alloc_page() cache ops
206 CacheopReadOrAllocPageInProgress uint64
207 // Number of in-progress read_or_alloc_pages() cache ops
208 CacheopReadOrAllocPagesInProgress uint64
209 // Number of in-progress allocate_page() cache ops
210 CacheopAllocatePageInProgress uint64
211 // Number of in-progress allocate_pages() cache ops
212 CacheopAllocatePagesInProgress uint64
213 // Number of in-progress write_page() cache ops
214 CacheopWritePagesInProgress uint64
215 // Number of in-progress uncache_page() cache ops
216 CacheopUncachePagesInProgress uint64
217 // Number of in-progress dissociate_pages() cache ops
218 CacheopDissociatePagesInProgress uint64
219 // Number of object lookups/creations rejected due to lack of space
220 CacheevLookupsAndCreationsRejectedLackSpace uint64
221 // Number of stale objects deleted
222 CacheevStaleObjectsDeleted uint64
223 // Number of objects retired when relinquished
224 CacheevRetiredWhenReliquished uint64
225 // Number of objects culled
226 CacheevObjectsCulled uint64
227}
228
229// Fscacheinfo returns information about current fscache statistics.
230// See https://www.kernel.org/doc/Documentation/filesystems/caching/fscache.txt
231func (fs FS) Fscacheinfo() (Fscacheinfo, error) {
232 b, err := util.ReadFileNoStat(fs.proc.Path("fs/fscache/stats"))
233 if err != nil {
234 return Fscacheinfo{}, err
235 }
236
237 m, err := parseFscacheinfo(bytes.NewReader(b))
238 if err != nil {
239 return Fscacheinfo{}, fmt.Errorf("failed to parse Fscacheinfo: %w", err)
240 }
241
242 return *m, nil
243}
244
245func setFSCacheFields(fields []string, setFields ...*uint64) error {
246 var err error
247 if len(fields) < len(setFields) {
248 return fmt.Errorf("Insufficient number of fields, expected %v, got %v", len(setFields), len(fields))
249 }
250
251 for i := range setFields {
252 *setFields[i], err = strconv.ParseUint(strings.Split(fields[i], "=")[1], 0, 64)
253 if err != nil {
254 return err
255 }
256 }
257 return nil
258}
259
260func parseFscacheinfo(r io.Reader) (*Fscacheinfo, error) {
261 var m Fscacheinfo
262 s := bufio.NewScanner(r)
263 for s.Scan() {
264 fields := strings.Fields(s.Text())
265 if len(fields) < 2 {
266 return nil, fmt.Errorf("malformed Fscacheinfo line: %q", s.Text())
267 }
268
269 switch fields[0] {
270 case "Cookies:":
271 err := setFSCacheFields(fields[1:], &m.IndexCookiesAllocated, &m.DataStorageCookiesAllocated,
272 &m.SpecialCookiesAllocated)
273 if err != nil {
274 return &m, err
275 }
276 case "Objects:":
277 err := setFSCacheFields(fields[1:], &m.ObjectsAllocated, &m.ObjectAllocationsFailure,
278 &m.ObjectsAvailable, &m.ObjectsDead)
279 if err != nil {
280 return &m, err
281 }
282 case "ChkAux":
283 err := setFSCacheFields(fields[2:], &m.ObjectsWithoutCoherencyCheck, &m.ObjectsWithCoherencyCheck,
284 &m.ObjectsNeedCoherencyCheckUpdate, &m.ObjectsDeclaredObsolete)
285 if err != nil {
286 return &m, err
287 }
288 case "Pages":
289 err := setFSCacheFields(fields[2:], &m.PagesMarkedAsBeingCached, &m.UncachePagesRequestSeen)
290 if err != nil {
291 return &m, err
292 }
293 case "Acquire:":
294 err := setFSCacheFields(fields[1:], &m.AcquireCookiesRequestSeen, &m.AcquireRequestsWithNullParent,
295 &m.AcquireRequestsRejectedNoCacheAvailable, &m.AcquireRequestsSucceeded, &m.AcquireRequestsRejectedDueToError,
296 &m.AcquireRequestsFailedDueToEnomem)
297 if err != nil {
298 return &m, err
299 }
300 case "Lookups:":
301 err := setFSCacheFields(fields[1:], &m.LookupsNumber, &m.LookupsNegative, &m.LookupsPositive,
302 &m.ObjectsCreatedByLookup, &m.LookupsTimedOutAndRequed)
303 if err != nil {
304 return &m, err
305 }
306 case "Invals":
307 err := setFSCacheFields(fields[2:], &m.InvalidationsNumber, &m.InvalidationsRunning)
308 if err != nil {
309 return &m, err
310 }
311 case "Updates:":
312 err := setFSCacheFields(fields[1:], &m.UpdateCookieRequestSeen, &m.UpdateRequestsWithNullParent,
313 &m.UpdateRequestsRunning)
314 if err != nil {
315 return &m, err
316 }
317 case "Relinqs:":
318 err := setFSCacheFields(fields[1:], &m.RelinquishCookiesRequestSeen, &m.RelinquishCookiesWithNullParent,
319 &m.RelinquishRequestsWaitingCompleteCreation, &m.RelinquishRetries)
320 if err != nil {
321 return &m, err
322 }
323 case "AttrChg:":
324 err := setFSCacheFields(fields[1:], &m.AttributeChangedRequestsSeen, &m.AttributeChangedRequestsQueued,
325 &m.AttributeChangedRejectDueToEnobufs, &m.AttributeChangedFailedDueToEnomem, &m.AttributeChangedOps)
326 if err != nil {
327 return &m, err
328 }
329 case "Allocs":
330 if strings.Split(fields[2], "=")[0] == "n" {
331 err := setFSCacheFields(fields[2:], &m.AllocationRequestsSeen, &m.AllocationOkRequests,
332 &m.AllocationWaitingOnLookup, &m.AllocationsRejectedDueToEnobufs, &m.AllocationsAbortedDueToErestartsys)
333 if err != nil {
334 return &m, err
335 }
336 } else {
337 err := setFSCacheFields(fields[2:], &m.AllocationOperationsSubmitted, &m.AllocationsWaitedForCPU,
338 &m.AllocationsAbortedDueToObjectDeath)
339 if err != nil {
340 return &m, err
341 }
342 }
343 case "Retrvls:":
344 if strings.Split(fields[1], "=")[0] == "n" {
345 err := setFSCacheFields(fields[1:], &m.RetrievalsReadRequests, &m.RetrievalsOk, &m.RetrievalsWaitingLookupCompletion,
346 &m.RetrievalsReturnedEnodata, &m.RetrievalsRejectedDueToEnobufs, &m.RetrievalsAbortedDueToErestartsys,
347 &m.RetrievalsFailedDueToEnomem)
348 if err != nil {
349 return &m, err
350 }
351 } else {
352 err := setFSCacheFields(fields[1:], &m.RetrievalsRequests, &m.RetrievalsWaitingCPU, &m.RetrievalsAbortedDueToObjectDeath)
353 if err != nil {
354 return &m, err
355 }
356 }
357 case "Stores":
358 if strings.Split(fields[2], "=")[0] == "n" {
359 err := setFSCacheFields(fields[2:], &m.StoreWriteRequests, &m.StoreSuccessfulRequests,
360 &m.StoreRequestsOnPendingStorage, &m.StoreRequestsRejectedDueToEnobufs, &m.StoreRequestsFailedDueToEnomem)
361 if err != nil {
362 return &m, err
363 }
364 } else {
365 err := setFSCacheFields(fields[2:], &m.StoreRequestsSubmitted, &m.StoreRequestsRunning,
366 &m.StorePagesWithRequestsProcessing, &m.StoreRequestsDeleted, &m.StoreRequestsOverStoreLimit)
367 if err != nil {
368 return &m, err
369 }
370 }
371 case "VmScan":
372 err := setFSCacheFields(fields[2:], &m.ReleaseRequestsAgainstPagesWithNoPendingStorage,
373 &m.ReleaseRequestsAgainstPagesStoredByTimeLockGranted, &m.ReleaseRequestsIgnoredDueToInProgressStore,
374 &m.PageStoresCancelledByReleaseRequests, &m.VmscanWaiting)
375 if err != nil {
376 return &m, err
377 }
378 case "Ops":
379 if strings.Split(fields[2], "=")[0] == "pend" {
380 err := setFSCacheFields(fields[2:], &m.OpsPending, &m.OpsRunning, &m.OpsEnqueued, &m.OpsCancelled, &m.OpsRejected)
381 if err != nil {
382 return &m, err
383 }
384 } else {
385 err := setFSCacheFields(fields[2:], &m.OpsInitialised, &m.OpsDeferred, &m.OpsReleased, &m.OpsGarbageCollected)
386 if err != nil {
387 return &m, err
388 }
389 }
390 case "CacheOp:":
391 if strings.Split(fields[1], "=")[0] == "alo" {
392 err := setFSCacheFields(fields[1:], &m.CacheopAllocationsinProgress, &m.CacheopLookupObjectInProgress,
393 &m.CacheopLookupCompleteInPorgress, &m.CacheopGrabObjectInProgress)
394 if err != nil {
395 return &m, err
396 }
397 } else if strings.Split(fields[1], "=")[0] == "inv" {
398 err := setFSCacheFields(fields[1:], &m.CacheopInvalidations, &m.CacheopUpdateObjectInProgress,
399 &m.CacheopDropObjectInProgress, &m.CacheopPutObjectInProgress, &m.CacheopAttributeChangeInProgress,
400 &m.CacheopSyncCacheInProgress)
401 if err != nil {
402 return &m, err
403 }
404 } else {
405 err := setFSCacheFields(fields[1:], &m.CacheopReadOrAllocPageInProgress, &m.CacheopReadOrAllocPagesInProgress,
406 &m.CacheopAllocatePageInProgress, &m.CacheopAllocatePagesInProgress, &m.CacheopWritePagesInProgress,
407 &m.CacheopUncachePagesInProgress, &m.CacheopDissociatePagesInProgress)
408 if err != nil {
409 return &m, err
410 }
411 }
412 case "CacheEv:":
413 err := setFSCacheFields(fields[1:], &m.CacheevLookupsAndCreationsRejectedLackSpace, &m.CacheevStaleObjectsDeleted,
414 &m.CacheevRetiredWhenReliquished, &m.CacheevObjectsCulled)
415 if err != nil {
416 return &m, err
417 }
418 }
419 }
420
421 return &m, nil
422}