From 4f7c155c2eb241e87160db30de4e24e7d8931188 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Wed, 5 Jul 2017 16:10:38 -0700 Subject: [PATCH] rgw: add tail tag to track tail instance Use tail_tag instead of idtag. The tail_tag is modified when either creating a new tail, or adding a refcount to the tail (e.g., when copying object). When just modifying the object's head, tail_tag should remain the same. The gc will then use the tail_tag (if exists, idtag if not) as the refcount id. Fixes: http://tracker.ceph.com/issues/20234 Signed-off-by: Yehuda Sadeh (cherry picked from commit f71a3e525d9a69fe537428f25930fb207a602afe) --- src/rgw/rgw_common.h | 1 + src/rgw/rgw_op.cc | 2 ++ src/rgw/rgw_rados.cc | 43 +++++++++++++++++++++++++++++++++---------- src/rgw/rgw_rados.h | 12 +++++++++--- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 4fb476859e70b..8d299cf39d475 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -67,6 +67,7 @@ using ceph::crypto::MD5; #define RGW_ATTR_EXPIRES RGW_ATTR_PREFIX "expires" #define RGW_ATTR_DELETE_AT RGW_ATTR_PREFIX "delete_at" #define RGW_ATTR_ID_TAG RGW_ATTR_PREFIX "idtag" +#define RGW_ATTR_TAIL_TAG RGW_ATTR_PREFIX "tail_tag" #define RGW_ATTR_SHADOW_OBJ RGW_ATTR_PREFIX "shadow_name" #define RGW_ATTR_MANIFEST RGW_ATTR_PREFIX "manifest" #define RGW_ATTR_USER_MANIFEST RGW_ATTR_PREFIX "user_manifest" diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index c59c537665323..ac6f7b70081ae 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -3017,6 +3017,7 @@ int RGWPutObjProcessor_Multipart::do_complete(size_t accounted_size, head_obj_op.meta.owner = s->owner.get_id(); head_obj_op.meta.delete_at = delete_at; head_obj_op.meta.zones_trace = zones_trace; + head_obj_op.meta.modify_tail = true; int r = head_obj_op.write_meta(obj_len, accounted_size, attrs); if (r < 0) @@ -5450,6 +5451,7 @@ void RGWCompleteMultipart::execute() obj_op.meta.ptag = &s->req_id; /* use req_id as operation tag */ obj_op.meta.owner = s->owner.get_id(); obj_op.meta.flags = PUT_OBJ_CREATE; + obj_op.meta.modify_tail = true; op_ret = obj_op.write_meta(ofs, accounted_size, attrs); if (op_ret < 0) return; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 7a1fce857151b..7ca3184aec275 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -2780,6 +2780,7 @@ int RGWPutObjProcessor_Atomic::do_complete(size_t accounted_size, const string& obj_op.meta.delete_at = delete_at; obj_op.meta.user_data = user_data; obj_op.meta.zones_trace = zones_trace; + obj_op.meta.modify_tail = true; r = obj_op.write_meta(obj_len, accounted_size, attrs); if (r < 0) { @@ -6823,7 +6824,8 @@ int RGWRados::swift_versioning_restore(RGWObjectCtx& obj_ctx, * Returns: 0 on success, -ERR# otherwise. */ int RGWRados::Object::Write::_do_write_meta(uint64_t size, uint64_t accounted_size, - map& attrs, bool assume_noent, + map& attrs, + bool assume_noent, bool modify_tail, void *_index_op) { RGWRados::Bucket::UpdateIndex *index_op = static_cast(_index_op); @@ -6856,7 +6858,7 @@ int RGWRados::Object::Write::_do_write_meta(uint64_t size, uint64_t accounted_si if (!ptag && !index_op->get_optag()->empty()) { ptag = index_op->get_optag(); } - r = target->prepare_atomic_modification(op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false); + r = target->prepare_atomic_modification(op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false, modify_tail); if (r < 0) return r; @@ -7072,13 +7074,13 @@ int RGWRados::Object::Write::write_meta(uint64_t size, uint64_t accounted_size, bool assume_noent = (meta.if_match == NULL && meta.if_nomatch == NULL); int r; if (assume_noent) { - r = _do_write_meta(size, accounted_size, attrs, assume_noent, (void *)&index_op); + r = _do_write_meta(size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op); if (r == -EEXIST) { assume_noent = false; } } if (!assume_noent) { - r = _do_write_meta(size, accounted_size, attrs, assume_noent, (void *)&index_op); + r = _do_write_meta(size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op); } return r; } @@ -7391,6 +7393,12 @@ static void set_copy_attrs(map& src_attrs, if (!attrs[RGW_ATTR_ETAG].length()) { attrs[RGW_ATTR_ETAG] = src_attrs[RGW_ATTR_ETAG]; } + if (!attrs[RGW_ATTR_TAIL_TAG].length()) { + auto ttiter = src_attrs.find(RGW_ATTR_TAIL_TAG); + if (ttiter != src_attrs.end()) { + attrs[RGW_ATTR_TAIL_TAG] = src_attrs[RGW_ATTR_TAIL_TAG]; + } + } break; case RGWRados::ATTRSMOD_MERGE: for (map::iterator it = src_attrs.begin(); it != src_attrs.end(); ++it) { @@ -7422,6 +7430,7 @@ int RGWRados::rewrite_obj(RGWBucketInfo& dest_bucket_info, rgw_obj& obj) return ret; attrset.erase(RGW_ATTR_ID_TAG); + attrset.erase(RGW_ATTR_TAIL_TAG); uint64_t max_chunk_size; @@ -8117,6 +8126,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, } if (!copy_itself) { + attrs.erase(RGW_ATTR_TAIL_TAG); manifest = astate->manifest; const rgw_bucket_placement& tail_placement = manifest.get_tail_placement(); if (tail_placement.bucket.name.empty()) { @@ -8163,6 +8173,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx, write_op.meta.category = category; write_op.meta.olh_epoch = olh_epoch; write_op.meta.delete_at = delete_at; + write_op.meta.modify_tail = !copy_itself; ret = write_op.write_meta(obj_size, astate->accounted_size, attrs); if (ret < 0) { @@ -8475,7 +8486,7 @@ int RGWRados::Object::complete_atomic_modification() return 0; } - string tag = state->obj_tag.to_str(); + string tag = (state->tail_tag.length() > 0 ? state->tail_tag.to_str() : state->obj_tag.to_str()); return store->gc->send_chain(chain, tag, false); // do it async } @@ -8692,13 +8703,17 @@ int RGWRados::defer_gc(void *ctx, const RGWBucketInfo& bucket_info, const rgw_ob return -EINVAL; } - if (state->obj_tag.length() == 0) {// check for backward compatibility + string tag; + + if (state->tail_tag.length() > 0) { + tag = state->tail_tag.c_str(); + } else if (state->obj_tag.length() > 0) { + tag = state->obj_tag.c_str(); + } else { ldout(cct, 20) << "state->obj_tag is empty, not deferring gc operation" << dendl; return -EINVAL; } - string tag = state->obj_tag.c_str(); - ldout(cct, 0) << "defer chain tag=" << tag << dendl; return gc->defer_chain(tag, false); @@ -8861,7 +8876,7 @@ int RGWRados::Object::Delete::delete_obj() return -ENOENT; } - r = target->prepare_atomic_modification(op, false, NULL, NULL, NULL, true); + r = target->prepare_atomic_modification(op, false, NULL, NULL, NULL, true, false); if (r < 0) return r; @@ -9195,6 +9210,10 @@ int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, const RGWBucketInfo& bucket s->shadow_obj[bl.length()] = '\0'; } s->obj_tag = s->attrset[RGW_ATTR_ID_TAG]; + auto ttiter = s->attrset.find(RGW_ATTR_TAIL_TAG); + if (ttiter != s->attrset.end()) { + s->tail_tag = s->attrset[RGW_ATTR_TAIL_TAG]; + } bufferlist manifest_bl = s->attrset[RGW_ATTR_MANIFEST]; if (manifest_bl.length()) { @@ -9467,7 +9486,8 @@ void RGWRados::SystemObject::invalidate_state() } int RGWRados::Object::prepare_atomic_modification(ObjectWriteOperation& op, bool reset_obj, const string *ptag, - const char *if_match, const char *if_nomatch, bool removal_op) + const char *if_match, const char *if_nomatch, bool removal_op, + bool modify_tail) { int r = get_state(&state, false); if (r < 0) @@ -9551,6 +9571,9 @@ int RGWRados::Object::prepare_atomic_modification(ObjectWriteOperation& op, bool ldout(store->ctx(), 10) << "setting object write_tag=" << state->write_tag << dendl; op.setxattr(RGW_ATTR_ID_TAG, bl); + if (modify_tail) { + op.setxattr(RGW_ATTR_TAIL_TAG, bl); + } return 0; } diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 23caafd6314f4..b911601be19bb 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -874,6 +874,7 @@ struct RGWObjState { ceph::real_time mtime; uint64_t epoch; bufferlist obj_tag; + bufferlist tail_tag; string write_tag; bool fake_tag; RGWObjManifest manifest; @@ -908,6 +909,9 @@ struct RGWObjState { if (rhs.obj_tag.length()) { obj_tag = rhs.obj_tag; } + if (rhs.tail_tag.length()) { + tail_tag = rhs.tail_tag; + } write_tag = rhs.write_tag; fake_tag = rhs.fake_tag; if (rhs.has_manifest) { @@ -2702,7 +2706,7 @@ public: void invalidate_state(); int prepare_atomic_modification(librados::ObjectWriteOperation& op, bool reset_obj, const string *ptag, - const char *ifmatch, const char *ifnomatch, bool removal_op); + const char *ifmatch, const char *ifnomatch, bool removal_op, bool modify_tail); int complete_atomic_modification(); public: @@ -2798,17 +2802,19 @@ public: bool canceled; const string *user_data; rgw_zone_set *zones_trace; + bool modify_tail; MetaParams() : mtime(NULL), rmattrs(NULL), data(NULL), manifest(NULL), ptag(NULL), remove_objs(NULL), category(RGW_OBJ_CATEGORY_MAIN), flags(0), - if_match(NULL), if_nomatch(NULL), olh_epoch(0), canceled(false), user_data(nullptr), zones_trace(nullptr) {} + if_match(NULL), if_nomatch(NULL), olh_epoch(0), canceled(false), user_data(nullptr), zones_trace(nullptr), + modify_tail(false) {} } meta; explicit Write(RGWRados::Object *_target) : target(_target) {} int _do_write_meta(uint64_t size, uint64_t accounted_size, map& attrs, - bool assume_noent, + bool modify_tail, bool assume_noent, void *index_op); int write_meta(uint64_t size, uint64_t accounted_size, map& attrs); -- 2.39.5