mirror of
https://github.com/ceph/go-ceph
synced 2025-01-12 00:59:58 +00:00
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>
This commit is contained in:
parent
3d86572bf6
commit
51b8287148
@ -1918,7 +1918,14 @@
|
||||
"became_stable_version": "v0.24.0"
|
||||
}
|
||||
],
|
||||
"preview_api": []
|
||||
"preview_api": [
|
||||
{
|
||||
"name": "Image.Resize2",
|
||||
"comment": "Resize2 resizes an rbd image and allows configuration of allow_shrink and a callback function. The callback\nfunction will be called with the first argument as the progress, the second argument as the total, and the third\nargument as an opaque value that is passed to the Resize2 function's data argument in each callback execution.\nThe resize operation will be aborted if the progress callback returns a non-zero value.\n\nImplements:\n\n\tint rbd_resize(rbd_image_t image, uint64_t size, allow_shrink bool, librbd_progress_fn_t cb, void *cbdata);\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rbd/admin": {
|
||||
"stable_api": [
|
||||
@ -2209,4 +2216,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,12 @@ No Preview/Deprecated APIs found. All APIs are considered stable.
|
||||
|
||||
## Package: rbd
|
||||
|
||||
### Preview APIs
|
||||
|
||||
Name | Added in Version | Expected Stable Version |
|
||||
---- | ---------------- | ----------------------- |
|
||||
Image.Resize2 | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
Name | Deprecated in Version | Expected Removal Version |
|
||||
|
77
rbd/resize.go
Normal file
77
rbd/resize.go
Normal file
@ -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)
|
||||
|
||||
}
|
73
rbd/resize_test.go
Normal file
73
rbd/resize_test.go
Normal file
@ -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()
|
||||
}
|
Loading…
Reference in New Issue
Block a user