diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-02-15 10:22:54 -0800 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-02-19 17:58:52 -0800 |
commit | 34f885be536d0ac89c10fd29b1518751d2ffc547 (patch) | |
tree | 96c145982ca1708f4b8df3787980ada23de1ffde | |
parent | 4eb9bf21cb2909ffd46e7c8b9ae79f6aac6403c6 (diff) | |
download | ceph-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.cc | 63 |
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; |