diff options
author | Yehuda Sadeh <yehuda@hq.newdream.net> | 2011-08-19 12:27:43 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@hq.newdream.net> | 2011-08-19 12:27:43 -0700 |
commit | 32db9dc5bff7405620953d42fcfef7007f7999dc (patch) | |
tree | e1ef02aeb018e3cafcd2dbef744c3b5306c695b3 /src/rgw | |
parent | e759021b9bee8f662dc6ab49dcac39df4d9e4604 (diff) | |
download | ceph-32db9dc5bff7405620953d42fcfef7007f7999dc.tar.gz |
rgw: some more race fixes
Diffstat (limited to 'src/rgw')
-rw-r--r-- | src/rgw/rgw_rados.cc | 42 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 15 |
2 files changed, 55 insertions, 2 deletions
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index f86322db69d..3945dc4c4f5 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -678,6 +678,7 @@ int RGWRados::bucket_suspended(std::string& bucket, bool *suspended) *suspended = (auid == RGW_SUSPENDED_USER_AUID); return 0; } + /** * Delete an object. * id: unused @@ -685,7 +686,7 @@ int RGWRados::bucket_suspended(std::string& bucket, bool *suspended) * obj: name of the object to delete * Returns: 0 on success, -ERR# otherwise. */ -int RGWRados::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync) +int RGWRados::delete_obj_impl(void *ctx, std::string& id, rgw_obj& obj, bool sync) { std::string& bucket = obj.bucket; std::string& oid = obj.object; @@ -712,12 +713,24 @@ int RGWRados::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync) r = io_ctx.aio_operate(obj.object, completion, &op); completion->release(); } + + atomic_write_finish(state, r); + if (r < 0) return r; return 0; } +int RGWRados::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync) +{ + int r; + do { + r = delete_obj_impl(ctx, id, obj, sync); + } while (r == -ECANCELED); + return r; +} + int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, librados::IoCtx& io_ctx, string& actual_obj, RGWObjState **state) { RGWObjState *s = rctx->get_state(obj); @@ -847,6 +860,7 @@ int RGWRados::prepare_atomic_for_write_impl(RGWRadosCtx *rctx, rgw_obj& obj, lib if (state->obj_tag.length() == 0 || state->shadow_obj.size() == 0) { RGW_LOG(0) << "can't clone object " << obj << " to shadow object, tag/shadow_obj haven't been set" << dendl; + // FIXME: need to test object does not exist } else { RGW_LOG(0) << "cloning object " << obj << " to name=" << state->shadow_obj << dendl; rgw_obj dest_obj(obj.bucket, state->shadow_obj); @@ -874,6 +888,10 @@ int RGWRados::prepare_atomic_for_write_impl(RGWRadosCtx *rctx, rgw_obj& obj, lib RGW_LOG(0) << "ERROR: failed to clone object r=" << r << dendl; return r; } + + /* first verify that the object wasn't replaced under */ + op.cmpxattr(RGW_ATTR_ID_TAG, LIBRADOS_CMPXATTR_OP_EQ, state->obj_tag); + // FIXME: need to add FAIL_NOTEXIST_OK for racing deletion } string tag; @@ -881,6 +899,7 @@ int RGWRados::prepare_atomic_for_write_impl(RGWRadosCtx *rctx, rgw_obj& obj, lib bufferlist bl; bl.append(tag); + op.setxattr(RGW_ATTR_ID_TAG, bl); string shadow = obj.object; @@ -1109,7 +1128,7 @@ done_err: return r; } -int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj, +int RGWRados::clone_objs_impl(void *ctx, rgw_obj& dst_obj, vector<RGWCloneRangeInfo>& ranges, map<string, bufferlist> attrs, string& category, @@ -1180,9 +1199,28 @@ int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj, bufferlist outbl; int ret = io_ctx.operate(dst_oid, &op); + + atomic_write_finish(state, ret); + return ret; } +int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj, + vector<RGWCloneRangeInfo>& ranges, + map<string, bufferlist> attrs, + string& category, + time_t *pmtime, + bool truncate_dest, + pair<string, bufferlist> *xattr_cond) +{ + int r; + do { + r = clone_objs_impl(ctx, dst_obj, ranges, attrs, category, pmtime, truncate_dest, xattr_cond); + } while (r == -ECANCELED); + return r; +} + + int RGWRados::get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end) { diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 847d2d1fab6..c645354aee3 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -89,6 +89,21 @@ class RGWRados : public RGWAccess string& actual_obj, librados::ObjectWriteOperation& op, RGWObjState **pstate); int prepare_atomic_for_write(RGWRadosCtx *rctx, rgw_obj& obj, librados::IoCtx& io_ctx, string& actual_obj, librados::ObjectWriteOperation& op, RGWObjState **pstate); + + void atomic_write_finish(RGWObjState *state, int r) { + if (r == -ECANCELED) { + state->clear(); + } + } + + int clone_objs_impl(void *ctx, rgw_obj& dst_obj, + vector<RGWCloneRangeInfo>& ranges, + map<string, bufferlist> attrs, + string& category, + time_t *pmtime, + bool truncate_dest, + pair<string, bufferlist> *cmp_xattr); + int delete_obj_impl(void *ctx, std::string& id, rgw_obj& src_obj, bool sync); public: RGWRados() : watcher(NULL), watch_handle(0) {} |