]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: refactor export/import to v1 and v2 methods.
authorDongsheng Yang <dongsheng.yang@easystack.cn>
Thu, 20 Oct 2016 12:07:31 +0000 (08:07 -0400)
committerDongsheng Yang <dongsheng.yang@easystack.cn>
Sun, 19 Feb 2017 12:42:03 +0000 (20:42 +0800)
Signed-off-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
src/tools/rbd/Utils.h
src/tools/rbd/action/Export.cc
src/tools/rbd/action/Import.cc

index 9ecb21eecc61d813f4d93d2e16d1611ddc02d03d..0023d431dfed56fa6275877e00c66871639d5b84 100644 (file)
@@ -29,8 +29,8 @@ static const std::string RBD_DIFF_BANNER_V2 ("rbd diff v2\n");
 
 #define RBD_EXPORT_IMAGE_ORDER         'O'
 #define RBD_EXPORT_IMAGE_FEATURES      'T'
-#define RBD_EXPORT_IMAGE_STRIPEUNIT    'U'
-#define RBD_EXPORT_IMAGE_STRIPECOUNT   'C'
+#define RBD_EXPORT_IMAGE_STRIPE_UNIT   'U'
+#define RBD_EXPORT_IMAGE_STRIPE_COUNT  'C'
 #define RBD_EXPORT_IMAGE_END           'E'
 
 enum SnapshotPresence {
index b7fa6a44d21034e973849641f2deba30c7317b9c..771db32279c1eb058a484a54553b71aa3134581c 100644 (file)
@@ -356,6 +356,133 @@ private:
   int m_fd;
 };
 
