From: Jason Dillaman Date: Tue, 10 Mar 2015 01:30:17 +0000 (-0400) Subject: librbd: queue multiple resize requests X-Git-Tag: v0.94~47^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9c5c665bc7b3018261574177884f913b0fda3cba;p=ceph.git librbd: queue multiple resize requests Only allow a single resize request to be executed concurrently. Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/AsyncResizeRequest.cc b/src/librbd/AsyncResizeRequest.cc index d79832939595..7459f2c3ad23 100644 --- a/src/librbd/AsyncResizeRequest.cc +++ b/src/librbd/AsyncResizeRequest.cc @@ -16,8 +16,35 @@ 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; @@ -81,8 +108,20 @@ bool AsyncResizeRequest::should_complete(int r) } 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; diff --git a/src/librbd/AsyncResizeRequest.h b/src/librbd/AsyncResizeRequest.h index a341a3ae6844..de6a49b0ee98 100644 --- a/src/librbd/AsyncResizeRequest.h +++ b/src/librbd/AsyncResizeRequest.h @@ -4,6 +4,7 @@ #define CEPH_LIBRBD_ASYNC_RESIZE_REQUEST_H #include "librbd/AsyncRequest.h" +#include "include/xlist.h" namespace librbd { @@ -16,17 +17,12 @@ class AsyncResizeRequest : public AsyncRequest 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: @@ -74,6 +70,8 @@ protected: uint64_t m_original_parent_overlap; uint64_t m_new_parent_overlap; + xlist::item m_xlist_item; + virtual bool should_complete(int r); void send_flush(); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index a35e40b54b4b..7cb6e3a00c62 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -38,6 +38,7 @@ namespace librbd { class AsyncOperation; class AsyncRequest; + class AsyncResizeRequest; class CopyupRequest; class ImageWatcher; @@ -89,7 +90,7 @@ namespace librbd { 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; @@ -127,6 +128,8 @@ namespace librbd { atomic_t async_request_seq; + xlist async_resize_reqs; + /** * Either image_name or image_id must be set. * If id is not known, pass the empty std::string,