Skip to content

Commit

Permalink
fs: get inodes via pure go instead of find
Browse files Browse the repository at this point in the history
This also makes the count more accurate since hardlinks no longer
double-count.
  • Loading branch information
euank committed Jan 16, 2017
1 parent 1fa56cb commit 1d32c47
Showing 1 changed file with 15 additions and 26 deletions.
41 changes: 15 additions & 26 deletions fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package fs

import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -474,24 +473,22 @@ func (self *RealFsInfo) GetDirInodeUsage(dir string, timeout time.Duration) (uin
if dir == "" {
return 0, fmt.Errorf("invalid directory")
}
var counter byteCounter
var stderr bytes.Buffer
claimToken()
defer releaseToken()
findCmd := exec.Command("find", dir, "-xdev", "-printf", ".")
findCmd.Stdout, findCmd.Stderr = &counter, &stderr
if err := findCmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr: %v", findCmd.Args, err, stderr.String())
}
timer := time.AfterFunc(timeout, func() {
glog.Infof("killing cmd %v due to timeout(%s)", findCmd.Args, timeout.String())
findCmd.Process.Kill()

inodes := map[uint64]struct{}{}

err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("unable to count inodes for part of dir %s: %s", dir, err)
}
s, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return fmt.Errorf("unsupported fileinfo; could not convert to stat_t")
}
inodes[s.Ino] = struct{}{}
return nil
})
if err := findCmd.Wait(); err != nil {
return 0, fmt.Errorf("cmd %v failed. stderr: %s; err: %v", findCmd.Args, stderr.String(), err)
}
timer.Stop()
return counter.bytesWritten, nil

return uint64(len(inodes)), err
}

func getVfsStats(path string) (total uint64, free uint64, avail uint64, inodes uint64, inodesFree uint64, err error) {
Expand Down Expand Up @@ -603,11 +600,3 @@ func getZfstats(poolName string) (uint64, uint64, uint64, error) {

return total, dataset.Avail, dataset.Avail, nil
}

// Simple io.Writer implementation that counts how many bytes were written.
type byteCounter struct{ bytesWritten uint64 }

func (b *byteCounter) Write(p []byte) (int, error) {
b.bytesWritten += uint64(len(p))
return len(p), nil
}

0 comments on commit 1d32c47

Please sign in to comment.