go-ceph/rbd/snapshot_nautilus.go
Sven Anderson 6c944e8b65 rbd: make RBDError type unexported
In order to avoid external dependencies on implementation details,
this change replaces RBDError with the unexported rbdError. In case
some application really needs access to the integer value, it can use
the pattern
  var errno interface{ Errno() int }
  if errors.As(err, errno) { ... errno.Errno() ... }

Signed-off-by: Sven Anderson <sven@redhat.com>
2020-07-17 13:47:32 -04:00

107 lines
2.9 KiB
Go

// +build !luminous,!mimic
//
// Ceph Nautilus introduced rbd_get_parent() and deprecated rbd_get_parent_info().
// Ceph Nautilus introduced rbd_list_children3() and deprecated rbd_list_children().
package rbd
// #cgo LDFLAGS: -lrbd
// #include <rbd/librbd.h>
// #include <errno.h>
import "C"
import (
"unsafe"
"github.com/ceph/go-ceph/internal/retry"
)
// GetParentInfo looks for the parent of the image and stores the pool, name
// and snapshot-name in the byte-arrays that are passed as arguments.
//
// Implements:
// int rbd_get_parent(rbd_image_t image,
// rbd_linked_image_spec_t *parent_image,
// rbd_snap_spec_t *parent_snap)
func (image *Image) GetParentInfo(pool, name, snapname []byte) error {
if err := image.validate(imageIsOpen); err != nil {
return err
}
parentImage := C.rbd_linked_image_spec_t{}
parentSnap := C.rbd_snap_spec_t{}
ret := C.rbd_get_parent(image.image, &parentImage, &parentSnap)
if ret != 0 {
return rbdError(ret)
}
defer C.rbd_linked_image_spec_cleanup(&parentImage)
defer C.rbd_snap_spec_cleanup(&parentSnap)
strlen := int(C.strlen(parentImage.pool_name))
if len(pool) < strlen {
return rbdError(C.ERANGE)
}
if copy(pool, C.GoString(parentImage.pool_name)) != strlen {
return rbdError(C.ERANGE)
}
strlen = int(C.strlen(parentImage.image_name))
if len(name) < strlen {
return rbdError(C.ERANGE)
}
if copy(name, C.GoString(parentImage.image_name)) != strlen {
return rbdError(C.ERANGE)
}
strlen = int(C.strlen(parentSnap.name))
if len(snapname) < strlen {
return rbdError(C.ERANGE)
}
if copy(snapname, C.GoString(parentSnap.name)) != strlen {
return rbdError(C.ERANGE)
}
return nil
}
// ListChildren returns arrays with the pools and names of the images that are
// children of the given image. The index of the pools and images arrays can be
// used to link the two items together.
//
// Implements:
// int rbd_list_children3(rbd_image_t image, rbd_linked_image_spec_t *images,
// size_t *max_images);
func (image *Image) ListChildren() (pools []string, images []string, err error) {
if err := image.validate(imageIsOpen); err != nil {
return nil, 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, nil, err
}
defer C.rbd_linked_image_spec_list_cleanup((*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])), csize)
pools = make([]string, csize)
images = make([]string, csize)
for i, child := range children[:csize] {
pools[i] = C.GoString(child.pool_name)
images[i] = C.GoString(child.image_name)
}
return pools, images, nil
}