rebase: update go-ceph to v0.5.0

as go-ceph is 0.5.0 is released updating
the dependency to latest release.
more info about release at
https://github.com/ceph/go-ceph/releases/tag/v0.5.0

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
Madhu Rajanna
2020-08-11 20:12:21 +05:30
committed by mergify[bot]
parent 5f6fec5f0a
commit 2808d526bb
26 changed files with 816 additions and 199 deletions

View File

@ -1,13 +0,0 @@
package rbd
/*
#include <rbd/librbd.h>
extern int diffIterateCallback(uint64_t ofs, size_t len, int exists, int index);
int callDiffIterateCallback(uint64_t ofs, size_t len, int exists, int index) {
return diffIterateCallback(ofs, len, exists, index);
}
*/
import "C"

View File

@ -7,7 +7,7 @@ package rbd
#include <stdlib.h>
#include <rbd/librbd.h>
extern int callDiffIterateCallback(uint64_t ofs, size_t len, int exists, int index);
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.
@ -16,9 +16,8 @@ static inline int wrap_rbd_diff_iterate2(
const char *fromsnapname,
uint64_t ofs, uint64_t len,
uint8_t include_parent, uint8_t whole_object,
void *cb,
uintptr_t arg) {
return rbd_diff_iterate2(image, fromsnapname, ofs, len, include_parent, whole_object, cb, (void*)arg);
uintptr_t index) {
return rbd_diff_iterate2(image, fromsnapname, ofs, len, include_parent, whole_object, diffIterateCallback, (void*)index);
}
*/
import "C"
@ -99,7 +98,7 @@ func (image *Image) DiffIterate(config DiffIterateConfig) error {
return err
}
if config.Callback == nil {
return RBDError(C.EINVAL)
return rbdError(C.EINVAL)
}
var cSnapName *C.char
@ -118,7 +117,6 @@ func (image *Image) DiffIterate(config DiffIterateConfig) error {
C.uint64_t(config.Length),
C.uint8_t(config.IncludeParent),
C.uint8_t(config.WholeObject),
C.callDiffIterateCallback,
C.uintptr_t(cbIndex))
return getError(ret)
@ -126,9 +124,9 @@ func (image *Image) DiffIterate(config DiffIterateConfig) error {
//export diffIterateCallback
func diffIterateCallback(
offset C.uint64_t, length C.size_t, exists, index C.int) C.int {
offset C.uint64_t, length C.size_t, exists C.int, index unsafe.Pointer) C.int {
v := diffIterateCallbacks.Lookup(int(index))
v := diffIterateCallbacks.Lookup(int(uintptr(index)))
config := v.(DiffIterateConfig)
return C.int(config.Callback(
uint64(offset), uint64(length), int(exists), config.Data))

View File

@ -7,24 +7,19 @@ import "C"
import (
"errors"
"fmt"
"github.com/ceph/go-ceph/internal/errutil"
)
// revive:disable:exported Temporarily live with stuttering
// rbdError represents an error condition returned from the librbd APIs.
type rbdError int
// RBDError represents an error condition returned from the librbd APIs.
type RBDError int
func (e rbdError) Error() string {
return errutil.FormatErrorCode("rbd", int(e))
}
// revive:enable:exported
func (e RBDError) Error() string {
errno, s := errutil.FormatErrno(int(e))
if s == "" {
return fmt.Sprintf("rbd: ret=%d", errno)
}
return fmt.Sprintf("rbd: ret=%d, %s", errno, s)
func (e rbdError) ErrorCode() int {
return int(e)
}
func getError(err C.int) error {
@ -32,7 +27,7 @@ func getError(err C.int) error {
if err == -C.ENOENT {
return ErrNotFound
}
return RBDError(err)
return rbdError(err)
}
return nil
}
@ -79,5 +74,5 @@ var (
// Private errors:
const (
errRange = RBDError(-C.ERANGE)
errRange = rbdError(-C.ERANGE)
)

View File

@ -152,7 +152,7 @@ func (image *Image) GetFeatures() (features uint64, err error) {
}
if ret := C.rbd_get_features(image.image, (*C.uint64_t)(&features)); ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
return features, nil

View File

@ -13,9 +13,9 @@ package rbd
import "C"
import (
"bytes"
"unsafe"
"github.com/ceph/go-ceph/internal/cutil"
"github.com/ceph/go-ceph/internal/retry"
"github.com/ceph/go-ceph/rados"
)
@ -100,12 +100,7 @@ func NamespaceList(ioctx *rados.IOContext) (names []string, err error) {
if err != nil {
return nil, err
}
tmpList := bytes.Split(buf[:cSize-1], []byte{0})
for _, s := range tmpList {
if len(s) > 0 {
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
names = append(names, name)
}
}
names = cutil.SplitSparseBuffer(buf[:cSize])
return names, nil
}

View File

@ -9,4 +9,8 @@ const (
// ImageOptionFlatten is the representation of RBD_IMAGE_OPTION_FLATTEN
// from librbd
ImageOptionFlatten = C.RBD_IMAGE_OPTION_FLATTEN
// ImageOptionCloneFormat is the representation of
// RBD_IMAGE_OPTION_CLONE_FORMAT from librbd
ImageOptionCloneFormat = C.RBD_IMAGE_OPTION_CLONE_FORMAT
)

View File

@ -1,12 +0,0 @@
// +build !luminous,!mimic
package rbd
// #include <rbd/librbd.h>
import "C"
const (
// ImageOptionCloneFormat is the representation of
// RBD_IMAGE_OPTION_CLONE_FORMAT from librbd
ImageOptionCloneFormat = C.RBD_IMAGE_OPTION_CLONE_FORMAT
)

View File

@ -84,3 +84,134 @@ func RemovePoolMetadata(ioctx *rados.IOContext, key string) error {
ret := C.rbd_pool_metadata_remove(cephIoctx(ioctx), cKey)
return getError(ret)
}
// PoolInit initializes a pool for use by rbd.
// This function does not create new pools, rather it prepares the pool
// to host rbd images.
//
// Implements:
// int rbd_pool_init(rados_ioctx_t io, bool force)
func PoolInit(ioctx *rados.IOContext, force bool) error {
if ioctx == nil {
return ErrNoIOContext
}
ret := C.rbd_pool_init(cephIoctx(ioctx), C.bool(force))
return getError(ret)
}
// poolStats represents RBD pool stats variable.
type poolStats struct {
stats C.rbd_pool_stats_t
}
// poolStatsCreate creates a new poolStats struct.
//
// Implements:
// void rbd_pool_stats_create(rbd_pool_stats_t *stats)
func poolStatsCreate() *poolStats {
poolstats := &poolStats{}
C.rbd_pool_stats_create(&poolstats.stats)
return poolstats
}
// destroy a poolStats struct and free the associated resources.
//
// Implements:
// void rbd_pool_stats_destroy(rbd_pool_stats_t stats)
func (poolstats *poolStats) destroy() {
C.rbd_pool_stats_destroy(poolstats.stats)
if poolstats.stats != nil {
poolstats.stats = nil
}
}
// PoolStatOption represents a group of configurable pool stat options.
type PoolStatOption C.rbd_pool_stat_option_t
const (
// PoolStatOptionImages is the representation of
// RBD_POOL_STAT_OPTION_IMAGES from librbd.
PoolStatOptionImages = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGES)
// PoolStatOptionImageProvisionedBytes is the representation of
// RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES from librbd.
PoolStatOptionImageProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES)
// PoolStatOptionImageMaxProvisionedBytes is the representation of
// RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES from librbd.
PoolStatOptionImageMaxProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES)
// PoolStatOptionImageSnapshots is the representation of
// RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS from librbd.
PoolStatOptionImageSnapshots = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS)
// PoolStatOptionTrashImages is the representation of
// RBD_POOL_STAT_OPTION_TRASH_IMAGES from librbd.
PoolStatOptionTrashImages = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_IMAGES)
// PoolStatOptionTrashProvisionedBytes is the representation of
// RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES from librbd.
PoolStatOptionTrashProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES)
// PoolStatOptionTrashMaxProvisionedBytes is the representation of
// RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES from librbd.
PoolStatOptionTrashMaxProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES)
// PoolStatOptionTrashSnapshots is the representation of
// RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS from librbd.
PoolStatOptionTrashSnapshots = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS)
)
// addPoolStatOption adds the given PoolStatOption to PoolStats.
//
// Implements:
// int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats, int stat_option, uint64_t* stat_val)
func (poolstats *poolStats) addPoolStatOption(option PoolStatOption, val *uint64) error {
ret := C.rbd_pool_stats_option_add_uint64(
poolstats.stats,
C.int(option),
(*C.uint64_t)(val))
return getError(ret)
}
// GetAllPoolStats returns a map of all PoolStatOption(s) to their respective values.
//
// Implements:
// int rbd_pool_stats_get(rados_ioctx_t io, rbd_pool_stats_t stats);
func GetAllPoolStats(ioctx *rados.IOContext) (map[PoolStatOption]uint64, error) {
var omap = make(map[PoolStatOption]uint64)
if ioctx == nil {
return omap, ErrNoIOContext
}
poolstats := poolStatsCreate()
defer func() {
poolstats.destroy()
}()
var keys [8]PoolStatOption
keys[0] = PoolStatOptionImages
keys[1] = PoolStatOptionImageProvisionedBytes
keys[2] = PoolStatOptionImageMaxProvisionedBytes
keys[3] = PoolStatOptionImageSnapshots
keys[4] = PoolStatOptionTrashImages
keys[5] = PoolStatOptionTrashProvisionedBytes
keys[6] = PoolStatOptionTrashMaxProvisionedBytes
keys[7] = PoolStatOptionTrashSnapshots
ovalArray := make([]uint64, len(keys))
// add option with the address where the respective value would be stored.
for i, key := range keys {
err := poolstats.addPoolStatOption(key, &ovalArray[i])
if err != nil {
return omap, err
}
}
ret := C.rbd_pool_stats_get(cephIoctx(ioctx), poolstats.stats)
if ret < 0 {
return omap, getError(ret)
}
for j, key := range keys {
omap[key] = ovalArray[j]
}
return omap, nil
}

