]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: allow export to stdout, add tests
authorDan Mick <dan.mick@inktank.com>
Wed, 28 Nov 2012 01:06:43 +0000 (17:06 -0800)
committerSage Weil <sage@inktank.com>
Wed, 28 Nov 2012 19:45:27 +0000 (11:45 -0800)
Fixes: #3502
Signed-off-by: Dan Mick <dan.mick@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
(cherry picked from commit a738f44bc4e23c8ad18f24a835fe253d5b27b9d9)

qa/workunits/rbd/import_export.sh
src/rbd.cc
src/test/cli/rbd/help.t

index 005044ab0783ca55263d9d219c6badc976740092..7e794f46c9e97ecdfcb0c370c8d6927374b844bb 100755 (executable)
@@ -12,8 +12,11 @@ rbd rm testimg || true
 
 rbd import $RBD_CREATE_ARGS /tmp/img testimg
 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/img2 /tmp/img3
 
 cmp /tmp/img /tmp/img2
 
index ecdcfbe2ad073eebf296b6be5270b5cf1c2fc037..cf805211a0b633c8f5f1b2e3e2961e195b4efcdf 100644 (file)
@@ -82,9 +82,11 @@ void usage()
 "  resize --size <MB> <image-name>             resize (expand or contract) image\n"
 "  rm <image-name>                             delete an image\n"
 "  export <image-name> <path>                  export image to file\n"
+"                                              \"-\" for stdout\n"
 "  import <path> <image-name>                  import image from file\n"
-"                                              (dest defaults)\n"
-"                                              as the filename part of file)\n"
+"                                              (dest defaults\n"
+"                                               as the filename part of file)\n"
+"                                              \"-\" for stdin\n"
 "  (cp | copy) <src> <dest>                    copy src image to dest\n"
 "  (mv | rename) <src> <dest>                  rename src image to dest\n"
 "  snap ls <image-name>                        dump list of image snapshots\n"
@@ -671,14 +673,45 @@ static int export_read_cb(uint64_t ofs, size_t len, const char *buf, void *arg)
   ssize_t ret;
   ExportContext *ec = (ExportContext *)arg;
   int fd = ec->fd;
+  static char *localbuf = NULL;
+  static size_t maplen = 0;
+
+  if (fd == 1) {
+    if (!buf) {
+      // can't seek stdout; need actual data to write
+      if (maplen < len) {
+       // never mapped, or need to map larger
+       int r;
+       if (localbuf != NULL){
+         if ((r = munmap(localbuf, len)) < 0) {
+           cerr << "rbd: error " << r << "munmap'ing buffer" << std::endl;
+           return errno;
+         }
+       }
 
-  if (!buf) /* a hole */
-    return 0;
+       maplen = len;
+       localbuf = (char *)mmap(NULL, maplen, PROT_READ,
+                               MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+       if (localbuf == MAP_FAILED) {
+         cerr << "rbd: MAP_FAILED mmap'ing buffer for zero writes"
+              << std::endl;
+         return -ENOMEM;
+       }
+      }
+      ret = write(fd, localbuf, len);
+    } else {
+      ret = write(fd, buf, len);
+    }
+  } else {             // not stdout
+    if (!buf) /* a hole */
+      return 0;
+
+    ret = lseek64(fd, ofs, SEEK_SET);
+    if (ret < 0)
+      return -errno;
+    ret = write(fd, buf, len);
+  }
 
-  ret = lseek64(fd, ofs, SEEK_SET);
-  if (ret < 0)
-    return -errno;
-  ret = write(fd, buf, len);
   if (ret < 0)
     return -errno;
 
@@ -696,7 +729,10 @@ static int do_export(librbd::Image& image, const char *path)
   if (r < 0)
     return r;
 
-  fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644);
+  if (strcmp(path, "-") == 0)
+    fd = 1;
+  else
+    fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644);
   if (fd < 0)
     return -errno;
 
@@ -705,7 +741,8 @@ static int do_export(librbd::Image& image, const char *path)
   if (r < 0)
     goto out;
 
-  r = ftruncate(fd, info.size);
+  if (fd != 1)
+    r = ftruncate(fd, info.size);
   if (r < 0)
     goto out;
 
index 3e81b3d9c6e9687ed47744368698d5ecbab23b13..e1f6a2f9ecd5263c4b299868ef59e0cb208b7926 100644 (file)
     resize --size <MB> <image-name>             resize (expand or contract) image
     rm <image-name>                             delete an image
     export <image-name> <path>                  export image to file
+                                                "-" for stdout
     import <path> <image-name>                  import image from file
-                                                (dest defaults)
-                                                as the filename part of file)
+                                                (dest defaults
+                                                 as the filename part of file)
+                                                "-" for stdin
     (cp | copy) <src> <dest>                    copy src image to dest
     (mv | rename) <src> <dest>                  rename src image to dest
     snap ls <image-name>                        dump list of image snapshots