diff --git a/container/raw/handler.go b/container/raw/handler.go index 836d879a..a3a93b46 100644 --- a/container/raw/handler.go +++ b/container/raw/handler.go @@ -264,6 +264,7 @@ func (self *rawContainerHandler) getFsStats(stats *info.ContainerStats) error { Device: fs.Device, Limit: fs.Capacity, Usage: fs.Capacity - fs.Free, + Available: fs.Available, ReadsCompleted: fs.DiskStats.ReadsCompleted, ReadsMerged: fs.DiskStats.ReadsMerged, SectorsRead: fs.DiskStats.SectorsRead, diff --git a/fs/fs.go b/fs/fs.go index 613ebbcc..13a4475f 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -20,6 +20,7 @@ package fs /* extern int getBytesFree(const char *path, unsigned long long *bytes); extern int getBytesTotal(const char *path, unsigned long long *bytes); + extern int getBytesAvail(const char *path, unsigned long long *bytes); */ import "C" @@ -176,7 +177,7 @@ func (self *RealFsInfo) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, er _, hasMount := mountSet[partition.mountpoint] _, hasDevice := deviceSet[device] if mountSet == nil || (hasMount && !hasDevice) { - total, free, err := getVfsStats(partition.mountpoint) + total, free, avail, err := getVfsStats(partition.mountpoint) if err != nil { glog.Errorf("Statvfs failed. Error: %v", err) } else { @@ -186,7 +187,7 @@ func (self *RealFsInfo) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, er Major: uint(partition.major), Minor: uint(partition.minor), } - fs := Fs{deviceInfo, total, free, diskStatsMap[device]} + fs := Fs{deviceInfo, total, free, avail, diskStatsMap[device]} filesystems = append(filesystems, fs) } } @@ -287,18 +288,22 @@ func (self *RealFsInfo) GetDirUsage(dir string) (uint64, error) { return usageInKb * 1024, nil } -func getVfsStats(path string) (total uint64, free uint64, err error) { +func getVfsStats(path string) (total uint64, free uint64, avail uint64, err error) { _p0, err := syscall.BytePtrFromString(path) if err != nil { - return 0, 0, err + return 0, 0, 0, err } res, err := C.getBytesFree((*C.char)(unsafe.Pointer(_p0)), (*_Ctype_ulonglong)(unsafe.Pointer(&free))) if res != 0 { - return 0, 0, err + return 0, 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 0, 0, 0, err } - return total, free, nil + res, err = C.getBytesAvail((*C.char)(unsafe.Pointer(_p0)), (*_Ctype_ulonglong)(unsafe.Pointer(&avail))) + if res != 0 { + return 0, 0, 0, err + } + return total, free, avail, nil } diff --git a/fs/statvfs.c b/fs/statvfs.c index 6961df4f..3970f385 100644 --- a/fs/statvfs.c +++ b/fs/statvfs.c @@ -21,3 +21,14 @@ int getBytesTotal(const char *path, unsigned long long *bytes) { *bytes = buf.f_frsize * buf.f_blocks; return 0; } + +// Bytes available to non-root. +int getBytesAvail(const char *path, unsigned long long *bytes) { + struct statvfs buf; + int res; + if ((res = statvfs(path, &buf)) && res != 0) { + return -1; + } + *bytes = buf.f_frsize * buf.f_bavail; + return 0; +} diff --git a/fs/types.go b/fs/types.go index 77a46a88..37f0db2a 100644 --- a/fs/types.go +++ b/fs/types.go @@ -24,6 +24,7 @@ type Fs struct { DeviceInfo Capacity uint64 Free uint64 + Available uint64 DiskStats DiskStats } diff --git a/info/v1/container.go b/info/v1/container.go index 26e85e15..0e4b89bb 100644 --- a/info/v1/container.go +++ b/info/v1/container.go @@ -341,6 +341,9 @@ type FsStats struct { // Number of bytes that is consumed by the container on this filesystem. Usage uint64 `json:"usage"` + // Number of bytes available for non-root user. + Available uint64 `json:"available"` + // Number of reads completed // This is the total number of reads completed successfully. ReadsCompleted uint64 `json:"reads_completed"`