Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rbd: add support for rbd_diff_iterate3 api #1064

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/api-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1959,6 +1959,12 @@
"comment": "EncryptionLoad2 enables IO on an open encrypted image. Multiple encryption\noption values can be passed to this call in a slice. For more information\nabout how items in the slice are applied to images, and possibly ancestor\nimages refer to the documentation in the C api for rbd_encryption_load2.\n\nImplements:\n\n\tint rbd_encryption_load2(rbd_image_t image,\n\t const rbd_encryption_spec_t *specs,\n\t size_t spec_count);\n",
"added_in_version": "v0.32.0",
"expected_stable_version": "v0.34.0"
},
{
"name": "Image.DiffIterateByID",
"comment": "DiffIterateByID calls a callback on changed extents of an image.\n\nCalling DiffIterateByID will cause the callback specified in the\nDiffIterateConfig to be called as many times as there are changed\nregions in the image (controlled by the parameters as passed to librbd).\n\nSee the documentation of DiffIterateCallback for a description of the\narguments to the callback and the return behavior.\n\nImplements:\n\n\tint rbd_diff_iterate3(rbd_image_t image,\n\t uint64_t from_snap_id,\n\t uint64_t ofs, uint64_t len,\n\t uint8_t include_parent, uint8_t whole_object,\n\t int (*cb)(uint64_t, size_t, int, void *),\n\t void *arg);\n",
"added_in_version": "$NEXT_RELEASE",
"expected_stable_version": "$NEXT_RELEASE_STABLE"
}
]
},
Expand Down
1 change: 1 addition & 0 deletions docs/api-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Conn.GetAddrs | v0.31.0 | v0.33.0 |
Name | Added in Version | Expected Stable Version |
---- | ---------------- | ----------------------- |
Image.EncryptionLoad2 | v0.32.0 | v0.34.0 |
Image.DiffIterateByID | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |

### Deprecated APIs

Expand Down
105 changes: 105 additions & 0 deletions rbd/diff_iterate_by_id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//go:build ceph_preview

package rbd

/*
#cgo LDFLAGS: -lrbd
#undef _GNU_SOURCE
#include <errno.h>
#include <stdlib.h>
#include <rbd/librbd.h>

extern int diffIterateCallback(uint64_t, size_t, int, uintptr_t);

// rbd_diff_iterate3_fn matches the rbd_diff_iterate3 function signature.
typedef int(*rbd_diff_iterate3_fn)(rbd_image_t image, uint64_t from_snap_id,
uint64_t ofs, uint64_t len, uint8_t include_parent, uint8_t whole_object,
int (*cb)(uint64_t, size_t, int, void *), void *arg);

// rbd_diff_iterate3_dlsym take *fn as rbd_diff_iterate3_fn and calls the dynamically loaded
// rbd_diff_iterate3 function passed as 1st argument.
static inline int rbd_diff_iterate3_dlsym(void *fn, rbd_image_t image,
uint64_t from_snap_id, uint64_t ofs, uint64_t len, uint8_t include_parent,
uint8_t whole_object, uintptr_t arg) {
// cast function pointer fn to rbd_diff_iterate3 and call the function
return ((rbd_diff_iterate3_fn) fn)(image, from_snap_id, ofs, len, include_parent,
whole_object, (void*)diffIterateCallback, (void*)arg);
}
*/
import "C"

import (
"fmt"
"sync"
"unsafe"

"github.com/ceph/go-ceph/internal/dlsym"
)

var (
diffIterateByIDOnce sync.Once
diffIterateById unsafe.Pointer
diffIterateByIdErr error
)

// DiffIterateByIDConfig is used to define the parameters of a DiffIterateByID call.
// Callback, Offset, and Length should always be specified when passed to
// DiffIterateByID. The other values are optional.
type DiffIterateByIDConfig struct {
FromSnapID uint64
Offset uint64
Length uint64
IncludeParent DiffIncludeParent
WholeObject DiffWholeObject
Callback DiffIterateCallback
Data interface{}
}

// DiffIterateByID calls a callback on changed extents of an image.
//
// Calling DiffIterateByID will cause the callback specified in the
// DiffIterateConfig to be called as many times as there are changed
// regions in the image (controlled by the parameters as passed to librbd).
//
// See the documentation of DiffIterateCallback for a description of the
// arguments to the callback and the return behavior.
//
// Implements:
//
// int rbd_diff_iterate3(rbd_image_t image,
// uint64_t from_snap_id,
// uint64_t ofs, uint64_t len,
// uint8_t include_parent, uint8_t whole_object,
// int (*cb)(uint64_t, size_t, int, void *),
// void *arg);
func (image *Image) DiffIterateByID(config DiffIterateByIDConfig) error {
if err := image.validate(imageIsOpen); err != nil {
return err
}
if config.Callback == nil {
return getError(C.EINVAL)
}

diffIterateByIDOnce.Do(func() {
diffIterateById, diffIterateByIdErr = dlsym.LookupSymbol("rbd_diff_iterate3")
})

if diffIterateByIdErr != nil {
return fmt.Errorf("%w: %w", ErrNotImplemented, diffIterateByIdErr)
}

cbIndex := diffIterateCallbacks.Add(config)
defer diffIterateCallbacks.Remove(cbIndex)

ret := C.rbd_diff_iterate3_dlsym(
diffIterateById,
image.image,
C.uint64_t(config.FromSnapID),
C.uint64_t(config.Offset),
C.uint64_t(config.Length),
C.uint8_t(config.IncludeParent),
C.uint8_t(config.WholeObject),
C.uintptr_t(cbIndex))

return getError(ret)
}