rbd中涉及的回调,以写入为例,跟踪回调函数的变迁。
@rbd.cc
################################################ ******AioExportContext && librbd::RBD::AioCompletion
AioExportContext(SimpleThrottle &simple_throttle, librbd::Image &image,
uint64_t offset, uint64_t length, int fd)
: m_aio_completion(
new librbd::RBD::AioCompletion(this, &AioExportContext::aio_callback)), //this==AioExportContext AioExportContext::aio_callback
m_throttle(simple_throttle),
m_offset(offset),
m_fd(fd)
{
m_throttle.start_op();
int op_flags = LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL |
LIBRADOS_OP_FLAG_FADVISE_NOCACHE;
int r = image.aio_read2(offset, length, m_bufferlist, m_aio_completion,
op_flags);
if (r < 0) {
cerr << "rbd: error requesting read from source image" << std::endl;
m_throttle.end_op(r);
}
}
@librbd/librbd.cc
####################################### ******librbd::AioCompletion
RBD::AioCompletion::AioCompletion(void *cb_arg, callback_t complete_cb)
{
librbd::AioCompletion *c = librbd::aio_create_completion(cb_arg, //cb_arg == AioExportContext complete_cb == AioExportContext::aio_callback
complete_cb);
pc = (void *)c;
c->rbd_comp = this;
}
@librbd/internal.cc
####################################################
AioCompletion *aio_create_completion(void *cb_arg, callback_t cb_complete) {
AioCompletion *c = new AioCompletion();
c->set_complete_cb(cb_arg, cb_complete); //cb_arg == AioExportContext complete_cb == AioExportContext::aio_callback
return c;
}
@librbd/AioCompletion.h
######################################################
struct AioCompletion {
¦ Mutex lock;
¦ Cond cond;
¦ bool done;
¦ ssize_t rval;
¦ callback_t complete_cb;
¦ void *complete_arg;
¦ rbd_completion_t rbd_comp;
¦ int pending_count; ///< number of requests
¦ uint32_t blockers;
¦ int ref;
¦ bool released;
¦ ImageCtx *ictx;
¦ utime_t start_time;
¦ aio_type_t aio_type;
¦ Striper::StripedReadResult destriper;
¦ bufferlist *read_bl;
¦ char *read_buf;
¦ size_t read_buf_len;
¦ AsyncOperation async_op;
¦ AioCompletion() : lock("AioCompletion::lock", true, false),
¦ ¦ ¦ done(false), rval(0), complete_cb(NULL),
¦ ¦ ¦ complete_arg(NULL), rbd_comp(NULL),
¦ ¦ ¦ pending_count(0), blockers(1),
¦ ¦ ¦ ref(1), released(false), ictx(NULL),
¦ ¦ ¦ aio_type(AIO_TYPE_NONE),
¦ ¦ ¦ read_bl(NULL), read_buf(NULL), read_buf_len(0) {
¦ }
...
}
¦ void set_complete_cb(void *cb_arg, callback_t cb) {
¦ complete_cb = cb; // cb == AioExportContext cb_arg == AioExportContext::aio_callback
¦ complete_arg = cb_arg;
}
@librbd/internal.cc aio_read()
######################################### *******C_AioRead
C_AioRead *req_comp = new C_AioRead(ictx->cct, c) //librbd::AioCompletion
AioRead *req = new AioRead(ictx, q->oid.name, q->objectno, q->offset,q->length, q->buffer_extents, snap_id, true,req_comp, op_flags) //req_comp == C_AioRead
@librbd/AioRequest.cc
########################################## ********* librados::AioCompletion
librados::AioCompletion *rados_completion = librados::Rados::aio_create_completion(this, rados_req_cb, NULL) //this == AioRead rados_req_cb==rados_req_cb(librbd/internal.h)
librados::AioCompletion *librados::Rados::aio_create_completion(void *cb_arg,
callback_t cb_complete,
callback_t cb_safe)
{
AioCompletionImpl *c;
int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe, (void**)&c);
assert(r == 0);
return new AioCompletion(c);
}
@/librados/librados.cc
#######################################################
int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe, (void**)&c) //cb_arg == AioRead cb_complete==rados_req_cb(librbd/internal.h)
@librados/librados.cc
######################################################### ************* librados::AioCompletionImpl
extern "C" int rados_aio_create_completion(void *cb_arg, //cb_arg == AioRead cb_complete==rados_req_cb(librbd/internal.h)
rados_callback_t cb_complete,
rados_callback_t cb_safe,
rados_completion_t *pc)
{
tracepoint(librados, rados_aio_create_completion_enter, cb_arg, cb_complete, cb_safe);
librados::AioCompletionImpl *c = new librados::AioCompletionImpl;
if (cb_complete)
c->set_complete_callback(cb_arg, cb_complete);
if (cb_safe)
c->set_safe_callback(cb_arg, cb_safe);
*pc = c;
tracepoint(librados, rados_aio_create_completion_exit, 0, *pc);
return 0;
}
总之在主逻辑进入不同的层级时都会伴随着回调的变迁(封装),最后他们的调用跟封装过程是相反的。