]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: fix import from stdin, add test
authorDan Mick <dan.mick@inktank.com>
Wed, 28 Nov 2012 00:54:43 +0000 (16:54 -0800)
committerSage Weil <sage@inktank.com>
Wed, 28 Nov 2012 19:45:31 +0000 (11:45 -0800)
Make import work; do I/O in image native block size.
Note: creating sparse images is not currently attempted; could
scan for runs of zeros and write discontiguous chunks to image.

Fixes: #3503
Signed-off-by: Dan Mick <dan.mick@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
(cherry picked from commit c99d9c3ae782597984f0c67dd1488fb95bd2ce54)

qa/workunits/rbd/import_export.sh
src/rbd.cc

index 7e794f46c9e97ecdfcb0c370c8d6927374b844bb..e6d14d0884ae3f31bcae2356513676907222fa17 100755 (executable)
@@ -18,8 +18,14 @@ cmp /tmp/img /tmp/img2
 cmp /tmp/img /tmp/img3
 rm /tmp/img2 /tmp/img3
 
+# try again, importing from stdin
+rbd import $RBD_CREATE_ARGS - testimg < /tmp/img
+rbd export testimg /tmp/img2
+rbd export testimg - > /tmp/img3
+rbd rm testimg
 cmp /tmp/img /tmp/img2
+cmp /tmp/img /tmp/img3
 
-rm /tmp/img /tmp/img2
+rm /tmp/img /tmp/img2 /tmp/img3
 
 echo OK
index cf805211a0b633c8f5f1b2e3e2961e195b4efcdf..a68efb10d85a009ed5166d6ed048c6d0fe4b0e91 100644 (file)
@@ -811,6 +811,58 @@ done_img:
   update_snap_name(*new_img, snap);
 }
 
+static int do_import_from_stdin(librbd::RBD &rbd, librados::IoCtx& io_ctx,
+                               const char *imgname, int *order, int format,
+                               int64_t features, int64_t size)
+{
+  int r;
+  // start with inherent block size; double as needed; fix when done
+  size_t cur_size = 1 << *order;
+
+  r = do_create(rbd, io_ctx, imgname, cur_size, order, format, features, 0, 0);
+  if (r < 0) {
+    cerr << "rbd: image creation failed" << std::endl;
+    return r;
+  }
+  librbd::Image image;
+  r = rbd.open(io_ctx, image, imgname);
+  if (r < 0) {
+    cerr << "rbd: failed to open image" << std::endl;
+    return r;
+  }
+
+  size_t readlen;
+  off_t file_pos = 0;
+
+  size_t len = 1 << *order;
+  bufferptr p(len);
+
+  while ((readlen = ::read(0, p.c_str(), len)) > 0) {
+    bufferlist bl;
+    bl.append(p);
+    if ((file_pos + readlen) > cur_size) {
+      cur_size *= 2;
+      r = image.resize(cur_size);
+      if (r < 0) {
+       cerr << "rbd: can't resize image during import" << std::endl;
+       return r;
+      }
+    }
+    r = image.write(file_pos, readlen, bl);
+    if (r < 0) {
+      cerr << "rbd: error writing to image block" << std::endl;
+      return r;
+    }
+    file_pos += readlen;
+  }
+  r = image.resize(file_pos);
+  if (r < 0) {
+    cerr << "rbd: final image resize failed" << std::endl;
+    return r;
+  }
+  return readlen;      // 0 or error
+}
+
 static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
                     const char *imgname, int *order, const char *path,
                     int format, uint64_t features, int64_t size)
@@ -820,11 +872,16 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
   struct fiemap *fiemap;
   MyProgressContext pc("Importing image");
 
-  if (! strcmp(path, "-")) {
-    fd = 0;
-  } else {
-    fd = open(path, O_RDONLY);
-  }
+  assert(imgname);
+
+  // default order as usual
+  if (*order == 0)
+    *order = 22;
+
+  if (!strcmp(path, "-"))
+    return do_import_from_stdin(rbd, io_ctx, imgname, order, format,
+                               features, size);
+  fd = open(path, O_RDONLY);
 
   if (fd < 0) {
     r = -errno;
@@ -852,8 +909,6 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
     }
   }
 
-  assert(imgname);
-
   r = do_create(rbd, io_ctx, imgname, size, order, format, features, 0, 0);
   if (r < 0) {
     cerr << "rbd: image creation failed" << std::endl;
@@ -867,6 +922,7 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
     close(fd);
     return r;
   }
+
   fsync(fd); /* flush it first, otherwise extents information might not have been flushed yet */
   fiemap = read_fiemap(fd);
   if (fiemap && !fiemap->fm_mapped_extents) {
@@ -897,6 +953,7 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
   while (extent < fiemap->fm_mapped_extents) {
     off_t file_pos, end_ofs;
     size_t extent_len = 0;
+    size_t read_len = 1ULL << *order;
 
     file_pos = fiemap->fm_extents[extent].fe_logical; /* position within the file we're reading */
 
@@ -915,11 +972,10 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
 
     } while (end_ofs == (off_t)fiemap->fm_extents[extent].fe_logical);
 
-#define READ_BLOCK_LEN (4 * 1024 * 1024)
     uint64_t left = end_ofs - file_pos;
     while (left) {
       pc.update_progress(file_pos, size);
-      uint64_t cur_seg = (left < READ_BLOCK_LEN ? left : READ_BLOCK_LEN);
+      uint64_t cur_seg = (left < read_len ? left : read_len);
       while (cur_seg) {
         bufferptr p(cur_seg);
        ssize_t rval;
@@ -945,7 +1001,7 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx,
           r = -ENOMEM;
           goto done;
         }
-        r = image.aio_write(file_pos, len, bl, completion);
+       r = image.aio_write(file_pos, len, bl, completion);
         if (r < 0)
           goto done;
        completion->wait_for_complete();