From 29c78f97c0e41665c2cba0756fc12aaf5c93b32c Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Tue, 13 Oct 2020 17:22:31 +0200 Subject: [PATCH] rebase: update vendored go-ceph to v0.6 Closes: #1547 Signed-off-by: Niels de Vos --- go.mod | 2 +- go.sum | 4 +- .../go-ceph/internal/callbacks/callbacks.go | 12 +-- .../ceph/go-ceph/internal/cutil/cutil.go | 14 ++++ .../ceph/go-ceph/internal/cutil/iovec.go | 78 +++++++++++++++++++ .../ceph/go-ceph/rbd/diff_iterate.go | 20 ++--- .../ceph/go-ceph/rbd/rbd_nautilus.go | 14 ++++ .../github.com/ceph/go-ceph/rbd/snapshot.go | 24 ++++++ .../ceph/go-ceph/rbd/snapshot_nautilus.go | 68 ++++++++++++++++ .../ceph/go-ceph/rbd/snapshot_octopus.go | 66 ++++++++++++++++ .../ceph/go-ceph/rbd/watchers_mimic.go | 22 ++---- vendor/modules.txt | 2 +- 12 files changed, 286 insertions(+), 40 deletions(-) create mode 100644 vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go create mode 100644 vendor/github.com/ceph/go-ceph/internal/cutil/iovec.go create mode 100644 vendor/github.com/ceph/go-ceph/rbd/snapshot_octopus.go diff --git a/go.mod b/go.mod index 60e44d61b..638932584 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ceph/ceph-csi go 1.13 require ( - github.com/ceph/go-ceph v0.5.0 + github.com/ceph/go-ceph v0.6.0 github.com/container-storage-interface/spec v1.3.0 github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect diff --git a/go.sum b/go.sum index 234b59c72..9306add5d 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/ceph/go-ceph v0.5.0 h1:x5VmFq19Op6DjzWuxAUG3wZZoC3L160Rt6pJOOiRfW0= -github.com/ceph/go-ceph v0.5.0/go.mod h1:wd+keAOqrcsN//20VQnHBGtnBnY0KHl0PA024Ng8HfQ= +github.com/ceph/go-ceph v0.6.0 h1:/sCL9a6nTIqTCgDAnNeK88Aw+i7rD4bpK+QpxgdDeP4= +github.com/ceph/go-ceph v0.6.0/go.mod h1:wd+keAOqrcsN//20VQnHBGtnBnY0KHl0PA024Ng8HfQ= github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= diff --git a/vendor/github.com/ceph/go-ceph/internal/callbacks/callbacks.go b/vendor/github.com/ceph/go-ceph/internal/callbacks/callbacks.go index 2bce42a86..a3c3e7ae1 100644 --- a/vendor/github.com/ceph/go-ceph/internal/callbacks/callbacks.go +++ b/vendor/github.com/ceph/go-ceph/internal/callbacks/callbacks.go @@ -19,17 +19,17 @@ import ( // to control and validate what "callbacks" get used. type Callbacks struct { mutex sync.RWMutex - cmap map[int]interface{} + cmap map[uintptr]interface{} } // New returns a new callbacks tracker. func New() *Callbacks { - return &Callbacks{cmap: make(map[int]interface{})} + return &Callbacks{cmap: make(map[uintptr]interface{})} } // Add a callback/object to the tracker and return a new index // for the object. -func (cb *Callbacks) Add(v interface{}) int { +func (cb *Callbacks) Add(v interface{}) uintptr { cb.mutex.Lock() defer cb.mutex.Unlock() // this approach assumes that there are typically very few callbacks @@ -38,7 +38,7 @@ func (cb *Callbacks) Add(v interface{}) int { // until we find a free key like in the cgo wiki page. // If this code ever becomes a hot path there's surely plenty of room // for optimization in the future :-) - index := len(cb.cmap) + 1 + index := uintptr(len(cb.cmap) + 1) for { if _, found := cb.cmap[index]; !found { break @@ -50,14 +50,14 @@ func (cb *Callbacks) Add(v interface{}) int { } // Remove a callback/object given it's index. -func (cb *Callbacks) Remove(index int) { +func (cb *Callbacks) Remove(index uintptr) { cb.mutex.Lock() defer cb.mutex.Unlock() delete(cb.cmap, index) } // Lookup returns a mapped callback/object given an index. -func (cb *Callbacks) Lookup(index int) interface{} { +func (cb *Callbacks) Lookup(index uintptr) interface{} { cb.mutex.RLock() defer cb.mutex.RUnlock() return cb.cmap[index] diff --git a/vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go b/vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go new file mode 100644 index 000000000..ae55f869c --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go @@ -0,0 +1,14 @@ +package cutil + +import "unsafe" + +// VoidPtr casts a uintptr value to an unsafe.Pointer value in order to use it +// directly as a void* argument in a C function call. +// CAUTION: NEVER store the result in a variable, or the Go GC could panic. +func VoidPtr(i uintptr) unsafe.Pointer { + var nullPtr unsafe.Pointer + // It's not possible to cast uintptr directly to unsafe.Pointer. Therefore we + // cast a null pointer to uintptr and apply pointer arithmetic on it, which + // allows us to cast it back to unsafe.Pointer. + return unsafe.Pointer(uintptr(nullPtr) + i) +} diff --git a/vendor/github.com/ceph/go-ceph/internal/cutil/iovec.go b/vendor/github.com/ceph/go-ceph/internal/cutil/iovec.go new file mode 100644 index 000000000..d89de06e1 --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/internal/cutil/iovec.go @@ -0,0 +1,78 @@ +package cutil + +/* +#include +#include +*/ +import "C" + +import ( + "unsafe" +) + +var iovecSize uintptr + +// StructIovecPtr is an unsafe pointer wrapping C's `*struct iovec`. +type StructIovecPtr unsafe.Pointer + +// Iovec helps manage struct iovec arrays needed by some C functions. +type Iovec struct { + // cvec represents an array of struct iovec C memory + cvec unsafe.Pointer + // length of the array (in elements) + length int +} + +// NewIovec creates an Iovec, and underlying C memory, of the specified size. +func NewIovec(l int) *Iovec { + r := &Iovec{ + cvec: C.malloc(C.size_t(l) * C.size_t(iovecSize)), + length: l, + } + return r +} + +// ByteSlicesToIovec takes a slice of byte slices and returns a new iovec that +// maps the slice data to struct iovec entries. +func ByteSlicesToIovec(data [][]byte) *Iovec { + iov := NewIovec(len(data)) + for i := range data { + iov.Set(i, data[i]) + } + return iov +} + +// Pointer returns a StructIovecPtr that represents the C memory of the +// underlying array. +func (v *Iovec) Pointer() StructIovecPtr { + return StructIovecPtr(unsafe.Pointer(v.cvec)) +} + +// Len returns the number of entries in the Iovec. +func (v *Iovec) Len() int { + return v.length +} + +// Free the C memory in the Iovec. +func (v *Iovec) Free() { + if v.cvec != nil { + C.free(v.cvec) + v.cvec = nil + v.length = 0 + } +} + +// Set will map the memory of the given byte slice to the iovec at the +// specified position. +func (v *Iovec) Set(i int, buf []byte) { + offset := uintptr(i) * iovecSize + iov := (*C.struct_iovec)(unsafe.Pointer( + uintptr(unsafe.Pointer(v.cvec)) + offset)) + iov.iov_base = unsafe.Pointer(&buf[0]) + iov.iov_len = C.size_t(len(buf)) +} + +func init() { + var iovec C.struct_iovec + iovecSize = unsafe.Sizeof(iovec) +} diff --git a/vendor/github.com/ceph/go-ceph/rbd/diff_iterate.go b/vendor/github.com/ceph/go-ceph/rbd/diff_iterate.go index b8fcadc79..41ab9ef87 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/diff_iterate.go +++ b/vendor/github.com/ceph/go-ceph/rbd/diff_iterate.go @@ -7,18 +7,8 @@ package rbd #include #include +typedef int (*diff_iterate_callback_t)(uint64_t, size_t, int, void *); extern int diffIterateCallback(uint64_t, size_t, int, void *); - -// cgo is having trouble converting the callback from the librbd header -// to a unsafe.Pointer. This shim exists solely to help it along. -static inline int wrap_rbd_diff_iterate2( - rbd_image_t image, - const char *fromsnapname, - uint64_t ofs, uint64_t len, - uint8_t include_parent, uint8_t whole_object, - uintptr_t index) { - return rbd_diff_iterate2(image, fromsnapname, ofs, len, include_parent, whole_object, diffIterateCallback, (void*)index); -} */ import "C" @@ -26,6 +16,7 @@ import ( "unsafe" "github.com/ceph/go-ceph/internal/callbacks" + "github.com/ceph/go-ceph/internal/cutil" ) var diffIterateCallbacks = callbacks.New() @@ -110,14 +101,15 @@ func (image *Image) DiffIterate(config DiffIterateConfig) error { cbIndex := diffIterateCallbacks.Add(config) defer diffIterateCallbacks.Remove(cbIndex) - ret := C.wrap_rbd_diff_iterate2( + ret := C.rbd_diff_iterate2( image.image, cSnapName, C.uint64_t(config.Offset), C.uint64_t(config.Length), C.uint8_t(config.IncludeParent), C.uint8_t(config.WholeObject), - C.uintptr_t(cbIndex)) + C.diff_iterate_callback_t(C.diffIterateCallback), + cutil.VoidPtr(cbIndex)) return getError(ret) } @@ -126,7 +118,7 @@ func (image *Image) DiffIterate(config DiffIterateConfig) error { func diffIterateCallback( offset C.uint64_t, length C.size_t, exists C.int, index unsafe.Pointer) C.int { - v := diffIterateCallbacks.Lookup(int(uintptr(index))) + v := diffIterateCallbacks.Lookup(uintptr(index)) config := v.(DiffIterateConfig) return C.int(config.Callback( uint64(offset), uint64(length), int(exists), config.Data)) diff --git a/vendor/github.com/ceph/go-ceph/rbd/rbd_nautilus.go b/vendor/github.com/ceph/go-ceph/rbd/rbd_nautilus.go index 3ae2a485b..37cb405bd 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/rbd_nautilus.go +++ b/vendor/github.com/ceph/go-ceph/rbd/rbd_nautilus.go @@ -101,3 +101,17 @@ func (image *Image) GetModifyTimestamp() (Timespec, error) { return Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&cts))), nil } + +// Sparsify makes an image sparse by deallocating runs of zeros. +// The sparseSize value will be used to find runs of zeros and must be +// a power of two no less than 4096 and no larger than the image size. +// +// Implements: +// int rbd_sparsify(rbd_image_t image, size_t sparse_size); +func (image *Image) Sparsify(sparseSize uint) error { + if err := image.validate(imageIsOpen); err != nil { + return err + } + + return getError(C.rbd_sparsify(image.image, C.size_t(sparseSize))) +} diff --git a/vendor/github.com/ceph/go-ceph/rbd/snapshot.go b/vendor/github.com/ceph/go-ceph/rbd/snapshot.go index 1f020f79f..9f10c63c4 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/snapshot.go +++ b/vendor/github.com/ceph/go-ceph/rbd/snapshot.go @@ -7,6 +7,8 @@ import "C" import ( "unsafe" + + ts "github.com/ceph/go-ceph/internal/timespec" ) // Snapshot represents a snapshot on a particular rbd image. @@ -160,3 +162,25 @@ func (snapshot *Snapshot) Set() error { return getError(C.rbd_snap_set(snapshot.image.image, c_snapname)) } + +// GetSnapTimestamp returns the timestamp of a snapshot for an image. +// For a non-existing snap ID, GetSnapTimestamp() may trigger an assertion +// and crash in the ceph library. +// Check https://tracker.ceph.com/issues/47287 for details. +// +// Implements: +// int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp) +func (image *Image) GetSnapTimestamp(snapID uint64) (Timespec, error) { + if err := image.validate(imageIsOpen); err != nil { + return Timespec{}, err + } + + var cts C.struct_timespec + + ret := C.rbd_snap_get_timestamp(image.image, C.uint64_t(snapID), &cts) + if ret < 0 { + return Timespec{}, getError(ret) + } + + return Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&cts))), nil +} diff --git a/vendor/github.com/ceph/go-ceph/rbd/snapshot_nautilus.go b/vendor/github.com/ceph/go-ceph/rbd/snapshot_nautilus.go index f0eed0cb4..7bccc6b84 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/snapshot_nautilus.go +++ b/vendor/github.com/ceph/go-ceph/rbd/snapshot_nautilus.go @@ -65,6 +65,60 @@ func (image *Image) GetParentInfo(pool, name, snapname []byte) error { return nil } +// ImageSpec represents the image information. +type ImageSpec struct { + ImageName string + PoolName string +} + +// SnapSpec represents the snapshot infomation. +type SnapSpec struct { + ID uint64 + SnapName string +} + +// ParentInfo represents the parent image and the parent snapshot information. +type ParentInfo struct { + Image ImageSpec + Snap SnapSpec +} + +// GetParent looks for the parent of the image and returns the parent image +// information which includes the image name, the pool name and +// the snapshot information. +// +// Implements: +// int rbd_get_parent(rbd_image_t image, rbd_linked_image_spec_t *parent_image, rbd_snap_spec_t *parent_snap) +func (image *Image) GetParent() (*ParentInfo, error) { + if err := image.validate(imageIsOpen); err != nil { + return nil, err + } + + parentImage := C.rbd_linked_image_spec_t{} + parentSnap := C.rbd_snap_spec_t{} + ret := C.rbd_get_parent(image.image, &parentImage, &parentSnap) + if ret != 0 { + return nil, getError(ret) + } + defer C.rbd_linked_image_spec_cleanup(&parentImage) + defer C.rbd_snap_spec_cleanup(&parentSnap) + + imageSpec := ImageSpec{ + ImageName: C.GoString(parentImage.image_name), + PoolName: C.GoString(parentImage.pool_name), + } + + snapSpec := SnapSpec{ + ID: uint64(parentSnap.id), + SnapName: C.GoString(parentSnap.name), + } + + return &ParentInfo{ + Image: imageSpec, + Snap: snapSpec, + }, nil +} + // ListChildren returns arrays with the pools and names of the images that are // children of the given image. The index of the pools and images arrays can be // used to link the two items together. @@ -104,3 +158,17 @@ func (image *Image) ListChildren() (pools []string, images []string, err error) } return pools, images, nil } + +// SetSnapByID updates the rbd image (not the Snapshot) such that the snapshot +// is the source of readable data. +// +// Implements: +// int rbd_snap_set_by_id(rbd_image_t image, uint64_t snap_id); +func (image *Image) SetSnapByID(snapID uint64) error { + if err := image.validate(imageIsOpen); err != nil { + return err + } + + ret := C.rbd_snap_set_by_id(image.image, C.uint64_t(snapID)) + return getError(ret) +} diff --git a/vendor/github.com/ceph/go-ceph/rbd/snapshot_octopus.go b/vendor/github.com/ceph/go-ceph/rbd/snapshot_octopus.go new file mode 100644 index 000000000..765eb9232 --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/rbd/snapshot_octopus.go @@ -0,0 +1,66 @@ +// +build octopus + +package rbd + +// #cgo LDFLAGS: -lrbd +// #include +// #include +import "C" + +import ( + "unsafe" + + "github.com/ceph/go-ceph/internal/retry" +) + +// GetSnapID returns the snapshot ID for the given snapshot name. +// +// Implements: +// int rbd_snap_get_id(rbd_image_t image, const char *snapname, uint64_t *snap_id) +func (image *Image) GetSnapID(snapName string) (uint64, error) { + var snapID C.uint64_t + if err := image.validate(imageIsOpen); err != nil { + return uint64(snapID), err + } + if snapName == "" { + return uint64(snapID), ErrSnapshotNoName + } + + cSnapName := C.CString(snapName) + defer C.free(unsafe.Pointer(cSnapName)) + + ret := C.rbd_snap_get_id(image.image, cSnapName, &snapID) + return uint64(snapID), getError(ret) +} + +// GetSnapByID returns the snapshot name for the given snapshot ID. +// +// Implements: +// int rbd_snap_get_name(rbd_image_t image, uint64_t snap_id, char *snapname, size_t *name_len) +func (image *Image) GetSnapByID(snapID uint64) (string, error) { + if err := image.validate(imageIsOpen); err != nil { + return "", err + } + + var ( + buf []byte + err error + ) + // range from 1k to 64KiB + retry.WithSizes(1024, 1<<16, func(len int) retry.Hint { + cLen := C.size_t(len) + buf = make([]byte, cLen) + ret := C.rbd_snap_get_name( + image.image, + (C.uint64_t)(snapID), + (*C.char)(unsafe.Pointer(&buf[0])), + &cLen) + err = getError(ret) + return retry.Size(int(cLen)).If(err == errRange) + }) + + if err != nil { + return "", err + } + return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil +} diff --git a/vendor/github.com/ceph/go-ceph/rbd/watchers_mimic.go b/vendor/github.com/ceph/go-ceph/rbd/watchers_mimic.go index e8c89783b..96c31affc 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/watchers_mimic.go +++ b/vendor/github.com/ceph/go-ceph/rbd/watchers_mimic.go @@ -9,18 +9,6 @@ package rbd #include extern void imageWatchCallback(void *); - -// cgo has trouble converting the types of the callback and data arg defined in -// librbd header. It wants the callback function to be a byte pointer and -// the arg to be a pointer, which is pretty much the opposite of what we -// actually want. This shim exists to help coerce the auto-type-conversion -// to do the right thing for us. -static inline int wrap_rbd_update_watch( - rbd_image_t image, - uint64_t *handle, - uintptr_t index) { - return rbd_update_watch(image, handle, imageWatchCallback, (void*)index); -} */ import "C" @@ -28,6 +16,7 @@ import ( "unsafe" "github.com/ceph/go-ceph/internal/callbacks" + "github.com/ceph/go-ceph/internal/cutil" "github.com/ceph/go-ceph/internal/retry" ) @@ -95,7 +84,7 @@ type Watch struct { image *Image wcc watchCallbackCtx handle C.uint64_t - cbIndex int + cbIndex uintptr } // UpdateWatch updates the image object to watch metadata changes to the @@ -118,10 +107,11 @@ func (image *Image) UpdateWatch(cb WatchCallback, data interface{}) (*Watch, err cbIndex: watchCallbacks.Add(wcc), } - ret := C.wrap_rbd_update_watch( + ret := C.rbd_update_watch( image.image, &w.handle, - C.uintptr_t(w.cbIndex)) + C.rbd_update_callback_t(C.imageWatchCallback), + cutil.VoidPtr(w.cbIndex)) if ret != 0 { return nil, getError(ret) } @@ -146,7 +136,7 @@ func (w *Watch) Unwatch() error { //export imageWatchCallback func imageWatchCallback(index unsafe.Pointer) { - v := watchCallbacks.Lookup(int(uintptr(index))) + v := watchCallbacks.Lookup(uintptr(index)) wcc := v.(watchCallbackCtx) wcc.callback(wcc.data) } diff --git a/vendor/modules.txt b/vendor/modules.txt index b20c0ffef..4d9f00175 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,7 +2,7 @@ github.com/beorn7/perks/quantile # github.com/blang/semver v3.5.0+incompatible github.com/blang/semver -# github.com/ceph/go-ceph v0.5.0 +# github.com/ceph/go-ceph v0.6.0 github.com/ceph/go-ceph/internal/callbacks github.com/ceph/go-ceph/internal/cutil github.com/ceph/go-ceph/internal/errutil