diff --git a/internal/rbd/controllerserver.go b/internal/rbd/controllerserver.go index 3b6c58d06a9a..056fb3aa57eb 100644 --- a/internal/rbd/controllerserver.go +++ b/internal/rbd/controllerserver.go @@ -1217,6 +1217,11 @@ func (cs *ControllerServer) CreateSnapshot( return nil, status.Error(codes.Internal, err.Error()) } + // remove the extra size of the LUKS header, if the volume is block encrypted. + if vol.isBlockEncrypted() { + vol.VolSize -= util.GetLuksHeaderSize() + } + return &csi.CreateSnapshotResponse{ Snapshot: &csi.Snapshot{ SizeBytes: vol.VolSize, diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 7b37a70eb614..b785966e882f 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -443,8 +443,14 @@ func createImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) er return fmt.Errorf("failed to get IOContext: %w", err) } - err = librbd.CreateImage(pOpts.ioctx, pOpts.RbdImageName, - uint64(util.RoundOffVolSize(pOpts.VolSize)*helpers.MiB), options) + size := uint64(util.RoundOffVolSize(pOpts.VolSize) * helpers.MiB) + + // add the extra size of the LUKS header to the image size if block encryption is enabled. + if pOpts.isBlockEncrypted() { + size += uint64(util.GetLuksHeaderSize()) + } + + err = librbd.CreateImage(pOpts.ioctx, pOpts.RbdImageName, size, options) if err != nil { return fmt.Errorf("failed to create rbd image: %w", err) } @@ -1598,6 +1604,11 @@ func (ri *rbdImage) getImageInfo() error { // TODO: can rv.VolSize not be a uint64? Or initialize it to -1? ri.VolSize = int64(imageInfo.Size) + // remove the extra size of the LUKS header, if the volume is block encrypted. + if ri.isBlockEncrypted() { + ri.VolSize -= util.GetLuksHeaderSize() + } + features, err := image.GetFeatures() if err != nil { return err @@ -1846,7 +1857,14 @@ func (ri *rbdImage) resize(newSize int64) error { } defer image.Close() - err = image.Resize(uint64(util.RoundOffVolSize(newSize) * helpers.MiB)) + size := uint64(util.RoundOffVolSize(newSize) * helpers.MiB) + + // add the extra size of the LUKS header to the image size if block encryption is enabled. + if ri.isBlockEncrypted() { + size += uint64(util.GetLuksHeaderSize()) + } + + err = image.Resize(size) if err != nil { return err } diff --git a/internal/util/cryptsetup.go b/internal/util/cryptsetup.go index e5669b425337..8fcd3185578c 100644 --- a/internal/util/cryptsetup.go +++ b/internal/util/cryptsetup.go @@ -22,10 +22,22 @@ import ( "os/exec" "strconv" "strings" + + "k8s.io/cloud-provider/volume/helpers" ) // Limit memory used by Argon2i PBKDF to 32 MiB. -const cryptsetupPBKDFMemoryLimit = 32 << 10 // 32768 KiB +const ( + cryptsetupPBKDFMemoryLimit = 32 << 10 // 32768 KiB + luks2MetadataSize = 32 << 7 // 4096 KiB + luks2KeySlotsSize = 32 << 8 // 8192 KiB +) + +func GetLuksHeaderSize() int64 { + size := int64((((2 * luks2MetadataSize) + luks2KeySlotsSize) * helpers.KiB)) + + return size +} // LuksFormat sets up volume as an encrypted LUKS partition. func LuksFormat(devicePath, passphrase string) (string, string, error) { @@ -37,6 +49,10 @@ func LuksFormat(devicePath, passphrase string) (string, string, error) { "luks2", "--hash", "sha256", + "--luks2-metadata-size", + strconv.Itoa(luks2MetadataSize)+"k", + "--luks2-keyslots-size", + strconv.Itoa(luks2KeySlotsSize)+"k", "--pbkdf-memory", strconv.Itoa(cryptsetupPBKDFMemoryLimit), devicePath,