//go:build ceph_preview package rbd /* #cgo LDFLAGS: -lrbd #include #include #include // 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 }