fscache.go 15 KB

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