+static int do_export_v2(librbd::Image& image, librbd::image_info_t &info, int fd,
+                       uint64_t period, int max_concurrent_ops, utils::ProgressContext &pc)
+{
+  int r = 0;
+  size_t offset = 0;
+  // header
+  bufferlist bl;
+  bl.append(utils::RBD_IMAGE_BANNER_V2);
+
+  __u8 tag;
+  uint64_t length;
+  // encode order
+  tag = RBD_EXPORT_IMAGE_ORDER;
+  length = 8;
+  ::encode(tag, bl);
+  ::encode(length, bl);
+  ::encode(uint64_t(info.order), bl);
+
+  // encode features
+  tag = RBD_EXPORT_IMAGE_FEATURES;
+  uint64_t features;
+  image.features(&features);
+  length = 8;
+  ::encode(tag, bl);
+  ::encode(length, bl);
+  ::encode(features, bl);
+
+  // encode stripe_unit and stripe_count
+  tag = RBD_EXPORT_IMAGE_STRIPE_UNIT;
+  uint64_t stripe_unit;
+  stripe_unit = image.get_stripe_unit();
+  length = 8;
+  ::encode(tag, bl);
+  ::encode(length, bl);
+  ::encode(stripe_unit, bl);
+
+  tag = RBD_EXPORT_IMAGE_STRIPE_COUNT;
+  uint64_t stripe_count;
+  stripe_count = image.get_stripe_count();
+  length = 8;
+  ::encode(tag, bl);
+  ::encode(length, bl);
+  ::encode(stripe_count, bl);
+
+  // encode end tag
+  tag = RBD_EXPORT_IMAGE_END;
+  ::encode(tag, bl);
+
+  // write bl to fd.
+  r = bl.write_fd(fd);
+  if (r < 0) {
+    return r;
+  }
+  offset += bl.length();
+
+  lseek(fd, offset, SEEK_SET);
+
+  // header for snapshots
+  bl.clear();
+  bl.append(utils::RBD_IMAGE_DIFFS_BANNER_V2);
+
+  std::vector<librbd::snap_info_t> snaps;
+  r = image.snap_list(snaps);
+  if (r < 0) {
+    return r;
+  }
+
+  uint64_t diff_num = snaps.size() + 1;
+  ::encode(diff_num, bl);
+
+  r = bl.write_fd(fd);
+  if (r < 0) {
+    return r;
+  }
+
+  if (0 == diff_num) {
+    return r;
+  } else {
+    const char *last_snap = NULL;
+    for (size_t i = 0; i < snaps.size(); ++i) {
+      utils::snap_set(image, snaps[i].name.c_str());
+      r = do_export_diff_fd(image, last_snap, snaps[i].name.c_str(), false, fd, true, 2);
+      if (r < 0) {
+       return r;
+      }
+      pc.update_progress(i, snaps.size() + 1);
+      last_snap = snaps[i].name.c_str();
+    }
+    utils::snap_set(image, std::string(""));
+    r = do_export_diff_fd(image, last_snap, nullptr, false, fd, true, 2);
+    if (r < 0) {
+      return r;
+    }
+    pc.update_progress(snaps.size() + 1, snaps.size() + 1);
+  }
+  return r;
+}
+
+static int do_export_v1(librbd::Image& image, librbd::image_info_t &info, int fd,
+                       uint64_t period, int max_concurrent_ops, utils::ProgressContext &pc)
+{
+  int r = 0;
+  size_t file_size = 0;
+  SimpleThrottle throttle(max_concurrent_ops, false);
+  for (uint64_t offset = 0; offset < info.size; offset += period) {
+    if (throttle.pending_error()) {
+      break;
+    }
+
+    uint64_t length = min(period, info.size - offset);
+    C_Export *ctx = new C_Export(throttle, image, file_size + offset, offset, length, fd);
+    ctx->send();
+
+    pc.update_progress(offset, info.size);
+  }
+
+  file_size += info.size;
+  r = throttle.wait_for_ret();
+  if (fd != 1) {
+    if (r >= 0) {
+      r = ftruncate(fd, file_size);
+      r = lseek(fd, file_size, SEEK_SET);
+    }
+  }
+  return r;
+}
+
 static int do_export(librbd::Image& image, const char *path, bool no_progress, int export_format)
 {
   librbd::image_info_t info;
@@ -381,123 +508,13 @@ static int do_export(librbd::Image& image, const char *path, bool no_progress, i
   }
 
   utils::ProgressContext pc("Exporting image", no_progress);
-  SimpleThrottle throttle(max_concurrent_ops, false);
   uint64_t period = image.get_stripe_count() * (1ull << info.order);
 
-  if (export_format == 2) {
-    size_t offset = 0;
-    // header
-    bufferlist bl;
-    bl.append(utils::RBD_IMAGE_BANNER_V2);
-
-    // size in header
-    uint64_t size = info.size;
-    ::encode(size, bl);
-
-    // TODO add more priorities here, such as image_feature...
-    __u8 tag;
-
-    // encode order
-    tag = RBD_EXPORT_IMAGE_ORDER;
-    ::encode(tag, bl);
-    ::encode(uint64_t(info.order), bl);
-
-    // encode features
-    tag = RBD_EXPORT_IMAGE_FEATURES;
-    uint64_t features;
-    image.features(&features);
-    ::encode(tag, bl);
-    ::encode(features, bl);
-
-    // encode stripe_unit and stripe_count
-    tag = RBD_EXPORT_IMAGE_STRIPEUNIT;
-    uint64_t stripe_unit;
-    stripe_unit = image.get_stripe_unit();
-    ::encode(tag, bl);
-    ::encode(stripe_unit, bl);
-
-    tag = RBD_EXPORT_IMAGE_STRIPECOUNT;
-    uint64_t stripe_count;
-    stripe_count = image.get_stripe_count();
-    ::encode(tag, bl);
-    ::encode(stripe_count, bl);
-
-    // encode end tag
-    tag = RBD_EXPORT_IMAGE_END;
-    ::encode(tag, bl);
-
-    // write bl to fd.
-    r = bl.write_fd(fd);
-    if (r < 0) {
-      goto out;
-    }
-    offset += bl.length();
-
-    lseek(fd, offset, SEEK_SET);
-
-    // header for snapshots
-    bl.clear();
-    bl.append(utils::RBD_IMAGE_SNAPS_BANNER_V2);
-
-    std::vector<librbd::snap_info_t> snaps;
-    r = image.snap_list(snaps);
-    if (r < 0) {
-      goto out;
-    }
-
-    uint64_t snap_num = snaps.size() + 1;
-    ::encode(snap_num, bl);
-
-    r = bl.write_fd(fd);
-    if (r < 0) {
-      goto out;
-    }
-
-    if (0 == snap_num) {
-      goto out;
-    } else {
-      const char *last_snap = NULL;
-      for (size_t i = 0; i < snaps.size(); ++i) {
-       utils::snap_set(image, snaps[i].name.c_str());
-       r = do_export_diff_fd(image, last_snap, snaps[i].name.c_str(), false, fd, true, 2);
-       if (r < 0) {
-         goto out;
-       }
-       pc.update_progress(i, snaps.size() + 1);
-       last_snap = snaps[i].name.c_str();
-      }
-      utils::snap_set(image, std::string(""));
-      r = do_export_diff_fd(image, last_snap, nullptr, false, fd, true, 2);
-      if (r < 0) {
-       goto out;
-      }
-      pc.update_progress(snaps.size() + 1, snaps.size() + 1);
-    }
-  } else {
-    size_t file_size = 0;
-    for (uint64_t offset = 0; offset < info.size; offset += period) {
-      if (throttle.pending_error()) {
-       break;
-      }
-
-      uint64_t length = min(period, info.size - offset);
-      C_Export *ctx = new C_Export(throttle, image, file_size + offset, offset, length, fd);
-      ctx->send();
-
-      pc.update_progress(offset, info.size);
-    }
-
-    file_size += info.size;
-    r = throttle.wait_for_ret();
-    if (!to_stdout) {
-      if (r >= 0) {
-       r = ftruncate(fd, file_size);
-       r = lseek(fd, file_size, SEEK_SET);
-      }
-    }
-  }
+  if (export_format == 1)
+    r = do_export_v1(image, info, fd, period, max_concurrent_ops, pc);
+  else
+    r = do_export_v2(image, info, fd, period, max_concurrent_ops, pc);
 
-out:
   if (r < 0)
     pc.fail();
   else
@@ -547,7 +564,7 @@ int execute(const po::variables_map &vm) {
   
   int format = 1;
   if (vm.count("export-format"))
-    format = vm["export-format"].as<int>();
+    format = vm["export-format"].as<uint64_t>();
 
   r = do_export(image, path.c_str(), vm[at::NO_PROGRESS].as<bool>(), format);
   if (r < 0) {
index 342f43e14c1defbfa283f9cfbdd297d8c0962e3d..8dac188aebb68d77e964999259ac35336f115845 100644 (file)
@@ -29,7 +29,7 @@ int do_import_diff_fd(librbd::Image &image, int fd,
   uint64_t size = 0;
   uint64_t off = 0;
   string from, to;
-  string banner = (format == 1 ? utils::RBD_DIFF_BANNER:utils::RBD_DIFF_BANNER_V2);
+  string banner = (format == 1 ? utils::RBD_DIFF_BANNER : utils::RBD_DIFF_BANNER_V2);
   char buf[banner.size() + 1];
 
   bool from_stdin = (fd == 0);
@@ -289,6 +289,211 @@ private:
   uint64_t m_offset;
 };
 
+static int do_import_header(int fd, int import_format, uint64_t &size, librbd::ImageOptions& opts)
+{
+  int r = 0;
+  char image_buf[utils::RBD_IMAGE_BANNER_V2.size() + 1];
+
+  // There is no header in v1 image.
+  if (import_format == 1)
+    return r;
+
+  if (fd == 0 || size < utils::RBD_IMAGE_BANNER_V2.size()) {
+    r = -EINVAL;
+    return r;
+  }
+  r = safe_read_exact(fd, image_buf, utils::RBD_IMAGE_BANNER_V2.size());
+  if (r < 0)
+    return r;
+
+  image_buf[utils::RBD_IMAGE_BANNER_V2.size()] = '\0';
+  if (strcmp(image_buf, utils::RBD_IMAGE_BANNER_V2.c_str())) {
+    // Old format
+    r = -EINVAL;
+    return r;
+  }
+
+  char buf[8];
+  bufferlist bl;
+  bufferlist::iterator p;
+
+  // As V1 format for image is already deprecated, import image in V2 by default.
+  uint64_t image_format = 2;
+  if (opts.get(RBD_IMAGE_OPTION_FORMAT, &image_format) != 0) {
+    opts.set(RBD_IMAGE_OPTION_FORMAT, image_format);
+  }
+
+  while (1) {
+    __u8 tag;
+    uint64_t length;
+    r = safe_read_exact(fd, &tag, 1);
+    if (r < 0) {
+      return r;
+    }
+
+    if (tag == RBD_EXPORT_IMAGE_END) {
+      break;
+    } else {
+      r = safe_read_exact(fd, &length, 8);
+      if (r < 0) {
+       return r;
+      }
+
+      if (tag == RBD_EXPORT_IMAGE_ORDER) {
+       uint64_t order = 0;
+       r = safe_read_exact(fd, &order, 8);
+       if (r < 0) {
+         return r;
+       }
+       if (opts.get(RBD_IMAGE_OPTION_ORDER, &order) != 0) {
+         opts.set(RBD_IMAGE_OPTION_ORDER, order);
+       }
+      } else if (tag == RBD_EXPORT_IMAGE_FEATURES) {
+       uint64_t features = 0;
+       r = safe_read_exact(fd, &features, 8);
+       if (r < 0) {
+         return r;
+       }
+       if (opts.get(RBD_IMAGE_OPTION_FEATURES, &features) != 0) {
+         opts.set(RBD_IMAGE_OPTION_FEATURES, features);
+       }
+      } else if (tag == RBD_EXPORT_IMAGE_STRIPE_UNIT) {
+       uint64_t stripe_unit = 0;
+       r = safe_read_exact(fd, &stripe_unit, 8);
+       if (r < 0) {
+         return r;
+       }
+       if (opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit) != 0) {
+         opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit);
+       }
+      } else if (tag == RBD_EXPORT_IMAGE_STRIPE_COUNT) {
+       uint64_t stripe_count = 0;
+       r = safe_read_exact(fd, &stripe_count, 8);
+       if (r < 0) {
+         return r;
+       }
+       if (opts.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &stripe_count) != 0) {
+         opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count);
+       }
+      } else {
+       std::cerr << "rbd: invalid tag in image properties zone: " << tag << "Skip it." << std::endl;
+       ::lseek(fd, length, SEEK_CUR);
+      }
+    }
+  }
+
+  return r;
+}
+
+static int do_import_v2(int fd, librbd::Image &image, uint64_t size,
+                       size_t imgblklen, boost::scoped_ptr<SimpleThrottle> &throttle,
+                       utils::ProgressContext &pc)
+{
+  int r = 0;
+  char snap_buf[utils::RBD_IMAGE_DIFFS_BANNER_V2.size() + 1];
+  uint64_t diff_num;
+
+  r = safe_read_exact(fd, snap_buf, utils::RBD_IMAGE_DIFFS_BANNER_V2.size());
+  if (r < 0)
+    return r;
+  snap_buf[utils::RBD_IMAGE_DIFFS_BANNER_V2.size()] = '\0';
+  if (strcmp(snap_buf, utils::RBD_IMAGE_DIFFS_BANNER_V2.c_str())) {
+    cerr << "Incorrect RBD_IMAGE_DIFFS_BANNER." << snap_buf <<std::endl;
+    return -EINVAL;
+  } else {
+    r = safe_read_exact(fd, &diff_num, 8);
+    if (r < 0) {
+      return r;
+    }
+  }
+
+  for (size_t i = 0; i < diff_num; i++) {
+    r = do_import_diff_fd(image, fd, true, 2);
+    if (r < 0) {
+      pc.fail();
+      std::cerr << "rbd: import-diff failed: " << cpp_strerror(r) << std::endl;
+      return r;
+    }
+    pc.update_progress(i + 1, diff_num);
+  }
+
+  return r;
+}
+
+static int do_import_v1(int fd, librbd::Image &image, uint64_t size,
+                       size_t imgblklen, boost::scoped_ptr<SimpleThrottle> &throttle,
+                       utils::ProgressContext &pc)
+{
+  int r = 0;
+  size_t reqlen = imgblklen;    // amount requested from read
+  ssize_t readlen;              // amount received from one read
+  size_t blklen = 0;            // amount accumulated from reads to fill blk
+  char *p = new char[imgblklen];
+  uint64_t image_pos = 0;
+  bool from_stdin = (fd == 0);
+
+  reqlen = min(reqlen, size);
+  // loop body handles 0 return, as we may have a block to flush
+  while ((readlen = ::read(fd, p + blklen, reqlen)) >= 0) {
+    if (throttle->pending_error()) {
+      break;
+    }
+
+    blklen += readlen;
+    // if read was short, try again to fill the block before writing
+    if (readlen && ((size_t)readlen < reqlen)) {
+      reqlen -= readlen;
+      continue;
+    }
+    if (!from_stdin)
+      pc.update_progress(image_pos, size);
+
+    bufferlist bl(blklen);
+    bl.append(p, blklen);
+    // resize output image by binary expansion as we go for stdin
+    if (from_stdin && (image_pos + (size_t)blklen) > size) {
+      size *= 2;
+      r = image.resize(size);
+      if (r < 0) {
+       std::cerr << "rbd: can't resize image during import" << std::endl;
+       goto out;
+      }
+    }
+
+    // write as much as we got; perhaps less than imgblklen
+    // but skip writing zeros to create sparse images
+    if (!bl.is_zero()) {
+      C_Import *ctx = new C_Import(*throttle, image, bl, image_pos);
+      ctx->send();
+    }
+
+    // done with whole block, whether written or not
+    image_pos += blklen;
+    if (!from_stdin && image_pos >= size)
+      break;
+    // if read had returned 0, we're at EOF and should quit
+    if (readlen == 0)
+      break;
+    blklen = 0;
+    reqlen = imgblklen;
+  }
+  r = throttle->wait_for_ret();
+  if (r < 0) {
+    goto out;
+  }
+
+  if (fd == 0) {
+    r = image.resize(image_pos);
+    if (r < 0) {
+      std::cerr << "rbd: final image resize failed" << std::endl;
+      goto out;
+    }
+  }
+out:
+  delete[] p;
+  return r;
+}
+
 static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
                      const char *imgname, const char *path,
                     librbd::ImageOptions& opts, bool no_progress,
