}
}
- read_from_parent(image_extents);
-
- if (is_copy_on_read(m_ictx, m_snap_id))
+ if (is_copy_on_read(m_ictx, m_snap_id)) {
m_state = LIBRBD_AIO_READ_COPYUP;
- else
+ } else {
m_state = LIBRBD_AIO_READ_GUARD;
+ }
+ read_from_parent(image_extents);
finished = false;
}
}
m_ictx->copyup_list[m_object_no] = new_req;
m_ictx->copyup_list_lock.Unlock();
- new_req->read_from_parent(m_image_extents);
+ new_req->queue_read_from_parent(m_image_extents);
}
} else {
m_ictx->copyup_list_lock.Unlock();
aio_read(m_ictx->parent, image_extents, NULL, &m_copyup_data, m_parent_completion, 0);
}
+ void CopyupRequest::queue_read_from_parent(vector<pair<uint64_t,uint64_t> >& image_extents)
+ {
+ // TODO: once the ObjectCacher allows reentrant read requests, the finisher
+ // should be eliminated
+ C_ReadFromParent *ctx = new C_ReadFromParent(this, image_extents);
+ m_ictx->copyup_finisher->queue(ctx);
+ }
+
void CopyupRequest::rbd_read_from_parent_cb(completion_t cb, void *arg)
{
CopyupRequest *req = reinterpret_cast<CopyupRequest *>(arg);
void complete_all(int r);
void send_copyup(int r);
void read_from_parent(vector<pair<uint64_t,uint64_t> >& image_extents);
+ void queue_read_from_parent(vector<pair<uint64_t,uint64_t> >& image_extents);
static void rbd_read_from_parent_cb(completion_t cb, void *arg);
static void rbd_copyup_cb(completion_t aio_completion_impl, void *arg);
private:
ImageCtx *m_ictx;
+
+ class C_ReadFromParent : public Context {
+ public:
+ C_ReadFromParent(CopyupRequest *c, vector<pair<uint64_t,uint64_t> > i)
+ : m_req(c), m_image_extents(i) {}
+
+ virtual void finish(int r) {
+ m_req->read_from_parent(m_image_extents);
+ }
+
+ private:
+ CopyupRequest *m_req;
+ vector<pair<uint64_t,uint64_t> > m_image_extents;
+ };
+
std::string m_oid;
uint64_t m_object_no;
Mutex m_lock;
stripe_unit(0), stripe_count(0),
object_cacher(NULL), writeback_handler(NULL), object_set(NULL),
readahead(),
- total_bytes_read(0),
+ total_bytes_read(0), copyup_finisher(NULL),
pending_aio(0)
{
md_ctx.dup(p);
object_set->return_enoent = true;
object_cacher->start();
}
+
+ if (cct->_conf->rbd_clone_copy_on_read) {
+ copyup_finisher = new Finisher(cct);
+ copyup_finisher->start();
+ }
}
ImageCtx::~ImageCtx() {
delete object_set;
object_set = NULL;
}
+ if (copyup_finisher != NULL) {
+ delete copyup_finisher;
+ copyup_finisher = NULL;
+ }
delete[] format_string;
}
#include "librbd/parent_types.h"
class CephContext;
+class Finisher;
class PerfCounters;
namespace librbd {
Readahead readahead;
uint64_t total_bytes_read;
+
+ Finisher *copyup_finisher;
std::map<uint64_t, CopyupRequest*> copyup_list;
Cond pending_aio_cond;
if (ictx->image_watcher != NULL) {
ictx->image_watcher->flush_aio_operations();
}
- ictx->wait_for_pending_copyup();
if (ictx->object_cacher) {
ictx->shutdown_cache(); // implicitly flushes
} else {
ictx->wait_for_pending_aio();
}
+ if (ictx->copyup_finisher != NULL) {
+ ictx->copyup_finisher->wait_for_empty();
+ ictx->copyup_finisher->stop();
+ }
+ ictx->wait_for_pending_copyup();
+
if (ictx->parent) {
close_image(ictx->parent);
ictx->parent = NULL;