Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add flush request and time spend flushing diskstats for kernel 5.5+ #289

Merged
merged 2 commits into from
May 12, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions blockdevice/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,26 @@ type IOStats struct {
DiscardSectors uint64
// DiscardTicks is the total number of milliseconds spent by all discards.
DiscardTicks uint64
// FlushRequestsCompleted is the total number of flush request completed successfully.
FlushRequestsCompleted uint64
// TimeSpentFlushing is the total number of milliseconds spent flushing.
TimeSpentFlushing uint64
}

// Diskstats combines the device Info and IOStats
type Diskstats struct {
Info
IOStats
// IoStatsCount contains the number of io stats read. For kernel versions
// 4.18+, there should be 18 fields read. For earlier kernel versions this
// IoStatsCount contains the number of io stats read. For kernel versions 5.5+,
// there should be 20 fields read. For kernel versions 4.18+,
// there should be 18 fields read. For earlier kernel versions this
// will be 14 because the discard values are not available.
IoStatsCount int
}

const (
procDiskstatsPath = "diskstats"
procDiskstatsFormat = "%d %d %s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
procDiskstatsFormat = "%d %d %s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
sysBlockPath = "block"
sysBlockStatFormat = "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
)
Expand Down Expand Up @@ -153,13 +158,15 @@ func (fs FS) ProcDiskstats() ([]Diskstats, error) {
&d.DiscardMerges,
&d.DiscardSectors,
&d.DiscardTicks,
&d.FlushRequestsCompleted,
&d.TimeSpentFlushing,
)
// The io.EOF error can be safely ignored because it just means we read fewer than
// the full 18 fields.
// the full 20 fields.
if err != nil && err != io.EOF {
return diskstats, err
}
if d.IoStatsCount == 14 || d.IoStatsCount == 18 {
if d.IoStatsCount == 14 || d.IoStatsCount == 18 || d.IoStatsCount == 20 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this condition. I'd rather check if it's at least 14 or just get rid of it altogether.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pgier @SuperQ thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think that would be better assuming that sscanf doesn't fail on more than 20 fields.

diskstats = append(diskstats, *d)
}
}
Expand Down
11 changes: 10 additions & 1 deletion blockdevice/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestDiskstats(t *testing.T) {
if err != nil {
t.Fatal(err)
}
expectedNumOfDevices := 49
expectedNumOfDevices := 52
if len(diskstats) != expectedNumOfDevices {
t.Errorf(failMsgFormat, "Incorrect number of devices", expectedNumOfDevices, len(diskstats))
}
Expand All @@ -51,6 +51,15 @@ func TestDiskstats(t *testing.T) {
if diskstats[48].IoStatsCount != 18 {
t.Errorf(failMsgFormat, "Incorrect number of stats read", 18, diskstats[48].IoStatsCount)
}
if diskstats[49].IoStatsCount != 20 {
t.Errorf(failMsgFormat, "Incorrect number of stats read", 20, diskstats[50].IoStatsCount)
}
if diskstats[49].FlushRequestsCompleted != 127 {
t.Errorf(failMsgFormat, "Incorrect number of flash requests completed", 127, diskstats[50].FlushRequestsCompleted)
}
if diskstats[49].TimeSpentFlushing != 182 {
t.Errorf(failMsgFormat, "Incorrect time spend flushing", 182, diskstats[50].TimeSpentFlushing)
}
}

func TestBlockDevice(t *testing.T) {
Expand Down
5 changes: 4 additions & 1 deletion fixtures.ttar
Original file line number Diff line number Diff line change
Expand Up @@ -1841,7 +1841,7 @@ max keysize : 32
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/diskstats
Lines: 49
Lines: 52
1 0 ram0 0 0 0 0 0 0 0 0 0 0 0
1 1 ram1 0 0 0 0 0 0 0 0 0 0 0
1 2 ram2 0 0 0 0 0 0 0 0 0 0 0
Expand Down Expand Up @@ -1891,6 +1891,9 @@ Lines: 49
8 0 sdb 326552 841 9657779 84 41822 2895 1972905 5007 0 60730 67070 68851 0 1925173784 11130
8 1 sdb1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0
8 2 sdb2 326310 838 9622281 67 40726 2872 1972799 4924 0 58250 64567 68851 0 1925173784 11130
8 0 sdc 14202 71 579164 21861 2995 1589 180500 40875 0 11628 55200 0 0 0 0 127 182
8 1 sdc1 1027 0 13795 5021 2 0 4096 3 0 690 4579 0 0 0 0 0 0
8 2 sdc2 13126 71 561749 16802 2830 1589 176404 40620 0 10931 50449 0 0 0 0 0 0
Mode: 664
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/proc/fs
Expand Down