From 726f89d77a575c6a121829eb8fe63c1d3d6452fe Mon Sep 17 00:00:00 2001 From: Peter Volpe Date: Fri, 30 Jan 2015 22:21:34 -0800 Subject: [PATCH] Add available space to devicemapper status output Signed-off-by: Peter Volpe --- daemon/graphdriver/devmapper/README.md | 4 +++ daemon/graphdriver/devmapper/deviceset.go | 43 +++++++++++++++++++++-- daemon/graphdriver/devmapper/driver.go | 2 ++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/daemon/graphdriver/devmapper/README.md b/daemon/graphdriver/devmapper/README.md index e589bac536..93d0d447bb 100644 --- a/daemon/graphdriver/devmapper/README.md +++ b/daemon/graphdriver/devmapper/README.md @@ -42,8 +42,10 @@ will display something like: Metadata file: /dev/loop4 Data Space Used: 2.536 GB Data Space Total: 107.4 GB + Data Space Available: 104.8 GB Metadata Space Used: 7.93 MB Metadata Space Total: 2.147 GB + Metadata Space Available: 2.14 GB Udev Sync Supported: true Data loop file: /home/docker/devicemapper/devicemapper/data Metadata loop file: /home/docker/devicemapper/devicemapper/metadata @@ -60,8 +62,10 @@ status information about the driver. * `Metadata file` blockdevice file used for the devicemapper metadata * `Data Space Used` tells how much of `Data file` is currently used * `Data Space Total` tells max size the `Data file` + * `Data Space Available` tells how much free space there is in the `Data file` * `Metadata Space Used` tells how much of `Metadata file` is currently used * `Metadata Space Total` tells max size the `Metadata file` + * `Metadata Space Available` tells how much free space there is in the `Metadata file` * `Udev Sync Supported` tells whether devicemapper is able to sync with Udev. Should be `true`. * `Data loop file` file attached to `Data file`, if loopback device is used * `Metadata loop file` file attached to `Metadata file`, if loopback device is used diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index 51ce54941d..5a90f73888 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -100,8 +100,9 @@ type DeviceSet struct { } type DiskUsage struct { - Used uint64 - Total uint64 + Used uint64 + Total uint64 + Available uint64 } type Status struct { @@ -1574,6 +1575,28 @@ func (devices *DeviceSet) MetadataDevicePath() string { return devices.metadataDevice } +func (devices *DeviceSet) getUnderlyingAvailableSpace(loopFile string) (uint64, error) { + buf := new(syscall.Statfs_t) + err := syscall.Statfs(loopFile, buf) + if err != nil { + log.Warnf("Warning: Couldn't stat loopfile filesystem %v: %v", loopFile, err) + return 0, err + } + return buf.Bfree * uint64(buf.Bsize), nil +} + +func (devices *DeviceSet) isRealFile(loopFile string) (bool, error) { + if loopFile != "" { + fi, err := os.Stat(loopFile) + if err != nil { + log.Warnf("Warning: Couldn't stat loopfile %v: %v", loopFile, err) + return false, err + } + return fi.Mode().IsRegular(), nil + } + return false, nil +} + // Status returns the current status of this deviceset func (devices *DeviceSet) Status() *Status { devices.Lock() @@ -1595,12 +1618,28 @@ func (devices *DeviceSet) Status() *Status { status.Data.Used = dataUsed * blockSizeInSectors * 512 status.Data.Total = dataTotal * blockSizeInSectors * 512 + status.Data.Available = status.Data.Total - status.Data.Used // metadata blocks are always 4k status.Metadata.Used = metadataUsed * 4096 status.Metadata.Total = metadataTotal * 4096 + status.Metadata.Available = status.Metadata.Total - status.Metadata.Used status.SectorSize = blockSizeInSectors * 512 + + if check, _ := devices.isRealFile(devices.dataLoopFile); check { + actualSpace, err := devices.getUnderlyingAvailableSpace(devices.dataLoopFile) + if err == nil && actualSpace < status.Data.Available { + status.Data.Available = actualSpace + } + } + + if check, _ := devices.isRealFile(devices.metadataLoopFile); check { + actualSpace, err := devices.getUnderlyingAvailableSpace(devices.metadataLoopFile) + if err == nil && actualSpace < status.Metadata.Available { + status.Metadata.Available = actualSpace + } + } } return status diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 2feed5720f..1d3d803e2c 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -72,8 +72,10 @@ func (d *Driver) Status() [][2]string { {"Metadata file", s.MetadataFile}, {"Data Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Used)))}, {"Data Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Total)))}, + {"Data Space Available", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Available)))}, {"Metadata Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Used)))}, {"Metadata Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Total)))}, + {"Metadata Space Available", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Available)))}, {"Udev Sync Supported", fmt.Sprintf("%v", s.UdevSyncSupported)}, } if len(s.DataLoopback) > 0 {