From 80c506d4b95cd76feecea8fea9de4fbbf4310368 Mon Sep 17 00:00:00 2001 From: Dan Mick Date: Tue, 27 Nov 2012 16:54:43 -0800 Subject: [PATCH] rbd: fix import from stdin, add test 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 Reviewed-by: Josh Durgin (cherry picked from commit c99d9c3ae782597984f0c67dd1488fb95bd2ce54) --- qa/workunits/rbd/import_export.sh | 8 +++- src/rbd.cc | 76 +++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/qa/workunits/rbd/import_export.sh b/qa/workunits/rbd/import_export.sh index 7e794f46c9e97..e6d14d0884ae3 100755 --- a/qa/workunits/rbd/import_export.sh +++ b/qa/workunits/rbd/import_export.sh @@ -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 diff --git a/src/rbd.cc b/src/rbd.cc index cf805211a0b63..a68efb10d85a0 100644 --- a/src/rbd.cc +++ b/src/rbd.cc @@ -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(); -- 2.39.5