summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Dillaman <dillaman@redhat.com>2015-08-11 15:26:33 +0200
committerJason Dillaman <dillaman@redhat.com>2015-08-11 15:26:33 +0200
commit6ec431bac1cf9446f3af90209d193dfcf003f2c5 (patch)
tree5f10808cb7b2f6a367411d4f79a3535d51a9f068
parentMerge pull request #5492 from ceph/wip-vxattr-setall (diff)
downloadceph-6ec431bac1cf9446f3af90209d193dfcf003f2c5.tar.xz
ceph-6ec431bac1cf9446f3af90209d193dfcf003f2c5.zip
librbd: prevent race condition between resize requests
It was possible that the same resize request could be sent twice if a completed resize op started a newly created resize op while it was also being concurrently started by another thread. Fixes: #12664 Backport: hammer Signed-off-by: Jason Dillaman <dillaman@redhat.com>
-rw-r--r--src/librbd/AsyncResizeRequest.cc25
1 files changed, 12 insertions, 13 deletions
diff --git a/src/librbd/AsyncResizeRequest.cc b/src/librbd/AsyncResizeRequest.cc
index bbd697f7cff..732e3f734f2 100644
--- a/src/librbd/AsyncResizeRequest.cc
+++ b/src/librbd/AsyncResizeRequest.cc
@@ -24,21 +24,15 @@ AsyncResizeRequest::AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish,
m_prog_ctx(prog_ctx), 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);
- m_original_size = m_image_ctx.size;
- compute_parent_overlap();
}
AsyncResizeRequest::~AsyncResizeRequest() {
AsyncResizeRequest *next_req = NULL;
{
- RWLock::WLocker l(m_image_ctx.snap_lock);
+ RWLock::WLocker snap_locker(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();
- next_req->m_original_size = m_image_ctx.size;
- next_req->compute_parent_overlap();
}
}
@@ -123,14 +117,19 @@ bool AsyncResizeRequest::should_complete(int r) {
void AsyncResizeRequest::send() {
assert(m_image_ctx.owner_lock.is_locked());
- {
- 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;
+ {
+ RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+ if (!m_xlist_item.is_on_list()) {
+ m_image_ctx.async_resize_reqs.push_back(&m_xlist_item);
+ if (m_image_ctx.async_resize_reqs.front() != this) {
+ return;
+ }
}
+
+ assert(m_image_ctx.async_resize_reqs.front() == this);
+ m_original_size = m_image_ctx.size;
+ compute_parent_overlap();
}
CephContext *cct = m_image_ctx.cct;