namespace librbd
{
-bool AsyncResizeRequest::should_complete(int r)
+AsyncResizeRequest::AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish,
+ uint64_t original_size,
+ uint64_t new_size,
+ ProgressContext &prog_ctx)
+ : AsyncRequest(image_ctx, on_finish),
+ m_original_size(original_size), m_new_size(new_size),
+ m_prog_ctx(prog_ctx), m_original_parent_overlap(0),
+ m_new_parent_overlap(0), m_xlist_item(this)
{
+ RWLock::WLocker l(m_image_ctx.snap_lock);
+ m_image_ctx.async_resize_reqs.push_back(&m_xlist_item);
+}
+
+AsyncResizeRequest::~AsyncResizeRequest() {
+ AsyncResizeRequest *next_req = NULL;
+ {
+ RWLock::WLocker l(m_image_ctx.snap_lock);
+ assert(m_xlist_item.remove_myself());
+ if (!m_image_ctx.async_resize_reqs.empty()) {
+ next_req = m_image_ctx.async_resize_reqs.front();
+ }
+ }
+
+ if (next_req != NULL) {
+ next_req->send();
+ }
+}
+
+bool AsyncResizeRequest::should_complete(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl;
}
void AsyncResizeRequest::send() {
+ {
+ RWLock::RLocker l(m_image_ctx.snap_lock);
+ assert(!m_image_ctx.async_resize_reqs.empty());
+
+ // only allow a single concurrent resize request
+ if (m_image_ctx.async_resize_reqs.front() != this) {
+ return;
+ }
+ }
+
CephContext *cct = m_image_ctx.cct;
- if (m_original_size == m_new_size) {
+ if (is_canceled()) {
+ complete(-ERESTART);
+ } else if (m_original_size == m_new_size) {
ldout(cct, 2) << this << " no change in size (" << m_original_size
<< " -> " << m_new_size << ")" << dendl;
m_state = STATE_FINISHED;
#define CEPH_LIBRBD_ASYNC_RESIZE_REQUEST_H
#include "librbd/AsyncRequest.h"
+#include "include/xlist.h"
namespace librbd
{
public:
AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish,
uint64_t original_size, uint64_t new_size,
- ProgressContext &prog_ctx)
- : AsyncRequest(image_ctx, on_finish),
- m_original_size(original_size), m_new_size(new_size),
- m_prog_ctx(prog_ctx), m_original_parent_overlap(0),
- m_new_parent_overlap(0)
- {
- }
+ ProgressContext &prog_ctx);
+ virtual ~AsyncResizeRequest();
virtual void send();
-protected:
+private:
/**
* Resize goes through the following state machine to resize the image
* and update the object map:
uint64_t m_original_parent_overlap;
uint64_t m_new_parent_overlap;
+ xlist<AsyncResizeRequest *>::item m_xlist_item;
+
virtual bool should_complete(int r);
void send_flush();
class AsyncOperation;
class AsyncRequest;
+ class AsyncResizeRequest;
class CopyupRequest;
class ImageWatcher;
RWLock parent_lock; // protects parent_md and parent
Mutex refresh_lock; // protects refresh_seq and last_refresh
RWLock object_map_lock; // protects object map updates and object_map itself
- Mutex async_ops_lock; // protects async_ops
+ Mutex async_ops_lock; // protects async_ops and async_requests
Mutex copyup_list_lock; // protects copyup_waiting_list
unsigned extra_read_flags;
atomic_t async_request_seq;
+ xlist<AsyncResizeRequest*> async_resize_reqs;
+
/**
* Either image_name or image_id must be set.
* If id is not known, pass the empty std::string,