go-ceph/rbd/group_snap_info.go

155 lines
5.0 KiB
Go

//go:build ceph_preview
package rbd
/*
#cgo LDFLAGS: -lrbd
#include <errno.h>
#include <stdlib.h>
#include <rbd/librbd.h>
// Types and constants are copied from librbd.h with added "_" as prefix. This
// prevents redefinition of the types on librbd versions that have them
// already.
typedef enum {
_RBD_GROUP_SNAP_NAMESPACE_TYPE_USER = 0
} _rbd_group_snap_namespace_type_t;
typedef struct {
char *image_name;
int64_t pool_id;
uint64_t snap_id;
} _rbd_group_image_snap_info_t;
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;
// 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
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.
//
// Implements:
//
// int rbd_group_snap_get_info(rados_ioctx_t group_p,
// const char *group_name,
// 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{}
ret := C.rbd_group_snap_get_info_dlsym(
rbdGroupGetSnapInfo,
cephIoctx(ioctx),
cGroupName,
cSnapName,
&cSnapInfo)
err := getErrorIfNegative(ret)
if err != nil {
return GroupSnapInfo{}, err
}
snapCount := uint64(cSnapInfo.image_snaps_count)
snapInfo := GroupSnapInfo{
ID: C.GoString(cSnapInfo.id),
Name: C.GoString(cSnapInfo.name),
SnapName: C.GoString(cSnapInfo.image_snap_name),
State: GroupSnapState(cSnapInfo.state),
Snapshots: make([]GroupSnap, snapCount),
}
imgSnaps := (*imgSnapInfoArray)(unsafe.Pointer(cSnapInfo.image_snaps))[0:snapCount]
for i, imgSnap := range imgSnaps {
snapInfo.Snapshots[i].Name = C.GoString(imgSnap.image_name)
snapInfo.Snapshots[i].PoolID = uint64(imgSnap.pool_id)
snapInfo.Snapshots[i].SnapID = uint64(imgSnap.snap_id)
}
// free C memory allocated by C.rbd_group_snap_get_info call
C.rbd_group_snap_get_info_cleanup_dlsym(rbdGroupSnapGetInfoCleanup, &cSnapInfo)
return snapInfo, nil
}