]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw : fix race in RGWCompleteMultipart 16732/head
authorAbhishek Varshney <abhishek.varshney@flipkart.com>
Tue, 1 Aug 2017 14:46:52 +0000 (14:46 +0000)
committerAbhishek Varshney <abhishek.varshney@flipkart.com>
Wed, 2 Aug 2017 18:20:49 +0000 (18:20 +0000)
Fixes : http://tracker.ceph.com/issues/20861

Signed-off-by: Abhishek Varshney <abhishek.varshney@flipkart.com>
src/common/options.cc
src/rgw/rgw_op.cc
src/rgw/rgw_rados.h

index 4d6bbd1c17f54b97cb6d465e2fd9c7744229896a..85b5a099e300c9a342bb6b81995f4cf1ed209fd1 100644 (file)
@@ -3977,6 +3977,10 @@ std::vector<Option> get_rgw_options() {
     .set_default(-1)
     .set_description(""),
 
+    Option("rgw_mp_lock_max_time", Option::TYPE_INT, Option::LEVEL_ADVANCED)
+    .set_default(600)
+    .set_description(""),
+
     Option("rgw_script_uri", Option::TYPE_STR, Option::LEVEL_ADVANCED)
     .set_default("")
     .set_description(""),
index 72a4ec86fe28cdb889e6f6409486a4e8cddc3e45..01f89176ba25903843822ac7d2639dfb68b04696 100644 (file)
@@ -5276,6 +5276,33 @@ void RGWCompleteMultipart::execute()
   meta_obj.set_in_extra_data(true);
   meta_obj.index_hash_source = s->object.name;
 
+  /*take a cls lock on meta_obj to prevent racing completions (or retries)
+    from deleting the parts*/
+  rgw_pool meta_pool;
+  rgw_raw_obj raw_obj;
+  librados::ObjectWriteOperation op;
+  librados::IoCtx ioctx;
+  rados::cls::lock::Lock l("RGWCompleteMultipart");
+  int max_lock_secs_mp = s->cct->_conf->get_val<int64_t>("rgw_mp_lock_max_time");
+
+  op.assert_exists();
+  store->obj_to_raw((s->bucket_info).placement_rule, meta_obj, &raw_obj);
+  store->get_obj_data_pool((s->bucket_info).placement_rule,meta_obj,&meta_pool);
+  store->open_pool_ctx(meta_pool, ioctx);
+
+  const string raw_meta_oid = raw_obj.oid;
+  utime_t time(max_lock_secs_mp, 0);
+  l.set_duration(time);
+  l.lock_exclusive(&op);
+  op_ret = ioctx.operate(raw_meta_oid, &op);
+
+  if (op_ret < 0) {
+    dout(0) << "RGWCompleteMultipart::execute() failed to acquire lock " << dendl;
+    op_ret = -ERR_INTERNAL_ERROR;
+    s->err.message = "This multipart completion is already in progress";
+    return;
+  }
+
   op_ret = get_obj_attrs(store, s, meta_obj, attrs);
 
   if (op_ret < 0) {
@@ -5426,6 +5453,10 @@ void RGWCompleteMultipart::execute()
                            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, raw_meta_oid);
+    if (r < 0) {
+      ldout(store->ctx(), 0) << "WARNING: failed to unlock " << raw_meta_oid << dendl;
+    }
   }
 }
 
index 15a3d247dad1287ecf58bd5e76fa15367fd3b7e2..a356a456b4d137de4fa18ae4ff7e7cd4465356b6 100644 (file)
@@ -2213,6 +2213,7 @@ class RGWRados
   friend class RGWReshard;
   friend class RGWBucketReshard;
   friend class BucketIndexLockGuard;
+  friend class RGWCompleteMultipart;
 
   /** Open the pool used as root for this gateway */
   int open_root_pool_ctx();