mirror of https://github.com/ceph/go-ceph
rbd: Add rbd_sparsify_with_progress rbd API
Added a new rbd API `rbd_sparsify_with_progress`, and supporting tests. Fixes: #281 Signed-off-by: Nikhil-Ladha <nikhilladha1999@gmail.com>
This commit is contained in:
parent
66ffbfa633
commit
3d986f2bd3
|
@ -1867,6 +1867,12 @@
|
||||||
"comment": "SetMirrorPeerSiteDirection sets the direction of a mirror peer site.\n",
|
"comment": "SetMirrorPeerSiteDirection sets the direction of a mirror peer site.\n",
|
||||||
"added_in_version": "v0.21.0",
|
"added_in_version": "v0.21.0",
|
||||||
"expected_stable_version": "v0.23.0"
|
"expected_stable_version": "v0.23.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Image.SparsifyWithProgress",
|
||||||
|
"comment": "SparsifyWithProgress makes an image sparse by deallocating runs of zeros.\nThe sparseSize value will be used to find runs of zeros and must be\na power of two no less than 4096 and no larger than the image size.\nThe given progress callback will be called to report on the progress\nof sparse. The operation will be aborted if the progress callback returns\na non-zero value.\n\nImplements:\n\n\tint rbd_sparsify_with_progress(rbd_image_t image, size_t sparse_size,\n\t\t\t\t\t\t\t\t librbd_progress_fn_t cb, void *cbdata);\n",
|
||||||
|
"added_in_version": "$NEXT_RELEASE",
|
||||||
|
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -63,6 +63,7 @@ ListMirrorPeerSite | v0.21.0 | v0.23.0 |
|
||||||
SetMirrorPeerSiteClientName | v0.21.0 | v0.23.0 |
|
SetMirrorPeerSiteClientName | v0.21.0 | v0.23.0 |
|
||||||
SetMirrorPeerSiteName | v0.21.0 | v0.23.0 |
|
SetMirrorPeerSiteName | v0.21.0 | v0.23.0 |
|
||||||
SetMirrorPeerSiteDirection | v0.21.0 | v0.23.0 |
|
SetMirrorPeerSiteDirection | v0.21.0 | v0.23.0 |
|
||||||
|
Image.SparsifyWithProgress | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||||
|
|
||||||
### Deprecated APIs
|
### Deprecated APIs
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
//go:build !nautilus && ceph_preview
|
||||||
|
// +build !nautilus,ceph_preview
|
||||||
|
|
||||||
|
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.
|
||||||
|
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 rbdError(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))
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
//go:build !nautilus && ceph_preview
|
||||||
|
// +build !nautilus,ceph_preview
|
||||||
|
|
||||||
|
package rbd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSparsifyWithProgress(t *testing.T) {
|
||||||
|
conn := radosConnect(t)
|
||||||
|
defer conn.Shutdown()
|
||||||
|
|
||||||
|
poolname := GetUUID()
|
||||||
|
err := conn.MakePool(poolname)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer conn.DeletePool(poolname)
|
||||||
|
|
||||||
|
ioctx, err := conn.OpenIOContext(poolname)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer ioctx.Destroy()
|
||||||
|
|
||||||
|
name := GetUUID()
|
||||||
|
err = quickCreate(ioctx, name, testImageSize, testImageOrder)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, RemoveImage(ioctx, name)) }()
|
||||||
|
|
||||||
|
t.Run("valid", func(t *testing.T) {
|
||||||
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
cc := 0
|
||||||
|
cb := func(offset, total uint64, v interface{}) int {
|
||||||
|
cc++
|
||||||
|
val := v.(int)
|
||||||
|
assert.Equal(t, 0, val)
|
||||||
|
assert.Equal(t, uint64(1), total)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
err = img.SparsifyWithProgress(4096, cb, 0)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.GreaterOrEqual(t, cc, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("negativeReturnValue", func(t *testing.T) {
|
||||||
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
cc := 0
|
||||||
|
cb := func(offset, total uint64, v interface{}) int {
|
||||||
|
cc++
|
||||||
|
val := v.(int)
|
||||||
|
assert.Equal(t, 0, val)
|
||||||
|
assert.Equal(t, uint64(1), total)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
err = img.SparsifyWithProgress(4096, cb, 0)
|
||||||
|
assert.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("closedImage", func(t *testing.T) {
|
||||||
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, img.Close())
|
||||||
|
|
||||||
|
cc := 0
|
||||||
|
cb := func(offset, total uint64, v interface{}) int {
|
||||||
|
cc++
|
||||||
|
val := v.(int)
|
||||||
|
assert.Equal(t, 0, val)
|
||||||
|
assert.Equal(t, uint64(1), total)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
err = img.SparsifyWithProgress(4096, cb, 0)
|
||||||
|
assert.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalidValue", func(t *testing.T) {
|
||||||
|
img, err := OpenImage(ioctx, name, NoSnapshot)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
err = img.SparsifyWithProgress(4096, nil, nil)
|
||||||
|
assert.Error(t, err)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue