Skip to content

Commit

Permalink
feat: Add /sys/fs/btrfs/<FSID>/commit_stats statistics (#580)
Browse files Browse the repository at this point in the history
* Add commit_stats statistics

---------

Signed-off-by: dongjiang1989 <dongjiang1989@126.com>
Co-authored-by: Ben Kochie <superq@gmail.com>
  • Loading branch information
dongjiang1989 and SuperQ authored Feb 15, 2024
1 parent 51a293e commit f5f033b
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 14 deletions.
10 changes: 10 additions & 0 deletions btrfs/btrfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Stats struct {
NodeSize uint64
QuotaOverride uint64
SectorSize uint64
CommitStats CommitStats
}

// Allocation contains allocation statistics for data, metadata and system data.
Expand Down Expand Up @@ -65,3 +66,12 @@ type LayoutUsage struct {
type Device struct {
Size uint64
}

// Number of commits and various time related statistics.
// See Linux fs/btrfs/sysfs.c with 6.x version.
type CommitStats struct {
Commits uint64
LastCommitMs uint64
MaxCommitMs uint64
TotalCommitMs uint64
}
58 changes: 58 additions & 0 deletions btrfs/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
package btrfs

import (
"bufio"
"fmt"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -245,6 +247,62 @@ func (r *reader) readFilesystemStats() (s *Stats) {
Metadata: r.readAllocationStats("allocation/metadata"),
System: r.readAllocationStats("allocation/system"),
},

// Read commit stats data
CommitStats: r.readCommitStats("commit_stats"),
}
return
}

// readCommitStats returns the commit_stats information for commit stats metrics.
func (r *reader) readCommitStats(p string) CommitStats {
stats := CommitStats{}

f, err := os.Open(path.Join(r.path, p))
if err != nil {
// if commit_stats not found. maybe btrfs version < 6.0
if !os.IsNotExist(err) {
r.err = err
}
return stats
}
defer f.Close()

scanner := bufio.NewScanner(f)

for scanner.Scan() {
line := scanner.Text()
parts := strings.Fields(scanner.Text())
// require <key> <value>
if len(parts) != 2 {
r.err = fmt.Errorf("invalid commit_stats line %q", line)
return stats
}

value, err := strconv.ParseUint(parts[1], 10, 64)
if err != nil {
r.err = fmt.Errorf("error parsing commit_stats line: %w", err)
return stats
}

switch metricName := parts[0]; metricName {
case "commits":
stats.Commits = value
case "last_commit_ms":
stats.LastCommitMs = value
case "max_commit_ms":
stats.MaxCommitMs = value
case "total_commit_ms":
stats.TotalCommitMs = value
default:
continue
}
}

if err := scanner.Err(); err != nil {
r.err = fmt.Errorf("error scanning commit_stats file: %w", err)
return stats
}

return stats
}
54 changes: 40 additions & 14 deletions btrfs/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type testVector struct {
uuid, label string
devices, features int
data, meta, system alloc
commitstats commit
}

type alloc struct {
Expand All @@ -27,6 +28,13 @@ type alloc struct {
ratio float64
}

type commit struct {
commits uint64
lastCommitMs uint64
maxCommitMs uint64
totalCommitMs uint64
}

func TestFSBtrfsStats(t *testing.T) {
btrfs, err := NewFS("testdata/fixtures/sys")
if err != nil {
Expand All @@ -39,22 +47,24 @@ func TestFSBtrfsStats(t *testing.T) {

tests := []testVector{
{
uuid: "0abb23a9-579b-43e6-ad30-227ef47fcb9d",
label: "fixture",
devices: 2,
features: 4,
data: alloc{"raid0", 2147483648, 1},
meta: alloc{"raid1", 1073741824, 2},
system: alloc{"raid1", 8388608, 2},
uuid: "0abb23a9-579b-43e6-ad30-227ef47fcb9d",
label: "fixture",
devices: 2,
features: 4,
data: alloc{"raid0", 2147483648, 1},
meta: alloc{"raid1", 1073741824, 2},
system: alloc{"raid1", 8388608, 2},
commitstats: commit{258051, 1000, 51462, 47836090},
},
{
uuid: "7f07c59f-6136-449c-ab87-e1cf2328731b",
label: "",
devices: 4,
features: 5,
data: alloc{"raid5", 644087808, 4. / 3.},
meta: alloc{"raid6", 429391872, 4. / 2.},
system: alloc{"raid6", 16777216, 4. / 2.},
uuid: "7f07c59f-6136-449c-ab87-e1cf2328731b",
label: "",
devices: 4,
features: 5,
data: alloc{"raid5", 644087808, 4. / 3.},
meta: alloc{"raid6", 429391872, 4. / 2.},
system: alloc{"raid6", 16777216, 4. / 2.},
commitstats: commit{0, 0, 0, 0},
},
}

Expand Down Expand Up @@ -98,5 +108,21 @@ func TestFSBtrfsStats(t *testing.T) {
if want, got := tt.system.ratio, stats[i].Allocation.System.Layouts[tt.system.layout].Ratio; want != got {
t.Errorf("fs %q unexpected system ratio:\nwant: %f\nhave: %f", tt.uuid, want, got)
}

if want, got := tt.commitstats.commits, stats[i].CommitStats.Commits; want != got {
t.Errorf("fs %q unexpected commit stats commits:\nwant: %d\nhave: %d", tt.uuid, want, got)
}

if want, got := tt.commitstats.lastCommitMs, stats[i].CommitStats.LastCommitMs; want != got {
t.Errorf("fs %q unexpected commit stats last_commit_ms:\nwant: %d\nhave: %d", tt.uuid, want, got)
}

if want, got := tt.commitstats.maxCommitMs, stats[i].CommitStats.MaxCommitMs; want != got {
t.Errorf("fs %q unexpected commit stats max_commit_ms:\nwant: %d\nhave: %d", tt.uuid, want, got)
}

if want, got := tt.commitstats.totalCommitMs, stats[i].CommitStats.TotalCommitMs; want != got {
t.Errorf("fs %q unexpected commit stats total_commit_ms:\nwant: %d\nhave: %d", tt.uuid, want, got)
}
}
}
8 changes: 8 additions & 0 deletions testdata/fixtures.ttar
Original file line number Diff line number Diff line change
Expand Up @@ -14230,6 +14230,14 @@ Lines: 1
4096
Mode: 444
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/commit_stats
Lines: 4
commits 258051
last_commit_ms 1000
max_commit_ms 51462
total_commit_ms 47836090EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down

0 comments on commit f5f033b

Please sign in to comment.