Skip to content

Commit

Permalink
librbd exposes rbd_resize2, which allows clients to pass in a boolean…
Browse files Browse the repository at this point in the history
… 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
khayyamsaleem authored and mergify[bot] committed Nov 8, 2023
1 parent 3d86572 commit 51b8287
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 2 deletions.
11 changes: 9 additions & 2 deletions docs/api-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down Expand Up @@ -2209,4 +2216,4 @@
}
]
}
}
}
6 changes: 6 additions & 0 deletions docs/api-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
77 changes: 77 additions & 0 deletions rbd/resize.go
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)

}
73 changes: 73 additions & 0 deletions rbd/resize_test.go
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()
}

0 comments on commit 51b8287

Please sign in to comment.