1
2
3
4
5
6
7
8
9
10
11
12
13
14 package xfs
15
16 import (
17 "bufio"
18 "fmt"
19 "io"
20 "strings"
21
22 "github.com/prometheus/procfs/internal/util"
23 )
24
25
26
27 func ParseStats(r io.Reader) (*Stats, error) {
28 const (
29
30 fieldExtentAlloc = "extent_alloc"
31 fieldAbt = "abt"
32 fieldBlkMap = "blk_map"
33 fieldBmbt = "bmbt"
34 fieldDir = "dir"
35 fieldTrans = "trans"
36 fieldIg = "ig"
37 fieldLog = "log"
38 fieldPushAil = "push_ail"
39 fieldXstrat = "xstrat"
40 fieldRw = "rw"
41 fieldAttr = "attr"
42 fieldIcluster = "icluster"
43 fieldVnodes = "vnodes"
44 fieldBuf = "buf"
45 fieldXpc = "xpc"
46 fieldAbtb2 = "abtb2"
47 fieldAbtc2 = "abtc2"
48 fieldBmbt2 = "bmbt2"
49 fieldIbt2 = "ibt2"
50
51 fieldQm = "qm"
52 fieldDebug = "debug"
53
54
55
56
57 )
58
59 var xfss Stats
60
61 s := bufio.NewScanner(r)
62 for s.Scan() {
63
64
65
66 ss := strings.Fields(string(s.Bytes()))
67 if len(ss) < 2 {
68 continue
69 }
70 label := ss[0]
71
72
73 if label == fieldXpc {
74 us, err := util.ParseUint64s(ss[1:])
75 if err != nil {
76 return nil, err
77 }
78
79 xfss.ExtendedPrecision, err = extendedPrecisionStats(us)
80 if err != nil {
81 return nil, err
82 }
83
84 continue
85 }
86
87
88 us, err := util.ParseUint32s(ss[1:])
89 if err != nil {
90 return nil, err
91 }
92
93 switch label {
94 case fieldExtentAlloc:
95 xfss.ExtentAllocation, err = extentAllocationStats(us)
96 case fieldAbt:
97 xfss.AllocationBTree, err = btreeStats(us)
98 case fieldBlkMap:
99 xfss.BlockMapping, err = blockMappingStats(us)
100 case fieldBmbt:
101 xfss.BlockMapBTree, err = btreeStats(us)
102 case fieldDir:
103 xfss.DirectoryOperation, err = directoryOperationStats(us)
104 case fieldTrans:
105 xfss.Transaction, err = transactionStats(us)
106 case fieldIg:
107 xfss.InodeOperation, err = inodeOperationStats(us)
108 case fieldLog:
109 xfss.LogOperation, err = logOperationStats(us)
110 case fieldRw:
111 xfss.ReadWrite, err = readWriteStats(us)
112 case fieldAttr:
113 xfss.AttributeOperation, err = attributeOperationStats(us)
114 case fieldIcluster:
115 xfss.InodeClustering, err = inodeClusteringStats(us)
116 case fieldVnodes:
117 xfss.Vnode, err = vnodeStats(us)
118 case fieldBuf:
119 xfss.Buffer, err = bufferStats(us)
120 case fieldPushAil:
121 xfss.PushAil, err = pushAilStats(us)
122 case fieldXstrat:
123 xfss.Xstrat, err = xStratStats(us)
124 case fieldAbtb2:
125 xfss.BtreeAllocBlocks2, err = btreeAllocBlocks2Stats(us)
126 case fieldAbtc2:
127 xfss.BtreeAllocContig2, err = btreeAllocContig2Stats(us)
128 case fieldBmbt2:
129 xfss.BtreeBlockMap2, err = btreeBlockMap2Stats(us)
130 case fieldIbt2:
131 xfss.BtreeInode2, err = btreeInode2Stats(us)
132
133 case fieldQm:
134 xfss.QuotaManager, err = quotaManagerStats(us)
135 case fieldDebug:
136 xfss.Debug, err = debugStats(us)
137 }
138 if err != nil {
139 return nil, err
140 }
141 }
142
143 return &xfss, s.Err()
144 }
145
146
147 func extentAllocationStats(us []uint32) (ExtentAllocationStats, error) {
148 if l := len(us); l != 4 {
149 return ExtentAllocationStats{}, fmt.Errorf("incorrect number of values for XFS extent allocation stats: %d", l)
150 }
151
152 return ExtentAllocationStats{
153 ExtentsAllocated: us[0],
154 BlocksAllocated: us[1],
155 ExtentsFreed: us[2],
156 BlocksFreed: us[3],
157 }, nil
158 }
159
160
161 func btreeStats(us []uint32) (BTreeStats, error) {
162 if l := len(us); l != 4 {
163 return BTreeStats{}, fmt.Errorf("incorrect number of values for XFS btree stats: %d", l)
164 }
165
166 return BTreeStats{
167 Lookups: us[0],
168 Compares: us[1],
169 RecordsInserted: us[2],
170 RecordsDeleted: us[3],
171 }, nil
172 }
173
174
175 func blockMappingStats(us []uint32) (BlockMappingStats, error) {
176 if l := len(us); l != 7 {
177 return BlockMappingStats{}, fmt.Errorf("incorrect number of values for XFS block mapping stats: %d", l)
178 }
179
180 return BlockMappingStats{
181 Reads: us[0],
182 Writes: us[1],
183 Unmaps: us[2],
184 ExtentListInsertions: us[3],
185 ExtentListDeletions: us[4],
186 ExtentListLookups: us[5],
187 ExtentListCompares: us[6],
188 }, nil
189 }
190
191
192 func directoryOperationStats(us []uint32) (DirectoryOperationStats, error) {
193 if l := len(us); l != 4 {
194 return DirectoryOperationStats{}, fmt.Errorf("incorrect number of values for XFS directory operation stats: %d", l)
195 }
196
197 return DirectoryOperationStats{
198 Lookups: us[0],
199 Creates: us[1],
200 Removes: us[2],
201 Getdents: us[3],
202 }, nil
203 }
204
205
206 func transactionStats(us []uint32) (TransactionStats, error) {
207 if l := len(us); l != 3 {
208 return TransactionStats{}, fmt.Errorf("incorrect number of values for XFS transaction stats: %d", l)
209 }
210
211 return TransactionStats{
212 Sync: us[0],
213 Async: us[1],
214 Empty: us[2],
215 }, nil
216 }
217
218
219 func inodeOperationStats(us []uint32) (InodeOperationStats, error) {
220 if l := len(us); l != 7 {
221 return InodeOperationStats{}, fmt.Errorf("incorrect number of values for XFS inode operation stats: %d", l)
222 }
223
224 return InodeOperationStats{
225 Attempts: us[0],
226 Found: us[1],
227 Recycle: us[2],
228 Missed: us[3],
229 Duplicate: us[4],
230 Reclaims: us[5],
231 AttributeChange: us[6],
232 }, nil
233 }
234
235
236 func logOperationStats(us []uint32) (LogOperationStats, error) {
237 if l := len(us); l != 5 {
238 return LogOperationStats{}, fmt.Errorf("incorrect number of values for XFS log operation stats: %d", l)
239 }
240
241 return LogOperationStats{
242 Writes: us[0],
243 Blocks: us[1],
244 NoInternalBuffers: us[2],
245 Force: us[3],
246 ForceSleep: us[4],
247 }, nil
248 }
249
250
251 func pushAilStats(us []uint32) (PushAilStats, error) {
252 if l := len(us); l != 10 {
253 return PushAilStats{}, fmt.Errorf("incorrect number of values for XFS push ail stats: %d", l)
254 }
255
256 return PushAilStats{
257 TryLogspace: us[0],
258 SleepLogspace: us[1],
259 Pushes: us[2],
260 Success: us[3],
261 PushBuf: us[4],
262 Pinned: us[5],
263 Locked: us[6],
264 Flushing: us[7],
265 Restarts: us[8],
266 Flush: us[9],
267 }, nil
268 }
269
270
271 func xStratStats(us []uint32) (XstratStats, error) {
272 if l := len(us); l != 2 {
273 return XstratStats{}, fmt.Errorf("incorrect number of values for XFS xstrat stats: %d", l)
274 }
275
276 return XstratStats{
277 Quick: us[0],
278 Split: us[1],
279 }, nil
280 }
281
282
283 func readWriteStats(us []uint32) (ReadWriteStats, error) {
284 if l := len(us); l != 2 {
285 return ReadWriteStats{}, fmt.Errorf("incorrect number of values for XFS read write stats: %d", l)
286 }
287
288 return ReadWriteStats{
289 Write: us[0],
290 Read: us[1],
291 }, nil
292 }
293
294
295 func attributeOperationStats(us []uint32) (AttributeOperationStats, error) {
296 if l := len(us); l != 4 {
297 return AttributeOperationStats{}, fmt.Errorf("incorrect number of values for XFS attribute operation stats: %d", l)
298 }
299
300 return AttributeOperationStats{
301 Get: us[0],
302 Set: us[1],
303 Remove: us[2],
304 List: us[3],
305 }, nil
306 }
307
308
309 func inodeClusteringStats(us []uint32) (InodeClusteringStats, error) {
310 if l := len(us); l != 3 {
311 return InodeClusteringStats{}, fmt.Errorf("incorrect number of values for XFS inode clustering stats: %d", l)
312 }
313
314 return InodeClusteringStats{
315 Iflush: us[0],
316 Flush: us[1],
317 FlushInode: us[2],
318 }, nil
319 }
320
321
322 func vnodeStats(us []uint32) (VnodeStats, error) {
323
324
325
326 l := len(us)
327 if l != 7 && l != 8 {
328 return VnodeStats{}, fmt.Errorf("incorrect number of values for XFS vnode stats: %d", l)
329 }
330
331 s := VnodeStats{
332 Active: us[0],
333 Allocate: us[1],
334 Get: us[2],
335 Hold: us[3],
336 Release: us[4],
337 Reclaim: us[5],
338 Remove: us[6],
339 }
340
341
342
343 if l == 7 {
344 return s, nil
345 }
346
347 s.Free = us[7]
348 return s, nil
349 }
350
351
352 func bufferStats(us []uint32) (BufferStats, error) {
353 if l := len(us); l != 9 {
354 return BufferStats{}, fmt.Errorf("incorrect number of values for XFS buffer stats: %d", l)
355 }
356
357 return BufferStats{
358 Get: us[0],
359 Create: us[1],
360 GetLocked: us[2],
361 GetLockedWaited: us[3],
362 BusyLocked: us[4],
363 MissLocked: us[5],
364 PageRetries: us[6],
365 PageFound: us[7],
366 GetRead: us[8],
367 }, nil
368 }
369
370
371 func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) {
372 if l := len(us); l != 3 {
373 return ExtendedPrecisionStats{}, fmt.Errorf("incorrect number of values for XFS extended precision stats: %d", l)
374 }
375
376 return ExtendedPrecisionStats{
377 FlushBytes: us[0],
378 WriteBytes: us[1],
379 ReadBytes: us[2],
380 }, nil
381 }
382
383 func quotaManagerStats(us []uint32) (QuotaManagerStats, error) {
384
385
386
387 l := len(us)
388 if l != 8 && l != 9 {
389 return QuotaManagerStats{}, fmt.Errorf("incorrect number of values for XFS quota stats: %d", l)
390 }
391
392 s := QuotaManagerStats{
393 Reclaims: us[0],
394 ReclaimMisses: us[1],
395 DquoteDups: us[2],
396 CacheMisses: us[3],
397 CacheHits: us[4],
398 Wants: us[5],
399 ShakeReclaims: us[6],
400 InactReclaims: us[7],
401 }
402
403 if l > 8 {
404 s.Unused = us[8]
405 }
406
407 return s, nil
408 }
409
410 func debugStats(us []uint32) (DebugStats, error) {
411 if l := len(us); l != 1 {
412 return DebugStats{}, fmt.Errorf("incorrect number of values for XFS debug stats: %d", l)
413 }
414
415 return DebugStats{
416 Enabled: us[0],
417 }, nil
418 }
419
420
421 func btreeAllocBlocks2Stats(us []uint32) (BtreeAllocBlocks2Stats, error) {
422 if l := len(us); l != 15 {
423 return BtreeAllocBlocks2Stats{}, fmt.Errorf("incorrect number of values for abtb2 stats: %d", 1)
424 }
425
426 return BtreeAllocBlocks2Stats{
427 Lookup: us[0],
428 Compare: us[1],
429 Insrec: us[2],
430 Delrec: us[3],
431 NewRoot: us[4],
432 KillRoot: us[5],
433 Increment: us[6],
434 Decrement: us[7],
435 Lshift: us[8],
436 Rshift: us[9],
437 Split: us[10],
438 Join: us[11],
439 Alloc: us[12],
440 Free: us[13],
441 Moves: us[14],
442 }, nil
443 }
444
445
446 func btreeAllocContig2Stats(us []uint32) (BtreeAllocContig2Stats, error) {
447 if l := len(us); l != 15 {
448 return BtreeAllocContig2Stats{}, fmt.Errorf("incorrect number of values for abtc2 stats: %d", 1)
449 }
450
451 return BtreeAllocContig2Stats{
452 Lookup: us[0],
453 Compare: us[1],
454 Insrec: us[2],
455 Delrec: us[3],
456 NewRoot: us[4],
457 KillRoot: us[5],
458 Increment: us[6],
459 Decrement: us[7],
460 Lshift: us[8],
461 Rshift: us[9],
462 Split: us[10],
463 Join: us[11],
464 Alloc: us[12],
465 Free: us[13],
466 Moves: us[14],
467 }, nil
468 }
469
470
471 func btreeBlockMap2Stats(us []uint32) (BtreeBlockMap2Stats, error) {
472 if l := len(us); l != 15 {
473 return BtreeBlockMap2Stats{}, fmt.Errorf("incorrect number of values for bmbt2 stats: %d", 1)
474 }
475
476 return BtreeBlockMap2Stats{
477 Lookup: us[0],
478 Compare: us[1],
479 Insrec: us[2],
480 Delrec: us[3],
481 NewRoot: us[4],
482 KillRoot: us[5],
483 Increment: us[6],
484 Decrement: us[7],
485 Lshift: us[8],
486 Rshift: us[9],
487 Split: us[10],
488 Join: us[11],
489 Alloc: us[12],
490 Free: us[13],
491 Moves: us[14],
492 }, nil
493 }
494
495
496 func btreeInode2Stats(us []uint32) (BtreeInode2Stats, error) {
497 if l := len(us); l != 15 {
498 return BtreeInode2Stats{}, fmt.Errorf("incorrect number of values for ibt2 stats: %d", 1)
499 }
500
501 return BtreeInode2Stats{
502 Lookup: us[0],
503 Compare: us[1],
504 Insrec: us[2],
505 Delrec: us[3],
506 NewRoot: us[4],
507 KillRoot: us[5],
508 Increment: us[6],
509 Decrement: us[7],
510 Lshift: us[8],
511 Rshift: us[9],
512 Split: us[10],
513 Join: us[11],
514 Alloc: us[12],
515 Free: us[13],
516 Moves: us[14],
517 }, nil
518 }
519
View as plain text