From eeec1213cb63971239b009327aeb4960d517cc26 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Wed, 9 Dec 2020 11:16:45 +0530 Subject: [PATCH] rebase: update go-ceph to v0.7.0 updating go-ceph to latest 0.7.0 release. Signed-off-by: Madhu Rajanna --- go.mod | 2 +- go.sum | 4 +- .../ceph/go-ceph/cephfs/admin/flags.go | 60 +++++++ .../ceph/go-ceph/cephfs/admin/fsadmin.go | 15 -- .../ceph/go-ceph/cephfs/admin/subvolume.go | 24 ++- .../go-ceph/cephfs/admin/subvolumegroup.go | 66 +------- .../go-ceph/internal/callbacks/callbacks.go | 51 +++--- .../ceph/go-ceph/internal/cutil/cutil.go | 14 -- vendor/github.com/ceph/go-ceph/rados/ioctx.go | 4 + .../ceph/go-ceph/rados/ioctx_nautilus.go | 43 +++++ vendor/github.com/ceph/go-ceph/rados/rados.go | 27 ++++ .../ceph/go-ceph/rados/rados_nautilus.go | 12 ++ .../ceph/go-ceph/rbd/diff_iterate.go | 21 ++- .../github.com/ceph/go-ceph/rbd/metadata.go | 149 ++++++++++++++++++ vendor/github.com/ceph/go-ceph/rbd/rbd.go | 104 ++++-------- .../ceph/go-ceph/rbd/watchers_mimic.go | 21 +-- vendor/modules.txt | 2 +- 17 files changed, 401 insertions(+), 218 deletions(-) create mode 100644 vendor/github.com/ceph/go-ceph/cephfs/admin/flags.go delete mode 100644 vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go create mode 100644 vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go create mode 100644 vendor/github.com/ceph/go-ceph/rados/rados_nautilus.go create mode 100644 vendor/github.com/ceph/go-ceph/rbd/metadata.go diff --git a/go.mod b/go.mod index e83859ff6..dc0c77cff 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.6.0 + github.com/ceph/go-ceph v0.7.0 github.com/container-storage-interface/spec v1.3.0 github.com/go-logr/logr v0.2.1 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect diff --git a/go.sum b/go.sum index c23fc3862..68ea10538 100644 --- a/go.sum +++ b/go.sum @@ -152,8 +152,8 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU= github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE= -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/ceph/go-ceph v0.7.0 h1:+4oWZCuvh9B7/kZVJVw/DSuk9Qby38KWY1pMQ5gYGyY= +github.com/ceph/go-ceph v0.7.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/cephfs/admin/flags.go b/vendor/github.com/ceph/go-ceph/cephfs/admin/flags.go new file mode 100644 index 000000000..393ebe356 --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/cephfs/admin/flags.go @@ -0,0 +1,60 @@ +// +build !luminous,!mimic + +package admin + +// For APIs that accept extra sets of "boolean" flags we may end up wanting +// multiple different sets of supported flags. Example: most rm functions +// accept a force flag, but only subvolume delete has retain snapshots. +// To make this somewhat uniform in the admin package we define a utility +// interface and helper function to merge flags with naming options. + +type flagSet interface { + flags() map[string]bool +} + +type commonRmFlags struct { + force bool +} + +func (f commonRmFlags) flags() map[string]bool { + o := make(map[string]bool) + if f.force { + o["force"] = true + } + return o +} + +// SubVolRmFlags does not embed other types to simplify and keep the +// interface with the type flat and simple. At the cost of some code +// duplication we get a nicer UX for those using the library. + +// SubVolRmFlags may be used to specify behavior modifying flags when +// removing sub volumes. +type SubVolRmFlags struct { + Force bool + RetainSnapshots bool +} + +func (f SubVolRmFlags) flags() map[string]bool { + o := make(map[string]bool) + if f.Force { + o["force"] = true + } + if f.RetainSnapshots { + o["retain-snapshots"] = true + } + return o +} + +// mergeFlags combines a set of key-value settings with any type implementing +// the flagSet interface. +func mergeFlags(m map[string]string, f flagSet) map[string]interface{} { + o := make(map[string]interface{}) + for k, v := range m { + o[k] = v + } + for k, v := range f.flags() { + o[k] = v + } + return o +} diff --git a/vendor/github.com/ceph/go-ceph/cephfs/admin/fsadmin.go b/vendor/github.com/ceph/go-ceph/cephfs/admin/fsadmin.go index 2b49980f2..e7bed2d16 100644 --- a/vendor/github.com/ceph/go-ceph/cephfs/admin/fsadmin.go +++ b/vendor/github.com/ceph/go-ceph/cephfs/admin/fsadmin.go @@ -143,18 +143,3 @@ func modeString(m int, force bool) string { func uint64String(v uint64) string { return strconv.FormatUint(uint64(v), 10) } - -type rmFlags struct { - force bool -} - -func (f rmFlags) Update(m map[string]string) map[string]interface{} { - o := make(map[string]interface{}) - for k, v := range m { - o[k] = v - } - if f.force { - o["force"] = true - } - return o -} diff --git a/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go b/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go index b0d69353a..ac189832a 100644 --- a/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go +++ b/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go @@ -87,7 +87,7 @@ func (fsa *FSAdmin) ListSubVolumes(volume, group string) ([]string, error) { // Similar To: // ceph fs subvolume rm --group-name= func (fsa *FSAdmin) RemoveSubVolume(volume, group, name string) error { - return fsa.rmSubVolume(volume, group, name, rmFlags{}) + return fsa.RemoveSubVolumeWithFlags(volume, group, name, SubVolRmFlags{}) } // ForceRemoveSubVolume will delete a CephFS subvolume in a volume and optional @@ -96,10 +96,18 @@ func (fsa *FSAdmin) RemoveSubVolume(volume, group, name string) error { // Similar To: // ceph fs subvolume rm --group-name= --force func (fsa *FSAdmin) ForceRemoveSubVolume(volume, group, name string) error { - return fsa.rmSubVolume(volume, group, name, rmFlags{force: true}) + return fsa.RemoveSubVolumeWithFlags(volume, group, name, SubVolRmFlags{Force: true}) } -func (fsa *FSAdmin) rmSubVolume(volume, group, name string, o rmFlags) error { +// RemoveSubVolumeWithFlags will delete a CephFS subvolume in a volume and +// optional subvolume group. This function accepts a SubVolRmFlags type that +// can be used to specify flags that modify the operations behavior. +// Equivalent to RemoveSubVolume with no flags set. +// Equivalent to ForceRemoveSubVolume if only the "Force" flag is set. +// +// Similar To: +// ceph fs subvolume rm --group-name= [...flags...] +func (fsa *FSAdmin) RemoveSubVolumeWithFlags(volume, group, name string, o SubVolRmFlags) error { m := map[string]string{ "prefix": "fs subvolume rm", "vol_name": volume, @@ -109,7 +117,7 @@ func (fsa *FSAdmin) rmSubVolume(volume, group, name string, o rmFlags) error { if group != NoGroup { m["group_name"] = group } - return fsa.marshalMgrCommand(o.Update(m)).noData().End() + return fsa.marshalMgrCommand(mergeFlags(m, o)).noData().End() } type subVolumeResizeFields struct { @@ -264,7 +272,7 @@ func (fsa *FSAdmin) CreateSubVolumeSnapshot(volume, group, source, name string) // Similar To: // ceph fs subvolume snapshot rm --group-name= func (fsa *FSAdmin) RemoveSubVolumeSnapshot(volume, group, subvolume, name string) error { - return fsa.rmSubVolumeSnapshot(volume, group, subvolume, name, rmFlags{}) + return fsa.rmSubVolumeSnapshot(volume, group, subvolume, name, commonRmFlags{}) } // ForceRemoveSubVolumeSnapshot removes the specified snapshot from the subvolume. @@ -272,10 +280,10 @@ func (fsa *FSAdmin) RemoveSubVolumeSnapshot(volume, group, subvolume, name strin // Similar To: // ceph fs subvolume snapshot rm --group-name= --force func (fsa *FSAdmin) ForceRemoveSubVolumeSnapshot(volume, group, subvolume, name string) error { - return fsa.rmSubVolumeSnapshot(volume, group, subvolume, name, rmFlags{force: true}) + return fsa.rmSubVolumeSnapshot(volume, group, subvolume, name, commonRmFlags{force: true}) } -func (fsa *FSAdmin) rmSubVolumeSnapshot(volume, group, subvolume, name string, o rmFlags) error { +func (fsa *FSAdmin) rmSubVolumeSnapshot(volume, group, subvolume, name string, o commonRmFlags) error { m := map[string]string{ "prefix": "fs subvolume snapshot rm", @@ -287,7 +295,7 @@ func (fsa *FSAdmin) rmSubVolumeSnapshot(volume, group, subvolume, name string, o if group != NoGroup { m["group_name"] = group } - return fsa.marshalMgrCommand(o.Update(m)).noData().End() + return fsa.marshalMgrCommand(mergeFlags(m, o)).noData().End() } // ListSubVolumeSnapshots returns a listing of snapshots for a given subvolume. diff --git a/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolumegroup.go b/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolumegroup.go index f5426bac4..573c8c162 100644 --- a/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolumegroup.go +++ b/vendor/github.com/ceph/go-ceph/cephfs/admin/subvolumegroup.go @@ -69,23 +69,23 @@ func (fsa *FSAdmin) ListSubVolumeGroups(volume string) ([]string, error) { // Similar To: // ceph fs subvolumegroup rm func (fsa *FSAdmin) RemoveSubVolumeGroup(volume, name string) error { - return fsa.rmSubVolumeGroup(volume, name, rmFlags{}) + return fsa.rmSubVolumeGroup(volume, name, commonRmFlags{}) } // ForceRemoveSubVolumeGroup will delete a subvolume group in a volume. // Similar To: // ceph fs subvolumegroup rm --force func (fsa *FSAdmin) ForceRemoveSubVolumeGroup(volume, name string) error { - return fsa.rmSubVolumeGroup(volume, name, rmFlags{force: true}) + return fsa.rmSubVolumeGroup(volume, name, commonRmFlags{force: true}) } -func (fsa *FSAdmin) rmSubVolumeGroup(volume, name string, o rmFlags) error { - res := fsa.marshalMgrCommand(o.Update(map[string]string{ +func (fsa *FSAdmin) rmSubVolumeGroup(volume, name string, o commonRmFlags) error { + res := fsa.marshalMgrCommand(mergeFlags(map[string]string{ "prefix": "fs subvolumegroup rm", "vol_name": volume, "group_name": name, "format": "json", - })) + }, o)) return res.noData().End() } @@ -103,59 +103,3 @@ func (fsa *FSAdmin) SubVolumeGroupPath(volume, name string) (string, error) { } return parsePathResponse(fsa.marshalMgrCommand(m)) } - -// CreateSubVolumeGroupSnapshot creates a new snapshot from the source subvolume group. -// -// Similar To: -// ceph fs subvolumegroup snapshot create -func (fsa *FSAdmin) CreateSubVolumeGroupSnapshot(volume, group, name string) error { - m := map[string]string{ - "prefix": "fs subvolumegroup snapshot create", - "vol_name": volume, - "group_name": group, - "snap_name": name, - "format": "json", - } - return fsa.marshalMgrCommand(m).noData().End() -} - -// RemoveSubVolumeGroupSnapshot removes the specified snapshot from the subvolume group. -// -// Similar To: -// ceph fs subvolumegroup snapshot rm -func (fsa *FSAdmin) RemoveSubVolumeGroupSnapshot(volume, group, name string) error { - return fsa.rmSubVolumeGroupSnapshot(volume, group, name, rmFlags{}) -} - -// ForceRemoveSubVolumeGroupSnapshot removes the specified snapshot from the subvolume group. -// -// Similar To: -// ceph fs subvolumegroup snapshot rm --force -func (fsa *FSAdmin) ForceRemoveSubVolumeGroupSnapshot(volume, group, name string) error { - return fsa.rmSubVolumeGroupSnapshot(volume, group, name, rmFlags{force: true}) -} - -func (fsa *FSAdmin) rmSubVolumeGroupSnapshot(volume, group, name string, o rmFlags) error { - m := map[string]string{ - "prefix": "fs subvolumegroup snapshot rm", - "vol_name": volume, - "group_name": group, - "snap_name": name, - "format": "json", - } - return fsa.marshalMgrCommand(o.Update(m)).noData().End() -} - -// ListSubVolumeGroupSnapshots returns a listing of snapshots for a given subvolume group. -// -// Similar To: -// ceph fs subvolumegroup snapshot ls -func (fsa *FSAdmin) ListSubVolumeGroupSnapshots(volume, group string) ([]string, error) { - m := map[string]string{ - "prefix": "fs subvolumegroup snapshot ls", - "vol_name": volume, - "group_name": group, - "format": "json", - } - return parseListNames(fsa.marshalMgrCommand(m)) -} 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 a3c3e7ae1..93bbb7280 100644 --- a/vendor/github.com/ceph/go-ceph/internal/callbacks/callbacks.go +++ b/vendor/github.com/ceph/go-ceph/internal/callbacks/callbacks.go @@ -12,14 +12,15 @@ import ( // Callbacks provides a tracker for data that is to be passed between Go // and C callback functions. The Go callback/object may not be passed -// by a pointer to C code and so instead integer indexes into an internal +// by a pointer to C code and so instead integer IDs into an internal // map are used. // Typically the item being added will either be a callback function or // a data structure containing a callback function. It is up to the caller // to control and validate what "callbacks" get used. type Callbacks struct { - mutex sync.RWMutex - cmap map[uintptr]interface{} + mutex sync.RWMutex + cmap map[uintptr]interface{} + lastID uintptr } // New returns a new callbacks tracker. @@ -27,38 +28,38 @@ func New() *Callbacks { return &Callbacks{cmap: make(map[uintptr]interface{})} } -// Add a callback/object to the tracker and return a new index +// getID returns a unique ID. +// NOTE: cb.mutex must be locked already! +func (cb *Callbacks) getID() uintptr { + for exists := true; exists; { + cb.lastID++ + // Sanity check for the very unlikely case of an integer overflow in long + // running processes. + _, exists = cb.cmap[cb.lastID] + } + return cb.lastID +} + +// Add a callback/object to the tracker and return a new ID // for the object. func (cb *Callbacks) Add(v interface{}) uintptr { cb.mutex.Lock() defer cb.mutex.Unlock() - // this approach assumes that there are typically very few callbacks - // in play at once and can just use the length of the map as our - // index. But in case of collisions we fall back to simply incrementing - // 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 := uintptr(len(cb.cmap) + 1) - for { - if _, found := cb.cmap[index]; !found { - break - } - index++ - } - cb.cmap[index] = v - return index + id := cb.getID() + cb.cmap[id] = v + return id } -// Remove a callback/object given it's index. -func (cb *Callbacks) Remove(index uintptr) { +// Remove a callback/object given it's ID. +func (cb *Callbacks) Remove(id uintptr) { cb.mutex.Lock() defer cb.mutex.Unlock() - delete(cb.cmap, index) + delete(cb.cmap, id) } -// Lookup returns a mapped callback/object given an index. -func (cb *Callbacks) Lookup(index uintptr) interface{} { +// Lookup returns a mapped callback/object given an ID. +func (cb *Callbacks) Lookup(id uintptr) interface{} { cb.mutex.RLock() defer cb.mutex.RUnlock() - return cb.cmap[index] + return cb.cmap[id] } diff --git a/vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go b/vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go deleted file mode 100644 index ae55f869c..000000000 --- a/vendor/github.com/ceph/go-ceph/internal/cutil/cutil.go +++ /dev/null @@ -1,14 +0,0 @@ -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/rados/ioctx.go b/vendor/github.com/ceph/go-ceph/rados/ioctx.go index 26519d618..d7a5d214c 100644 --- a/vendor/github.com/ceph/go-ceph/rados/ioctx.go +++ b/vendor/github.com/ceph/go-ceph/rados/ioctx.go @@ -109,6 +109,10 @@ func (ioctx *IOContext) Pointer() unsafe.Pointer { // SetNamespace sets the namespace for objects within this IO context (pool). // Setting namespace to a empty or zero length string sets the pool to the default namespace. +// +// Implements: +// void rados_ioctx_set_namespace(rados_ioctx_t io, +// const char *nspace); func (ioctx *IOContext) SetNamespace(namespace string) { var c_ns *C.char if len(namespace) > 0 { diff --git a/vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go b/vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go new file mode 100644 index 000000000..f9a168b19 --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go @@ -0,0 +1,43 @@ +// +build !luminous,!mimic + +package rados + +// #cgo LDFLAGS: -lrados +// #include +// +import "C" + +import ( + "unsafe" + + "github.com/ceph/go-ceph/internal/retry" +) + +// GetNamespace gets the namespace used for objects within this IO context. +// +// Implements: +// int rados_ioctx_get_namespace(rados_ioctx_t io, char *buf, +// unsigned maxlen); +func (ioctx *IOContext) GetNamespace() (string, error) { + if err := ioctx.validate(); err != nil { + return "", err + } + var ( + err error + buf []byte + ret C.int + ) + retry.WithSizes(128, 8192, func(size int) retry.Hint { + buf = make([]byte, size) + ret = C.rados_ioctx_get_namespace( + ioctx.ioctx, + (*C.char)(unsafe.Pointer(&buf[0])), + C.unsigned(len(buf))) + err = getErrorIfNegative(ret) + return retry.DoubleSize.If(err == errRange) + }) + if err != nil { + return "", err + } + return string(buf[:ret]), nil +} diff --git a/vendor/github.com/ceph/go-ceph/rados/rados.go b/vendor/github.com/ceph/go-ceph/rados/rados.go index d1f000ac0..b18fe0846 100644 --- a/vendor/github.com/ceph/go-ceph/rados/rados.go +++ b/vendor/github.com/ceph/go-ceph/rados/rados.go @@ -25,6 +25,33 @@ const ( RadosAllNamespaces = AllNamespaces ) +// OpFlags are flags that can be set on a per-op basis. +type OpFlags uint + +const ( + // OpFlagNone can be use to not set any flags. + OpFlagNone = OpFlags(0) + // OpFlagExcl marks an op to fail a create operation if the object + // already exists. + OpFlagExcl = OpFlags(C.LIBRADOS_OP_FLAG_EXCL) + // OpFlagFailOk allows the transaction to succeed even if the flagged + // op fails. + OpFlagFailOk = OpFlags(C.LIBRADOS_OP_FLAG_FAILOK) + // OpFlagFAdviseRandom indicates read/write op random. + OpFlagFAdviseRandom = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_RANDOM) + // OpFlagFAdviseSequential indicates read/write op sequential. + OpFlagFAdviseSequential = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL) + // OpFlagFAdviseWillNeed indicates read/write data will be accessed in + // the near future (by someone). + OpFlagFAdviseWillNeed = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_WILLNEED) + // OpFlagFAdviseDontNeed indicates read/write data will not accessed in + // the near future (by anyone). + OpFlagFAdviseDontNeed = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_DONTNEED) + // OpFlagFAdviseNoCache indicates read/write data will not accessed + // again (by *this* client). + OpFlagFAdviseNoCache = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_NOCACHE) +) + // Version returns the major, minor, and patch components of the version of // the RADOS library linked against. func Version() (int, int, int) { diff --git a/vendor/github.com/ceph/go-ceph/rados/rados_nautilus.go b/vendor/github.com/ceph/go-ceph/rados/rados_nautilus.go new file mode 100644 index 000000000..e12e62a07 --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/rados/rados_nautilus.go @@ -0,0 +1,12 @@ +// +build !mimic + +package rados + +// #include +import "C" + +const ( + // OpFlagFAdviseFUA optionally support FUA (force unit access) on write + // requests. + OpFlagFAdviseFUA = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_FUA) +) 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 41ab9ef87..19a60bcd6 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/diff_iterate.go +++ b/vendor/github.com/ceph/go-ceph/rbd/diff_iterate.go @@ -7,8 +7,15 @@ 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 *); +extern int diffIterateCallback(uint64_t, size_t, int, uintptr_t); + +// inline wrapper to cast uintptr_t to void* +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 arg) { + return rbd_diff_iterate2(image, fromsnapname, ofs, len, include_parent, + whole_object, (void*)diffIterateCallback, (void*)arg); +}; */ import "C" @@ -16,7 +23,6 @@ import ( "unsafe" "github.com/ceph/go-ceph/internal/callbacks" - "github.com/ceph/go-ceph/internal/cutil" ) var diffIterateCallbacks = callbacks.New() @@ -101,24 +107,23 @@ func (image *Image) DiffIterate(config DiffIterateConfig) error { cbIndex := diffIterateCallbacks.Add(config) defer diffIterateCallbacks.Remove(cbIndex) - ret := C.rbd_diff_iterate2( + ret := C.wrap_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.diff_iterate_callback_t(C.diffIterateCallback), - cutil.VoidPtr(cbIndex)) + C.uintptr_t(cbIndex)) return getError(ret) } //export diffIterateCallback func diffIterateCallback( - offset C.uint64_t, length C.size_t, exists C.int, index unsafe.Pointer) C.int { + offset C.uint64_t, length C.size_t, exists C.int, index uintptr) C.int { - v := diffIterateCallbacks.Lookup(uintptr(index)) + v := diffIterateCallbacks.Lookup(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/metadata.go b/vendor/github.com/ceph/go-ceph/rbd/metadata.go new file mode 100644 index 000000000..3be2d955a --- /dev/null +++ b/vendor/github.com/ceph/go-ceph/rbd/metadata.go @@ -0,0 +1,149 @@ +package rbd + +// #cgo LDFLAGS: -lrbd +// #include +// #include +import "C" + +import ( + "unsafe" + + "github.com/ceph/go-ceph/internal/cutil" + "github.com/ceph/go-ceph/internal/retry" +) + +// GetMetadata returns the metadata string associated with the given key. +// +// Implements: +// int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen) +func (image *Image) GetMetadata(key string) (string, error) { + if err := image.validate(imageIsOpen); err != nil { + return "", err + } + + c_key := C.CString(key) + defer C.free(unsafe.Pointer(c_key)) + + var ( + buf []byte + err error + ) + retry.WithSizes(4096, 262144, func(size int) retry.Hint { + csize := C.size_t(size) + buf = make([]byte, csize) + // rbd_metadata_get is a bit quirky and *does not* update the size + // value if the size passed in >= the needed size. + ret := C.rbd_metadata_get( + image.image, c_key, (*C.char)(unsafe.Pointer(&buf[0])), &csize) + err = getError(ret) + return retry.Size(int(csize)).If(err == errRange) + }) + if err != nil { + return "", err + } + return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil +} + +// SetMetadata updates the metadata string associated with the given key. +// +// Implements: +// int rbd_metadata_set(rbd_image_t image, const char *key, const char *value) +func (image *Image) SetMetadata(key string, value string) error { + if err := image.validate(imageIsOpen); err != nil { + return err + } + + c_key := C.CString(key) + c_value := C.CString(value) + defer C.free(unsafe.Pointer(c_key)) + defer C.free(unsafe.Pointer(c_value)) + + ret := C.rbd_metadata_set(image.image, c_key, c_value) + if ret < 0 { + return rbdError(ret) + } + + return nil +} + +// RemoveMetadata clears the metadata associated with the given key. +// +// Implements: +// int rbd_metadata_remove(rbd_image_t image, const char *key) +func (image *Image) RemoveMetadata(key string) error { + if err := image.validate(imageIsOpen); err != nil { + return err + } + + c_key := C.CString(key) + defer C.free(unsafe.Pointer(c_key)) + + ret := C.rbd_metadata_remove(image.image, c_key) + if ret < 0 { + return rbdError(ret) + } + + return nil +} + +// ListMetadata returns a map containing all metadata assigned to the RBD image. +// +// Implements: +// int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max, +// char *keys, size_t *key_len, char *values, size_t *vals_len); +func (image *Image) ListMetadata() (map[string]string, error) { + if err := image.validate(imageIsOpen); err != nil { + return nil, err + } + + var ( + err error + keysbuf []byte + keysSize C.size_t + valsbuf []byte + valsSize C.size_t + ) + retry.WithSizes(4096, 262144, func(size int) retry.Hint { + keysbuf = make([]byte, size) + keysSize = C.size_t(size) + valsbuf = make([]byte, size) + valsSize = C.size_t(size) + // the rbd_metadata_list function can use a start point and a limit. + // we do not use it and prefer our retry helper and just allocating + // buffers large enough to take all the keys and values + ret := C.rbd_metadata_list( + image.image, + (*C.char)(unsafe.Pointer(&empty[0])), // always start at the beginning (no paging) + 0, // fetch all key-value pairs + (*C.char)(unsafe.Pointer(&keysbuf[0])), + &keysSize, + (*C.char)(unsafe.Pointer(&valsbuf[0])), + &valsSize) + + err = getError(ret) + nextSize := valsSize + if keysSize > nextSize { + nextSize = keysSize + } + return retry.Size(int(nextSize)).If(err == errRange) + }) + if err != nil { + return nil, err + } + + m := map[string]string{} + keys := cutil.SplitBuffer(keysbuf[:keysSize]) + vals := cutil.SplitBuffer(valsbuf[:valsSize]) + if len(keys) != len(vals) { + // this should not happen (famous last words) + return nil, errRange + } + for i := range keys { + m[keys[i]] = vals[i] + } + return m, nil +} + +// rather than allocate memory every time that ListMetadata is called, +// define a static byte slice to stand in for the C "empty string" +var empty = []byte{0} diff --git a/vendor/github.com/ceph/go-ceph/rbd/rbd.go b/vendor/github.com/ceph/go-ceph/rbd/rbd.go index b5f0648db..7eb4bb8bd 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/rbd.go +++ b/vendor/github.com/ceph/go-ceph/rbd/rbd.go @@ -808,6 +808,36 @@ func (image *Image) WriteAt(data []byte, off int64) (n int, err error) { return ret, err } +// WriteSame repeats writing data from starting point ofs until n bytes have +// been written. +// +// Implements: +// ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len, +// const char *buf, size_t data_len, int op_flags); +func (image *Image) WriteSame(ofs, n uint64, data []byte, flags rados.OpFlags) (int64, error) { + var err error + + if err = image.validate(imageIsOpen); err != nil { + return 0, err + } + + if len(data) == 0 { + return 0, nil + } + + ret := C.rbd_writesame(image.image, + C.uint64_t(ofs), + C.uint64_t(n), + (*C.char)(unsafe.Pointer(&data[0])), + C.size_t(len(data)), + C.int(flags)) + if ret < 0 { + err = getError(C.int(ret)) + } + + return int64(ret), err +} + // Flush all cached writes to storage. // // Implements: @@ -853,80 +883,6 @@ func (image *Image) GetSnapshotNames() (snaps []SnapInfo, err error) { return snaps[:len(snaps)-1], nil } -// GetMetadata returns the metadata string associated with the given key. -// -// Implements: -// int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen) -func (image *Image) GetMetadata(key string) (string, error) { - if err := image.validate(imageIsOpen); err != nil { - return "", err - } - - c_key := C.CString(key) - defer C.free(unsafe.Pointer(c_key)) - - var ( - buf []byte - err error - ) - retry.WithSizes(4096, 262144, func(size int) retry.Hint { - csize := C.size_t(size) - buf = make([]byte, csize) - // rbd_metadata_get is a bit quirky and *does not* update the size - // value if the size passed in >= the needed size. - ret := C.rbd_metadata_get( - image.image, c_key, (*C.char)(unsafe.Pointer(&buf[0])), &csize) - err = getError(ret) - return retry.Size(int(csize)).If(err == errRange) - }) - if err != nil { - return "", err - } - return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil -} - -// SetMetadata updates the metadata string associated with the given key. -// -// Implements: -// int rbd_metadata_set(rbd_image_t image, const char *key, const char *value) -func (image *Image) SetMetadata(key string, value string) error { - if err := image.validate(imageIsOpen); err != nil { - return err - } - - c_key := C.CString(key) - c_value := C.CString(value) - defer C.free(unsafe.Pointer(c_key)) - defer C.free(unsafe.Pointer(c_value)) - - ret := C.rbd_metadata_set(image.image, c_key, c_value) - if ret < 0 { - return rbdError(ret) - } - - return nil -} - -// RemoveMetadata clears the metadata associated with the given key. -// -// Implements: -// int rbd_metadata_remove(rbd_image_t image, const char *key) -func (image *Image) RemoveMetadata(key string) error { - if err := image.validate(imageIsOpen); err != nil { - return err - } - - c_key := C.CString(key) - defer C.free(unsafe.Pointer(c_key)) - - ret := C.rbd_metadata_remove(image.image, c_key) - if ret < 0 { - return rbdError(ret) - } - - return nil -} - // GetId returns the internal image ID string. // // Implements: 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 96c31affc..1204fb905 100644 --- a/vendor/github.com/ceph/go-ceph/rbd/watchers_mimic.go +++ b/vendor/github.com/ceph/go-ceph/rbd/watchers_mimic.go @@ -8,15 +8,19 @@ package rbd #cgo LDFLAGS: -lrbd #include -extern void imageWatchCallback(void *); +extern void imageWatchCallback(uintptr_t); + +// inline wrapper to cast uintptr_t to void* +static inline int wrap_rbd_update_watch(rbd_image_t image, uint64_t *handle, + uintptr_t arg) { + return rbd_update_watch(image, handle, (void*)imageWatchCallback, (void*)arg); + }; + */ import "C" import ( - "unsafe" - "github.com/ceph/go-ceph/internal/callbacks" - "github.com/ceph/go-ceph/internal/cutil" "github.com/ceph/go-ceph/internal/retry" ) @@ -107,11 +111,10 @@ func (image *Image) UpdateWatch(cb WatchCallback, data interface{}) (*Watch, err cbIndex: watchCallbacks.Add(wcc), } - ret := C.rbd_update_watch( + ret := C.wrap_rbd_update_watch( image.image, &w.handle, - C.rbd_update_callback_t(C.imageWatchCallback), - cutil.VoidPtr(w.cbIndex)) + C.uintptr_t(w.cbIndex)) if ret != 0 { return nil, getError(ret) } @@ -135,8 +138,8 @@ func (w *Watch) Unwatch() error { } //export imageWatchCallback -func imageWatchCallback(index unsafe.Pointer) { - v := watchCallbacks.Lookup(uintptr(index)) +func imageWatchCallback(index uintptr) { + v := watchCallbacks.Lookup(index) wcc := v.(watchCallbackCtx) wcc.callback(wcc.data) } diff --git a/vendor/modules.txt b/vendor/modules.txt index f01cce911..c4603d761 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.6.0 +# github.com/ceph/go-ceph v0.7.0 github.com/ceph/go-ceph/cephfs/admin github.com/ceph/go-ceph/internal/callbacks github.com/ceph/go-ceph/internal/cutil