rbd: use ListChildrenAttributes() instead of ListChildren()

This commit modifies listSnapAndChildren() to make use of
ListChildrenAttributes() instead of ListChildren() which
allows us to filter out images in trash.
This commit also order the alive images so that temp clone
images are followed by images backing volume snapshots so
that temp clone images are flattened first.

Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
Rakshith R
2025-03-10 15:15:45 +05:30
committed by mergify[bot]
parent 355a8fab9f
commit 796e6b6c44
12 changed files with 163 additions and 40 deletions

View File

@ -61,30 +61,44 @@ type EncryptionOptions interface {
}
func (opts EncryptionOptionsLUKS1) allocateEncryptionOptions() cEncryptionData {
var cOpts C.rbd_encryption_luks1_format_options_t
var retData cEncryptionData
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
// CBytes allocates memory. it will be freed when cEncryptionData.free is called
cOpts.passphrase = (*C.char)(C.CBytes(opts.Passphrase))
cPassphrase := (*C.char)(C.CBytes(opts.Passphrase))
cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks1_format_options_t)
cOpts := (*C.rbd_encryption_luks1_format_options_t)(C.malloc(cOptsSize))
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
cOpts.passphrase = cPassphrase
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))
retData.opts = C.rbd_encryption_options_t(&cOpts)
retData.optsSize = C.size_t(C.sizeof_rbd_encryption_luks1_format_options_t)
retData.free = func() { C.free(unsafe.Pointer(cOpts.passphrase)) }
retData.format = C.RBD_ENCRYPTION_FORMAT_LUKS1
retData.opts = C.rbd_encryption_options_t(cOpts)
retData.optsSize = cOptsSize
retData.free = func() {
C.free(unsafe.Pointer(cOpts.passphrase))
C.free(unsafe.Pointer(cOpts))
}
return retData
}
func (opts EncryptionOptionsLUKS2) allocateEncryptionOptions() cEncryptionData {
var cOpts C.rbd_encryption_luks2_format_options_t
var retData cEncryptionData
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
// CBytes allocates memory. it will be freed when cEncryptionData.free is called
cOpts.passphrase = (*C.char)(C.CBytes(opts.Passphrase))
cPassphrase := (*C.char)(C.CBytes(opts.Passphrase))
cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks2_format_options_t)
cOpts := (*C.rbd_encryption_luks2_format_options_t)(C.malloc(cOptsSize))
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
cOpts.passphrase = cPassphrase
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))
retData.opts = C.rbd_encryption_options_t(&cOpts)
retData.optsSize = C.size_t(C.sizeof_rbd_encryption_luks2_format_options_t)
retData.free = func() { C.free(unsafe.Pointer(cOpts.passphrase)) }
retData.format = C.RBD_ENCRYPTION_FORMAT_LUKS2
retData.opts = C.rbd_encryption_options_t(cOpts)
retData.optsSize = cOptsSize
retData.free = func() {
C.free(unsafe.Pointer(cOpts.passphrase))
C.free(unsafe.Pointer(cOpts))
}
return retData
}

View File

@ -81,25 +81,22 @@ func (image *Image) EncryptionLoad2(opts []EncryptionOptions) error {
}
length := len(opts)
cspecs := (*C.rbd_encryption_spec_t)(C.malloc(
C.size_t(C.sizeof_rbd_encryption_spec_t * length)))
specs := unsafe.Slice(cspecs, length)
cspecs := make([]C.rbd_encryption_spec_t, length)
freeFuncs := make([]func(), length)
for idx, option := range opts {
f := option.(encryptionOptions2).writeEncryptionSpec(&specs[idx])
f := option.(encryptionOptions2).writeEncryptionSpec(&cspecs[idx])
freeFuncs[idx] = f
}
defer func() {
for _, f := range freeFuncs {
f()
}
C.free(unsafe.Pointer(cspecs))
}()
ret := C.rbd_encryption_load2(
image.image,
cspecs,
(*C.rbd_encryption_spec_t)(unsafe.Pointer(&cspecs[0])),
C.size_t(length))
return getError(ret)
}

View File

@ -21,15 +21,22 @@ type EncryptionOptionsLUKS struct {
}
func (opts EncryptionOptionsLUKS) allocateEncryptionOptions() cEncryptionData {
var cOpts C.rbd_encryption_luks_format_options_t
var retData cEncryptionData
// CBytes allocates memory. it will be freed when cEncryptionData.free is called
cOpts.passphrase = (*C.char)(C.CBytes(opts.Passphrase))
cPassphrase := (*C.char)(C.CBytes(opts.Passphrase))
cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks_format_options_t)
cOpts := (*C.rbd_encryption_luks_format_options_t)(C.malloc(cOptsSize))
cOpts.passphrase = cPassphrase
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))
retData.opts = C.rbd_encryption_options_t(&cOpts)
retData.optsSize = C.size_t(C.sizeof_rbd_encryption_luks_format_options_t)
retData.free = func() { C.free(unsafe.Pointer(cOpts.passphrase)) }
retData.format = C.RBD_ENCRYPTION_FORMAT_LUKS
retData.opts = C.rbd_encryption_options_t(cOpts)
retData.optsSize = cOptsSize
retData.free = func() {
C.free(unsafe.Pointer(cOpts.passphrase))
C.free(unsafe.Pointer(cOpts))
}
return retData
}

View File

@ -168,6 +168,50 @@ func (image *Image) ListChildren() (pools []string, images []string, err error)
return pools, images, nil
}
// ListChildrenAttributes returns an array of struct with the names and ids of the
// images and pools and the trash of the images that are children of the given image.
//
// Implements:
//
// int rbd_list_children3(rbd_image_t image, rbd_linked_image_spec_t *images,
// size_t *max_images);
func (image *Image) ListChildrenAttributes() (imgSpec []ImageSpec, err error) {
if err := image.validate(imageIsOpen); err != nil {
return nil, err
}
var (
csize C.size_t
children []C.rbd_linked_image_spec_t
)
retry.WithSizes(16, 4096, func(size int) retry.Hint {
csize = C.size_t(size)
children = make([]C.rbd_linked_image_spec_t, csize)
ret := C.rbd_list_children3(
image.image,
(*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])),
&csize)
err = getErrorIfNegative(ret)
return retry.Size(int(csize)).If(err == errRange)
})
if err != nil {
return nil, err
}
defer C.rbd_linked_image_spec_list_cleanup((*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])), csize)
imgSpec = make([]ImageSpec, csize)
for i, child := range children[:csize] {
imgSpec[i] = ImageSpec{
ImageName: C.GoString(child.image_name),
ImageID: C.GoString(child.image_id),
PoolName: C.GoString(child.pool_name),
PoolNamespace: C.GoString(child.pool_namespace),
PoolID: uint64(child.pool_id),
Trash: bool(child.trash),
}
}
return imgSpec, nil
}
// SetSnapByID updates the rbd image (not the Snapshot) such that the snapshot
// is the source of readable data.
//