package rbd /* #cgo LDFLAGS: -lrbd #include #include #include extern int snapRollbackCallback(uint64_t, uint64_t, uintptr_t); // inline wrapper to cast uintptr_t to void* static inline int wrap_rbd_group_snap_rollback_with_progress( rados_ioctx_t group_p, const char *group_name, const char *snap_name, uintptr_t arg) { return rbd_group_snap_rollback_with_progress( group_p, group_name, snap_name, (librbd_progress_fn_t)snapRollbackCallback, (void*)arg); }; */ import "C" import ( "unsafe" "github.com/ceph/go-ceph/internal/callbacks" "github.com/ceph/go-ceph/internal/retry" "github.com/ceph/go-ceph/rados" ) // GroupSnapCreate will create a group snapshot. // // Implements: // // int rbd_group_snap_create(rados_ioctx_t group_p, // const char *group_name, // const char *snap_name); func GroupSnapCreate(ioctx *rados.IOContext, group, snap string) error { cGroupName := C.CString(group) defer C.free(unsafe.Pointer(cGroupName)) cSnapName := C.CString(snap) defer C.free(unsafe.Pointer(cSnapName)) ret := C.rbd_group_snap_create(cephIoctx(ioctx), cGroupName, cSnapName) return getError(ret) } // GroupSnapRemove removes an existing group snapshot. // // Implements: // // int rbd_group_snap_remove(rados_ioctx_t group_p, // const char *group_name, // const char *snap_name); func GroupSnapRemove(ioctx *rados.IOContext, group, snap string) error { cGroupName := C.CString(group) defer C.free(unsafe.Pointer(cGroupName)) cSnapName := C.CString(snap) defer C.free(unsafe.Pointer(cSnapName)) ret := C.rbd_group_snap_remove(cephIoctx(ioctx), cGroupName, cSnapName) return getError(ret) } // GroupSnapRename will rename an existing group snapshot. // // Implements: // // int rbd_group_snap_rename(rados_ioctx_t group_p, // const char *group_name, // const char *old_snap_name, // const char *new_snap_name); func GroupSnapRename(ioctx *rados.IOContext, group, src, dest string) error { cGroupName := C.CString(group) defer C.free(unsafe.Pointer(cGroupName)) cOldSnapName := C.CString(src) defer C.free(unsafe.Pointer(cOldSnapName)) cNewSnapName := C.CString(dest) defer C.free(unsafe.Pointer(cNewSnapName)) ret := C.rbd_group_snap_rename( cephIoctx(ioctx), cGroupName, cOldSnapName, cNewSnapName) return getError(ret) } // GroupSnapState represents the state of a group snapshot in GroupSnapInfo. type GroupSnapState int const ( // GroupSnapStateIncomplete is equivalent to RBD_GROUP_SNAP_STATE_INCOMPLETE. GroupSnapStateIncomplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_INCOMPLETE) // GroupSnapStateComplete is equivalent to RBD_GROUP_SNAP_STATE_COMPLETE. GroupSnapStateComplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_COMPLETE) ) // GroupSnap contains the information of a single snapshot that is part of a // group snapshot. type GroupSnap struct { Name string PoolID uint64 SnapID uint64 } // GroupSnapInfo values are returned by GroupSnapList and GroupSnapGetInfo, // representing the group snapshots that are created of an rbd group. // SnapName, ID and Snapshots are only set by the GroupSnapGetInfo function. type GroupSnapInfo struct { Name string State GroupSnapState SnapName string ID string Snapshots []GroupSnap } // GroupSnapList returns a slice of snapshots in a group. // // Implements: // // int rbd_group_snap_list(rados_ioctx_t group_p, // const char *group_name, // rbd_group_snap_info_t *snaps, // size_t group_snap_info_size, // size_t *num_entries); func GroupSnapList(ioctx *rados.IOContext, group string) ([]GroupSnapInfo, error) { cGroupName := C.CString(group) defer C.free(unsafe.Pointer(cGroupName)) var ( cSnaps []C.rbd_group_snap_info_t cSize C.size_t err error ) retry.WithSizes(1024, 262144, func(size int) retry.Hint { cSize = C.size_t(size) cSnaps = make([]C.rbd_group_snap_info_t, cSize) ret := C.rbd_group_snap_list( cephIoctx(ioctx), cGroupName, (*C.rbd_group_snap_info_t)(unsafe.Pointer(&cSnaps[0])), C.sizeof_rbd_group_snap_info_t, &cSize) err = getErrorIfNegative(ret) return retry.Size(int(cSize)).If(err == errRange) }) if err != nil { return nil, err } snaps := make([]GroupSnapInfo, cSize) for i := range snaps { snaps[i].Name = C.GoString(cSnaps[i].name) snaps[i].State = GroupSnapState(cSnaps[i].state) } // free C memory allocated by C.rbd_group_snap_list call ret := C.rbd_group_snap_list_cleanup( (*C.rbd_group_snap_info_t)(unsafe.Pointer(&cSnaps[0])), C.sizeof_rbd_group_snap_info_t, cSize) return snaps, getError(ret) } // GroupSnapRollback will roll back the images in the group to that of the // given snapshot. // // Implements: // // int rbd_group_snap_rollback(rados_ioctx_t group_p, // const char *group_name, // const char *snap_name); func GroupSnapRollback(ioctx *rados.IOContext, group, snap string) error { cGroupName := C.CString(group) defer C.free(unsafe.Pointer(cGroupName)) cSnapName := C.CString(snap) defer C.free(unsafe.Pointer(cSnapName)) ret := C.rbd_group_snap_rollback(cephIoctx(ioctx), cGroupName, cSnapName) return getError(ret) } // GroupSnapRollbackCallback defines the function signature needed for the // GroupSnapRollbackWithProgress callback. // // This callback will be called by GroupSnapRollbackWithProgress when it // wishes to report progress rolling back a group snapshot. type GroupSnapRollbackCallback func(uint64, uint64, interface{}) int var groupSnapRollbackCallbacks = callbacks.New() // GroupSnapRollbackWithProgress will roll back the images in the group // to that of given snapshot. The given progress callback will be called // to report on the progress of the snapshot rollback. // // Implements: // // int rbd_group_snap_rollback_with_progress(rados_ioctx_t group_p, // const char *group_name, // const char *snap_name, // librbd_progress_fn_t cb, // void *cbdata); func GroupSnapRollbackWithProgress( ioctx *rados.IOContext, group, snap string, cb GroupSnapRollbackCallback, data interface{}) error { // the provided callback must be a real function if cb == nil { return getError(C.EINVAL) } cGroupName := C.CString(group) defer C.free(unsafe.Pointer(cGroupName)) cSnapName := C.CString(snap) defer C.free(unsafe.Pointer(cSnapName)) ctx := gsnapRollbackCallbackCtx{ callback: cb, data: data, } cbIndex := groupSnapRollbackCallbacks.Add(ctx) defer diffIterateCallbacks.Remove(cbIndex) ret := C.wrap_rbd_group_snap_rollback_with_progress( cephIoctx(ioctx), cGroupName, cSnapName, C.uintptr_t(cbIndex)) return getError(ret) } type gsnapRollbackCallbackCtx struct { callback GroupSnapRollbackCallback data interface{} } //export snapRollbackCallback func snapRollbackCallback( offset, total C.uint64_t, index uintptr) C.int { v := groupSnapRollbackCallbacks.Lookup(index) ctx := v.(gsnapRollbackCallbackCtx) return C.int(ctx.callback(uint64(offset), uint64(total), ctx.data)) }