]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: handle racing object puts when object doesn't exist
authorYehuda Sadeh <yehuda@inktank.com>
Thu, 16 Jan 2014 19:45:27 +0000 (11:45 -0800)
committerYehuda Sadeh <yehuda@inktank.com>
Tue, 28 Jan 2014 20:24:32 +0000 (12:24 -0800)
If the object didn't exist before and now we have multiple puts coming
in concurrently, we need to make sure that we behave correctly. Only one
needs to win, the other one can fail silently. We do that by setting
exclusive flag on the object creation and handling the error correctly.
Note that we still want to return -EEXIST in some cases (when the
exclusive flag is passed to put_obj_meta(), e.g., on bucket creation).

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
(cherry picked from commit 86c15480fc3e33b9a3b84d0af68d8398fc732bae)

src/rgw/rgw_rados.cc

index 7127e0d2335ee8fa2bf59825094d59caf0857987..098325b36db4775ec4c103f06eb9d801e086e957 100644 (file)
@@ -2322,7 +2322,9 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
     return r;
 
   r = io_ctx.operate(oid, &op);
-  if (r < 0)
+  if (r < 0) /* we can expect to get -ECANCELED if object was replaced under,
+                or -ENOENT if was removed, or -EEXIST if it did not exist
+                before and now it does */
     goto done_cancel;
 
   if (objv_tracker) {
@@ -2353,11 +2355,17 @@ done_cancel:
   if (ret < 0) {
     ldout(cct, 0) << "ERROR: complete_update_index_cancel() returned ret=" << ret << dendl;
   }
-  /* we lost in a race, object was already overwritten, we
+  /* we lost in a race. There are a few options:
+   * - existing object was rewritten (ECANCELED)
+   * - non existing object was created (EEXIST)
+   * - object was removed (ENOENT)
    * should treat it as a success
    */
-  if (r == -ECANCELED || r == -ENOENT)
+  if ((r == -ECANCELED || r == -ENOENT) ||
+      (!(flags & PUT_OBJ_EXCL) && r == -EEXIST)) {
     r = 0;
+  }
+
   return r;
 }
 
@@ -3443,8 +3451,12 @@ int RGWRados::prepare_atomic_for_write_impl(RGWRadosCtx *rctx, rgw_obj& obj,
   }
 
   if (reset_obj) {
-    op.create(false);
-    op.remove();
+    if (state->exists) {
+      op.create(false);
+      op.remove();
+    } else {
+      op.create(true);
+    }
   }
 
   if (ptag) {