Skip to content

Commit

Permalink
rbd: dlsym-ify GroupSnapGetInfo
Browse files Browse the repository at this point in the history
Signed-off-by: Niels de Vos <[email protected]>
  • Loading branch information
nixpanic committed Sep 11, 2024
1 parent 160a5b9 commit b798342
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
87 changes: 82 additions & 5 deletions rbd/group_snap_info.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build ceph_preview && !(nautilus || octopus || pacific || quincy || reef || squid)
//go:build ceph_preview

package rbd

Expand All @@ -8,17 +8,77 @@ package rbd
#include <stdlib.h>
#include <rbd/librbd.h>
// exact copy of librbd.h:rbd_group_image_snap_info_t as it is not included in all versions
typedef struct {
char *image_name;
int64_t pool_id;
uint64_t snap_id;
} _rbd_group_image_snap_info_t; // added "_" prefix
// exact copy of librbd.h:rbd_group_snap_info2_t as it is not included in all versions
typedef struct {
char *id;
char *name;
char *image_snap_name;
rbd_group_snap_state_t state;
//rbd_group_snap_namespace_type_t namespace_type;
size_t image_snaps_count;
_rbd_group_image_snap_info_t *image_snaps;
} _rbd_group_snap_info2_t; // added "_" prefix
// rbd_group_snap_get_info_fn matches the rbd_group_snap_get_info function signature.
typedef int(*rbd_group_snap_get_info_fn)(rados_ioctx_t group_p,
const char *group_name,
const char *snap_name,
_rbd_group_snap_info2_t *snaps);
// rbd_group_snap_get_info_dlsym take *fn as rbd_group_snap_get_info_fn and
// calls the dynamically loaded rbd_group_snap_get_info function passed as 1st
// argument.
static inline int rbd_group_snap_get_info_dlsym(void *fn,
rados_ioctx_t group_p,
const char *group_name,
const char *snap_name,
_rbd_group_snap_info2_t *snaps) {
// cast function pointer fn to rbd_group_snap_get_info and call the function
return ((rbd_group_snap_get_info_fn) fn)(group_p, group_name, snap_name, snaps);
}
// rbd_group_snap_get_info_cleanup_fn matches the rbd_group_snap_get_info_cleanup function signature.
typedef int(*rbd_group_snap_get_info_cleanup_fn)(_rbd_group_snap_info2_t *snaps);
// rbd_group_snap_get_info_cleanup_dlsym take *fn as rbd_group_snap_get_info_cleanup_fn and
// calls the dynamically loaded rbd_group_snap_get_info_cleanup function passed as 1st
// argument.
static inline int rbd_group_snap_get_info_cleanup_dlsym(void *fn,
_rbd_group_snap_info2_t *snaps) {
// cast function pointer fn to rbd_group_snap_get_info_cleanup and call the function
return ((rbd_group_snap_get_info_cleanup_fn) fn)(snaps);
}
*/
import "C"

import (
"fmt"
"sync"
"unsafe"

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

type imgSnapInfoArray [cutil.MaxIdx]C.rbd_group_image_snap_info_t
type imgSnapInfoArray [cutil.MaxIdx]C._rbd_group_image_snap_info_t

var (
rbdGroupGetSnapInfoOnce sync.Once
rbdGroupGetSnapInfo unsafe.Pointer
rbdGroupGetSnapInfoErr error

rbdGroupSnapGetInfoCleanupOnce sync.Once
rbdGroupSnapGetInfoCleanup unsafe.Pointer
rbdGroupSnapGetInfoCleanupErr error
)

// GroupSnapGetInfo returns a slice of RBD image snapshots that are part of a
// group snapshot.
Expand All @@ -30,14 +90,31 @@ type imgSnapInfoArray [cutil.MaxIdx]C.rbd_group_image_snap_info_t
// const char *snap_name,
// rbd_group_snap_info2_t *snaps);
func GroupSnapGetInfo(ioctx *rados.IOContext, group, snap string) (GroupSnapInfo, error) {
rbdGroupGetSnapInfoOnce.Do(func() {
rbdGroupGetSnapInfo, rbdGroupGetSnapInfoErr = dlsym.LookupSymbol("rbd_group_snap_get_info")
})

if rbdGroupGetSnapInfoErr != nil {
return GroupSnapInfo{}, fmt.Errorf("%w: %w", ErrNotImplemented, rbdGroupGetSnapInfoErr)
}

rbdGroupSnapGetInfoCleanupOnce.Do(func() {
rbdGroupSnapGetInfoCleanup, rbdGroupSnapGetInfoCleanupErr = dlsym.LookupSymbol("rbd_group_snap_get_info_cleanup")
})

if rbdGroupSnapGetInfoCleanupErr != nil {
return GroupSnapInfo{}, fmt.Errorf("%w: %w", ErrNotImplemented, rbdGroupSnapGetInfoCleanupErr)
}

cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cSnapName := C.CString(snap)
defer C.free(unsafe.Pointer(cSnapName))

cSnapInfo := C.rbd_group_snap_info2_t{}
cSnapInfo := C._rbd_group_snap_info2_t{}

ret := C.rbd_group_snap_get_info(
ret := C.rbd_group_snap_get_info_dlsym(
rbdGroupGetSnapInfo,
cephIoctx(ioctx),
cGroupName,
cSnapName,
Expand Down Expand Up @@ -66,6 +143,6 @@ func GroupSnapGetInfo(ioctx *rados.IOContext, group, snap string) (GroupSnapInfo
}

// free C memory allocated by C.rbd_group_snap_get_info call
C.rbd_group_snap_get_info_cleanup(&cSnapInfo)
C.rbd_group_snap_get_info_cleanup_dlsym(rbdGroupSnapGetInfoCleanup, &cSnapInfo)
return snapInfo, nil
}
4 changes: 4 additions & 0 deletions rbd/group_snap_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rbd

import (
"errors"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -113,6 +114,9 @@ func TestGroupSnapshots(t *testing.T) {
}()

info, err := GroupSnapGetInfo(ioctx, gname, "snapDetails")
if errors.Is(err, ErrNotImplemented) {
t.Skipf("GroupSnapGetInfo is not supported: %v", err)
}
assert.NoError(t, err)

assert.Equal(t, GroupSnapStateComplete, info.State)
Expand Down

0 comments on commit b798342

Please sign in to comment.