From f60a8823a2547cfc8ec1da0f44f74b2c11e7bc60 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Fri, 1 Nov 2019 10:38:52 -0400 Subject: [PATCH] rgw: apply_olh_log filters out older instances of same epoch when apply_olh_log() detects multiple instances with the same epoch, we only promote the one that the bucket index lists as more current Fixes: https://tracker.ceph.com/issues/39142 Signed-off-by: Casey Bodley (cherry picked from commit 15aa3ad341ab0df128464d22cd97bd33f185e41a) --- src/rgw/rgw_rados.cc | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 476a9c80a254a..f5fa849a85360 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -7481,17 +7481,40 @@ int RGWRados::apply_olh_log(RGWObjectCtx& obj_ctx, RGWObjState& state, const RGW op.mtime2(&mtime_ts); bool need_to_link = false; + uint64_t link_epoch = 0; cls_rgw_obj_key key; bool delete_marker = false; list remove_instances; bool need_to_remove = false; + // decode current epoch and instance + auto olh_ver = state.attrset.find(RGW_ATTR_OLH_VER); + if (olh_ver != state.attrset.end()) { + std::string str = olh_ver->second.to_str(); + std::string err; + link_epoch = strict_strtoll(str.c_str(), 10, &err); + if (!err.empty()) { + ldout(cct, 0) << "apply_olh_log failed to decode olh ver '" << str << "'" << dendl; + return -EINVAL; + } + } + auto olh_info = state.attrset.find(RGW_ATTR_OLH_INFO); + if (olh_info != state.attrset.end()) { + RGWOLHInfo info; + int r = decode_olh_info(cct, olh_info->second, &info); + if (r < 0) { + return r; + } + info.target.key.get_index_key(&key); + delete_marker = info.removed; + } + for (iter = log.begin(); iter != log.end(); ++iter) { vector::iterator viter = iter->second.begin(); for (; viter != iter->second.end(); ++viter) { rgw_bucket_olh_log_entry& entry = *viter; - ldout(cct, 20) << "olh_log_entry: op=" << (int)entry.op + ldout(cct, 20) << "olh_log_entry: epoch=" << iter->first << " op=" << (int)entry.op << " key=" << entry.key.name << "[" << entry.key.instance << "] " << (entry.delete_marker ? "(delete)" : "") << dendl; switch (entry.op) { @@ -7499,10 +7522,19 @@ int RGWRados::apply_olh_log(RGWObjectCtx& obj_ctx, RGWObjState& state, const RGW remove_instances.push_back(entry.key); break; case CLS_RGW_OLH_OP_LINK_OLH: - need_to_link = true; - need_to_remove = false; - key = entry.key; - delete_marker = entry.delete_marker; + // only overwrite a link of the same epoch if its key sorts before + if (link_epoch < iter->first || key.instance.empty() || + key.instance > entry.key.instance) { + ldout(cct, 20) << "apply_olh_log applying key=" << entry.key << " epoch=" << iter->first << " delete_marker=" << entry.delete_marker + << " over current=" << key << " epoch=" << link_epoch << " delete_marker=" << delete_marker << dendl; + need_to_link = true; + need_to_remove = false; + key = entry.key; + delete_marker = entry.delete_marker; + } else { + ldout(cct, 20) << "apply_olh skipping key=" << entry.key<< " epoch=" << iter->first << " delete_marker=" << entry.delete_marker + << " before current=" << key << " epoch=" << link_epoch << " delete_marker=" << delete_marker << dendl; + } break; case CLS_RGW_OLH_OP_UNLINK_OLH: need_to_remove = true; -- 2.39.5