From: Mykola Golub Date: Wed, 16 Nov 2016 10:01:00 +0000 (+0200) Subject: librbd: request exclusive lock if current owner cannot execute op X-Git-Tag: v0.94.10~61^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=d89b1f848b8c942d150076cef99491e4c5031bda;p=ceph.git librbd: request exclusive lock if current owner cannot execute op This is a direct commit to hammer due to librbd code has evolved significantly in the master. Fixes: http://tracker.ceph.com/issues/17068 Signed-off-by: Mykola Golub --- diff --git a/src/librbd/AioCompletion.cc b/src/librbd/AioCompletion.cc index efbc84945ffbf..cdd2f2fa9367a 100644 --- a/src/librbd/AioCompletion.cc +++ b/src/librbd/AioCompletion.cc @@ -79,6 +79,8 @@ namespace librbd { ictx->perfcounter->tinc(l_librbd_aio_discard_latency, elapsed); break; case AIO_TYPE_FLUSH: ictx->perfcounter->tinc(l_librbd_aio_flush_latency, elapsed); break; + case AIO_TYPE_NONE: + break; default: lderr(cct) << "completed invalid aio_type: " << aio_type << dendl; break; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index f4b110eea8ce0..c38d6ae848e26 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -87,6 +87,23 @@ int prepare_image_update(ImageCtx *ictx) { return r; } +void acquire_lock(ImageCtx *ictx) { + assert(ictx->owner_lock.is_locked()); + AioCompletion *comp = aio_create_completion(); + comp->add_request(); + comp->finish_adding_requests(ictx->cct); + + ictx->image_watcher->request_lock( + boost::bind(&AioCompletion::complete_request, _1, ictx->cct, 0), + comp); + + ictx->owner_lock.put_read(); + int r = comp->wait_for_complete(); + assert(r == 0); + comp->release(); + ictx->owner_lock.get_read(); +} + int invoke_async_request(ImageCtx *ictx, const std::string& request_type, bool permit_snapshot, const boost::function& local_request, @@ -104,15 +121,25 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, } } + bool request_lock = false; while (ictx->image_watcher->is_lock_supported()) { + if (request_lock) { + acquire_lock(ictx); + } r = prepare_image_update(ictx); if (r < 0) { return -EROFS; } else if (ictx->image_watcher->is_lock_owner()) { break; + } else if (request_lock) { + return -EOPNOTSUPP; } r = remote_request(); + if (r == -EOPNOTSUPP) { + request_lock = true; + continue; + } if (r != -ETIMEDOUT && r != -ERESTART) { return r; }