char *parent_snapname,
size_t psnapnamelen);
CEPH_RBD_API int rbd_get_flags(rbd_image_t image, uint64_t *flags);
+CEPH_RBD_API int rbd_set_image_notification(rbd_image_t image, int fd, int type);
/* exclusive lock feature */
CEPH_RBD_API int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner);
char *buf, rbd_completion_t c, int op_flags);
CEPH_RBD_API int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
rbd_completion_t c);
+
CEPH_RBD_API int rbd_aio_create_completion(void *cb_arg,
rbd_callback_t complete_cb,
rbd_completion_t *c);
*/
CEPH_RBD_API int rbd_invalidate_cache(rbd_image_t image);
+CEPH_RBD_API int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp, int max);
+
CEPH_RBD_API int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *val_len);
CEPH_RBD_API int rbd_metadata_set(rbd_image_t image, const char *key, const char *value);
CEPH_RBD_API int rbd_metadata_remove(rbd_image_t image, const char *key);
int update_features(uint64_t features, bool enabled);
int overlap(uint64_t *overlap);
int get_flags(uint64_t *flags);
+ int set_image_notification(int fd, int type);
/* exclusive lock feature */
int is_exclusive_lock_owner(bool *is_owner);
*/
int invalidate_cache();
+ int poll_io_events(RBD::AioCompletion **comps, int numcomp, int max);
+
int metadata_get(const std::string &key, std::string *value);
int metadata_set(const std::string &key, const std::string &value);
int metadata_remove(const std::string &key);
async_op.finish_op();
}
+ lock.Unlock();
if (complete_cb) {
- lock.Unlock();
complete_cb(rbd_comp, complete_arg);
- lock.Lock();
}
+
+ lock.Lock();
done = true;
+ if (event_notify && ictx->event_socket.is_valid()) {
+ ictx->completed_reqs_lock.Lock();
+ ictx->completed_reqs.push_back(&m_xlist_item);
+ ictx->completed_reqs_lock.Unlock();
+ ictx->event_socket.notify();
+ }
cond.Signal();
tracepoint(librbd, aio_complete_exit);
}
AsyncOperation async_op;
uint64_t journal_tid;
+ xlist<AioCompletion*>::item m_xlist_item;
+ bool event_notify;
AioCompletion() : lock("AioCompletion::lock", true, false),
done(false), rval(0), complete_cb(NULL),
aio_type(AIO_TYPE_NONE),
read_bl(NULL), read_buf(NULL), read_buf_len(0),
journal_tid(0) {
+ m_xlist_item(this), event_notify(false) {
}
~AioCompletion() {
}
assert(ref > 0);
int n = --ref;
lock.Unlock();
- if (!n)
- delete this;
+ if (!n) {
+ ictx->completed_reqs_lock.Lock();
+ m_xlist_item.remove_myself();
+ ictx->completed_reqs_lock.Unlock();
+ delete this;
+ }
}
void block() {
complete(cct);
}
}
+
+ void enable_event_notify() {
+ Mutex::Locker l(lock);
+ event_notify = true;
+ }
};
class C_AioRequest : public Context {
object_map_lock(unique_lock_name("librbd::ImageCtx::object_map_lock", this)),
async_ops_lock(unique_lock_name("librbd::ImageCtx::async_ops_lock", this)),
copyup_list_lock(unique_lock_name("librbd::ImageCtx::copyup_list_lock", this)),
+ completed_reqs_lock(unique_lock_name("librbd::ImageCtx::completed_reqs_lock", this)),
extra_read_flags(0),
old_format(true),
order(0), size(0), features(0),
#include <boost/optional.hpp>
#include "common/Cond.h"
+#include "common/event_socket.h"
#include "common/Mutex.h"
#include "common/Readahead.h"
#include "common/RWLock.h"
class LibrbdAdminSocketHook;
class ImageWatcher;
class Journal;
+ class AioCompletion;
namespace operation {
class ResizeRequest;
RWLock object_map_lock; // protects object map updates and object_map itself
Mutex async_ops_lock; // protects async_ops and async_requests
Mutex copyup_list_lock; // protects copyup_waiting_list
+ Mutex completed_reqs_lock; // protects completed_reqs
unsigned extra_read_flags;
xlist<operation::ResizeRequest*> resize_reqs;
AioImageRequestWQ *aio_work_queue;
+ xlist<AioCompletion*> completed_reqs;
+ EventSocket event_socket;
+
ContextWQ *op_work_queue;
Cond refresh_cond;
#include "common/ContextCompletion.h"
#include "common/Throttle.h"
#include "common/WorkQueue.h"
+#include "common/event_socket.h"
#include "cls/lock/cls_lock_client.h"
#include "include/stringify.h"
return ictx->get_flags(ictx->snap_id, flags);
}
+ int set_image_notification(ImageCtx *ictx, int fd, int type)
+ {
+ CephContext *cct = ictx->cct;
+ ldout(cct, 20) << __func__ << " " << ictx << " fd " << fd << " type" << type << dendl;
+
+ int r = ictx_check(ictx);
+ if (r < 0) {
+ return r;
+ }
+
+ if (ictx->event_socket.is_valid())
+ return -EINVAL;
+ return ictx->event_socket.init(fd, type);
+ }
+
int is_exclusive_lock_owner(ImageCtx *ictx, bool *is_owner)
{
RWLock::RLocker l(ictx->owner_lock);
return r;
}
+ int poll_io_events(ImageCtx *ictx, AioCompletion **comps, int numcomp, int max)
+ {
+ if (numcomp < max || numcomp <= 0)
+ return -EINVAL;
+ CephContext *cct = ictx->cct;
+ ldout(cct, 20) << __func__ << " " << ictx << " numcomp = " << numcomp << " max " << max << dendl;
+ int i = 0;
+ Mutex::Locker l(ictx->completed_reqs_lock);
+ while (i < max) {
+ if (ictx->completed_reqs.empty())
+ break;
+ comps[i++] = ictx->completed_reqs.front();
+ ictx->completed_reqs.pop_front();
+ }
+ return i;
+ }
+
int metadata_get(ImageCtx *ictx, const string &key, string *value)
{
CephContext *cct = ictx->cct;
int get_parent_info(ImageCtx *ictx, std::string *parent_pool_name,
std::string *parent_name, std::string *parent_snap_name);
int get_flags(ImageCtx *ictx, uint64_t *flags);
+ int set_image_notification(ImageCtx *ictx, int fd, int type);
int is_exclusive_lock_owner(ImageCtx *ictx, bool *is_owner);
int remove(librados::IoCtx& io_ctx, const char *imgname,
int flush(ImageCtx *ictx);
int invalidate_cache(ImageCtx *ictx);
+ int poll_io_events(ImageCtx *ictx, AioCompletion **comps, int numcomp, int max);
int metadata_list(ImageCtx *ictx, const string &last, uint64_t max, map<string, bufferlist> *pairs);
int metadata_get(ImageCtx *ictx, const std::string &key, std::string *value);
int metadata_set(ImageCtx *ictx, const std::string &key, const std::string &value);
#include "common/perf_counters.h"
#include "common/TracepointProvider.h"
#include "include/Context.h"
-#include "include/rbd/librbd.hpp"
#include "osdc/ObjectCacher.h"
#include "librbd/AioCompletion.h"
complete_cb);
pc = (void *)c;
c->rbd_comp = this;
+ c->enable_event_notify();
}
bool RBD::AioCompletion::is_complete()
return r;
}
+ int Image::set_image_notification(int fd, int type)
+ {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
+ int r = librbd::set_image_notification(ictx, fd, type);
+ tracepoint(librbd, set_image_notification_exit, ictx, r);
+ return r;
+ }
+
int Image::is_exclusive_lock_owner(bool *is_owner)
{
ImageCtx *ictx = (ImageCtx *)ctx;
return r;
}
+ int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp, int max)
+ {
+ AioCompletion *cs[numcomp];
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, poll_io_events_enter, numcomp, max);
+ int r = librbd::poll_io_events(ictx, cs, numcomp, max);
+ tracepoint(librbd, poll_io_events_exit, r);
+ if (r > 0) {
+ for (int i = 0; i < numcomp; ++i)
+ comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
+ }
+ return r;
+ }
+
int Image::metadata_get(const std::string &key, std::string *value)
{
ImageCtx *ictx = (ImageCtx *)ctx;
return r;
}
+extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
+ int r = librbd::set_image_notification(ictx, fd, type);
+ tracepoint(librbd, set_image_notification_exit, ictx, r);
+ return r;
+}
+
extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
return r;
}
+extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp, int max)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ librbd::AioCompletion *cs[numcomp];
+ tracepoint(librbd, poll_io_events_enter, numcomp, max);
+ int r = librbd::poll_io_events(ictx, cs, numcomp, max);
+ tracepoint(librbd, poll_io_events_exit, r);
+ if (r > 0) {
+ for (int i = 0; i < r; ++i)
+ comps[i] = cs[i]->rbd_comp;
+ }
+ return r;
+}
+
extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
)
)
+TRACEPOINT_EVENT(librbd, poll_io_events_enter,
+ TP_ARGS(
+ void*, imagectx,
+ int, numcomp,
+ int, max),
+ TP_FIELDS(
+ ctf_integer_hex(void*, imagectx, imagectx)
+ ctf_integer(int, numcomp, numcomp)
+ ctf_integer(int, max, max)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, poll_io_events_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
TRACEPOINT_EVENT(librbd, metadata_get_enter,
TP_ARGS(
void*, imagectx,
)
)
+TRACEPOINT_EVENT(librbd, set_image_notification_enter,
+ TP_ARGS(
+ void*, imagectx,
+ int, fd,
+ int type),
+ TP_FIELDS(
+ ctf_integer_hex(void*, imagectx, imagectx)
+ ctf_integer(int, fd, fd)
+ ctf_integer(int, type, type)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, set_image_notification_exit,
+ TP_ARGS(
+ void*, imagectx,
+ int, retval)
+ TP_FIELDS(
+ ctf_integer_hex(void*, imagectx, imagectx)
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librbd, is_exclusive_lock_owner_enter,
TP_ARGS(
void*, imagectx),