From: Dan Mick Date: Wed, 28 Nov 2012 01:06:43 +0000 (-0800) Subject: rbd: allow export to stdout, add tests X-Git-Tag: v0.56~172 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a738f44bc4e23c8ad18f24a835fe253d5b27b9d9;p=ceph.git rbd: allow export to stdout, add tests Fixes: #3502 Signed-off-by: Dan Mick Reviewed-by: Josh Durgin --- diff --git a/qa/workunits/rbd/import_export.sh b/qa/workunits/rbd/import_export.sh index 005044ab0783..7e794f46c9e9 100755 --- a/qa/workunits/rbd/import_export.sh +++ b/qa/workunits/rbd/import_export.sh @@ -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 diff --git a/src/rbd.cc b/src/rbd.cc index ecdcfbe2ad07..cf805211a0b6 100644 --- a/src/rbd.cc +++ b/src/rbd.cc @@ -82,9 +82,11 @@ void usage() " resize --size resize (expand or contract) image\n" " rm delete an image\n" " export export image to file\n" +" \"-\" for stdout\n" " import 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) copy src image to dest\n" " (mv | rename) rename src image to dest\n" " snap ls 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; diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index 3e81b3d9c6e9..e1f6a2f9ecd5 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -15,9 +15,11 @@ resize --size resize (expand or contract) image rm delete an image export export image to file + "-" for stdout import import image from file - (dest defaults) - as the filename part of file) + (dest defaults + as the filename part of file) + "-" for stdin (cp | copy) copy src image to dest (mv | rename) rename src image to dest snap ls dump list of image snapshots