go-ceph/rbd/sparsify.go

90 lines
2.7 KiB
Go

//go:build !nautilus
// +build !nautilus
package rbd
/*
#cgo LDFLAGS: -lrbd
#include <errno.h>
#include <stdlib.h>
#include <rbd/librbd.h>
extern int sparsifyCallback(uint64_t, uint64_t, uintptr_t);
// inline wrapper to cast uintptr_t to void*
static inline int wrap_rbd_sparsify_with_progress(
rbd_image_t image, size_t sparse_size, uintptr_t arg) {
return rbd_sparsify_with_progress(
image, sparse_size, (librbd_progress_fn_t)sparsifyCallback, (void*)arg);
};
*/
import "C"
import (
"github.com/ceph/go-ceph/internal/callbacks"
)
// SparsifyCallback defines the function signature needed for the
// SparsifyWithProgress callback.
//
// This callback will be called by SparsifyWithProgress when it wishes to
// report progress on sparse. The callback function will be called with the
// first argument containing the current offset within the image being made
// sparse and the second argument containing the total size of the image. The
// third argument is an opaque value that is passed to the SparsifyWithProgress
// function's data argument and every call to the callback will receive the
// same object. The sparsify operation will be aborted if the progress
// callback returns a non-zero value.
type SparsifyCallback func(uint64, uint64, interface{}) int
var sparsifyCallbacks = callbacks.New()
type sparsifyCallbackCtx struct {
callback SparsifyCallback
data interface{}
}
// SparsifyWithProgress makes an image sparse by deallocating runs of zeros.
// The sparseSize value will be used to find runs of zeros and must be
// a power of two no less than 4096 and no larger than the image size.
// The given progress callback will be called to report on the progress
// of sparse. The operation will be aborted if the progress callback returns
// a non-zero value.
//
// Implements:
//
// int rbd_sparsify_with_progress(rbd_image_t image, size_t sparse_size,
// librbd_progress_fn_t cb, void *cbdata);
func (image *Image) SparsifyWithProgress(
sparseSize uint, cb SparsifyCallback, data interface{},
) error {
// the provided callback must be a real function
if cb == nil {
return getError(C.EINVAL)
}
if err := image.validate(imageIsOpen); err != nil {
return err
}
ctx := sparsifyCallbackCtx{
callback: cb,
data: data,
}
cbIndex := sparsifyCallbacks.Add(ctx)
defer diffIterateCallbacks.Remove(cbIndex)
ret := C.wrap_rbd_sparsify_with_progress(image.image, C.size_t(sparseSize), C.uintptr_t(cbIndex))
return getError(ret)
}
//export sparsifyCallback
func sparsifyCallback(
offset, total C.uint64_t, index uintptr,
) C.int {
v := sparsifyCallbacks.Lookup(index)
ctx := v.(sparsifyCallbackCtx)
return C.int(ctx.callback(uint64(offset), uint64(total), ctx.data))
}