rebase: update go-ceph to v0.7.0

updating go-ceph to latest 0.7.0
release.

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
Madhu Rajanna 2020-12-09 11:16:45 +05:30 committed by mergify[bot]
parent 97acd47ae9
commit eeec1213cb
17 changed files with 401 additions and 218 deletions

2
go.mod
View File

@ -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

4
go.sum
View File

@ -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=

60
vendor/github.com/ceph/go-ceph/cephfs/admin/flags.go generated vendored Normal file
View File

@ -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
}

View File

@ -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
}

View File

@ -87,7 +87,7 @@ func (fsa *FSAdmin) ListSubVolumes(volume, group string) ([]string, error) {
// Similar To:
// ceph fs subvolume rm <volume> --group-name=<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 <volume> --group-name=<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 <volume> --group-name=<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 <volume> --group-name=<group> <subvolume> <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 <volume> --group-name=<group> <subvolume> <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.

View File

@ -69,23 +69,23 @@ func (fsa *FSAdmin) ListSubVolumeGroups(volume string) ([]string, error) {
// Similar To:
// ceph fs subvolumegroup rm <volume> <group_name>
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 <volume> <group_name> --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 <volume> <group> <name>
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 <volume> <group> <name>
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 <volume> <group> <name> --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 <volume> <group>
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))
}

View File

@ -12,7 +12,7 @@ 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
@ -20,6 +20,7 @@ import (
type Callbacks struct {
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]
}

View File

@ -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)
}

View File

@ -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 {

43
vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go generated vendored Normal file
View File

@ -0,0 +1,43 @@
// +build !luminous,!mimic
package rados
// #cgo LDFLAGS: -lrados
// #include <rados/librados.h>
//
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
}

View File

@ -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) {

12
vendor/github.com/ceph/go-ceph/rados/rados_nautilus.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// +build !mimic
package rados
// #include <rados/librados.h>
import "C"
const (
// OpFlagFAdviseFUA optionally support FUA (force unit access) on write
// requests.
OpFlagFAdviseFUA = OpFlags(C.LIBRADOS_OP_FLAG_FADVISE_FUA)
)

View File

@ -7,8 +7,15 @@ package rbd
#include <stdlib.h>
#include <rbd/librbd.h>
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))

149
vendor/github.com/ceph/go-ceph/rbd/metadata.go generated vendored Normal file
View File

@ -0,0 +1,149 @@
package rbd
// #cgo LDFLAGS: -lrbd
// #include <stdlib.h>
// #include <rbd/librbd.h>
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}

View File

@ -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:

View File

@ -8,15 +8,19 @@ package rbd
#cgo LDFLAGS: -lrbd
#include <rbd/librbd.h>
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)
}

2
vendor/modules.txt vendored
View File

@ -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