summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-02-15 10:22:54 -0800
committerYehuda Sadeh <yehuda@inktank.com>2013-02-19 17:58:52 -0800
commit34f885be536d0ac89c10fd29b1518751d2ffc547 (patch)
tree96c145982ca1708f4b8df3787980ada23de1ffde
parent4eb9bf21cb2909ffd46e7c8b9ae79f6aac6403c6 (diff)
downloadceph-34f885be536d0ac89c10fd29b1518751d2ffc547.tar.gz
rgw: don't copy object when it's copied into itself
Fixes: #4150 Backport: bobtail When object copied into itself, object will not be fully copied: tail reference count stays the same, head part is rewritten. Signed-off-by: Yehuda Sadeh <yehuda@inktank.com> Reviewed-by: Greg Farnum <greg@inktank.com>
-rw-r--r--src/rgw/rgw_rados.cc63
1 files changed, 38 insertions, 25 deletions
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc
index ad81259a95d..9675a75b63b 100644
--- a/src/rgw/rgw_rados.cc
+++ b/src/rgw/rgw_rados.cc
@@ -1317,22 +1317,34 @@ int RGWRados::copy_obj(void *ctx,
bufferlist first_chunk;
string tag;
- append_rand_alpha(cct, tag, tag, 32);
+ bool copy_itself = (dest_obj == src_obj);
+ RGWObjManifest *pmanifest;
+ ldout(cct, 0) << "dest_obj=" << dest_obj << " src_obj=" << src_obj << " copy_itself=" << (int)copy_itself << dendl;
- for (; miter != astate->manifest.objs.end(); ++miter) {
- RGWObjManifestPart& part = miter->second;
- ObjectWriteOperation op;
- manifest.objs[miter->first] = part;
- cls_refcount_get(op, tag, true);
+ if (!copy_itself) {
+ append_rand_alpha(cct, tag, tag, 32);
- get_obj_bucket_and_oid_key(part.loc, bucket, oid, key);
- io_ctx.locator_set_key(key);
+ for (; miter != astate->manifest.objs.end(); ++miter) {
+ RGWObjManifestPart& part = miter->second;
+ ObjectWriteOperation op;
+ manifest.objs[miter->first] = part;
+ cls_refcount_get(op, tag, true);
- ret = io_ctx.operate(oid, &op);
- if (ret < 0)
- goto done_ret;
+ get_obj_bucket_and_oid_key(part.loc, bucket, oid, key);
+ io_ctx.locator_set_key(key);
+
+ ret = io_ctx.operate(oid, &op);
+ if (ret < 0)
+ goto done_ret;
- ref_objs.push_back(part.loc);
+ ref_objs.push_back(part.loc);
+ }
+ manifest.obj_size = total_len;
+
+ pmanifest = &manifest;
+ } else {
+ pmanifest = &astate->manifest;
+ tag = astate->obj_tag.c_str();
}
if (copy_first) {
@@ -1340,34 +1352,35 @@ int RGWRados::copy_obj(void *ctx,
if (ret < 0)
goto done_ret;
- first_part = &manifest.objs[0];
+ first_part = &pmanifest->objs[0];
first_part->loc = dest_obj;
first_part->loc_ofs = 0;
first_part->size = first_chunk.length();
}
- manifest.obj_size = total_len;
+ ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, PUT_OBJ_CREATE, NULL, &first_chunk, pmanifest, &tag, NULL);
- ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, &tag, NULL);
if (mtime)
obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL, NULL);
return 0;
done_ret:
- vector<rgw_obj>::iterator riter;
+ if (!copy_itself) {
+ vector<rgw_obj>::iterator riter;
- /* rollback reference */
- for (riter = ref_objs.begin(); riter != ref_objs.end(); ++riter) {
- ObjectWriteOperation op;
- cls_refcount_put(op, tag, true);
+ /* rollback reference */
+ for (riter = ref_objs.begin(); riter != ref_objs.end(); ++riter) {
+ ObjectWriteOperation op;
+ cls_refcount_put(op, tag, true);
- get_obj_bucket_and_oid_key(*riter, bucket, oid, key);
- io_ctx.locator_set_key(key);
+ get_obj_bucket_and_oid_key(*riter, bucket, oid, key);
+ io_ctx.locator_set_key(key);
- int r = io_ctx.operate(oid, &op);
- if (r < 0) {
- ldout(cct, 0) << "ERROR: cleanup after error failed to drop reference on obj=" << *riter << dendl;
+ int r = io_ctx.operate(oid, &op);
+ if (r < 0) {
+ ldout(cct, 0) << "ERROR: cleanup after error failed to drop reference on obj=" << *riter << dendl;
+ }
}
}
return ret;