} // anonymous namespace
-void AioImageRequest::aio_read(
- ImageCtx *ictx, AioCompletion *c,
+template <typename I>
+void AioImageRequest<I>::aio_read(
+ I *ictx, AioCompletion *c,
const std::vector<std::pair<uint64_t,uint64_t> > &extents,
char *buf, bufferlist *pbl, int op_flags) {
AioImageRead req(*ictx, c, extents, buf, pbl, op_flags);
req.send();
}
-void AioImageRequest::aio_read(ImageCtx *ictx, AioCompletion *c, uint64_t off,
- size_t len, char *buf, bufferlist *pbl,
- int op_flags) {
+template <typename I>
+void AioImageRequest<I>::aio_read(I *ictx, AioCompletion *c,
+ uint64_t off, size_t len, char *buf,
+ bufferlist *pbl, int op_flags) {
AioImageRead req(*ictx, c, off, len, buf, pbl, op_flags);
req.send();
}
-void AioImageRequest::aio_write(ImageCtx *ictx, AioCompletion *c, uint64_t off,
- size_t len, const char *buf, int op_flags) {
+template <typename I>
+void AioImageRequest<I>::aio_write(I *ictx, AioCompletion *c,
+ uint64_t off, size_t len, const char *buf,
+ int op_flags) {
AioImageWrite req(*ictx, c, off, len, buf, op_flags);
req.send();
}
-void AioImageRequest::aio_discard(ImageCtx *ictx, AioCompletion *c,
- uint64_t off, uint64_t len) {
+template <typename I>
+void AioImageRequest<I>::aio_discard(I *ictx, AioCompletion *c,
+ uint64_t off, uint64_t len) {
AioImageDiscard req(*ictx, c, off, len);
req.send();
}
-void AioImageRequest::aio_flush(ImageCtx *ictx, AioCompletion *c) {
+template <typename I>
+void AioImageRequest<I>::aio_flush(I *ictx, AioCompletion *c) {
AioImageFlush req(*ictx, c);
req.send();
}
-void AioImageRequest::send() {
+template <typename I>
+void AioImageRequest<I>::send() {
assert(m_image_ctx.owner_lock.is_locked());
CephContext *cct = m_image_ctx.cct;
send_request();
}
-void AioImageRequest::fail(int r) {
+template <typename I>
+void AioImageRequest<I>::fail(int r) {
m_aio_comp->get();
m_aio_comp->fail(m_image_ctx.cct, r);
}
}
} // namespace librbd
+
+template class librbd::AioImageRequest<librbd::ImageCtx>;
class AioObjectRequest;
class ImageCtx;
+template <typename ImageCtxT = ImageCtx>
class AioImageRequest {
public:
typedef std::vector<std::pair<uint64_t,uint64_t> > Extents;
virtual ~AioImageRequest() {}
- static void aio_read(ImageCtx *ictx, AioCompletion *c,
+ static void aio_read(ImageCtxT *ictx, AioCompletion *c,
const std::vector<std::pair<uint64_t,uint64_t> > &extents,
char *buf, bufferlist *pbl, int op_flags);
- static void aio_read(ImageCtx *ictx, AioCompletion *c, uint64_t off,
+ static void aio_read(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
size_t len, char *buf, bufferlist *pbl, int op_flags);
- static void aio_write(ImageCtx *ictx, AioCompletion *c, uint64_t off,
+ static void aio_write(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
size_t len, const char *buf, int op_flags);
- static void aio_discard(ImageCtx *ictx, AioCompletion *c, uint64_t off,
+ static void aio_discard(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
uint64_t len);
- static void aio_flush(ImageCtx *ictx, AioCompletion *c);
+ static void aio_flush(ImageCtxT *ictx, AioCompletion *c);
virtual bool is_write_op() const {
return false;
protected:
typedef std::list<AioObjectRequest *> AioObjectRequests;
- ImageCtx &m_image_ctx;
+ ImageCtxT &m_image_ctx;
AioCompletion *m_aio_comp;
- AioImageRequest(ImageCtx &image_ctx, AioCompletion *aio_comp)
+ AioImageRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp)
: m_image_ctx(image_ctx), m_aio_comp(aio_comp) {}
virtual void send_request() = 0;
virtual const char *get_request_type() const = 0;
};
-class AioImageRead : public AioImageRequest {
+class AioImageRead : public AioImageRequest<> {
public:
AioImageRead(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off,
size_t len, char *buf, bufferlist *pbl, int op_flags)
int m_op_flags;
};
-class AbstractAioImageWrite : public AioImageRequest {
+class AbstractAioImageWrite : public AioImageRequest<> {
public:
virtual bool is_write_op() const {
return true;
virtual void update_stats(size_t length);
};
-class AioImageFlush : public AioImageRequest {
+class AioImageFlush : public AioImageRequest<> {
public:
AioImageFlush(ImageCtx &image_ctx, AioCompletion *aio_comp)
: AioImageRequest(image_ctx, aio_comp) {
} // namespace librbd
+extern template class librbd::AioImageRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_AIO_IMAGE_REQUEST_H
AioImageRequestWQ::AioImageRequestWQ(ImageCtx *image_ctx, const string &name,
time_t ti, ThreadPool *tp)
- : ThreadPool::PointerWQ<AioImageRequest>(name, ti, 0, tp),
+ : ThreadPool::PointerWQ<AioImageRequest<> >(name, ti, 0, tp),
m_image_ctx(*image_ctx),
m_lock(util::unique_lock_name("AioImageRequestWQ::m_lock", this)),
m_write_blockers(0), m_in_progress_writes(0), m_queued_writes(0),
if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty()) {
queue(new AioImageRead(m_image_ctx, c, off, len, buf, pbl, op_flags));
} else {
- AioImageRequest::aio_read(&m_image_ctx, c, off, len, buf, pbl, op_flags);
+ AioImageRequest<>::aio_read(&m_image_ctx, c, off, len, buf, pbl, op_flags);
finish_in_flight_op();
}
}
writes_blocked()) {
queue(new AioImageWrite(m_image_ctx, c, off, len, buf, op_flags));
} else {
- AioImageRequest::aio_write(&m_image_ctx, c, off, len, buf, op_flags);
+ AioImageRequest<>::aio_write(&m_image_ctx, c, off, len, buf, op_flags);
finish_in_flight_op();
}
}
writes_blocked()) {
queue(new AioImageDiscard(m_image_ctx, c, off, len));
} else {
- AioImageRequest::aio_discard(&m_image_ctx, c, off, len);
+ AioImageRequest<>::aio_discard(&m_image_ctx, c, off, len);
finish_in_flight_op();
}
}
writes_blocked() || !writes_empty()) {
queue(new AioImageFlush(m_image_ctx, c));
} else {
- AioImageRequest::aio_flush(&m_image_ctx, c);
+ AioImageRequest<>::aio_flush(&m_image_ctx, c);
finish_in_flight_op();
}
}
}
void *AioImageRequestWQ::_void_dequeue() {
- AioImageRequest *peek_item = front();
+ AioImageRequest<> *peek_item = front();
if (peek_item == NULL || m_refresh_in_progress) {
return NULL;
}
m_in_progress_writes.inc();
}
- AioImageRequest *item = reinterpret_cast<AioImageRequest *>(
- ThreadPool::PointerWQ<AioImageRequest>::_void_dequeue());
+ AioImageRequest<> *item = reinterpret_cast<AioImageRequest<> *>(
+ ThreadPool::PointerWQ<AioImageRequest<> >::_void_dequeue());
assert(peek_item == item);
if (m_image_ctx.state->is_refresh_required()) {
return item;
}
-void AioImageRequestWQ::process(AioImageRequest *req) {
+void AioImageRequestWQ::process(AioImageRequest<> *req) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << __func__ << ": ictx=" << &m_image_ctx << ", "
<< "req=" << req << dendl;
return (!m_image_ctx.exclusive_lock->is_lock_owner());
}
-void AioImageRequestWQ::queue(AioImageRequest *req) {
+void AioImageRequestWQ::queue(AioImageRequest<> *req) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << __func__ << ": ictx=" << &m_image_ctx << ", "
<< "req=" << req << dendl;
m_queued_writes.inc();
}
- ThreadPool::PointerWQ<AioImageRequest>::queue(req);
+ ThreadPool::PointerWQ<AioImageRequest<> >::queue(req);
if (write_op && is_lock_required()) {
m_image_ctx.exclusive_lock->request_lock(nullptr);
}
}
-void AioImageRequestWQ::handle_refreshed(int r, AioImageRequest *req) {
+void AioImageRequestWQ::handle_refreshed(int r, AioImageRequest<> *req) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 15) << "resuming IO after image refresh: r=" << r << ", "
<< "req=" << req << dendl;
namespace librbd {
class AioCompletion;
-class AioImageRequest;
+template <typename> class AioImageRequest;
class ImageCtx;
-class AioImageRequestWQ : protected ThreadPool::PointerWQ<AioImageRequest> {
+class AioImageRequestWQ : protected ThreadPool::PointerWQ<AioImageRequest<ImageCtx> > {
public:
AioImageRequestWQ(ImageCtx *image_ctx, const string &name, time_t ti,
ThreadPool *tp);
bufferlist *pbl, int op_flags, bool native_async=true);
void aio_write(AioCompletion *c, uint64_t off, uint64_t len, const char *buf,
int op_flags, bool native_async=true);
- void aio_discard(AioCompletion *c, uint64_t off, uint64_t len, bool native_async=true);
+ void aio_discard(AioCompletion *c, uint64_t off, uint64_t len,
+ bool native_async=true);
void aio_flush(AioCompletion *c, bool native_async=true);
- using ThreadPool::PointerWQ<AioImageRequest>::drain;
- using ThreadPool::PointerWQ<AioImageRequest>::empty;
+ using typename ThreadPool::PointerWQ<AioImageRequest<ImageCtx> >::drain;
+ using typename ThreadPool::PointerWQ<AioImageRequest<ImageCtx> >::empty;
inline bool writes_empty() const {
RWLock::RLocker locker(m_lock);
protected:
virtual void *_void_dequeue();
- virtual void process(AioImageRequest *req);
+ virtual void process(AioImageRequest<ImageCtx> *req);
private:
typedef std::list<Context *> Contexts;
struct C_RefreshFinish : public Context {
AioImageRequestWQ *aio_work_queue;
- AioImageRequest *aio_image_request;
+ AioImageRequest<ImageCtx> *aio_image_request;
C_RefreshFinish(AioImageRequestWQ *aio_work_queue,
- AioImageRequest *aio_image_request)
+ AioImageRequest<ImageCtx> *aio_image_request)
: aio_work_queue(aio_work_queue), aio_image_request(aio_image_request) {
}
virtual void finish(int r) override {
bool is_journal_required() const;
bool is_lock_required() const;
- void queue(AioImageRequest *req);
+ void queue(AioImageRequest<ImageCtx> *req);
- void handle_refreshed(int r, AioImageRequest *req);
+ void handle_refreshed(int r, AioImageRequest<ImageCtx> *req);
void handle_blocked_writes(int r);
};
<< " extents " << parent_extents
<< dendl;
RWLock::RLocker owner_locker(m_ictx->parent->owner_lock);
- AioImageRequest::aio_read(m_ictx->parent, m_parent_completion,
- parent_extents, NULL, &m_read_data, 0);
+ AioImageRequest<>::aio_read(m_ictx->parent, m_parent_completion,
+ parent_extents, NULL, &m_read_data, 0);
}
/** write **/
<< ", extents " << m_image_extents
<< dendl;
RWLock::RLocker owner_locker(m_ictx->parent->owner_lock);
- AioImageRequest::aio_read(m_ictx->parent, comp, m_image_extents, NULL,
- &m_copyup_data, 0);
+ AioImageRequest<>::aio_read(m_ictx->parent, comp, m_image_extents, NULL,
+ &m_copyup_data, 0);
}
void CopyupRequest::complete(int r)
bufferlist *bl = new bufferlist();
Context *ctx = new C_CopyRead(&throttle, dest, offset, bl);
AioCompletion *comp = AioCompletion::create(ctx);
- AioImageRequest::aio_read(src, comp, offset, len, NULL, bl,
- fadvise_flags);
+ AioImageRequest<>::aio_read(src, comp, offset, len, NULL, bl,
+ fadvise_flags);
prog_ctx.update_progress(offset, src_size);
}
C_SaferCond ctx;
AioCompletion *c = AioCompletion::create(&ctx);
- AioImageRequest::aio_read(ictx, c, off, read_len, NULL, &bl, 0);
+ AioImageRequest<>::aio_read(ictx, c, off, read_len, NULL, &bl, 0);
int ret = ctx.wait();
if (ret < 0) {
ldout(cct, 20) << this << " " << __func__ << ": AIO discard event" << dendl;
AioCompletion *aio_comp = create_aio_completion(on_safe);
- AioImageRequest::aio_discard(&m_image_ctx, aio_comp, event.offset,
- event.length);
+ AioImageRequest<I>::aio_discard(&m_image_ctx, aio_comp, event.offset,
+ event.length);
}
template <typename I>
bufferlist data = event.data;
AioCompletion *aio_comp = create_aio_completion(on_safe);
- AioImageRequest::aio_write(&m_image_ctx, aio_comp, event.offset, event.length,
- data.c_str(), 0);
+ AioImageRequest<I>::aio_write(&m_image_ctx, aio_comp, event.offset,
+ event.length, data.c_str(), 0);
}
template <typename I>
ldout(cct, 20) << this << " " << __func__ << ": AIO flush event" << dendl;
AioCompletion *aio_comp = create_aio_completion(on_safe);
- AioImageRequest::aio_flush(&m_image_ctx, aio_comp);
+ AioImageRequest<I>::aio_flush(&m_image_ctx, aio_comp);
}
template <typename I>