@@ -306,16 +511,9 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
   }
 
   // try to fill whole imgblklen blocks for sparsification
-  uint64_t image_pos = 0;
   size_t imgblklen = 1 << order;
-  char *p = new char[imgblklen];
-  size_t reqlen = imgblklen;    // amount requested from read
-  ssize_t readlen;              // amount received from one read
-  size_t blklen = 0;            // amount accumulated from reads to fill blk
   librbd::Image image;
   uint64_t size = 0;
-  uint64_t snap_num;
-  char image_buf[utils::RBD_IMAGE_BANNER_V2.size() + 1];
 
   boost::scoped_ptr<SimpleThrottle> throttle;
   bool from_stdin = !strcmp(path, "-");
@@ -360,85 +558,11 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
     posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
 #endif
   }
-  
-  if (import_format == 2) {
-    if (from_stdin || size < utils::RBD_IMAGE_BANNER_V2.size()) {
-      r = -EINVAL;
-      goto done;
-    }
-    r = safe_read_exact(fd, image_buf, utils::RBD_IMAGE_BANNER_V2.size());
-    if (r < 0)
-      goto done;
-
-    image_buf[utils::RBD_IMAGE_BANNER_V2.size()] = '\0';
-    if (strcmp(image_buf, utils::RBD_IMAGE_BANNER_V2.c_str())) {
-      // Old format
-      r = -EINVAL;
-      goto done;
-    }
 
-    r = safe_read_exact(fd, &size, 8);
-    if (r < 0) {
-      goto done;
-    }
-
-    // As V1 format for image is already deprecated, import image in V2 by default.
-    uint64_t image_format = 2;
-    if (opts.get(RBD_IMAGE_OPTION_FORMAT, &image_format) != 0) {
-      opts.set(RBD_IMAGE_OPTION_FORMAT, image_format);
-    }
-
-    while (1) {
-      __u8 tag;
-      r = safe_read_exact(fd, &tag, 1);
-      if (r < 0) {
-       goto done;
-      }
-
-      if (tag == RBD_EXPORT_IMAGE_END) {
-       break;
-      } else if (tag == RBD_EXPORT_IMAGE_ORDER) {
-       uint64_t order = 0;
-       r = safe_read_exact(fd, &order, 8);
-       if (r < 0) {
-         goto done;
-       }
-       if (opts.get(RBD_IMAGE_OPTION_ORDER, &order) != 0) {
-         opts.set(RBD_IMAGE_OPTION_ORDER, order);
-      } else if (tag == RBD_EXPORT_IMAGE_FEATURES) {
-       uint64_t features = 0;
-       r = safe_read_exact(fd, &features, 8);
-       if (r < 0) {
-         goto done;
-       }
-       if (opts.get(RBD_IMAGE_OPTION_FEATURES, &features) != 0) {
-         opts.set(RBD_IMAGE_OPTION_FEATURES, features);
-       }
-      } else if (tag == RBD_EXPORT_IMAGE_STRIPEUNIT) {
-       uint64_t stripe_unit = 0;
-       r = safe_read_exact(fd, &stripe_unit, 8);
-       if (r < 0) {
-         goto done;
-       }
-       if (opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit) != 0) {
-         opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit);
-       }
-      } else if (tag == RBD_EXPORT_IMAGE_STRIPECOUNT) {
-       uint64_t stripe_count = 0;
-       r = safe_read_exact(fd, &stripe_count, 8);
-       if (r < 0) {
-         goto done;
-       }
-       if (opts.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &stripe_count) != 0) {
-         opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count);
-       }
-      } else {
-       std::cerr << "rbd: invalid tag in image priority zone: " << tag << std::endl;
-       r = -EINVAL;
-       goto done;
-      }
-      //TODO, set the image options according flags and appending data.
-    }
+  r = do_import_header(fd, import_format, size, opts);
+  if (r < 0) {
+    std::cerr << "rbd: import header failed." << std::endl;
+    goto done;
   }
 
   r = rbd.create4(io_ctx, imgname, size, opts);
