From d43b69e529328f73da6c29cd746557788a989ae0 Mon Sep 17 00:00:00 2001 From: Yang Honggang Date: Tue, 4 Oct 2016 09:18:09 +0800 Subject: [PATCH] rgw: fix versioned object IO error When accessing a copied destination object, its source object's instance ID information is needed, however it's missing now in the destination object's manifest. In order to fix this problem, we can record source object's version_id/instance into dest object's manifest(a new filed 'tail_instance' is added). When creating a new object(not copy), 'tail_instance' should be equal to its instance value. When copy/get a object, 'tail_instance' should always be used to get the right tail objects. Fixes: http://tracker.ceph.com/issues/17111 Signed-off-by: Yang Honggang --- src/rgw/rgw_dencoder.cc | 4 ++++ src/rgw/rgw_json_enc.cc | 1 + src/rgw/rgw_rados.cc | 6 +++++- src/rgw/rgw_rados.h | 22 ++++++++++++++++++++-- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/rgw/rgw_dencoder.cc b/src/rgw/rgw_dencoder.cc index 0b4fdf5944c..74563963d92 100644 --- a/src/rgw/rgw_dencoder.cc +++ b/src/rgw/rgw_dencoder.cc @@ -188,6 +188,10 @@ void RGWObjManifest::get_implicit_location(uint64_t cur_part_id, uint64_t cur_st } location->init_ns(*bucket, oid, ns); + + // Always overwrite instance with tail_instance + // to get the right shadow object location + location->set_instance(tail_instance); } diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index b519e6a1c67..20a47b6006a 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -87,6 +87,7 @@ void RGWObjManifest::dump(Formatter *f) const ::encode_json("prefix", prefix, f); ::encode_json("tail_bucket", tail_bucket, f); ::encode_json("rules", rules, f); + ::encode_json("tail_instance", tail_instance, f); } void rgw_log_entry::dump(Formatter *f) const diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 7d6dc05010e..1e67f172266 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -1948,6 +1948,9 @@ int RGWObjManifest::generator::create_begin(CephContext *cct, RGWObjManifest *_m manifest->get_implicit_location(cur_part_id, cur_stripe, 0, NULL, &cur_obj); + // Normal object which not generated through copy operation + manifest->set_tail_instance(_h.get_instance()); + manifest->update_iterators(); return 0; @@ -7018,7 +7021,8 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, RGWObjManifest manifest; RGWObjState *astate = NULL; - ret = get_obj_state(&obj_ctx, src_obj, &astate, NULL); + + ret = get_obj_state(&obj_ctx, src_obj, &astate); if (ret < 0) { return ret; } diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 850fb79e287..00da971f46a 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -254,6 +254,8 @@ protected: as object might have been copied across buckets */ map rules; + string tail_instance; /* tail object's instance */ + void convert_to_explicit(); int append_explicit(RGWObjManifest& m); void append_rules(RGWObjManifest& m, map::iterator& iter, string *override_prefix); @@ -279,6 +281,7 @@ public: prefix = rhs.prefix; tail_bucket = rhs.tail_bucket; rules = rhs.rules; + tail_instance = rhs.tail_instance; begin_iter.set_manifest(this); end_iter.set_manifest(this); @@ -316,7 +319,7 @@ public: } void encode(bufferlist& bl) const { - ENCODE_START(4, 3, bl); + ENCODE_START(5, 3, bl); ::encode(obj_size, bl); ::encode(objs, bl); ::encode(explicit_objs, bl); @@ -326,11 +329,12 @@ public: ::encode(prefix, bl); ::encode(rules, bl); ::encode(tail_bucket, bl); + ::encode(tail_instance, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN_32(4, 2, 2, bl); + DECODE_START_LEGACY_COMPAT_LEN_32(5, 2, 2, bl); ::decode(obj_size, bl); ::decode(objs, bl); if (struct_v >= 3) { @@ -354,6 +358,12 @@ public: ::decode(tail_bucket, bl); } + if (struct_v >= 5) { + ::decode(tail_instance, bl); + } else { // old object created before 'tail_instance' field added to manifest + tail_instance = head_obj.get_instance(); + } + update_iterators(); DECODE_FINISH(bl); } @@ -411,6 +421,14 @@ public: return prefix; } + void set_tail_instance(const string& _ti) { + tail_instance = _ti; + } + + const string& get_tail_instance() { + return tail_instance; + } + void set_head_size(uint64_t _s) { head_size = _s; } -- 2.47.3