Skip to content

Commit

Permalink
rgw: add tail tag to track tail instance
Browse files Browse the repository at this point in the history
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 <yehuda@redhat.com>
  • Loading branch information
yehudasa committed Jul 5, 2017
1 parent 1174a2f commit ce90d94
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/rgw/rgw_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions src/rgw/rgw_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2970,6 +2970,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)
Expand Down Expand Up @@ -5321,6 +5322,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;
Expand Down
43 changes: 33 additions & 10 deletions src/rgw/rgw_rados.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2762,6 +2762,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) {
Expand Down Expand Up @@ -6723,7 +6724,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<string, bufferlist>& attrs, bool assume_noent,
map<string, bufferlist>& attrs,
bool assume_noent, bool modify_tail,
void *_index_op)
{
RGWRados::Bucket::UpdateIndex *index_op = static_cast<RGWRados::Bucket::UpdateIndex *>(_index_op);
Expand Down Expand Up @@ -6757,7 +6759,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;

Expand Down Expand Up @@ -6966,13 +6968,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;
}
Expand Down Expand Up @@ -7287,6 +7289,12 @@ static void set_copy_attrs(map<string, bufferlist>& 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<string, bufferlist>::iterator it = src_attrs.begin(); it != src_attrs.end(); ++it) {
Expand Down Expand Up @@ -7318,6 +7326,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;

Expand Down Expand Up @@ -8012,6 +8021,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()) {
Expand Down Expand Up @@ -8059,6 +8069,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) {
Expand Down Expand Up @@ -8373,7 +8384,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
}

Expand Down Expand Up @@ -8590,13 +8601,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);
Expand Down Expand Up @@ -8757,7 +8772,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;

Expand Down Expand Up @@ -9095,6 +9110,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()) {
Expand Down Expand Up @@ -9368,7 +9387,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)
Expand Down Expand Up @@ -9452,6 +9472,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;
}
Expand Down
12 changes: 9 additions & 3 deletions src/rgw/rgw_rados.h
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ struct RGWObjState {
ceph::real_time mtime;
uint64_t epoch;
bufferlist obj_tag;
bufferlist tail_tag;
string write_tag;
bool fake_tag;
RGWObjManifest manifest;
Expand Down Expand Up @@ -909,6 +910,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) {
Expand Down Expand Up @@ -2697,7 +2701,7 @@ class RGWRados
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:
Expand Down Expand Up @@ -2793,17 +2797,19 @@ class RGWRados
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<std::string, bufferlist>& attrs,
bool assume_noent,
bool modify_tail, bool assume_noent,
void *index_op);
int write_meta(uint64_t size, uint64_t accounted_size,
map<std::string, bufferlist>& attrs);
Expand Down

0 comments on commit ce90d94

Please sign in to comment.