mirror of https://github.com/ceph/go-ceph
rbd: let CloneImageByID check for rbd_clone4 at runtime
Some versions of librbd provide the rbd_clone4 function, and others do not. Squid will have the function backported in the 1st update, the initial release of Squid does not have it. This makes checking for the function based on the named Ceph version impractical. With the new dlsym.LookupSymbol() function, it is now possible to check the availability of rbd_clone4 during runtime. If the symbol is not found ErrNotImplemented is returned, which can be used to detect the unavailability of the function. Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
parent
8bced26404
commit
a9ce294dbb
|
@ -1,20 +1,46 @@
|
|||
//go:build !(nautilus || octopus || pacific || quincy || reef) && ceph_preview
|
||||
//go:build ceph_preview
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <errno.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <rados/librados.h>
|
||||
// #include <rbd/librbd.h>
|
||||
/*
|
||||
#cgo LDFLAGS: -lrbd
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <rados/librados.h>
|
||||
#include <rbd/librbd.h>
|
||||
|
||||
// rbd_clone4_fn matches the rbd_clone4 function signature.
|
||||
typedef int(*rbd_clone4_fn)(rados_ioctx_t p_ioctx, const char *p_name,
|
||||
uint64_t p_snap_id, rados_ioctx_t c_ioctx,
|
||||
const char *c_name, rbd_image_options_t c_opts);
|
||||
|
||||
// rbd_clone4_dlsym take *fn as rbd_clone4_fn and calls the dynamically loaded
|
||||
// rbd_clone4 function passed as 1st argument.
|
||||
static inline int rbd_clone4_dlsym(void *fn, rados_ioctx_t p_ioctx,
|
||||
const char *p_name, uint64_t p_snap_id,
|
||||
rados_ioctx_t c_ioctx, const char *c_name,
|
||||
rbd_image_options_t c_opts) {
|
||||
// cast function pointer fn to rbd_clone4 and call the function
|
||||
return ((rbd_clone4_fn) fn)(p_ioctx, p_name, p_snap_id, c_ioctx, c_name, c_opts);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ceph/go-ceph/internal/dlsym"
|
||||
"github.com/ceph/go-ceph/rados"
|
||||
)
|
||||
|
||||
var (
|
||||
rbdClone4Once sync.Once
|
||||
rbdClone4 unsafe.Pointer
|
||||
rbdClone4Err error
|
||||
)
|
||||
|
||||
// CloneImageByID creates a clone of the image from a snapshot with the given
|
||||
// ID in the provided io-context with the given name and image options.
|
||||
//
|
||||
|
@ -25,22 +51,33 @@ import (
|
|||
// const char *c_name, rbd_image_options_t c_opts);
|
||||
func CloneImageByID(ioctx *rados.IOContext, parentName string, snapID uint64,
|
||||
destctx *rados.IOContext, name string, rio *ImageOptions) error {
|
||||
|
||||
if rio == nil {
|
||||
return rbdError(C.EINVAL)
|
||||
}
|
||||
|
||||
rbdClone4Once.Do(func() {
|
||||
rbdClone4, rbdClone4Err = dlsym.LookupSymbol("rbd_clone4")
|
||||
})
|
||||
|
||||
if rbdClone4Err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrNotImplemented, rbdClone4Err)
|
||||
}
|
||||
|
||||
cParentName := C.CString(parentName)
|
||||
defer C.free(unsafe.Pointer(cParentName))
|
||||
cCloneName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cCloneName))
|
||||
|
||||
ret := C.rbd_clone4(
|
||||
// call rbd_clone4_dlsym with the function pointer to rbd_clone4 as 1st
|
||||
// argument
|
||||
ret := C.rbd_clone4_dlsym(
|
||||
rbdClone4,
|
||||
cephIoctx(ioctx),
|
||||
cParentName,
|
||||
C.uint64_t(snapID),
|
||||
cephIoctx(destctx),
|
||||
cCloneName,
|
||||
C.rbd_image_options_t(rio.options))
|
||||
|
||||
return getError(ret)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//go:build !(nautilus || octopus || pacific || quincy || reef) && ceph_preview
|
||||
//go:build ceph_preview
|
||||
|
||||
package rbd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -91,6 +92,9 @@ func TestCloneImageByID(t *testing.T) {
|
|||
|
||||
// Create a clone of the image using the snapshot.
|
||||
err = CloneImageByID(ioctx, name1, snapID, ioctx, cloneName, optionsClone)
|
||||
if errors.Is(err, ErrNotImplemented) {
|
||||
t.Skipf("CloneImageByID is not supported: %v", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
defer func() { assert.NoError(t, RemoveImage(ioctx, cloneName)) }()
|
||||
|
||||
|
@ -135,6 +139,9 @@ func TestCloneImageByID(t *testing.T) {
|
|||
|
||||
// Create a clone of the image using the snapshot.
|
||||
err = CloneImageByID(ioctx, name1, snapID, ioctx, cloneName, optionsClone)
|
||||
if errors.Is(err, ErrNotImplemented) {
|
||||
t.Skipf("CloneImageByID is not supported: %v", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
defer func() { assert.NoError(t, RemoveImage(ioctx, cloneName)) }()
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ var (
|
|||
const (
|
||||
// ErrNotExist indicates a non-specific missing resource.
|
||||
ErrNotExist = rbdError(-C.ENOENT)
|
||||
// ErrNotImplemented indicates a function is not implemented in by librbd.
|
||||
ErrNotImplemented = rbdError(-C.ENOSYS)
|
||||
)
|
||||
|
||||
// Private errors:
|
||||
|
|
Loading…
Reference in New Issue