]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: clean up after errors in create
authorJosh Durgin <josh.durgin@inktank.com>
Wed, 5 Dec 2012 23:52:41 +0000 (15:52 -0800)
committerJosh Durgin <josh.durgin@inktank.com>
Fri, 7 Dec 2012 18:37:51 +0000 (10:37 -0800)
Split format 1 and 2 image creation into separate functions for better
readability. Format 2 requires more error handling.

Fixes: #2677
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
src/librbd/internal.cc

index 2be4f2d70399b74142e91938a9c812197a226d5f..147c7cd4779089ca47dd87d5d8b18307a3822fa2 100644 (file)
@@ -652,6 +652,127 @@ reprotect_and_return_err:
     return ictx->is_snap_protected(snap_name, is_protected);
   }
 
+  int create_v1(IoCtx& io_ctx, const char *imgname, uint64_t bid,
+               uint64_t size, int *order)
+  {
+    CephContext *cct = (CephContext *)io_ctx.cct();
+    ldout(cct, 2) << "adding rbd image to directory..." << dendl;
+    int r = tmap_set(io_ctx, imgname);
+    if (r < 0) {
+      lderr(cct) << "error adding image to directory: " << cpp_strerror(r)
+                << dendl;
+      return r;
+    }
+
+    ldout(cct, 2) << "creating rbd image..." << dendl;
+    struct rbd_obj_header_ondisk header;
+    init_rbd_header(header, size, order, bid);
+
+    bufferlist bl;
+    bl.append((const char *)&header, sizeof(header));
+
+    string header_oid = old_header_name(imgname);
+    r = io_ctx.write(header_oid, bl, bl.length(), 0);
+    if (r < 0) {
+      lderr(cct) << "Error writing image header: " << cpp_strerror(r)
+                << dendl;
+      int remove_r = tmap_rm(io_ctx, imgname);
+      if (remove_r < 0) {
+       lderr(cct) << "Could not remove image from directory after "
+                  << "header creation failed: "
+                  << cpp_strerror(r) << dendl;
+      }
+      return r;
+    }
+
+    ldout(cct, 2) << "done." << dendl;
+    return 0;
+  }
+
+  int create_v2(IoCtx& io_ctx, const char *imgname, uint64_t bid, uint64_t size,
+               int *order, uint64_t features, uint64_t stripe_unit,
+               uint64_t stripe_count)
+  {
+    ostringstream bid_ss;
+    uint32_t extra;
+    string id, id_obj, header_oid;
+    int remove_r;
+    ostringstream oss;
+    CephContext *cct = (CephContext *)io_ctx.cct();
+
+    id_obj = id_obj_name(imgname);
+
+    int r = io_ctx.create(id_obj, true);
+    if (r < 0) {
+      lderr(cct) << "error creating rbd id object: " << cpp_strerror(r)
+                << dendl;
+      return r;
+    }
+
+    extra = rand() % 0xFFFFFFFF;
+    bid_ss << std::hex << bid << std::hex << extra;
+    id = bid_ss.str();
+    r = cls_client::set_id(&io_ctx, id_obj, id);
+    if (r < 0) {
+      lderr(cct) << "error setting image id: " << cpp_strerror(r) << dendl;
+      goto err_remove_id;
+    }
+
+    ldout(cct, 2) << "adding rbd image to directory..." << dendl;
+    r = cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, imgname, id);
+    if (r < 0) {
+      lderr(cct) << "error adding image to directory: " << cpp_strerror(r)
+                << dendl;
+      goto err_remove_id;
+    }
+
+    oss << RBD_DATA_PREFIX << id;
+    header_oid = header_name(id);
+    r = cls_client::create_image(&io_ctx, header_oid, size, *order,
+                                features, oss.str());
+    if (r < 0) {
+      lderr(cct) << "error writing header: " << cpp_strerror(r) << dendl;
+      goto err_remove_from_dir;
+    }
+
+    if ((stripe_unit || stripe_count) &&
+       (stripe_count != 1 || stripe_unit != (1ull<<*order))) {
+      r = cls_client::set_stripe_unit_count(&io_ctx, header_oid,
+                                           stripe_unit, stripe_count);
+      if (r < 0) {
+       lderr(cct) << "error setting striping parameters: "
+                  << cpp_strerror(r) << dendl;
+       goto err_remove_header;
+      }
+    }
+
+    ldout(cct, 2) << "done." << dendl;
+    return 0;
+
+  err_remove_header:
+    remove_r = io_ctx.remove(header_oid);
+    if (remove_r < 0) {
+      lderr(cct) << "error cleaning up image header after creation failed: "
+                << dendl;
+    }
+  err_remove_from_dir:
+    remove_r = cls_client::dir_remove_image(&io_ctx, RBD_DIRECTORY,
+                                           imgname, id);
+    if (remove_r < 0) {
+      lderr(cct) << "error cleaning up image from rbd_directory object "
+                << "after creation failed: " << cpp_strerror(remove_r)
+                << dendl;
+    }
+  err_remove_id:
+    remove_r = io_ctx.remove(id_obj);
+    if (remove_r < 0) {
+      lderr(cct) << "error cleaning up id object after creation failed: "
+                << cpp_strerror(remove_r) << dendl;
+    }
+
+    return r;
+  }
+
   int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
             bool old_format, uint64_t features, int *order,
             uint64_t stripe_unit, uint64_t stripe_count)
