@@ -3,12 +3,12 @@ package cgroups
33import (
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
317304func major (devNumber uint64 ) uint64 {
0 commit comments