]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: don't copy object when it's copied into itself
authorYehuda Sadeh <yehuda@inktank.com>
Fri, 15 Feb 2013 18:22:54 +0000 (10:22 -0800)
committerYehuda Sadeh <yehuda@inktank.com>
Wed, 20 Feb 2013 01:58:52 +0000 (17:58 -0800)
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>
src/rgw/rgw_rados.cc

index ad81259a95d8a661eaa2e1b6f15841296298f685..9675a75b63bd76b03212b976e99bad1486c8ac49 100644 (file)
@@ -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;