@@ -453,93 +577,12 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
     goto err;
   }
 
-  if (import_format == 2) {
-    char snap_buf[utils::RBD_IMAGE_SNAPS_BANNER_V2.size() + 1];
-
-    r = safe_read_exact(fd, snap_buf, utils::RBD_IMAGE_SNAPS_BANNER_V2.size());
-    if (r < 0)
-      goto done;
-    snap_buf[utils::RBD_IMAGE_SNAPS_BANNER_V2.size()] = '\0';
-    if (strcmp(snap_buf, utils::RBD_IMAGE_SNAPS_BANNER_V2.c_str())) {
-      cerr << "Incorrect RBD_IMAGE_SNAPS_BANNER." << std::endl;
-      return -EINVAL;
-    } else {
-      r = safe_read_exact(fd, &snap_num, 8);
-      if (r < 0) {
-        goto close;
-      }
-    }
-
-    for (size_t i = 0; i < snap_num; i++) {
-      r = do_import_diff_fd(image, fd, true, 2);
-      if (r < 0) {
-       pc.fail();
-       std::cerr << "rbd: import-diff failed: " << cpp_strerror(r) << std::endl;
-       return r;
-      }
-      pc.update_progress(i + 1, snap_num);
-    }
+  if (import_format == 1) {
+    r = do_import_v1(fd, image, size, imgblklen, throttle, pc);
   } else {
-    reqlen = min(reqlen, size);
-    // loop body handles 0 return, as we may have a block to flush
-    while ((readlen = ::read(fd, p + blklen, reqlen)) >= 0) {
-      if (throttle->pending_error()) {
-       break;
-      }
-
-      blklen += readlen;
-      // if read was short, try again to fill the block before writing
-      if (readlen && ((size_t)readlen < reqlen)) {
-       reqlen -= readlen;
-       continue;
-      }
-      if (!from_stdin)
-       pc.update_progress(image_pos, size);
-
-      bufferlist bl(blklen);
-      bl.append(p, blklen);
-      // resize output image by binary expansion as we go for stdin
-      if (from_stdin && (image_pos + (size_t)blklen) > size) {
-       size *= 2;
-       r = image.resize(size);
-       if (r < 0) {
-         std::cerr << "rbd: can't resize image during import" << std::endl;
-         goto close;
-       }
-      }
-
-      // write as much as we got; perhaps less than imgblklen
-      // but skip writing zeros to create sparse images
-      if (!bl.is_zero()) {
-       C_Import *ctx = new C_Import(*throttle, image, bl, image_pos);
-       ctx->send();
-      }
-
-      // done with whole block, whether written or not
-      image_pos += blklen;
-      if (!from_stdin && image_pos >= size)
-       break;
-      // if read had returned 0, we're at EOF and should quit
-      if (readlen == 0)
-       break;
-      blklen = 0;
-      reqlen = imgblklen;
-    }
-    r = throttle->wait_for_ret();
-    if (r < 0) {
-      goto close;
-    }
-
-    if (from_stdin) {
-      r = image.resize(image_pos);
-      if (r < 0) {
-       std::cerr << "rbd: final image resize failed" << std::endl;
-       goto close;
-      }
-    }
+    r = do_import_v2(fd, image, size, imgblklen, throttle, pc);
   }
 
-close:
   r = image.close();
 err:
   if (r < 0)
@@ -552,7 +595,6 @@ done:
   if (!from_stdin)
     close(fd);
 done2:
-  delete[] p;
   return r;
 }
 
@@ -627,8 +669,8 @@ int execute(const po::variables_map &vm) {
   }
 
   int format = 1;
-  if (vm.count("import-format"))
-    format = vm["import-format"].as<int>();
+  if (vm.count("export-format"))
+    format = vm["export-format"].as<uint64_t>();
 
   librbd::RBD rbd;
   r = do_import(rbd, io_ctx, image_name.c_str(), path.c_str(),