Add available space to devicemapper status output
| ... | ... |
@@ -42,8 +42,10 @@ will display something like: |
| 42 | 42 |
Metadata file: /dev/loop4 |
| 43 | 43 |
Data Space Used: 2.536 GB |
| 44 | 44 |
Data Space Total: 107.4 GB |
| 45 |
+ Data Space Available: 104.8 GB |
|
| 45 | 46 |
Metadata Space Used: 7.93 MB |
| 46 | 47 |
Metadata Space Total: 2.147 GB |
| 48 |
+ Metadata Space Available: 2.14 GB |
|
| 47 | 49 |
Udev Sync Supported: true |
| 48 | 50 |
Data loop file: /home/docker/devicemapper/devicemapper/data |
| 49 | 51 |
Metadata loop file: /home/docker/devicemapper/devicemapper/metadata |
| ... | ... |
@@ -60,8 +62,10 @@ status information about the driver. |
| 60 | 60 |
* `Metadata file` blockdevice file used for the devicemapper metadata |
| 61 | 61 |
* `Data Space Used` tells how much of `Data file` is currently used |
| 62 | 62 |
* `Data Space Total` tells max size the `Data file` |
| 63 |
+ * `Data Space Available` tells how much free space there is in the `Data file`. If you are using a loop device this will report the actual space available to the loop device on the underlying filesystem. |
|
| 63 | 64 |
* `Metadata Space Used` tells how much of `Metadata file` is currently used |
| 64 | 65 |
* `Metadata Space Total` tells max size the `Metadata file` |
| 66 |
+ * `Metadata Space Available` tells how much free space there is in the `Metadata file`. If you are using a loop device this will report the actual space available to the loop device on the underlying filesystem. |
|
| 65 | 67 |
* `Udev Sync Supported` tells whether devicemapper is able to sync with Udev. Should be `true`. |
| 66 | 68 |
* `Data loop file` file attached to `Data file`, if loopback device is used |
| 67 | 69 |
* `Metadata loop file` file attached to `Metadata file`, if loopback device is used |
| ... | ... |
@@ -100,8 +100,9 @@ type DeviceSet struct {
|
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 | 102 |
type DiskUsage struct {
|
| 103 |
- Used uint64 |
|
| 104 |
- Total uint64 |
|
| 103 |
+ Used uint64 |
|
| 104 |
+ Total uint64 |
|
| 105 |
+ Available uint64 |
|
| 105 | 106 |
} |
| 106 | 107 |
|
| 107 | 108 |
type Status struct {
|
| ... | ... |
@@ -1579,6 +1580,28 @@ func (devices *DeviceSet) MetadataDevicePath() string {
|
| 1579 | 1579 |
return devices.metadataDevice |
| 1580 | 1580 |
} |
| 1581 | 1581 |
|
| 1582 |
+func (devices *DeviceSet) getUnderlyingAvailableSpace(loopFile string) (uint64, error) {
|
|
| 1583 |
+ buf := new(syscall.Statfs_t) |
|
| 1584 |
+ err := syscall.Statfs(loopFile, buf) |
|
| 1585 |
+ if err != nil {
|
|
| 1586 |
+ log.Warnf("Warning: Couldn't stat loopfile filesystem %v: %v", loopFile, err)
|
|
| 1587 |
+ return 0, err |
|
| 1588 |
+ } |
|
| 1589 |
+ return buf.Bfree * uint64(buf.Bsize), nil |
|
| 1590 |
+} |
|
| 1591 |
+ |
|
| 1592 |
+func (devices *DeviceSet) isRealFile(loopFile string) (bool, error) {
|
|
| 1593 |
+ if loopFile != "" {
|
|
| 1594 |
+ fi, err := os.Stat(loopFile) |
|
| 1595 |
+ if err != nil {
|
|
| 1596 |
+ log.Warnf("Warning: Couldn't stat loopfile %v: %v", loopFile, err)
|
|
| 1597 |
+ return false, err |
|
| 1598 |
+ } |
|
| 1599 |
+ return fi.Mode().IsRegular(), nil |
|
| 1600 |
+ } |
|
| 1601 |
+ return false, nil |
|
| 1602 |
+} |
|
| 1603 |
+ |
|
| 1582 | 1604 |
// Status returns the current status of this deviceset |
| 1583 | 1605 |
func (devices *DeviceSet) Status() *Status {
|
| 1584 | 1606 |
devices.Lock() |
| ... | ... |
@@ -1600,12 +1623,28 @@ func (devices *DeviceSet) Status() *Status {
|
| 1600 | 1600 |
|
| 1601 | 1601 |
status.Data.Used = dataUsed * blockSizeInSectors * 512 |
| 1602 | 1602 |
status.Data.Total = dataTotal * blockSizeInSectors * 512 |
| 1603 |
+ status.Data.Available = status.Data.Total - status.Data.Used |
|
| 1603 | 1604 |
|
| 1604 | 1605 |
// metadata blocks are always 4k |
| 1605 | 1606 |
status.Metadata.Used = metadataUsed * 4096 |
| 1606 | 1607 |
status.Metadata.Total = metadataTotal * 4096 |
| 1608 |
+ status.Metadata.Available = status.Metadata.Total - status.Metadata.Used |
|
| 1607 | 1609 |
|
| 1608 | 1610 |
status.SectorSize = blockSizeInSectors * 512 |
| 1611 |
+ |
|
| 1612 |
+ if check, _ := devices.isRealFile(devices.dataLoopFile); check {
|
|
| 1613 |
+ actualSpace, err := devices.getUnderlyingAvailableSpace(devices.dataLoopFile) |
|
| 1614 |
+ if err == nil && actualSpace < status.Data.Available {
|
|
| 1615 |
+ status.Data.Available = actualSpace |
|
| 1616 |
+ } |
|
| 1617 |
+ } |
|
| 1618 |
+ |
|
| 1619 |
+ if check, _ := devices.isRealFile(devices.metadataLoopFile); check {
|
|
| 1620 |
+ actualSpace, err := devices.getUnderlyingAvailableSpace(devices.metadataLoopFile) |
|
| 1621 |
+ if err == nil && actualSpace < status.Metadata.Available {
|
|
| 1622 |
+ status.Metadata.Available = actualSpace |
|
| 1623 |
+ } |
|
| 1624 |
+ } |
|
| 1609 | 1625 |
} |
| 1610 | 1626 |
|
| 1611 | 1627 |
return status |
| ... | ... |
@@ -72,8 +72,10 @@ func (d *Driver) Status() [][2]string {
|
| 72 | 72 |
{"Metadata file", s.MetadataFile},
|
| 73 | 73 |
{"Data Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Used)))},
|
| 74 | 74 |
{"Data Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Total)))},
|
| 75 |
+ {"Data Space Available", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Available)))},
|
|
| 75 | 76 |
{"Metadata Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Used)))},
|
| 76 | 77 |
{"Metadata Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Total)))},
|
| 78 |
+ {"Metadata Space Available", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Available)))},
|
|
| 77 | 79 |
{"Udev Sync Supported", fmt.Sprintf("%v", s.UdevSyncSupported)},
|
| 78 | 80 |
} |
| 79 | 81 |
if len(s.DataLoopback) > 0 {
|