Skip to content

Commit 77e6285

Browse files
committed
Use /proc/diskstats to get device names
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
1 parent c2fe3b0 commit 77e6285

File tree

2 files changed

+64
-42
lines changed

2 files changed

+64
-42
lines changed

blkio.go

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package cgroups
33
import (
44
"bufio"
55
"fmt"
6+
"io"
67
"io/ioutil"
78
"os"
89
"path/filepath"
910
"strconv"
1011
"strings"
11-
"syscall"
1212

1313
specs "github.com/opencontainers/runtime-spec/specs-go"
1414
)
@@ -105,8 +105,13 @@ func (b *blkioController) Stat(path string, stats *Metrics) error {
105105
},
106106
)
107107
}
108+
f, err := os.Open("/proc/diskstats")
109+
if err != nil {
110+
return err
111+
}
112+
defer f.Close()
108113

109-
devices, err := getDevices("/dev")
114+
devices, err := getDevices(f)
110115
if err != nil {
111116
return err
112117
}
@@ -268,50 +273,32 @@ type deviceKey struct {
268273
// getDevices makes a best effort attempt to read all the devices into a map
269274
// keyed by major and minor number. Since devices may be mapped multiple times,
270275
// we err on taking the first occurrence.
271-
func getDevices(path string) (map[deviceKey]string, error) {
272-
// TODO(stevvooe): We are ignoring lots of errors. It might be kind of
273-
// challenging to debug this if we aren't mapping devices correctly.
274-
// Consider logging these errors.
275-
devices := map[deviceKey]string{}
276-
if err := filepath.Walk(path, func(p string, fi os.FileInfo, err error) error {
276+
func getDevices(r io.Reader) (map[deviceKey]string, error) {
277+
278+
var (
279+
s = bufio.NewScanner(r)
280+
devices = make(map[deviceKey]string)
281+
)
282+
for s.Scan() {
283+
fields := strings.Fields(s.Text())
284+
major, err := strconv.Atoi(fields[0])
277285
if err != nil {
278-
return err
286+
return nil, err
279287
}
280-
switch {
281-
case fi.IsDir():
282-
switch fi.Name() {
283-
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
284-
return filepath.SkipDir
285-
default:
286-
return nil
287-
}
288-
case fi.Name() == "console":
289-
return nil
290-
default:
291-
if fi.Mode()&os.ModeDevice == 0 {
292-
// skip non-devices
293-
return nil
294-
}
295-
296-
st, ok := fi.Sys().(*syscall.Stat_t)
297-
if !ok {
298-
return fmt.Errorf("%s: unable to convert to system stat", p)
299-
}
300-
301-
key := deviceKey{major(st.Rdev), minor(st.Rdev)}
302-
if _, ok := devices[key]; ok {
303-
return nil // skip it if we have already populated the path.
304-
}
305-
306-
devices[key] = p
288+
minor, err := strconv.Atoi(fields[1])
289+
if err != nil {
290+
return nil, err
307291
}
308-
309-
return nil
310-
}); err != nil {
311-
return nil, err
292+
key := deviceKey{
293+
major: uint64(major),
294+
minor: uint64(minor),
295+
}
296+
if _, ok := devices[key]; ok {
297+
continue
298+
}
299+
devices[key] = filepath.Join("/dev", fields[2])
312300
}
313-
314-
return devices, nil
301+
return devices, s.Err()
315302
}
316303

317304
func major(devNumber uint64) uint64 {

blkio_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cgroups
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
const data = ` 7 0 loop0 0 0 0 0 0 0 0 0 0 0 0
9+
7 1 loop1 0 0 0 0 0 0 0 0 0 0 0
10+
7 2 loop2 0 0 0 0 0 0 0 0 0 0 0
11+
7 3 loop3 0 0 0 0 0 0 0 0 0 0 0
12+
7 4 loop4 0 0 0 0 0 0 0 0 0 0 0
13+
7 5 loop5 0 0 0 0 0 0 0 0 0 0 0
14+
7 6 loop6 0 0 0 0 0 0 0 0 0 0 0
15+
7 7 loop7 0 0 0 0 0 0 0 0 0 0 0
16+
8 0 sda 1892042 187697 63489222 1246284 1389086 2887005 134903104 11390608 1 1068060 12692228
17+
8 1 sda1 1762875 37086 61241570 1200512 1270037 2444415 131214808 11152764 1 882624 12409308
18+
8 2 sda2 2 0 4 0 0 0 0 0 0 0 0
19+
8 5 sda5 129102 150611 2244440 45716 18447 442590 3688296 67268 0 62584 112984`
20+
21+
func TestGetDevices(t *testing.T) {
22+
r := strings.NewReader(data)
23+
devices, err := getDevices(r)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
name, ok := devices[deviceKey{8, 0}]
28+
if !ok {
29+
t.Fatal("no device found for 8,0")
30+
}
31+
const expected = "/dev/sda"
32+
if name != expected {
33+
t.Fatalf("expected device name %q but received %q", expected, name)
34+
}
35+
}

0 commit comments

Comments
 (0)