cadvisor/fs/fs.go
2014-10-01 00:28:01 +00:00

85 lines
1.9 KiB
Go

// +build linux
//
// Provides Filesystem Stats
package fs
/*
extern int getBytesFree(const char *path, unsigned long long *bytes);
extern int getBytesTotal(const char *path, unsigned long long *bytes);
*/
import "C"
import (
"strings"
"syscall"
"unsafe"
"github.com/docker/docker/pkg/mount"
"github.com/golang/glog"
)
type partition struct {
mountpoint string
major uint32
minor uint32
}
type FsInfoImpl struct {
partitions map[string]partition
}
func NewFsInfo() (FsInfo, error) {
mounts, err := mount.GetMounts()
if err != nil {
return nil, err
}
partitions := make(map[string]partition, 0)
for _, mount := range mounts {
if !strings.HasPrefix(mount.Fstype, "ext") {
continue
}
// Avoid bind mounts.
if _, ok := partitions[mount.Source]; ok {
continue
}
partitions[mount.Source] = partition{mount.Mountpoint, uint32(mount.Major), uint32(mount.Minor)}
}
return &FsInfoImpl{partitions}, nil
}
func (self *FsInfoImpl) GetFsStats() ([]FsStats, error) {
filesystems := make([]FsStats, 0)
for device, partition := range self.partitions {
total, free, err := getVfsStats(partition.mountpoint)
if err != nil {
glog.Errorf("Statvfs failed. Error: %v", err)
} else {
fsStat := FsStats{
Device: device,
Major: uint(partition.major),
Minor: uint(partition.minor),
Capacity: total,
Free: free,
}
filesystems = append(filesystems, fsStat)
}
}
return filesystems, nil
}
func getVfsStats(path string) (total uint64, free uint64, err error) {
_p0, err := syscall.BytePtrFromString(path)
if err != nil {
return 0, 0, err
}
res, err := C.getBytesFree((*C.char)(unsafe.Pointer(_p0)), (*_Ctype_ulonglong)(unsafe.Pointer(&free)))
if res != 0 {
return 0, 0, err
}
res, err = C.getBytesTotal((*C.char)(unsafe.Pointer(_p0)), (*_Ctype_ulonglong)(unsafe.Pointer(&total)))
if res != 0 {
return 0, 0, err
}
return total, free, nil
}