@@ -714,68 +835,11 @@ reprotect_and_return_err:
       if (stripe_count && stripe_count != 1)
        return -EINVAL;
 
-      ldout(cct, 2) << "adding rbd image to directory..." << dendl;
-      r = tmap_set(io_ctx, imgname);
-      if (r < 0) {
-       lderr(cct) << "error adding image to directory: " << cpp_strerror(r)
-                  << dendl;
-       return r;
-      }
-
-      ldout(cct, 2) << "creating rbd image..." << dendl;
-      struct rbd_obj_header_ondisk header;
-      init_rbd_header(header, size, order, bid);
-
-      bufferlist bl;
-      bl.append((const char *)&header, sizeof(header));
-
-      string header_oid = old_header_name(imgname);
-      r = io_ctx.write(header_oid, bl, bl.length(), 0);
+      return create_v1(io_ctx, imgname, bid, size, order);
     } else {
-      string id_obj = id_obj_name(imgname);
-      r = io_ctx.create(id_obj, true);
-      if (r < 0) {
-       lderr(cct) << "error creating rbd id object: " << cpp_strerror(r)
-                  << dendl;
-       return r;
-      }
-
-      ostringstream bid_ss;
-      uint32_t extra = rand() % 0xFFFFFFFF;
-      bid_ss << std::hex << bid << std::hex << extra;
-      string id = bid_ss.str();
-      r = cls_client::set_id(&io_ctx, id_obj, id);
-      if (r < 0) {
-       lderr(cct) << "error setting image id: " << cpp_strerror(r) << dendl;
-       return r;
-      }
-
-      ldout(cct, 2) << "adding rbd image to directory..." << dendl;
-      r = cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, imgname, id);
-      if (r < 0) {
-       lderr(cct) << "error adding image to directory: " << cpp_strerror(r)
-                  << dendl;
-       return r;
-      }
-
-      ostringstream oss;
-      oss << RBD_DATA_PREFIX << id;
-      r = cls_client::create_image(&io_ctx, header_name(id), size, *order,
-                                  features, oss.str());
-      if (r == 0 &&
-         (stripe_unit || stripe_count) &&
-         (stripe_count != 1 || stripe_unit != (1ull<<*order))) {
-       r = cls_client::set_stripe_unit_count(&io_ctx, header_name(id), stripe_unit, stripe_count);
-      }
+      return create_v2(io_ctx, imgname, bid, size, order, features,
+                      stripe_unit, stripe_count);
     }
-
-    if (r < 0) {
-      lderr(cct) << "error writing header: " << cpp_strerror(r) << dendl;
-      return r;
-    }
-
-    ldout(cct, 2) << "done." << dendl;
-    return 0;
   }
 
   /*