From cccf9d5feca1cc6d6635da6d9ab9913c6bf7e7bf Mon Sep 17 00:00:00 2001 From: derekwaynecarr Date: Tue, 26 Jul 2016 11:15:07 -0400 Subject: [PATCH] Allow clients to know if inodes are supported on a filesystem --- container/raw/handler.go | 75 ++++++++++++++++++---------------------- fs/fs.go | 5 ++- fs/types.go | 4 +-- info/v1/container.go | 3 ++ info/v1/machine.go | 3 ++ info/v2/container.go | 4 +-- info/v2/conversion.go | 22 +++++++----- machine/info.go | 9 +++-- manager/manager.go | 11 ++++-- 9 files changed, 76 insertions(+), 60 deletions(-) diff --git a/container/raw/handler.go b/container/raw/handler.go index 29bf7c1e53..62ca193709 100644 --- a/container/raw/handler.go +++ b/container/raw/handler.go @@ -165,6 +165,34 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) { return spec, nil } +func fsToFsStats(fs *fs.Fs) info.FsStats { + inodesFree := uint64(0) + hasInodes := fs.InodesFree != nil + if hasInodes { + inodesFree = *fs.InodesFree + } + return info.FsStats{ + Device: fs.Device, + Type: fs.Type.String(), + Limit: fs.Capacity, + Usage: fs.Capacity - fs.Free, + HasInodes: hasInodes, + InodesFree: inodesFree, + Available: fs.Available, + ReadsCompleted: fs.DiskStats.ReadsCompleted, + ReadsMerged: fs.DiskStats.ReadsMerged, + SectorsRead: fs.DiskStats.SectorsRead, + ReadTime: fs.DiskStats.ReadTime, + WritesCompleted: fs.DiskStats.WritesCompleted, + WritesMerged: fs.DiskStats.WritesMerged, + SectorsWritten: fs.DiskStats.SectorsWritten, + WriteTime: fs.DiskStats.WriteTime, + IoInProgress: fs.DiskStats.IoInProgress, + IoTime: fs.DiskStats.IoTime, + WeightedIoTime: fs.DiskStats.WeightedIoTime, + } +} + func (self *rawContainerHandler) getFsStats(stats *info.ContainerStats) error { // Get Filesystem information only for the root cgroup. if isRootCgroup(self.name) { @@ -172,27 +200,9 @@ func (self *rawContainerHandler) getFsStats(stats *info.ContainerStats) error { if err != nil { return err } - for _, fs := range filesystems { - stats.Filesystem = append(stats.Filesystem, - info.FsStats{ - Device: fs.Device, - Type: fs.Type.String(), - Limit: fs.Capacity, - Usage: fs.Capacity - fs.Free, - Available: fs.Available, - InodesFree: fs.InodesFree, - ReadsCompleted: fs.DiskStats.ReadsCompleted, - ReadsMerged: fs.DiskStats.ReadsMerged, - SectorsRead: fs.DiskStats.SectorsRead, - ReadTime: fs.DiskStats.ReadTime, - WritesCompleted: fs.DiskStats.WritesCompleted, - WritesMerged: fs.DiskStats.WritesMerged, - SectorsWritten: fs.DiskStats.SectorsWritten, - WriteTime: fs.DiskStats.WriteTime, - IoInProgress: fs.DiskStats.IoInProgress, - IoTime: fs.DiskStats.IoTime, - WeightedIoTime: fs.DiskStats.WeightedIoTime, - }) + for i := range filesystems { + fs := filesystems[i] + stats.Filesystem = append(stats.Filesystem, fsToFsStats(&fs)) } } else if len(self.externalMounts) > 0 { var mountSet map[string]struct{} @@ -204,26 +214,9 @@ func (self *rawContainerHandler) getFsStats(stats *info.ContainerStats) error { if err != nil { return err } - for _, fs := range filesystems { - stats.Filesystem = append(stats.Filesystem, - info.FsStats{ - Device: fs.Device, - Type: fs.Type.String(), - Limit: fs.Capacity, - Usage: fs.Capacity - fs.Free, - InodesFree: fs.InodesFree, - ReadsCompleted: fs.DiskStats.ReadsCompleted, - ReadsMerged: fs.DiskStats.ReadsMerged, - SectorsRead: fs.DiskStats.SectorsRead, - ReadTime: fs.DiskStats.ReadTime, - WritesCompleted: fs.DiskStats.WritesCompleted, - WritesMerged: fs.DiskStats.WritesMerged, - SectorsWritten: fs.DiskStats.SectorsWritten, - WriteTime: fs.DiskStats.WriteTime, - IoInProgress: fs.DiskStats.IoInProgress, - IoTime: fs.DiskStats.IoTime, - WeightedIoTime: fs.DiskStats.WeightedIoTime, - }) + for i := range filesystems { + fs := filesystems[i] + stats.Filesystem = append(stats.Filesystem, fsToFsStats(&fs)) } } return nil diff --git a/fs/fs.go b/fs/fs.go index 4bc39e52da..248684dea3 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -322,7 +322,10 @@ func (self *RealFsInfo) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, er fs.Capacity, fs.Free, fs.Available, err = getZfstats(device) fs.Type = ZFS default: - fs.Capacity, fs.Free, fs.Available, fs.Inodes, fs.InodesFree, err = getVfsStats(partition.mountpoint) + var inodes, inodesFree uint64 + fs.Capacity, fs.Free, fs.Available, inodes, inodesFree, err = getVfsStats(partition.mountpoint) + fs.Inodes = &inodes + fs.InodesFree = &inodesFree fs.Type = VFS } if err != nil { diff --git a/fs/types.go b/fs/types.go index 317af49e36..140aff3fec 100644 --- a/fs/types.go +++ b/fs/types.go @@ -40,8 +40,8 @@ type Fs struct { Capacity uint64 Free uint64 Available uint64 - Inodes uint64 - InodesFree uint64 + Inodes *uint64 + InodesFree *uint64 DiskStats DiskStats } diff --git a/info/v1/container.go b/info/v1/container.go index 6e7e658975..ad57c8f439 100644 --- a/info/v1/container.go +++ b/info/v1/container.go @@ -415,6 +415,9 @@ type FsStats struct { // Number of bytes available for non-root user. Available uint64 `json:"available"` + // HasInodes when true, indicates that Inodes info will be available. + HasInodes bool `json:"has_inodes"` + // Number of available Inodes InodesFree uint64 `json:"inodes_free"` diff --git a/info/v1/machine.go b/info/v1/machine.go index 74a5df49c3..933b6f3020 100644 --- a/info/v1/machine.go +++ b/info/v1/machine.go @@ -26,6 +26,9 @@ type FsInfo struct { // Total number of inodes available on the filesystem. Inodes uint64 `json:"inodes"` + + // HasInodes when true, indicates that Inodes info will be available. + HasInodes bool `json:"has_inodes"` } type Node struct { diff --git a/info/v2/container.go b/info/v2/container.go index 42d990ff00..d900d94cc8 100644 --- a/info/v2/container.go +++ b/info/v2/container.go @@ -217,8 +217,8 @@ type FsInfo struct { // Labels associated with this filesystem. Labels []string `json:"labels"` - // Number of available Inodes. - InodesFree uint64 `json:"inodes_free"` + // Number of available Inodes (if known) + InodesFree *uint64 `json:"inodes_free,omitempty"` } type RequestOptions struct { diff --git a/info/v2/conversion.go b/info/v2/conversion.go index 2e6181203d..08e41a6f98 100644 --- a/info/v2/conversion.go +++ b/info/v2/conversion.go @@ -30,13 +30,12 @@ func machineFsStatsFromV1(fsStats []v1.FsStats) []MachineFsStats { writeDuration := time.Millisecond * time.Duration(stat.WriteTime) ioDuration := time.Millisecond * time.Duration(stat.IoTime) weightedDuration := time.Millisecond * time.Duration(stat.WeightedIoTime) - result = append(result, MachineFsStats{ - Device: stat.Device, - Type: stat.Type, - Capacity: &stat.Limit, - Usage: &stat.Usage, - Available: &stat.Available, - InodesFree: &stat.InodesFree, + machineFsStat := MachineFsStats{ + Device: stat.Device, + Type: stat.Type, + Capacity: &stat.Limit, + Usage: &stat.Usage, + Available: &stat.Available, DiskStats: DiskStats{ ReadsCompleted: &stat.ReadsCompleted, ReadsMerged: &stat.ReadsMerged, @@ -50,7 +49,11 @@ func machineFsStatsFromV1(fsStats []v1.FsStats) []MachineFsStats { IoDuration: &ioDuration, WeightedIoDuration: &weightedDuration, }, - }) + } + if stat.HasInodes { + machineFsStat.InodesFree = &stat.InodesFree + } + result = append(result, machineFsStat) } return result } @@ -58,7 +61,8 @@ func machineFsStatsFromV1(fsStats []v1.FsStats) []MachineFsStats { func MachineStatsFromV1(cont *v1.ContainerInfo) []MachineStats { var stats []MachineStats var last *v1.ContainerStats - for _, val := range cont.Stats { + for i := range cont.Stats { + val := cont.Stats[i] stat := MachineStats{ Timestamp: val.Timestamp, } diff --git a/machine/info.go b/machine/info.go index e26f950fbe..0478218eff 100644 --- a/machine/info.go +++ b/machine/info.go @@ -110,8 +110,13 @@ func Info(sysFs sysfs.SysFs, fsInfo fs.FsInfo, inHostNamespace bool) (*info.Mach InstanceID: instanceID, } - for _, fs := range filesystems { - machineInfo.Filesystems = append(machineInfo.Filesystems, info.FsInfo{Device: fs.Device, Type: fs.Type.String(), Capacity: fs.Capacity, Inodes: fs.Inodes}) + for i := range filesystems { + fs := filesystems[i] + inodes := uint64(0) + if fs.Inodes != nil { + inodes = *fs.Inodes + } + machineInfo.Filesystems = append(machineInfo.Filesystems, info.FsInfo{Device: fs.Device, Type: fs.Type.String(), Capacity: fs.Capacity, Inodes: inodes, HasInodes: fs.Inodes != nil}) } return machineInfo, nil diff --git a/manager/manager.go b/manager/manager.go index 8b3b902f6d..e41cf990c1 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -44,9 +44,10 @@ import ( "github.com/google/cadvisor/utils/sysfs" "github.com/google/cadvisor/version" + "net/http" + "github.com/golang/glog" "github.com/opencontainers/runc/libcontainer/cgroups" - "net/http" ) var globalHousekeepingInterval = flag.Duration("global_housekeeping_interval", 1*time.Minute, "Interval between global housekeepings") @@ -671,7 +672,8 @@ func (self *manager) GetFsInfo(label string) ([]v2.FsInfo, error) { } } fsInfo := []v2.FsInfo{} - for _, fs := range stats[0].Filesystem { + for i := range stats[0].Filesystem { + fs := stats[0].Filesystem[i] if len(label) != 0 && fs.Device != dev { continue } @@ -683,6 +685,7 @@ func (self *manager) GetFsInfo(label string) ([]v2.FsInfo, error) { if err != nil { return nil, err } + fi := v2.FsInfo{ Device: fs.Device, Mountpoint: mountpoint, @@ -690,7 +693,9 @@ func (self *manager) GetFsInfo(label string) ([]v2.FsInfo, error) { Usage: fs.Usage, Available: fs.Available, Labels: labels, - InodesFree: fs.InodesFree, + } + if fs.HasInodes { + fi.InodesFree = &fs.InodesFree } fsInfo = append(fsInfo, fi) }