-
Notifications
You must be signed in to change notification settings - Fork 0
/
disk.go
137 lines (130 loc) · 3.34 KB
/
disk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package proc
import (
"bufio"
"errors"
"os"
"strconv"
"strings"
)
// FSTabEntry describes a line from /proc/mounts, which is the fstab format. See 'man fstab' for the meaning
// of these fields.
// The field comments are examples of what might be found there (but see the man page for details).
type FSTabEntry struct {
Spec string // /dev/sda1
File string // /mnt/data
Vfstype string // ext4
Mntops []string // [rw, relatime]
Freq int // 0
Passno int // 0
}
var errMounts = errors.New("goproc: cannot parse /proc/mounts")
// Read mount information from /proc/mounts for the current process.
// BUG(caleb): This doesn't handle spaces in mount points, even though fstab specifies an encoding for them.
func Mounts() ([]*FSTabEntry, error) {
f, err := os.Open("/proc/mounts")
if err != nil {
return nil, err
}
results := []*FSTabEntry{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) != 6 {
return nil, errMounts
}
freq, err := strconv.Atoi(fields[4])
if err != nil {
return nil, err
}
passno, err := strconv.Atoi(fields[5])
if err != nil {
return nil, err
}
results = append(results, &FSTabEntry{
Spec: fields[0],
File: fields[1],
Vfstype: fields[2],
Mntops: strings.Split(fields[3], ","),
Freq: freq,
Passno: passno,
})
}
if err := scanner.Err(); err != nil {
return nil, err
}
return results, nil
}
// IOStatEntry represents a line in /proc/diskstats.
type IOStatEntry struct {
// Partition info
Major int
Minor int
Name string
// The rest of the fields are described in Linux's Documentation/iostats.txt.
ReadsCompleted uint64
ReadsMerged uint64
SectorsRead uint64
ReadMillis uint64
WritesCompleted uint64
WritesMerged uint64
SectorsWritten uint64
WriteMillis uint64
NumInProgressIOs uint64
IOMillis uint64
WeightedIOMillis uint64
}
var errDiskStats = errors.New("goproc: cannot parse /proc/diskstats")
// DiskStats reports disk information from /proc/diskstats.
func DiskStats() ([]*IOStatEntry, error) {
f, err := os.Open("/proc/diskstats")
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(f)
stats := []*IOStatEntry{}
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) != 14 {
return nil, errDiskStats
}
major, err := strconv.Atoi(fields[0])
if err != nil {
return nil, err
}
minor, err := strconv.Atoi(fields[1])
if err != nil {
return nil, err
}
statFields := make([]uint64, len(fields)-3)
for i, field := range fields[3:] {
v, err := strconv.ParseUint(field, 10, 64)
if err != nil {
return nil, err
}
statFields[i] = v
}
entry := &IOStatEntry{
Major: major,
Minor: minor,
Name: fields[2],
ReadsCompleted: statFields[0],
ReadsMerged: statFields[1],
SectorsRead: statFields[2],
ReadMillis: statFields[3],
WritesCompleted: statFields[4],
WritesMerged: statFields[5],
SectorsWritten: statFields[6],
WriteMillis: statFields[7],
NumInProgressIOs: statFields[8],
IOMillis: statFields[9],
WeightedIOMillis: statFields[10],
}
stats = append(stats, entry)
}
if err := scanner.Err(); err != nil {
return nil, err
}
return stats, nil
}