From 1e4cf3f933cfa9885d6729d87d04e04807e29357 Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 11:38:37 +0300 Subject: [PATCH 1/8] bcache: add writeback_rate_debug parsing Signed-off-by: Aleksei Zakharov --- bcache/bcache.go | 20 ++++++++--- bcache/get.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 4 deletions(-) diff --git a/bcache/bcache.go b/bcache/bcache.go index df724edaa..1176a558a 100644 --- a/bcache/bcache.go +++ b/bcache/bcache.go @@ -43,10 +43,11 @@ type BcacheStats struct { // nolint:golint // BdevStats contains statistics for one backing device. type BdevStats struct { - Name string - DirtyData uint64 - FiveMin PeriodStats - Total PeriodStats + Name string + DirtyData uint64 + FiveMin PeriodStats + Total PeriodStats + WritebackRateDebug WritebackRateDebugStats } // CacheStats contains statistics for one cache device. @@ -82,3 +83,14 @@ type PeriodStats struct { CacheMisses uint64 CacheReadaheads uint64 } + +// WritebackRateDebugStats contains bcache writeback statistics. +type WritebackRateDebugStats struct { + Rate uint64 + Dirty uint64 + Target uint64 + Proportional int64 + Integral int64 + Change int64 + NextIO int64 +} diff --git a/bcache/get.go b/bcache/get.go index 67fcf8b14..15a08544b 100644 --- a/bcache/get.go +++ b/bcache/get.go @@ -232,6 +232,95 @@ func parsePriorityStats(line string, ps *PriorityStats) error { return nil } +// ParseWritebackRateDebug parses lines from the writeback_rate_debug file. +func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { + var ( + value uint64 + svalue int64 + err error + ) + switch { + case strings.HasPrefix(line, "rate:"): + fields := strings.Fields(line) + rawValue := fields[len(fields)-1] + valueStr := strings.TrimSuffix(rawValue, "/sec") + value, err = dehumanize([]byte(valueStr)) + if err != nil { + return err + } + wrd.Rate = value + case strings.HasPrefix(line, "dirty:"): + fields := strings.Fields(line) + valueStr := fields[len(fields)-1] + value, err = dehumanize([]byte(valueStr)) + if err != nil { + return err + } + wrd.Dirty = value + case strings.HasPrefix(line, "target:"): + fields := strings.Fields(line) + valueStr := fields[len(fields)-1] + value, err = dehumanize([]byte(valueStr)) + if err != nil { + return err + } + wrd.Target = value + case strings.HasPrefix(line, "proportional:"): + fields := strings.Fields(line) + valueStr := fields[len(fields)-1] + neg := strings.HasPrefix(valueStr,"-") + value, err = dehumanize([]byte(strings.TrimPrefix(valueStr,"-"))) + if err != nil { + return err + } + if neg { + svalue = int64(-value) + } else { + svalue = int64(value) + } + wrd.Proportional = svalue + case strings.HasPrefix(line, "integral:"): + fields := strings.Fields(line) + valueStr := fields[len(fields)-1] + neg := strings.HasPrefix(valueStr,"-") + value, err = dehumanize([]byte(strings.TrimPrefix(valueStr,"-"))) + if err != nil { + return err + } + if neg { + svalue = int64(-value) + } else { + svalue = int64(value) + } + wrd.Integral = svalue + case strings.HasPrefix(line, "change:"): + fields := strings.Fields(line) + rawValue := fields[len(fields)-1] + valueStr := strings.TrimSuffix(rawValue, "/sec") + neg := strings.HasPrefix(valueStr,"-") + value, err = dehumanize([]byte(strings.TrimPrefix(valueStr,"-"))) + if err != nil { + return err + } + if neg { + svalue = int64(-value) + } else { + svalue = int64(value) + } + wrd.Change = svalue + case strings.HasPrefix(line, "next io:"): + fields := strings.Fields(line) + rawValue := fields[len(fields)-1] + valueStr := strings.TrimSuffix(rawValue, "ms") + svalue, err = strconv.ParseInt(valueStr, 10, 64) + if err != nil { + return err + } + wrd.NextIO = svalue + } + return nil +} + func (p *parser) getPriorityStats() PriorityStats { var res PriorityStats From eadda9579949a307971847ae113b5d94efb0a287 Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 11:38:58 +0300 Subject: [PATCH 2/8] bcache: add parseWritebackRateDebug tests Signed-off-by: Aleksei Zakharov --- bcache/get_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/bcache/get_test.go b/bcache/get_test.go index e448797ff..22f562e99 100644 --- a/bcache/get_test.go +++ b/bcache/get_test.go @@ -158,3 +158,61 @@ func TestPriorityStats(t *testing.T) { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.UnusedPercent, got.UnusedPercent) } } + +func TestWritebackRateDebug(t *testing.T) { + var want = WritebackRateDebugStats{ + Rate: 1765376, + Dirty: 21789409280, + Target: 21894266880, + Proportional: -1124, + Integral: -257624, + Change: 2648, + NextIO: -150773, + } + var ( + in string + gotErr error + got WritebackRateDebugStats + ) + in = "rate: 1.7M/sec" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.Rate != want.Rate { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Rate, got.Rate) + } + + in = "dirty: 20.3G" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.Dirty != want.Dirty { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Dirty, got.Dirty) + } + + in = "target: 20.4G" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.Target != want.Target { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Target, got.Target) + } + + in = "proportional: -1.1k" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.Proportional != want.Proportional { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Proportional, got.Proportional) + } + + in = "integral: -251.6k" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.Integral != want.Integral { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Integral, got.Integral) + } + + in = "change: 2.6k/sec" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.Change != want.Change { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Change, got.Change) + } + + in = "next io: -150773ms" + gotErr = parseWritebackRateDebug(in, &got) + if gotErr != nil || got.NextIO != want.NextIO { + t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.NextIO, got.NextIO) + } +} From b7505d636cabea56322ffdcdb991d4dbc581ac4a Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 13:42:08 +0300 Subject: [PATCH 3/8] bcache: add writeback_rate_debug stats collecting Signed-off-by: Aleksei Zakharov --- bcache/get.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/bcache/get.go b/bcache/get.go index 15a08544b..40fb98fc5 100644 --- a/bcache/get.go +++ b/bcache/get.go @@ -352,6 +352,35 @@ func (p *parser) getPriorityStats() PriorityStats { return res } +func (p *parser) getWritebackRateDebug() WritebackRateDebugStats { + var res WritebackRateDebugStats + + if p.err != nil { + return res + } + path := path.Join(p.currentDir, "writeback_rate_debug") + file, err := os.Open(path) + if err != nil { + p.err = fmt.Errorf("failed to read: %s", path) + return res + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + err = parseWritebackRateDebug(scanner.Text(), &res) + if err != nil { + p.err = fmt.Errorf("failed to parse: %s (%s)", path, err) + return res + } + } + if err := scanner.Err(); err != nil { + p.err = fmt.Errorf("failed to parse: %s (%s)", path, err) + return res + } + return res +} + // GetStats collects from sysfs files data tied to one bcache ID. func GetStats(uuidPath string, priorityStats bool) (*Stats, error) { var bs Stats @@ -428,6 +457,9 @@ func GetStats(uuidPath string, priorityStats bool) (*Stats, error) { par.setSubDir(bds.Name) bds.DirtyData = par.readValue("dirty_data") + wrd := par.getWritebackRateDebug() + bds.WritebackRateDebug = wrd + // dir //stats_five_minute par.setSubDir(bds.Name, "stats_five_minute") bds.FiveMin.Bypassed = par.readValue("bypassed") From 3b837b8191e103e9cbb1b9640133b67074ddd7a5 Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 13:42:47 +0300 Subject: [PATCH 4/8] bcache: gofmt Signed-off-by: Aleksei Zakharov --- bcache/get.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bcache/get.go b/bcache/get.go index 40fb98fc5..95774efef 100644 --- a/bcache/get.go +++ b/bcache/get.go @@ -235,9 +235,9 @@ func parsePriorityStats(line string, ps *PriorityStats) error { // ParseWritebackRateDebug parses lines from the writeback_rate_debug file. func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { var ( - value uint64 + value uint64 svalue int64 - err error + err error ) switch { case strings.HasPrefix(line, "rate:"): @@ -268,8 +268,8 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { case strings.HasPrefix(line, "proportional:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - neg := strings.HasPrefix(valueStr,"-") - value, err = dehumanize([]byte(strings.TrimPrefix(valueStr,"-"))) + neg := strings.HasPrefix(valueStr, "-") + value, err = dehumanize([]byte(strings.TrimPrefix(valueStr, "-"))) if err != nil { return err } @@ -282,8 +282,8 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { case strings.HasPrefix(line, "integral:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - neg := strings.HasPrefix(valueStr,"-") - value, err = dehumanize([]byte(strings.TrimPrefix(valueStr,"-"))) + neg := strings.HasPrefix(valueStr, "-") + value, err = dehumanize([]byte(strings.TrimPrefix(valueStr, "-"))) if err != nil { return err } @@ -297,8 +297,8 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "/sec") - neg := strings.HasPrefix(valueStr,"-") - value, err = dehumanize([]byte(strings.TrimPrefix(valueStr,"-"))) + neg := strings.HasPrefix(valueStr, "-") + value, err = dehumanize([]byte(strings.TrimPrefix(valueStr, "-"))) if err != nil { return err } From 677a61a50f9aad9b8528f370542bf95ad0a1cee0 Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 16:24:10 +0300 Subject: [PATCH 5/8] fixtures: add wrteback_rate_debug Signed-off-by: Aleksei Zakharov --- fixtures.ttar | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fixtures.ttar b/fixtures.ttar index 45a732155..0cd783632 100644 --- a/fixtures.ttar +++ b/fixtures.ttar @@ -4115,6 +4115,17 @@ Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/writeback_rate_debug +Lines: 7 +rate: 1.1M/sec +dirty: 20.4G +target: 20.4G +proportional: 427.5k +integral: 790.0k +change: 321.5k/sec +next io: 17ms +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 86510a01c50eca4b07619b7d37b0c14cc21023ae Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 17:14:22 +0300 Subject: [PATCH 6/8] bcache: add dehumanizeSigned to dehumanize signed Signed-off-by: Aleksei Zakharov --- bcache/get.go | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/bcache/get.go b/bcache/get.go index 95774efef..3f10c106b 100644 --- a/bcache/get.go +++ b/bcache/get.go @@ -174,6 +174,18 @@ func dehumanize(hbytes []byte) (uint64, error) { return res, nil } +func dehumanizeSigned(str string) (int64, error) { + value, err := dehumanize([]byte(strings.TrimPrefix(str, "-"))) + if err != nil { + return 0, err + } + if strings.HasPrefix(str, "-") { + return int64(-value), nil + } else { + return int64(value), nil + } +} + type parser struct { uuidPath string subDir string @@ -268,45 +280,27 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { case strings.HasPrefix(line, "proportional:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - neg := strings.HasPrefix(valueStr, "-") - value, err = dehumanize([]byte(strings.TrimPrefix(valueStr, "-"))) + svalue, err = dehumanizeSigned(valueStr) if err != nil { return err } - if neg { - svalue = int64(-value) - } else { - svalue = int64(value) - } wrd.Proportional = svalue case strings.HasPrefix(line, "integral:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - neg := strings.HasPrefix(valueStr, "-") - value, err = dehumanize([]byte(strings.TrimPrefix(valueStr, "-"))) + svalue, err = dehumanizeSigned(valueStr) if err != nil { return err } - if neg { - svalue = int64(-value) - } else { - svalue = int64(value) - } wrd.Integral = svalue case strings.HasPrefix(line, "change:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "/sec") - neg := strings.HasPrefix(valueStr, "-") - value, err = dehumanize([]byte(strings.TrimPrefix(valueStr, "-"))) + svalue, err = dehumanizeSigned(valueStr) if err != nil { return err } - if neg { - svalue = int64(-value) - } else { - svalue = int64(value) - } wrd.Change = svalue case strings.HasPrefix(line, "next io:"): fields := strings.Fields(line) From 68ac0f37d2519d1999680be7b709f5a73723d2fd Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 17:16:32 +0300 Subject: [PATCH 7/8] bcache: don't predefine vars Signed-off-by: Aleksei Zakharov --- bcache/get.go | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/bcache/get.go b/bcache/get.go index 3f10c106b..69d448d60 100644 --- a/bcache/get.go +++ b/bcache/get.go @@ -246,17 +246,12 @@ func parsePriorityStats(line string, ps *PriorityStats) error { // ParseWritebackRateDebug parses lines from the writeback_rate_debug file. func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { - var ( - value uint64 - svalue int64 - err error - ) switch { case strings.HasPrefix(line, "rate:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "/sec") - value, err = dehumanize([]byte(valueStr)) + value, err := dehumanize([]byte(valueStr)) if err != nil { return err } @@ -264,7 +259,7 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { case strings.HasPrefix(line, "dirty:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - value, err = dehumanize([]byte(valueStr)) + value, err := dehumanize([]byte(valueStr)) if err != nil { return err } @@ -272,7 +267,7 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { case strings.HasPrefix(line, "target:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - value, err = dehumanize([]byte(valueStr)) + value, err := dehumanize([]byte(valueStr)) if err != nil { return err } @@ -280,37 +275,37 @@ func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { case strings.HasPrefix(line, "proportional:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - svalue, err = dehumanizeSigned(valueStr) + value, err := dehumanizeSigned(valueStr) if err != nil { return err } - wrd.Proportional = svalue + wrd.Proportional = value case strings.HasPrefix(line, "integral:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] - svalue, err = dehumanizeSigned(valueStr) + value, err := dehumanizeSigned(valueStr) if err != nil { return err } - wrd.Integral = svalue + wrd.Integral = value case strings.HasPrefix(line, "change:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "/sec") - svalue, err = dehumanizeSigned(valueStr) + value, err := dehumanizeSigned(valueStr) if err != nil { return err } - wrd.Change = svalue + wrd.Change = value case strings.HasPrefix(line, "next io:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "ms") - svalue, err = strconv.ParseInt(valueStr, 10, 64) + value, err := strconv.ParseInt(valueStr, 10, 64) if err != nil { return err } - wrd.NextIO = svalue + wrd.NextIO = value } return nil } From 39fb8b8c053093cd0e351753d80fd9f490e56919 Mon Sep 17 00:00:00 2001 From: Aleksei Zakharov Date: Tue, 31 Mar 2020 18:12:15 +0300 Subject: [PATCH 8/8] bcache: golint fix Signed-off-by: Aleksei Zakharov --- bcache/get.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bcache/get.go b/bcache/get.go index 69d448d60..c4747ea53 100644 --- a/bcache/get.go +++ b/bcache/get.go @@ -181,9 +181,8 @@ func dehumanizeSigned(str string) (int64, error) { } if strings.HasPrefix(str, "-") { return int64(-value), nil - } else { - return int64(value), nil } + return int64(value), nil } type parser struct {