#include "librbd/AioImageRequest.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
+#include "librbd/ImageState.h"
#include "librbd/internal.h"
#include "librbd/Utils.h"
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),
- m_in_flight_ops(0), m_shutdown(false), m_on_shutdown(nullptr) {
+ m_in_flight_ops(0), m_refresh_in_progress(false),
+ m_shutdown(false), m_on_shutdown(nullptr) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 5) << this << " " << ": ictx=" << image_ctx << dendl;
}
void *AioImageRequestWQ::_void_dequeue() {
AioImageRequest *peek_item = front();
- if (peek_item == NULL) {
+ if (peek_item == NULL || m_refresh_in_progress) {
return NULL;
}
- {
- if (peek_item->is_write_op()) {
- RWLock::RLocker locker(m_lock);
- if (m_write_blockers > 0) {
- return NULL;
- }
- m_in_progress_writes.inc();
+ if (peek_item->is_write_op()) {
+ RWLock::RLocker locker(m_lock);
+ if (m_write_blockers > 0) {
+ return NULL;
}
+ m_in_progress_writes.inc();
}
AioImageRequest *item = reinterpret_cast<AioImageRequest *>(
ThreadPool::PointerWQ<AioImageRequest>::_void_dequeue());
assert(peek_item == item);
+
+ if (m_image_ctx.state->is_refresh_required()) {
+ ldout(m_image_ctx.cct, 15) << "image refresh required: delaying IO " << item
+ << dendl;
+ m_refresh_in_progress = true;
+
+ get_pool_lock().Unlock();
+ m_image_ctx.state->refresh(new C_RefreshFinish(this, item));
+ get_pool_lock().Lock();
+ return NULL;
+ }
return item;
}
}
}
+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;
+ if (r < 0) {
+ req->fail(r);
+ } else {
+ process(req);
+ process_finish();
+
+ m_refresh_in_progress = false;
+ signal();
+ }
+}
+
void AioImageRequestWQ::handle_blocked_writes(int r) {
Contexts contexts;
{
#include "include/Context.h"
#include "include/atomic.h"
-#include "common/WorkQueue.h"
+#include "common/Cond.h"
#include "common/RWLock.h"
+#include "common/WorkQueue.h"
+#include <list>
namespace librbd {
private:
typedef std::list<Context *> Contexts;
+ struct C_RefreshFinish : public Context {
+ AioImageRequestWQ *aio_work_queue;
+ AioImageRequest *aio_image_request;
+
+ C_RefreshFinish(AioImageRequestWQ *aio_work_queue,
+ AioImageRequest *aio_image_request)
+ : aio_work_queue(aio_work_queue), aio_image_request(aio_image_request) {
+ }
+ virtual void finish(int r) override {
+ aio_work_queue->handle_refreshed(r, aio_image_request);
+ }
+ };
+
struct C_BlockedWrites : public Context {
AioImageRequestWQ *aio_work_queue;
C_BlockedWrites(AioImageRequestWQ *_aio_work_queue)
atomic_t m_queued_writes;
atomic_t m_in_flight_ops;
+ bool m_refresh_in_progress;
+
bool m_shutdown;
Context *m_on_shutdown;
bool is_lock_required() const;
void queue(AioImageRequest *req);
+ void handle_refreshed(int r, AioImageRequest *req);
void handle_blocked_writes(int r);
};