-
Notifications
You must be signed in to change notification settings - Fork 258
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
librbd exposes rbd_resize2, which allows clients to pass in a boolean…
… controlling whether or not the allocation should be allowed to shrink, and a progress-tracking callback. This contribution extends go-ceph to be able to call rbd_resize2. Closes #933 Signed-off-by: Khayyam Saleem <khayyam.saleem@gmail.com>
- Loading branch information
1 parent
3d86572
commit 51b8287
Showing
4 changed files
with
165 additions
and
2 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,77 @@ | ||
//go:build ceph_preview | ||
|
||
package rbd | ||
|
||
/* | ||
#cgo LDFLAGS: -lrbd | ||
#define _POSIX_C_SOURCE 200112L | ||
#undef _GNU_SOURCE | ||
#include <errno.h> | ||
#include <stdlib.h> | ||
#include <rados/librados.h> | ||
#include <rbd/librbd.h> | ||
extern int resize2Callback(uint64_t, uint64_t, uintptr_t); | ||
// inline wrapper to cast uintptr_t to void* | ||
static inline int wrap_rbd_resize2( | ||
rbd_image_t image, uint64_t size, bool allow_shrink, uintptr_t arg) { | ||
return rbd_resize2( | ||
image, size, allow_shrink, (librbd_progress_fn_t)resize2Callback, (void*)arg); | ||
}; | ||
*/ | ||
import "C" | ||
|
||
import ( | ||
"github.com/ceph/go-ceph/internal/callbacks" | ||
) | ||
|
||
// Resize2ProgressCallback is the callback function type for Image.Resize2. | ||
type Resize2ProgressCallback func(progress uint64, total uint64, data interface{}) int | ||
|
||
var resizeCallbacks = callbacks.New() | ||
|
||
type resizeProgressCallbackCtx struct { | ||
callback Resize2ProgressCallback | ||
data interface{} | ||
} | ||
|
||
//export resize2Callback | ||
func resize2Callback( | ||
offset, total C.uint64_t, index uintptr, | ||
) C.int { | ||
v := resizeCallbacks.Lookup(index) | ||
ctx := v.(resizeProgressCallbackCtx) | ||
return C.int(ctx.callback(uint64(offset), uint64(total), ctx.data)) | ||
} | ||
|
||
// Resize2 resizes an rbd image and allows configuration of allow_shrink and a callback function. The callback | ||
// function will be called with the first argument as the progress, the second argument as the total, and the third | ||
// argument as an opaque value that is passed to the Resize2 function's data argument in each callback execution. | ||
// The resize operation will be aborted if the progress callback returns a non-zero value. | ||
// | ||
// Implements: | ||
// | ||
// int rbd_resize(rbd_image_t image, uint64_t size, allow_shrink bool, librbd_progress_fn_t cb, void *cbdata); | ||
func (image *Image) Resize2(size uint64, allowShrink bool, cb Resize2ProgressCallback, 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 := resizeProgressCallbackCtx{ | ||
callback: cb, | ||
data: data, | ||
} | ||
cbIndex := resizeCallbacks.Add(ctx) | ||
defer resizeCallbacks.Remove(cbIndex) | ||
|
||
ret := C.wrap_rbd_resize2(image.image, C.uint64_t(size), C.bool(allowShrink), C.uintptr_t(cbIndex)) | ||
|
||
return getError(ret) | ||
|
||
} |
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,73 @@ | ||
//go:build ceph_preview | ||
|
||
package rbd | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestImageResize2(t *testing.T) { | ||
cc := 0 | ||
cb := func(offset, total uint64, v interface{}) int { | ||
cc++ | ||
val := v.(int) | ||
assert.Equal(t, 0, val) | ||
assert.Equal(t, uint64(2), total) | ||
return 0 | ||
} | ||
|
||
conn := radosConnect(t) | ||
|
||
poolname := GetUUID() | ||
err := conn.MakePool(poolname) | ||
assert.NoError(t, err) | ||
|
||
ioctx, err := conn.OpenIOContext(poolname) | ||
require.NoError(t, err) | ||
|
||
name := GetUUID() | ||
reqSize := uint64(1024 * 1024 * 4) // 4MB | ||
err = quickCreate(ioctx, name, reqSize, testImageOrder) | ||
assert.NoError(t, err) | ||
|
||
image, err := OpenImage(ioctx, name, NoSnapshot) | ||
assert.NoError(t, err) | ||
|
||
size, err := image.GetSize() | ||
assert.NoError(t, err) | ||
assert.Equal(t, size, reqSize) | ||
|
||
newReqSize := reqSize * 2 | ||
|
||
// Test normal resize (no shrinking allowed) | ||
err = image.Resize2(newReqSize, false, cb, nil) | ||
assert.NoError(t, err) | ||
|
||
size, err = image.GetSize() | ||
assert.NoError(t, err) | ||
assert.Equal(t, size, newReqSize) | ||
|
||
// Resize to a smaller size with shrinking allowed | ||
err = image.Resize2(reqSize, true, cb, 0) | ||
assert.NoError(t, err) | ||
|
||
// Attempt to resize to a smaller size with shrinking disallowed (should error) | ||
err = image.Resize2(reqSize-1024*1024, false, cb, 0) | ||
assert.Error(t, err) | ||
|
||
err = image.Close() | ||
assert.NoError(t, err) | ||
|
||
err = image.Resize2(newReqSize, false, cb, 0) | ||
assert.Error(t, err) // Expect an error since the image is not open/ | ||
|
||
err = image.Remove() | ||
assert.NoError(t, err) | ||
|
||
ioctx.Destroy() | ||
conn.DeletePool(poolname) | ||
conn.Shutdown() | ||
} |