Skip to content

Commit 0f5e4f3

Browse files
authored
mountstats: handle extended per-op stats (#276)
Linux 5.3 added a field to the per-operator NFS mount stats. This change reads the extra field when it exists, and ignores any additional fields which may be added in the future. Signed-off-by: Paul Gier <[email protected]>
1 parent 7e52c11 commit 0f5e4f3

File tree

2 files changed

+102
-6
lines changed

2 files changed

+102
-6
lines changed

mountstats.go

+14-6
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ type NFSOperationStats struct {
186186
CumulativeTotalResponseMilliseconds uint64
187187
// Duration from when a request was enqueued to when it was completely handled.
188188
CumulativeTotalRequestMilliseconds uint64
189+
// The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions.
190+
Errors uint64
189191
}
190192

191193
// A NFSTransportStats contains statistics for the NFS mount RPC requests and
@@ -494,8 +496,8 @@ func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) {
494496
// line is reached.
495497
func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
496498
const (
497-
// Number of expected fields in each per-operation statistics set
498-
numFields = 9
499+
// Minimum number of expected fields in each per-operation statistics set
500+
minFields = 9
499501
)
500502

501503
var ops []NFSOperationStats
@@ -508,12 +510,12 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
508510
break
509511
}
510512

511-
if len(ss) != numFields {
513+
if len(ss) < minFields {
512514
return nil, fmt.Errorf("invalid NFS per-operations stats: %v", ss)
513515
}
514516

515517
// Skip string operation name for integers
516-
ns := make([]uint64, 0, numFields-1)
518+
ns := make([]uint64, 0, minFields-1)
517519
for _, st := range ss[1:] {
518520
n, err := strconv.ParseUint(st, 10, 64)
519521
if err != nil {
@@ -523,7 +525,7 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
523525
ns = append(ns, n)
524526
}
525527

526-
ops = append(ops, NFSOperationStats{
528+
opStats := NFSOperationStats{
527529
Operation: strings.TrimSuffix(ss[0], ":"),
528530
Requests: ns[0],
529531
Transmissions: ns[1],
@@ -533,7 +535,13 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
533535
CumulativeQueueMilliseconds: ns[5],
534536
CumulativeTotalResponseMilliseconds: ns[6],
535537
CumulativeTotalRequestMilliseconds: ns[7],
536-
})
538+
}
539+
540+
if len(ns) > 8 {
541+
opStats.Errors = ns[8]
542+
}
543+
544+
ops = append(ops, opStats)
537545
}
538546

539547
return ops, s.Err()

mountstats_test.go

+88
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,91 @@ func mountsStr(mounts []*Mount) string {
409409

410410
return out
411411
}
412+
413+
func TestMountStatsExtendedOperationStats(t *testing.T) {
414+
r := strings.NewReader(extendedOpsExampleMountstats)
415+
_, err := parseMountStats(r)
416+
if err != nil {
417+
t.Errorf("failed to parse mount stats with extended per-op statistics: %v", err)
418+
}
419+
}
420+
421+
const (
422+
extendedOpsExampleMountstats = `
423+
device fs.example.com:/volume4/apps/home-automation/node-red-data mounted on /var/lib/kubelet/pods/1c2215a7-0d92-4df5-83ce-a807bcc2f8c8/volumes/kubernetes.io~nfs/home-automation--node-red-data--pv0001 with fstype nfs4 statvers=1.1
424+
opts: rw,vers=4.1,rsize=131072,wsize=131072,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.191,local_lock=none
425+
age: 83520
426+
impl_id: name='',domain='',date='0,0'
427+
caps: caps=0x3fff7,wtmult=512,dtsize=32768,bsize=0,namlen=255
428+
nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x800,acl=0x0,sessions,pnfs=not configured,lease_time=90,lease_expired=0
429+
sec: flavor=1,pseudoflavor=1
430+
events: 52472 472680 16671 57552 2104 9565 749555 9568641 168 24103 1 267134 3350 20097 116581 18214 43757 111141 0 28 9563845 34 0 0 0 0 0
431+
bytes: 2021340783 39056395530 0 0 1788561151 39087991255 442605 9557343
432+
RPC iostats version: 1.1 p/v: 100003/4 (nfs)
433+
xprt: tcp 940 0 2 0 1 938505 938504 0 12756069 0 32 254729 10823602
434+
per-op statistics
435+
NULL: 1 1 0 44 24 0 0 0 0
436+
READ: 34096 34096 0 7103096 1792122744 2272 464840 467945 0
437+
WRITE: 322308 322308 0 39161277084 56725504 401718334 10139998 411864389 0
438+
COMMIT: 12541 12541 0 2709896 1304264 342 7179 7819 0
439+
OPEN: 12637 12637 0 3923256 4659940 871 57185 58251 394
440+
OPEN_CONFIRM: 0 0 0 0 0 0 0 0 0
441+
OPEN_NOATTR: 98741 98741 0 25656212 31630800 3366 77710 82693 0
442+
OPEN_DOWNGRADE: 0 0 0 0 0 0 0 0 0
443+
CLOSE: 87075 87075 0 18778608 15308496 2026 49131 52399 116
444+
SETATTR: 24576 24576 0 5825876 6522260 643 34384 35650 0
445+
FSINFO: 1 1 0 168 152 0 0 0 0
446+
RENEW: 0 0 0 0 0 0 0 0 0
447+
SETCLIENTID: 0 0 0 0 0 0 0 0 0
448+
SETCLIENTID_CONFIRM: 0 0 0 0 0 0 0 0 0
449+
LOCK: 22512 22512 0 5417628 2521312 1088 17407 18794 2
450+
LOCKT: 0 0 0 0 0 0 0 0 0
451+
LOCKU: 21247 21247 0 4589352 2379664 315 8409 9003 0
452+
ACCESS: 1466 1466 0 298160 246288 22 1394 1492 0
453+
GETATTR: 52480 52480 0 10015464 12694076 2930 30069 34502 0
454+
LOOKUP: 11727 11727 0 2518200 2886376 272 16935 17662 3546
455+
LOOKUP_ROOT: 0 0 0 0 0 0 0 0 0
456+
REMOVE: 833 833 0 172236 95268 15 4566 4617 68
457+
RENAME: 11431 11431 0 3150708 1737512 211 52649 53091 0
458+
LINK: 1 1 0 288 292 0 0 0 0
459+
SYMLINK: 0 0 0 0 0 0 0 0 0
460+
CREATE: 77 77 0 18292 23496 0 363 371 11
461+
PATHCONF: 1 1 0 164 116 0 0 0 0
462+
STATFS: 7420 7420 0 1394960 1187200 144 4672 4975 0
463+
READLINK: 4 4 0 704 488 0 1 1 0
464+
READDIR: 1353 1353 0 304024 2902928 11 4326 4411 0
465+
SERVER_CAPS: 9 9 0 1548 1476 0 3 3 0
466+
DELEGRETURN: 232 232 0 48896 37120 811 300 1115 0
467+
GETACL: 0 0 0 0 0 0 0 0 0
468+
SETACL: 0 0 0 0 0 0 0 0 0
469+
FS_LOCATIONS: 0 0 0 0 0 0 0 0 0
470+
RELEASE_LOCKOWNER: 0 0 0 0 0 0 0 0 0
471+
SECINFO: 0 0 0 0 0 0 0 0 0
472+
FSID_PRESENT: 0 0 0 0 0 0 0 0 0
473+
EXCHANGE_ID: 2 2 0 464 200 0 0 0 0
474+
CREATE_SESSION: 1 1 0 192 124 0 0 0 0
475+
DESTROY_SESSION: 0 0 0 0 0 0 0 0 0
476+
SEQUENCE: 0 0 0 0 0 0 0 0 0
477+
GET_LEASE_TIME: 0 0 0 0 0 0 0 0 0
478+
RECLAIM_COMPLETE: 1 1 0 124 88 0 81 81 0
479+
LAYOUTGET: 0 0 0 0 0 0 0 0 0
480+
GETDEVICEINFO: 0 0 0 0 0 0 0 0 0
481+
LAYOUTCOMMIT: 0 0 0 0 0 0 0 0 0
482+
LAYOUTRETURN: 0 0 0 0 0 0 0 0 0
483+
SECINFO_NO_NAME: 0 0 0 0 0 0 0 0 0
484+
TEST_STATEID: 0 0 0 0 0 0 0 0 0
485+
FREE_STATEID: 10413 10413 0 1416168 916344 147 3518 3871 10413
486+
GETDEVICELIST: 0 0 0 0 0 0 0 0 0
487+
BIND_CONN_TO_SESSION: 0 0 0 0 0 0 0 0 0
488+
DESTROY_CLIENTID: 0 0 0 0 0 0 0 0 0
489+
SEEK: 0 0 0 0 0 0 0 0 0
490+
ALLOCATE: 0 0 0 0 0 0 0 0 0
491+
DEALLOCATE: 0 0 0 0 0 0 0 0 0
492+
LAYOUTSTATS: 0 0 0 0 0 0 0 0 0
493+
CLONE: 0 0 0 0 0 0 0 0 0
494+
COPY: 0 0 0 0 0 0 0 0 0
495+
OFFLOAD_CANCEL: 0 0 0 0 0 0 0 0 0
496+
LOOKUPP: 0 0 0 0 0 0 0 0 0
497+
LAYOUTERROR: 0 0 0 0 0 0 0 0 0
498+
`
499+
)

0 commit comments

Comments
 (0)