Skip to content

Commit

Permalink
rbd: let CloneImageByID check for rbd_clone4 at runtime
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
nixpanic committed Jul 12, 2024
1 parent 63e64c2 commit 6e69c32
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
42 changes: 35 additions & 7 deletions rbd/clone_image_by_id.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
//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"
"unsafe"

"github.com/ceph/go-ceph/internal/dlsym"
"github.com/ceph/go-ceph/rados"
)

Expand All @@ -30,17 +49,26 @@ func CloneImageByID(ioctx *rados.IOContext, parentName string, snapID uint64,
return rbdError(C.EINVAL)
}

rbd_clone4, err := dlsym.LookupSymbol("rbd_clone4")

Check failure on line 52 in rbd/clone_image_by_id.go

View workflow job for this annotation

GitHub Actions / check

don't use underscores in Go names; var rbd_clone4 should be rbdClone4
if err != nil {
return fmt.Errorf("%w: %w", ErrNotImplemented, err)
}

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(
rbd_clone4,
cephIoctx(ioctx),
cParentName,
C.uint64_t(snapID),
cephIoctx(destctx),
cCloneName,
C.rbd_image_options_t(rio.options))

return getError(ret)
}
9 changes: 8 additions & 1 deletion rbd/clone_image_by_id_test.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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)) }()

Expand Down Expand Up @@ -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)) }()

Expand Down
2 changes: 2 additions & 0 deletions rbd/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 6e69c32

Please sign in to comment.