The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7151

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
- Removes block mode reporting for filesystem volumes (same as LVM driver, to avoid changing used reporting value whether instance is running or not). Now will only report usage when instance is running.
- Fixes cumulative block level reporting for block volumes.
- Adds block level CoW reporting for snapshot volumes (both filesystem and block volumes).

From 1da997a575fbff3e35385eda3a702b564eb71502 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 7 Apr 2020 17:33:56 +0100
Subject: [PATCH 1/2] lxd/storagr/drivers/driver/ceph/volumes: Adds support for
 snapshot usage reporting

Also removes block level usage reporting for filesystem volumes (to bring 
inline with how LVM driver does it).
Also adds block volume reporting total usage.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_ceph_volumes.go | 91 +++++++++++++---------
 1 file changed, 55 insertions(+), 36 deletions(-)

diff --git a/lxd/storage/drivers/driver_ceph_volumes.go 
b/lxd/storage/drivers/driver_ceph_volumes.go
index 56eefdcdb4..9c799793bf 100644
--- a/lxd/storage/drivers/driver_ceph_volumes.go
+++ b/lxd/storage/drivers/driver_ceph_volumes.go
@@ -668,7 +668,13 @@ func (d *ceph) UpdateVolume(vol Volume, changedConfig 
map[string]string) error {
 
 // GetVolumeUsage returns the disk space used by the volume.
 func (d *ceph) GetVolumeUsage(vol Volume) (int64, error) {
-       if vol.contentType == ContentTypeFS && 
shared.IsMountPoint(vol.MountPath()) {
+       isSnap := vol.IsSnapshot()
+
+       // For non-snapshot filesystem volumes, we only return usage when the 
volume is mounted.
+       // This is because to get an accurate value we cannot use blocks 
allocated, as the filesystem will likely
+       // consume blocks and not free them when files are deleted in the 
volume. This avoids returning different
+       // values depending on whether the volume is mounted or not.
+       if !isSnap && vol.contentType == ContentTypeFS && 
shared.IsMountPoint(vol.MountPath()) {
                var stat unix.Statfs_t
 
                err := unix.Statfs(vol.MountPath(), &stat)
@@ -677,49 +683,62 @@ func (d *ceph) GetVolumeUsage(vol Volume) (int64, error) {
                }
 
                return int64(stat.Blocks-stat.Bfree) * int64(stat.Bsize), nil
-       }
-
-       type cephDuLine struct {
-               Name            string `json:"name"`
-               Snapshot        string `json:"snapshot"`
-               ProvisionedSize int64  `json:"provisioned_size"`
-               UsedSize        int64  `json:"used_size"`
-       }
+       } else if vol.contentType == ContentTypeBlock || isSnap {
+               type cephDuLine struct {
+                       Name            string `json:"name"`
+                       Snapshot        string `json:"snapshot"`
+                       ProvisionedSize int64  `json:"provisioned_size"`
+                       UsedSize        int64  `json:"used_size"`
+               }
 
-       type cephDuInfo struct {
-               Images []cephDuLine `json:"images"`
-       }
+               type cephDuInfo struct {
+                       Images []cephDuLine `json:"images"`
+               }
 
-       jsonInfo, err := shared.TryRunCommand(
-               "rbd",
-               "du",
-               "--format", "json",
-               "--id", d.config["ceph.user.name"],
-               "--cluster", d.config["ceph.cluster_name"],
-               "--pool", d.config["ceph.osd.pool_name"],
-               d.getRBDVolumeName(vol, "", false, false))
+               jsonInfo, err := shared.TryRunCommand(
+                       "rbd",
+                       "du",
+                       "--format", "json",
+                       "--id", d.config["ceph.user.name"],
+                       "--cluster", d.config["ceph.cluster_name"],
+                       "--pool", d.config["ceph.osd.pool_name"],
+                       d.getRBDVolumeName(vol, "", false, false),
+               )
+               if err != nil {
+                       return -1, err
+               }
 
-       if err != nil {
-               return -1, err
-       }
+               var usedSize int64
+               var result cephDuInfo
 
-       var usedSize int64
-       var result cephDuInfo
+               err = json.Unmarshal([]byte(jsonInfo), &result)
+               if err != nil {
+                       return -1, err
+               }
 
-       err = json.Unmarshal([]byte(jsonInfo), &result)
-       if err != nil {
-               return -1, err
-       }
+               _, snapName, _ := 
shared.InstanceGetParentAndSnapshotName(vol.Name())
+               snapName = fmt.Sprintf("snapshot_%s", snapName)
 
-       // rbd du gives the output of all related rbd images, snapshots included
-       // to get the total size of the image we use the result that does not 
include
-       // a snapshot name, this is the total image size.
-       for _, image := range result.Images {
-               if image.Snapshot == "" {
-                       usedSize = image.UsedSize
+               // rbd du gives the output of all related rbd images, snapshots 
included.
+               for _, image := range result.Images {
+                       if isSnap {
+                               // For snapshot volumes we only want to get the 
specific image used so we can
+                               // indicate how much CoW usage that snapshot 
has.
+                               if image.Snapshot == snapName {
+                                       usedSize = image.UsedSize
+                                       break
+                               }
+                       } else {
+                               // For non-snapshot volumes, to get the total 
size of the volume we need to add up
+                               // all of the image's usage.
+                               usedSize += image.UsedSize
+                       }
                }
+
+               return usedSize, nil
        }
-       return usedSize, nil
+
+       return -1, ErrNotSupported
 }
 
 // SetVolumeQuota applies a size limit on volume.

From ff7affd99fbfafd97eaa7f3045840bce1a450fec Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 7 Apr 2020 17:36:38 +0100
Subject: [PATCH 2/2] lxd/storage/drivers/driver/lvm/volumes: Clarifies
 comments on LVM volume usage reporting

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_lvm_volumes.go | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lxd/storage/drivers/driver_lvm_volumes.go 
b/lxd/storage/drivers/driver_lvm_volumes.go
index ba41b10023..0c2257fa72 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -288,7 +288,10 @@ func (d *lvm) GetVolumeUsage(vol Volume) (int64, error) {
                return -1, ErrNotSupported
        }
 
-       // If volume has a filesystem and is mounted we can ask the filesystem 
for usage.
+       // For non-snapshot filesystem volumes, we only return usage when the 
volume is mounted.
+       // This is because to get an accurate value we cannot use blocks 
allocated, as the filesystem will likely
+       // consume blocks and not free them when files are deleted in the 
volume. This avoids returning different
+       // values depending on whether the volume is mounted or not.
        if vol.contentType == ContentTypeFS && 
shared.IsMountPoint(vol.MountPath()) {
                var stat unix.Statfs_t
                err := unix.Statfs(vol.MountPath(), &stat)
@@ -298,8 +301,8 @@ func (d *lvm) GetVolumeUsage(vol Volume) (int64, error) {
 
                return int64(stat.Blocks-stat.Bfree) * int64(stat.Bsize), nil
        } else if vol.contentType == ContentTypeBlock && d.usesThinpool() {
-               // For thin pool block volumes we can calculate an approximate 
usage using the space allocated to
-               // the volume from the thin pool.
+               // For non-snapshot thin pool block volumes we can calculate an 
approximate usage using the space
+               // allocated to the volume from the thin pool.
                volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], 
vol.volType, vol.contentType, vol.name)
                _, usedSize, err := d.thinPoolVolumeUsage(volDevPath)
                if err != nil {
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to