From: Yehuda Sadeh Date: Fri, 15 Feb 2013 18:22:54 +0000 (-0800) Subject: rgw: don't copy object when it's copied into itself X-Git-Tag: v0.56.4~62 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a44df9343594099fecb3897df393249d3d1992e2;p=ceph.git 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 Reviewed-by: Greg Farnum (cherry picked from commit 34f885be536d0ac89c10fd29b1518751d2ffc547) --- diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 80f0cd8c4e03..04fd97330ae1 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -1316,22 +1316,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) { @@ -1339,34 +1351,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::iterator riter; + if (!copy_itself) { + vector::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;