mirror of
https://github.com/ceph/go-ceph
synced 2025-02-03 12:02:05 +00:00
df352fd90b
Instead of removing a respective progress callback, DiffIterate extent callback is attempted to be removed. This leaks the progress callback and on top of that it's quite possible for DiffIterate to be disrupted as cbIndex is not a unique pointer but just an integer ID. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
244 lines
7.2 KiB
Go
244 lines
7.2 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)
|
|
)
|
|
|
|
// 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 groupSnapRollbackCallbacks.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))
|
|
}
|