View File

@ -11,13 +11,14 @@ package rbd
import "C"
import (
"bytes"
"errors"
"io"
"time"
"unsafe"
"github.com/ceph/go-ceph/internal/cutil"
"github.com/ceph/go-ceph/internal/retry"
ts "github.com/ceph/go-ceph/internal/timespec"
"github.com/ceph/go-ceph/rados"
)
@ -45,6 +46,9 @@ const (
NoSnapshot = ""
)
// Timespec is a public type for the internal C 'struct timespec'
type Timespec ts.Timespec
// ImageInfo represents the status information for an image.
type ImageInfo struct {
Size uint64
@ -52,8 +56,6 @@ type ImageInfo struct {
Num_objs uint64
Order int
Block_name_prefix string
Parent_pool int64
Parent_name string
}
// SnapInfo represents the status information for a snapshot.
@ -91,18 +93,6 @@ type TrashInfo struct {
DefermentEndTime time.Time // Date / time after which the trashed RBD may be permanently deleted.
}
//
func split(buf []byte) (values []string) {
tmp := bytes.Split(buf[:len(buf)-1], []byte{0})
for _, s := range tmp {
if len(s) > 0 {
go_s := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
values = append(values, go_s)
}
}
return values
}
// cephIoctx returns a ceph rados_ioctx_t given a go-ceph rados IOContext.
func cephIoctx(radosIoctx *rados.IOContext) C.rados_ioctx_t {
return C.rados_ioctx_t(radosIoctx.Pointer())
@ -178,7 +168,7 @@ func Create(ioctx *rados.IOContext, name string, size uint64, order int,
}
if ret < 0 {
return nil, RBDError(ret)
return nil, rbdError(ret)
}
return &Image{
@ -204,7 +194,7 @@ func Create2(ioctx *rados.IOContext, name string, size uint64, features uint64,
ret = C.rbd_create2(cephIoctx(ioctx), c_name,
C.uint64_t(size), C.uint64_t(features), &c_order)
if ret < 0 {
return nil, RBDError(ret)
return nil, rbdError(ret)
}
return &Image{
@ -233,7 +223,7 @@ func Create3(ioctx *rados.IOContext, name string, size uint64, features uint64,
C.uint64_t(size), C.uint64_t(features), &c_order,
C.uint64_t(stripe_unit), C.uint64_t(stripe_count))
if ret < 0 {
return nil, RBDError(ret)
return nil, rbdError(ret)
}
return &Image{
@ -267,7 +257,7 @@ func (image *Image) Clone(snapname string, c_ioctx *rados.IOContext, c_name stri
cephIoctx(c_ioctx),
c_c_name, C.uint64_t(features), &c_order)
if ret < 0 {
return nil, RBDError(ret)
return nil, rbdError(ret)
}
return &Image{
@ -316,7 +306,7 @@ func (image *Image) Rename(destname string) error {
defer C.free(unsafe.Pointer(c_srcname))
defer C.free(unsafe.Pointer(c_destname))
err := RBDError(C.rbd_rename(cephIoctx(image.ioctx),
err := rbdError(C.rbd_rename(cephIoctx(image.ioctx),
c_srcname, c_destname))
if err == 0 {
image.name = destname
@ -377,7 +367,7 @@ func (image *Image) Close() error {
}
if ret := C.rbd_close(image.image); ret != 0 {
return RBDError(ret)
return rbdError(ret)
}
image.image = nil
@ -408,7 +398,7 @@ func (image *Image) Stat() (info *ImageInfo, err error) {
var c_stat C.rbd_image_info_t
if ret := C.rbd_stat(image.image, &c_stat, C.size_t(unsafe.Sizeof(info))); ret < 0 {
return info, RBDError(ret)
return info, rbdError(ret)
}
return &ImageInfo{
@ -416,9 +406,7 @@ func (image *Image) Stat() (info *ImageInfo, err error) {
Obj_size: uint64(c_stat.obj_size),
Num_objs: uint64(c_stat.num_objs),
Order: int(c_stat.order),
Block_name_prefix: C.GoString((*C.char)(&c_stat.block_name_prefix[0])),
Parent_pool: int64(c_stat.parent_pool),
Parent_name: C.GoString((*C.char)(&c_stat.parent_name[0]))}, nil
Block_name_prefix: C.GoString((*C.char)(&c_stat.block_name_prefix[0]))}, nil
}
// IsOldFormat returns true if the rbd image uses the old format.
@ -434,7 +422,7 @@ func (image *Image) IsOldFormat() (old_format bool, err error) {
ret := C.rbd_get_old_format(image.image,
&c_old_format)
if ret < 0 {
return false, RBDError(ret)
return false, rbdError(ret)
}
return c_old_format != 0, nil
@ -450,7 +438,7 @@ func (image *Image) GetSize() (size uint64, err error) {
}
if ret := C.rbd_get_size(image.image, (*C.uint64_t)(&size)); ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
return size, nil
@ -466,7 +454,7 @@ func (image *Image) GetStripeUnit() (stripe_unit uint64, err error) {
}
if ret := C.rbd_get_stripe_unit(image.image, (*C.uint64_t)(&stripe_unit)); ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
return stripe_unit, nil
@ -482,7 +470,7 @@ func (image *Image) GetStripeCount() (stripe_count uint64, err error) {
}
if ret := C.rbd_get_stripe_count(image.image, (*C.uint64_t)(&stripe_count)); ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
return stripe_count, nil
@ -499,7 +487,7 @@ func (image *Image) GetOverlap() (overlap uint64, err error) {
}
if ret := C.rbd_get_overlap(image.image, (*C.uint64_t)(&overlap)); ret < 0 {
return overlap, RBDError(ret)
return overlap, rbdError(ret)
}
return overlap, nil
@ -598,12 +586,12 @@ func (image *Image) ListLockers() (tag string, lockers []Locker, err error) {
// but *0* is unexpected here because first rbd_list_lockers already
// dealt with no locker case
if int(c_locker_cnt) <= 0 {
return "", nil, RBDError(c_locker_cnt)
return "", nil, rbdError(c_locker_cnt)
}
clients := split(clients_buf)
cookies := split(cookies_buf)
addrs := split(addrs_buf)
clients := cutil.SplitSparseBuffer(clients_buf)
cookies := cutil.SplitSparseBuffer(cookies_buf)
addrs := cutil.SplitSparseBuffer(addrs_buf)
lockers = make([]Locker, c_locker_cnt)
for i := 0; i < int(c_locker_cnt); i++ {
@ -704,7 +692,7 @@ func (image *Image) Read(data []byte) (int, error) {
(*C.char)(unsafe.Pointer(&data[0]))))
if ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
image.offset += int64(ret)
@ -729,7 +717,7 @@ func (image *Image) Write(data []byte) (n int, err error) {
}
if ret != len(data) {
err = RBDError(-C.EPERM)
err = rbdError(-C.EPERM)
}
return ret, err
@ -767,7 +755,7 @@ func (image *Image) Discard(ofs uint64, length uint64) (int, error) {
ret := C.rbd_discard(image.image, C.uint64_t(ofs), C.uint64_t(length))
if ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
return int(ret), nil
@ -790,7 +778,7 @@ func (image *Image) ReadAt(data []byte, off int64) (int, error) {
(*C.char)(unsafe.Pointer(&data[0]))))
if ret < 0 {
return 0, RBDError(ret)
return 0, rbdError(ret)
}
if ret < len(data) {
@ -814,7 +802,7 @@ func (image *Image) WriteAt(data []byte, off int64) (n int, err error) {
C.size_t(len(data)), (*C.char)(unsafe.Pointer(&data[0]))))
if ret != len(data) {
err = RBDError(-C.EPERM)
err = rbdError(-C.EPERM)
}
return ret, err
@ -852,7 +840,7 @@ func (image *Image) GetSnapshotNames() (snaps []SnapInfo, err error) {
ret = C.rbd_snap_list(image.image,
&c_snaps[0], &c_max_snaps)
if ret < 0 {
return nil, RBDError(ret)
return nil, rbdError(ret)
}
for i, s := range c_snaps {
@ -913,7 +901,7 @@ func (image *Image) SetMetadata(key string, value string) error {
ret := C.rbd_metadata_set(image.image, c_key, c_value)
if ret < 0 {
return RBDError(ret)
return rbdError(ret)
}
return nil
@ -933,7 +921,7 @@ func (image *Image) RemoveMetadata(key string) error {
ret := C.rbd_metadata_remove(image.image, c_key)
if ret < 0 {
return RBDError(ret)
return rbdError(ret)
}
return nil
@ -1205,7 +1193,7 @@ func CreateImage(ioctx *rados.IOContext, name string, size uint64, rio *ImageOpt
return ErrNoName
}
if rio == nil {
return RBDError(C.EINVAL)
return rbdError(C.EINVAL)
}
c_name := C.CString(name)
@ -1244,7 +1232,7 @@ func CloneImage(ioctx *rados.IOContext, parentName, snapName string,
destctx *rados.IOContext, name string, rio *ImageOptions) error {
if rio == nil {
return RBDError(C.EINVAL)
return rbdError(C.EINVAL)
}
cParentName := C.CString(parentName)

View File

@ -12,9 +12,9 @@ package rbd
import "C"
import (
"bytes"
"unsafe"
"github.com/ceph/go-ceph/internal/cutil"
"github.com/ceph/go-ceph/internal/retry"
"github.com/ceph/go-ceph/rados"
)
@ -37,12 +37,6 @@ func GetImageNames(ioctx *rados.IOContext) (names []string, err error) {
if err != nil {
return nil, err
}
tmp := bytes.Split(buf[:csize-1], []byte{0})
for _, s := range tmp {
if len(s) > 0 {
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
names = append(names, name)
}
}
names = cutil.SplitSparseBuffer(buf[:csize])
return names, nil
}

View File

@ -1,6 +1,7 @@
// +build !luminous,!mimic
//
// Ceph Nautilus is the first release that includes rbd_list2().
// Ceph Nautilus is the first release that includes rbd_list2() and
// rbd_get_create_timestamp().
package rbd
@ -14,6 +15,7 @@ import (
"unsafe"
"github.com/ceph/go-ceph/internal/retry"
ts "github.com/ceph/go-ceph/internal/timespec"
"github.com/ceph/go-ceph/rados"
)
@ -45,3 +47,57 @@ func GetImageNames(ioctx *rados.IOContext) ([]string, error) {
}
return names, nil
}
// GetCreateTimestamp returns the time the rbd image was created.
//
// Implements:
// int rbd_get_create_timestamp(rbd_image_t image, struct timespec *timestamp);
func (image *Image) GetCreateTimestamp() (Timespec, error) {
if err := image.validate(imageIsOpen); err != nil {
return Timespec{}, err
}
var cts C.struct_timespec
if ret := C.rbd_get_create_timestamp(image.image, &cts); ret < 0 {
return Timespec{}, getError(ret)
}
return Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&cts))), nil
}
// GetAccessTimestamp returns the time the rbd image was last accessed.
//
// Implements:
// int rbd_get_access_timestamp(rbd_image_t image, struct timespec *timestamp);
func (image *Image) GetAccessTimestamp() (Timespec, error) {
if err := image.validate(imageIsOpen); err != nil {
return Timespec{}, err
}
var cts C.struct_timespec
if ret := C.rbd_get_access_timestamp(image.image, &cts); ret < 0 {
return Timespec{}, getError(ret)
}
return Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&cts))), nil
}
// GetModifyTimestamp returns the time the rbd image was last modified.
//
// Implements:
// int rbd_get_modify_timestamp(rbd_image_t image, struct timespec *timestamp);
func (image *Image) GetModifyTimestamp() (Timespec, error) {
if err := image.validate(imageIsOpen); err != nil {
return Timespec{}, err
}
var cts C.struct_timespec
if ret := C.rbd_get_modify_timestamp(image.image, &cts); ret < 0 {
return Timespec{}, getError(ret)
}
return Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&cts))), nil
}

View File

@ -30,7 +30,7 @@ func (image *Image) CreateSnapshot(snapname string) (*Snapshot, error) {
ret := C.rbd_snap_create(image.image, c_snapname)
if ret < 0 {
return nil, RBDError(ret)
return nil, rbdError(ret)
}
return &Snapshot{
@ -139,7 +139,7 @@ func (snapshot *Snapshot) IsProtected() (bool, error) {
ret := C.rbd_snap_is_protected(snapshot.image.image, c_snapname,
&c_is_protected)
if ret < 0 {
return false, RBDError(ret)
return false, rbdError(ret)
}
return c_is_protected != 0, nil

View File

@ -12,8 +12,9 @@ package rbd
import "C"
import (
"bytes"
"unsafe"
"github.com/ceph/go-ceph/internal/cutil"
)
// GetParentInfo looks for the parent of the image and stores the pool, name
@ -40,7 +41,7 @@ func (image *Image) GetParentInfo(p_pool, p_name, p_snapname []byte) error {
if ret == 0 {
return nil
} else {
return RBDError(ret)
return rbdError(ret)
}
}
@ -66,7 +67,7 @@ func (image *Image) ListChildren() (pools []string, images []string, err error)
return nil, nil, nil
}
if ret < 0 && ret != -C.ERANGE {
return nil, nil, RBDError(ret)
return nil, nil, rbdError(ret)
}
pools_buf := make([]byte, c_pools_len)
@ -78,24 +79,10 @@ func (image *Image) ListChildren() (pools []string, images []string, err error)
(*C.char)(unsafe.Pointer(&images_buf[0])),
&c_images_len)
if ret < 0 {
return nil, nil, RBDError(ret)
}
tmp := bytes.Split(pools_buf[:c_pools_len-1], []byte{0})
for _, s := range tmp {
if len(s) > 0 {
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
pools = append(pools, name)
}
}
tmp = bytes.Split(images_buf[:c_images_len-1], []byte{0})
for _, s := range tmp {
if len(s) > 0 {
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
images = append(images, name)
}
return nil, nil, rbdError(ret)
}
pools = cutil.SplitSparseBuffer(pools_buf[:c_pools_len])
images = cutil.SplitSparseBuffer(images_buf[:c_images_len])
return pools, images, nil
}

View File

@ -0,0 +1,80 @@
// +build !luminous
//
// Ceph Mimic introduced rbd_snap_get_namespace_type().
package rbd
// #cgo LDFLAGS: -lrbd
// #include <rbd/librbd.h>
import "C"
import (
"unsafe"
"github.com/ceph/go-ceph/internal/retry"
)
// SnapNamespaceType indicates the namespace to which the snapshot belongs to.
type SnapNamespaceType C.rbd_snap_namespace_type_t
const (
// SnapNamespaceTypeUser indicates that the snapshot belongs to user namespace.
SnapNamespaceTypeUser = SnapNamespaceType(C.RBD_SNAP_NAMESPACE_TYPE_USER)
// SnapNamespaceTypeGroup indicates that the snapshot belongs to group namespace.
// Such snapshots will have associated group information.
SnapNamespaceTypeGroup = SnapNamespaceType(C.RBD_SNAP_NAMESPACE_TYPE_GROUP)
// SnapNamespaceTypeTrash indicates that the snapshot belongs to trash namespace.
SnapNamespaceTypeTrash = SnapNamespaceType(C.RBD_SNAP_NAMESPACE_TYPE_TRASH)
)
// GetSnapNamespaceType gets the type of namespace to which the snapshot belongs to,
// returns error on failure.
//
// Implements:
// int rbd_snap_get_namespace_type(rbd_image_t image, uint64_t snap_id, rbd_snap_namespace_type_t *namespace_type)
func (image *Image) GetSnapNamespaceType(snapID uint64) (SnapNamespaceType, error) {
var nsType SnapNamespaceType
if err := image.validate(imageIsOpen); err != nil {
return nsType, err
}
ret := C.rbd_snap_get_namespace_type(image.image,
C.uint64_t(snapID),
(*C.rbd_snap_namespace_type_t)(&nsType))
return nsType, getError(ret)
}
// GetSnapTrashNamespace returns the original name of the snapshot which was
// moved to the Trash. The caller should make sure that the snapshot ID passed in this
// function belongs to a snapshot already in the Trash.
//
// Implements:
// int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id, char *original_name, size_t max_length)
func (image *Image) GetSnapTrashNamespace(snapID uint64) (string, error) {
if err := image.validate(imageIsOpen); err != nil {
return "", err
}
var (
buf []byte
err error
)
retry.WithSizes(4096, 262144, func(length int) retry.Hint {
cLength := C.size_t(length)
buf = make([]byte, cLength)
ret := C.rbd_snap_get_trash_namespace(image.image,
C.uint64_t(snapID),
(*C.char)(unsafe.Pointer(&buf[0])),
cLength)
err = getError(ret)
return retry.Size(int(cLength)).If(err == errRange)
})
if err != nil {
return "", err
}
return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
}

View File

@ -32,7 +32,7 @@ func (image *Image) GetParentInfo(pool, name, snapname []byte) error {
parentSnap := C.rbd_snap_spec_t{}
ret := C.rbd_get_parent(image.image, &parentImage, &parentSnap)
if ret != 0 {
return RBDError(ret)
return rbdError(ret)
}
defer C.rbd_linked_image_spec_cleanup(&parentImage)
@ -40,26 +40,26 @@ func (image *Image) GetParentInfo(pool, name, snapname []byte) error {
strlen := int(C.strlen(parentImage.pool_name))
if len(pool) < strlen {
return RBDError(C.ERANGE)
return rbdError(C.ERANGE)
}
if copy(pool, C.GoString(parentImage.pool_name)) != strlen {
return RBDError(C.ERANGE)
return rbdError(C.ERANGE)
}
strlen = int(C.strlen(parentImage.image_name))
if len(name) < strlen {
return RBDError(C.ERANGE)
return rbdError(C.ERANGE)
}
if copy(name, C.GoString(parentImage.image_name)) != strlen {
return RBDError(C.ERANGE)
return rbdError(C.ERANGE)
}
strlen = int(C.strlen(parentSnap.name))
if len(snapname) < strlen {
return RBDError(C.ERANGE)
return rbdError(C.ERANGE)
}
if copy(snapname, C.GoString(parentSnap.name)) != strlen {
return RBDError(C.ERANGE)
return rbdError(C.ERANGE)
}
return nil

View File

@ -4,12 +4,30 @@
package rbd
// #cgo LDFLAGS: -lrbd
// #include <errno.h>
// #include <rbd/librbd.h>
/*
#cgo LDFLAGS: -lrbd
#include <rbd/librbd.h>
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"
import (
"unsafe"
"github.com/ceph/go-ceph/internal/callbacks"
"github.com/ceph/go-ceph/internal/retry"
)
@ -59,3 +77,76 @@ func (image *Image) ListWatchers() ([]ImageWatcher, error) {
}
return imageWatchers, nil
}
// watchCallbacks tracks the active callbacks for rbd watches
var watchCallbacks = callbacks.New()
// WatchCallback defines the function signature needed for the UpdateWatch
// callback.
type WatchCallback func(interface{})
type watchCallbackCtx struct {
callback WatchCallback
data interface{}
}
// Watch represents an ongoing image metadata watch.
type Watch struct {
image *Image
wcc watchCallbackCtx
handle C.uint64_t
cbIndex int
}
// UpdateWatch updates the image object to watch metadata changes to the
// image, returning a Watch object.
//
// Implements:
// int rbd_update_watch(rbd_image_t image, uint64_t *handle,
// rbd_update_callback_t watch_cb, void *arg);
func (image *Image) UpdateWatch(cb WatchCallback, data interface{}) (*Watch, error) {
if err := image.validate(imageIsOpen); err != nil {
return nil, err
}
wcc := watchCallbackCtx{
callback: cb,
data: data,
}
w := &Watch{
image: image,
wcc: wcc,
cbIndex: watchCallbacks.Add(wcc),
}
ret := C.wrap_rbd_update_watch(
image.image,
&w.handle,
C.uintptr_t(w.cbIndex))
if ret != 0 {
return nil, getError(ret)
}
return w, nil
}
// Unwatch un-registers the image watch.
//
// Implements:
// int rbd_update_unwatch(rbd_image_t image, uint64_t handle);
func (w *Watch) Unwatch() error {
if w.image == nil {
return ErrImageNotOpen
}
if err := w.image.validate(imageIsOpen); err != nil {
return err
}
ret := C.rbd_update_unwatch(w.image.image, w.handle)
watchCallbacks.Remove(w.cbIndex)
return getError(ret)
}
//export imageWatchCallback
func imageWatchCallback(index unsafe.Pointer) {
v := watchCallbacks.Lookup(int(uintptr(index)))
wcc := v.(watchCallbackCtx)
wcc.callback(wcc.data)
}