Skip to content

Commit 7a572b7

Browse files
committed
rbd: add support for rbd_diff_iterate3 api
This commit adds support for rbd_diff_iterate3 through DiffIterateByID() which performs diff interate using snapshot id instead of snapshot name. This is useful in cases such as when rbd snapshot is in trash or rbd(group) snapshot in in group namespace. refer: - https://tracker.ceph.com/issues/65720 Signed-off-by: Rakshith R <rar@redhat.com>
1 parent d284d22 commit 7a572b7

File tree

4 files changed

+670
-0
lines changed

4 files changed

+670
-0
lines changed

docs/api-status.json

+6
Original file line numberDiff line numberDiff line change
@@ -1963,6 +1963,12 @@
19631963
"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",
19641964
"added_in_version": "v0.32.0",
19651965
"expected_stable_version": "v0.34.0"
1966+
},
1967+
{
1968+
"name": "Image.DiffIterateByID",
1969+
"comment": "DiffIterateByID calls a callback on changed extents of an image.\n\nCalling DiffIterateByID will cause the callback specified in the\nDiffIterateByIDConfig 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 uint32_t flags,\n\t int (*cb)(uint64_t, size_t, int, void *),\n\t void *arg);\n",
1970+
"added_in_version": "$NEXT_RELEASE",
1971+
"expected_stable_version": "$NEXT_RELEASE_STABLE"
19661972
}
19671973
]
19681974
},

docs/api-status.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Conn.GetAddrs | v0.31.0 | v0.33.0 |
2525
Name | Added in Version | Expected Stable Version |
2626
---- | ---------------- | ----------------------- |
2727
Image.EncryptionLoad2 | v0.32.0 | v0.34.0 |
28+
Image.DiffIterateByID | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
2829

2930
### Deprecated APIs
3031

rbd/diff_iterate_by_id.go

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//go:build ceph_preview
2+
3+
package rbd
4+
5+
/*
6+
#cgo LDFLAGS: -lrbd
7+
#undef _GNU_SOURCE
8+
#include <errno.h>
9+
#include <stdlib.h>
10+
#include <rbd/librbd.h>
11+
12+
#ifndef LIBRBD_SUPPORTS_DIFF_ITERATE3
13+
#define RBD_DIFF_ITERATE_FLAG_INCLUDE_PARENT (1U<<0) // SHOULD MATCH THE VALUE IN librbd.h
14+
#define RBD_DIFF_ITERATE_FLAG_WHOLE_OBJECT (1U<<1) // SHOULD MATCH THE VALUE IN librbd.h
15+
#endif
16+
17+
extern int diffIterateByIDCallback(uint64_t, size_t, int, uintptr_t);
18+
19+
// rbd_diff_iterate3_fn matches the rbd_diff_iterate3 function signature.
20+
typedef int(*rbd_diff_iterate3_fn)(rbd_image_t image, uint64_t from_snap_id,
21+
uint64_t ofs, uint64_t len, uint32_t flags,
22+
int (*cb)(uint64_t, size_t, int, void *), void *arg);
23+
24+
// rbd_diff_iterate3_dlsym take *fn as rbd_diff_iterate3_fn and calls the dynamically loaded
25+
// rbd_diff_iterate3 function passed as 1st argument.
26+
static inline int rbd_diff_iterate3_dlsym(void *fn, rbd_image_t image,
27+
uint64_t from_snap_id, uint64_t ofs, uint64_t len, uint32_t flags, uintptr_t arg) {
28+
// cast function pointer fn to rbd_diff_iterate3 and call the function
29+
return ((rbd_diff_iterate3_fn) fn)(image, from_snap_id, ofs, len, flags, (void*)diffIterateByIDCallback, (void*)arg);
30+
}
31+
*/
32+
import "C"
33+
34+
import (
35+
"fmt"
36+
"sync"
37+
"unsafe"
38+
39+
"github.com/ceph/go-ceph/internal/callbacks"
40+
"github.com/ceph/go-ceph/internal/dlsym"
41+
)
42+
43+
var (
44+
diffIterateByIDCallbacks = callbacks.New()
45+
diffIterateByIDOnce sync.Once
46+
diffIterateById unsafe.Pointer
47+
diffIterateByIdErr error
48+
)
49+
50+
// DiffIterateByIDConfig is used to define the parameters of a DiffIterateByID call.
51+
// Callback, Offset, and Length should always be specified when passed to
52+
// DiffIterateByID. The other values are optional.
53+
type DiffIterateByIDConfig struct {
54+
FromSnapID uint64
55+
Offset uint64
56+
Length uint64
57+
IncludeParent DiffIncludeParent
58+
WholeObject DiffWholeObject
59+
Callback DiffIterateCallback
60+
Data interface{}
61+
}
62+
63+
// DiffIterateByID calls a callback on changed extents of an image.
64+
//
65+
// Calling DiffIterateByID will cause the callback specified in the
66+
// DiffIterateByIDConfig to be called as many times as there are changed
67+
// regions in the image (controlled by the parameters as passed to librbd).
68+
//
69+
// See the documentation of DiffIterateCallback for a description of the
70+
// arguments to the callback and the return behavior.
71+
//
72+
// Implements:
73+
//
74+
// int rbd_diff_iterate3(rbd_image_t image,
75+
// uint64_t from_snap_id,
76+
// uint64_t ofs, uint64_t len,
77+
// uint32_t flags,
78+
// int (*cb)(uint64_t, size_t, int, void *),
79+
// void *arg);
80+
func (image *Image) DiffIterateByID(config DiffIterateByIDConfig) error {
81+
if err := image.validate(imageIsOpen); err != nil {
82+
return err
83+
}
84+
if config.Callback == nil {
85+
return getError(C.EINVAL)
86+
}
87+
88+
diffIterateByIDOnce.Do(func() {
89+
diffIterateById, diffIterateByIdErr = dlsym.LookupSymbol("rbd_diff_iterate3")
90+
})
91+
92+
if diffIterateByIdErr != nil {
93+
return fmt.Errorf("%w: %w", ErrNotImplemented, diffIterateByIdErr)
94+
}
95+
96+
cbIndex := diffIterateByIDCallbacks.Add(config)
97+
defer diffIterateByIDCallbacks.Remove(cbIndex)
98+
99+
flags := C.uint32_t(0)
100+
if config.IncludeParent == IncludeParent {
101+
flags |= C.RBD_DIFF_ITERATE_FLAG_INCLUDE_PARENT
102+
}
103+
if config.WholeObject == EnableWholeObject {
104+
flags |= C.RBD_DIFF_ITERATE_FLAG_WHOLE_OBJECT
105+
}
106+
107+
ret := C.rbd_diff_iterate3_dlsym(
108+
diffIterateById,
109+
image.image,
110+
C.uint64_t(config.FromSnapID),
111+
C.uint64_t(config.Offset),
112+
C.uint64_t(config.Length),
113+
flags,
114+
C.uintptr_t(cbIndex))
115+
116+
return getError(ret)
117+
}
118+
119+
//export diffIterateByIDCallback
120+
func diffIterateByIDCallback(
121+
offset C.uint64_t, length C.size_t, exists C.int, index uintptr) C.int {
122+
123+
v := diffIterateByIDCallbacks.Lookup(index)
124+
config := v.(DiffIterateByIDConfig)
125+
return C.int(config.Callback(
126+
uint64(offset), uint64(length), int(exists), config.Data))
127+
}

0 commit comments

Comments
 (0)