]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Add retry_raced_bucket_write
authorAdam C. Emerson <aemerson@redhat.com>
Fri, 17 Nov 2017 20:51:42 +0000 (15:51 -0500)
committerMatt Benjamin <mbenjamin@redhat.com>
Wed, 3 Jan 2018 20:28:22 +0000 (15:28 -0500)
If the OSD informs us that our bucket info is out of date when we need
to write, we should have a way to update it.

This template function allows us to wrap relevant sections of code so
they'll be retried against new bucket info on -ECANCELED.

Fixes: http://tracker.ceph.com/issues/22517
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
(cherry picked from commit 1a3fcc70c0747791aa423cd0aa7d2596eaf3d73c)

src/rgw/rgw_op.cc
src/rgw/rgw_op.h

index 0f5c74ce2222aa0db3690da8161eae5155972eb6..f48544ae7be6b81eaef598cebd2229ec559abf7e 100644 (file)
@@ -457,6 +457,37 @@ static void rgw_bucket_object_pre_exec(struct req_state *s)
   dump_bucket_from_state(s);
 }
 
+// So! Now and then when we try to update bucket information, the
+// bucket has changed during the course of the operation. (Or we have
+// a cache consistency problem that Watch/Notify isn't ruling out
+// completely.)
+//
+// When this happens, we need to update the bucket info and try
+// again. We have, however, to try the right *part* again.  We can't
+// simply re-send, since that will obliterate the previous update.
+//
+// Thus, callers of this function should include everything that
+// merges information to be changed into the bucket information as
+// well as the call to set it.
+//
+// The called function must return an integer, negative on error. In
+// general, they should just return op_ret.
+namespace {
+template<typename F>
+int retry_raced_bucket_write(RGWRados* g, req_state* s, const F& f) {
+  auto r = f();
+  for (auto i = 0u; i < 15u && r == -ECANCELED; ++i) {
+    r = g->try_refresh_bucket_info(s->bucket_info, nullptr,
+                                  &s->bucket_attrs);
+    if (r >= 0) {
+      r = f();
+    }
+  }
+  return r;
+}
+}
+
+
 int RGWGetObj::verify_permission()
 {
   obj = rgw_obj(s->bucket, s->object.name);
index ee01f32e79299a4437bf7326c5a33b89f81fca4f..e4468d22a8af3e0aa8db3941003d787cf236de0e 100644 (file)
@@ -59,6 +59,7 @@ protected:
   int do_aws4_auth_completion();
 
   virtual int init_quota();
+
 public:
 RGWOp() : s(nullptr), dialect_handler(nullptr), store(nullptr),
     cors_exist(false), op_ret(0) {}