From: Yang Honggang Date: Tue, 4 Oct 2016 01:18:09 +0000 (+0800) Subject: rgw: fix versioned object IO error X-Git-Tag: v11.0.1~19^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d43b69e529328f73da6c29cd746557788a989ae0;p=ceph.git 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 --- diff --git a/src/rgw/rgw_dencoder.cc b/src/rgw/rgw_dencoder.cc index 0b4fdf5944cf..74563963d923 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 b519e6a1c678..20a47b6006af 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 7d6dc05010e9..1e67f1722662 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 850fb79e2875..00da971f46a9 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; }