go-ceph/rbd/group_snap.go
John Mulligan 1286e0d4d0 rbd: add GroupSnapRollbackWithProgress function
* Add GroupSnapRollbackWithProgress implementing rbd_group_snap_rollback_with_progress

This has supporting code basically the same as our other existing
callback functions.
Tests too.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
2021-02-08 15:29:11 +00:00

224 lines
6.9 KiB
Go

package rbd
/*
#cgo LDFLAGS: -lrbd
#include <errno.h>
#include <stdlib.h>
#include <rbd/librbd.h>
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)
)
// GroupSnapInfo values are returned by GroupSnapList, representing the
// snapshots that are part of an rbd group.
type GroupSnapInfo struct {
Name string
State GroupSnapState
}
// 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 rbdError(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))
}