-
Notifications
You must be signed in to change notification settings - Fork 251
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
1 parent
66ffbfa
commit 275b36f
Showing
4 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
}) | ||
} |