From 294a0973bd1e088b8106c63f0194432d5a8c951c Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Thu, 28 Jan 2021 09:45:51 +0100 Subject: [PATCH] rbd: mark images thick-provisioned in metadata When images get resized/expanded, the additional space needs to be allocated if the image was initially thick-provisioned. By marking the image with a "thick-provisioned" key in the metadata, future operations can check the need. A missing "thick-provisioned" key indicates that the image has not been thick-provisioned. Signed-off-by: Niels de Vos --- internal/rbd/rbd_util.go | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 5d6df381e..89f73e3e2 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -53,6 +53,9 @@ const ( rbdTaskRemoveCmdInvalidString1 = "no valid command found" rbdTaskRemoveCmdInvalidString2 = "Error EINVAL: invalid command" rbdTaskRemoveCmdAccessDeniedMessage = "Error EACCES:" + + // image metadata key for thick-provisioning + thickProvisionMetaKey = ".rbd.csi.ceph.com/thick-provisioned" ) // rbdVolume represents a CSI volume and its RBD image specifics. @@ -232,6 +235,14 @@ func createImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) er _ = deleteImage(ctx, pOpts, cr) return fmt.Errorf("failed to thick provision image: %w", err) } + + err = pOpts.setThickProvisioned() + if err != nil { + // nolint:errcheck // deleteImage() will log errors in + // case it fails, no need to log them here again + _ = deleteImage(ctx, pOpts, cr) + return fmt.Errorf("failed to mark image as thick-provisioned: %w", err) + } } return nil @@ -1242,6 +1253,36 @@ func (rv *rbdVolume) SetMetadata(key, value string) error { return image.SetMetadata(key, value) } +// setThickProvisioned records in the image metadata that it has been +// thick-provisioned. +func (rv *rbdVolume) setThickProvisioned() error { + err := rv.SetMetadata(thickProvisionMetaKey, "true") + if err != nil { + return fmt.Errorf("failed to set metadata %q for %q: %w", thickProvisionMetaKey, rv.String(), err) + } + + return nil +} + +// isThickProvisioned checks in the image metadata if the image has been marked +// as thick-provisioned. This can be used while expanding the image, so that +// the expansion can be allocated too. +func (rv *rbdVolume) isThickProvisioned() (bool, error) { + value, err := rv.GetMetadata(thickProvisionMetaKey) + if err != nil { + if err == librbd.ErrNotFound { + return false, nil + } + return false, fmt.Errorf("failed to get metadata %q for %q: %w", thickProvisionMetaKey, rv.String(), err) + } + + thick, err := strconv.ParseBool(value) + if err != nil { + return false, fmt.Errorf("failed to convert %q=%q to a boolean: %w", thickProvisionMetaKey, value, err) + } + return thick, nil +} + func (rv *rbdVolume) listSnapshots() ([]librbd.SnapInfo, error) { image, err := rv.open() if err != nil {