diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-02-15 10:22:54 -0800 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-02-19 18:00:27 -0800 |
commit | a44df9343594099fecb3897df393249d3d1992e2 (patch) | |
tree | 6cf5fa3d1494eab87e110fa8a330afa2f47de528 | |
parent | 91d6be8353259ca30dc87062422e9ae334c3c344 (diff) | |
download | ceph-a44df9343594099fecb3897df393249d3d1992e2.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>
(cherry picked from commit 34f885be536d0ac89c10fd29b1518751d2ffc547)
-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 80f0cd8c4e0..04fd97330ae 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<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; |