From: Matt Benjamin Date: Tue, 3 Oct 2017 21:48:29 +0000 (-0400) Subject: rgw: release cls lock if taken in RGWCompleteMultipart X-Git-Tag: v10.2.11~143^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=270498d63c287ffebbbf65ceb32cafc547be2fb3;p=ceph.git rgw: release cls lock if taken in RGWCompleteMultipart Follows Casey's proposal to conditionally release the lock in ::complete(), in order to avoid duplicated code in various early return cases. Fixes: http://tracker.ceph.com/issues/21596 Signed-off-by: Matt Benjamin (cherry picked from commit 704f793f08a02760d23eb5778b738bb07be0e7cf) --- diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 0f5c74ce2222a..eccfeaf6f3f69 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -4238,9 +4238,7 @@ void RGWCompleteMultipart::execute() /*take a cls lock on meta_obj to prevent racing completions (or retries) from deleting the parts*/ - librados::IoCtx ioctx; - - op_ret = store->get_obj_ioctx(meta_obj, &ioctx); + op_ret = store->get_obj_ioctx(meta_obj, &serializer.ioctx); if (op_ret < 0) { ldout(s->cct, 0) << "ERROR: failed to open extra_dat_ctx, obj=" << raw_oid @@ -4248,16 +4246,11 @@ void RGWCompleteMultipart::execute() return; } - librados::ObjectWriteOperation op; - rados::cls::lock::Lock l("RGWCompleteMultipart"); - int max_lock_secs_mp = s->cct->_conf->rgw_mp_lock_max_time; - utime_t time(max_lock_secs_mp, 0); - - op.assert_exists(); - l.set_duration(time); - l.lock_exclusive(&op); + int max_lock_secs_mp = + s->cct->_conf->rgw_mp_lock_max_time; + utime_t dur(max_lock_secs_mp, 0); - op_ret = ioctx.operate(raw_oid, &op); + op_ret = serializer.try_lock(raw_oid, dur); if (op_ret < 0) { dout(0) << "RGWCompleteMultipart::execute() failed to acquire lock " << dendl; @@ -4378,13 +4371,41 @@ void RGWCompleteMultipart::execute() // remove the upload obj int r = store->delete_obj(*static_cast(s->obj_ctx), s->bucket_info, meta_obj, 0); - if (r < 0) { - ldout(store->ctx(), 0) << "WARNING: failed to remove object " << meta_obj << dendl; - r = l.unlock(&ioctx, meta_oid); + if (r >= 0) { + /* serializer's exclusive lock is released */ + serializer.clear_locked(); + } else { + ldout(store->ctx(), 0) << "WARNING: failed to remove object " + << meta_obj << dendl; + } +} + +int RGWCompleteMultipart::MPSerializer::try_lock( + const std::string& _oid, + utime_t dur) +{ + oid = _oid; + op.assert_exists(); + lock.set_duration(dur); + lock.lock_exclusive(&op); + int ret = ioctx.operate(oid, &op); + if (! ret) { + locked = true; + } + return ret; +} + +void RGWCompleteMultipart::complete() +{ + /* release exclusive lock iff not already */ + if (unlikely(serializer.locked)) { + int r = serializer.unlock(); if (r < 0) { - ldout(store->ctx(), 0) << "WARNING: failed to unlock " << meta_oid << dendl; + ldout(store->ctx(), 0) << "WARNING: failed to unlock " + << serializer.oid << dendl; } } + send_response(); } int RGWAbortMultipart::verify_permission() diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index ee01f32e79299..ae1bbc09830c2 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -34,6 +34,8 @@ #include "rgw_acl.h" #include "rgw_cors.h" #include "rgw_quota.h" +#include "cls/lock/cls_lock_client.h" +#include "cls/rgw/cls_rgw_client.h" #include "include/assert.h" @@ -1149,6 +1151,27 @@ protected: char *data; int len; + struct MPSerializer { + librados::IoCtx ioctx; + rados::cls::lock::Lock lock; + librados::ObjectWriteOperation op; + std::string oid; + bool locked; + + MPSerializer() : lock("RGWCompleteMultipart"), locked(false) + {} + + int try_lock(const std::string& oid, utime_t dur); + + int unlock() { + return lock.unlock(&ioctx, oid); + } + + void clear_locked() { + locked = false; + } + } serializer; + public: RGWCompleteMultipart() { data = NULL; @@ -1161,6 +1184,7 @@ public: int verify_permission(); void pre_exec(); void execute(); + void complete(); virtual int get_params() = 0; virtual void send_response() = 0;