From: Dongsheng Yang Date: Wed, 2 Nov 2016 08:30:00 +0000 (-0400) Subject: rbd: import_diff/export_diff: encode length for each tag. X-Git-Tag: v12.0.1~342^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=435104a294cdb4dfa65a2a990d9115744f9cfc72;p=ceph.git rbd: import_diff/export_diff: encode length for each tag. Signed-off-by: Dongsheng Yang --- diff --git a/src/tools/rbd/action/Export.cc b/src/tools/rbd/action/Export.cc index 771db32279c1..b09cca65dfdc 100644 --- a/src/tools/rbd/action/Export.cc +++ b/src/tools/rbd/action/Export.cc @@ -21,13 +21,14 @@ namespace action { struct ExportDiffContext { librbd::Image *image; int fd; + int export_format; uint64_t totalsize; utils::ProgressContext pc; OrderedThrottle throttle; ExportDiffContext(librbd::Image *i, int f, uint64_t t, int max_ops, - bool no_progress) : - image(i), fd(f), totalsize(t), pc("Exporting image", no_progress), + bool no_progress, int eformat) : + image(i), fd(f), export_format(eformat), totalsize(t), pc("Exporting image", no_progress), throttle(max_ops, true) { } }; @@ -35,9 +36,9 @@ struct ExportDiffContext { class C_ExportDiff : public Context { public: C_ExportDiff(ExportDiffContext *edc, uint64_t offset, uint64_t length, - bool exists) + bool exists, int export_format) : m_export_diff_context(edc), m_offset(offset), m_length(length), - m_exists(exists) { + m_exists(exists), m_export_format(export_format) { } int send() { @@ -64,10 +65,10 @@ public: } static int export_diff_cb(uint64_t offset, size_t length, int exists, - void *arg) { + void *arg) { ExportDiffContext *edc = reinterpret_cast(arg); - C_ExportDiff *context = new C_ExportDiff(edc, offset, length, exists); + C_ExportDiff *context = new C_ExportDiff(edc, offset, length, exists, edc->export_format); return context->send(); } @@ -77,7 +78,7 @@ protected: if (m_exists) { m_exists = !m_read_data.is_zero(); } - r = write_extent(m_export_diff_context, m_offset, m_length, m_exists); + r = write_extent(m_export_diff_context, m_offset, m_length, m_exists, m_export_format); if (r == 0 && m_exists) { r = m_read_data.write_fd(m_export_diff_context->fd); } @@ -90,14 +91,23 @@ private: uint64_t m_offset; uint64_t m_length; bool m_exists; + int m_export_format; bufferlist m_read_data; static int write_extent(ExportDiffContext *edc, uint64_t offset, - uint64_t length, bool exists) { + uint64_t length, bool exists, int export_format) { // extent bufferlist bl; __u8 tag = exists ? RBD_DIFF_WRITE : RBD_DIFF_ZERO; + uint64_t len = 0; ::encode(tag, bl); + if (export_format == 2) { + if (tag == RBD_DIFF_WRITE) + len = 8 + 8 + length; + else + len = 8 + 8; + ::encode(len, bl); + } ::encode(offset, bl); ::encode(length, bl); int r = bl.write_fd(edc->fd); @@ -128,10 +138,15 @@ int do_export_diff_fd(librbd::Image& image, const char *fromsnapname, bl.append(utils::RBD_DIFF_BANNER_V2); __u8 tag; + uint64_t len = 0; if (fromsnapname) { tag = RBD_DIFF_FROM_SNAP; ::encode(tag, bl); std::string from(fromsnapname); + if (export_format == 2) { + len = from.length() + 4; + ::encode(len, bl); + } ::encode(from, bl); } @@ -139,12 +154,20 @@ int do_export_diff_fd(librbd::Image& image, const char *fromsnapname, tag = RBD_DIFF_TO_SNAP; ::encode(tag, bl); std::string to(endsnapname); + if (export_format == 2) { + len = to.length() + 4; + ::encode(len, bl); + } ::encode(to, bl); } tag = RBD_DIFF_IMAGE_SIZE; ::encode(tag, bl); uint64_t endsize = info.size; + if (export_format == 2) { + len = 8; + ::encode(len, bl); + } ::encode(endsize, bl); r = bl.write_fd(fd); @@ -153,7 +176,8 @@ int do_export_diff_fd(librbd::Image& image, const char *fromsnapname, } } ExportDiffContext edc(&image, fd, info.size, - g_conf->rbd_concurrent_management_ops, no_progress); + g_conf->rbd_concurrent_management_ops, no_progress, + export_format); r = image.diff_iterate2(fromsnapname, 0, info.size, true, whole_object, &C_ExportDiff::export_diff_cb, (void *)&edc); if (r < 0) { diff --git a/src/tools/rbd/action/Import.cc b/src/tools/rbd/action/Import.cc index 8dac188aebb6..42bbc87409fe 100644 --- a/src/tools/rbd/action/Import.cc +++ b/src/tools/rbd/action/Import.cc @@ -53,6 +53,7 @@ int do_import_diff_fd(librbd::Image &image, int fd, while (true) { __u8 tag; + uint64_t length = 0; r = safe_read_exact(fd, &tag, 1); if (r < 0) { goto done; @@ -60,85 +61,98 @@ int do_import_diff_fd(librbd::Image &image, int fd, if (tag == RBD_DIFF_END) { break; - } else if (tag == RBD_DIFF_FROM_SNAP) { - r = utils::read_string(fd, 4096, &from); // 4k limit to make sure we don't get a garbage string - if (r < 0) - goto done; - - bool exists; - r = image.snap_exists2(from.c_str(), &exists); - if (r < 0) - goto done; - - if (!exists) { - std::cerr << "start snapshot '" << from - << "' does not exist in the image, aborting" << std::endl; - r = -EINVAL; - goto done; - } - } - else if (tag == RBD_DIFF_TO_SNAP) { - r = utils::read_string(fd, 4096, &to); // 4k limit to make sure we don't get a garbage string - if (r < 0) - goto done; - - // verify this snap isn't already present - bool exists; - r = image.snap_exists2(to.c_str(), &exists); - if (r < 0) - goto done; - - if (exists) { - std::cerr << "end snapshot '" << to - << "' already exists, aborting" << std::endl; - r = -EEXIST; - goto done; + } else { + if (format == 2) { + r = safe_read_exact(fd, &length, 8); + if (r < 0) { + return r; + } } - } else if (tag == RBD_DIFF_IMAGE_SIZE) { - uint64_t end_size; - char buf[8]; - r = safe_read_exact(fd, buf, 8); - if (r < 0) - goto done; - bufferlist bl; - bl.append(buf, 8); - bufferlist::iterator p = bl.begin(); - ::decode(end_size, p); - uint64_t cur_size; - image.size(&cur_size); - if (cur_size != end_size) { - image.resize(end_size); + + if (tag == RBD_DIFF_FROM_SNAP) { + r = utils::read_string(fd, 4096, &from); // 4k limit to make sure we don't get a garbage string + if (r < 0) + goto done; + + bool exists; + r = image.snap_exists2(from.c_str(), &exists); + if (r < 0) + goto done; + + if (!exists) { + std::cerr << "start snapshot '" << from + << "' does not exist in the image, aborting" << std::endl; + r = -EINVAL; + goto done; + } } - if (from_stdin) - size = end_size; - } else if (tag == RBD_DIFF_WRITE || tag == RBD_DIFF_ZERO) { - uint64_t len; - char buf[16]; - r = safe_read_exact(fd, buf, 16); - if (r < 0) - goto done; - bufferlist bl; - bl.append(buf, 16); - bufferlist::iterator p = bl.begin(); - ::decode(off, p); - ::decode(len, p); - - if (tag == RBD_DIFF_WRITE) { - bufferptr bp = buffer::create(len); - r = safe_read_exact(fd, bp.c_str(), len); + else if (tag == RBD_DIFF_TO_SNAP) { + r = utils::read_string(fd, 4096, &to); // 4k limit to make sure we don't get a garbage string if (r < 0) goto done; - bufferlist data; - data.append(bp); - image.write2(off, len, data, LIBRADOS_OP_FLAG_FADVISE_NOCACHE); + + // verify this snap isn't already present + bool exists; + r = image.snap_exists2(to.c_str(), &exists); + if (r < 0) + goto done; + + if (exists) { + std::cerr << "end snapshot '" << to + << "' already exists, aborting" << std::endl; + r = -EEXIST; + goto done; + } + } else if (tag == RBD_DIFF_IMAGE_SIZE) { + uint64_t end_size; + char buf[8]; + r = safe_read_exact(fd, buf, 8); + if (r < 0) + goto done; + bufferlist bl; + bl.append(buf, 8); + bufferlist::iterator p = bl.begin(); + ::decode(end_size, p); + uint64_t cur_size; + image.size(&cur_size); + if (cur_size != end_size) { + image.resize(end_size); + } + if (from_stdin) + size = end_size; + } else if (tag == RBD_DIFF_WRITE || tag == RBD_DIFF_ZERO) { + uint64_t len; + char buf[16]; + r = safe_read_exact(fd, buf, 16); + if (r < 0) + goto done; + bufferlist bl; + bl.append(buf, 16); + bufferlist::iterator p = bl.begin(); + ::decode(off, p); + ::decode(len, p); + + if (tag == RBD_DIFF_WRITE) { + bufferptr bp = buffer::create(len); + r = safe_read_exact(fd, bp.c_str(), len); + if (r < 0) + goto done; + bufferlist data; + data.append(bp); + image.write2(off, len, data, LIBRADOS_OP_FLAG_FADVISE_NOCACHE); + } else { + image.discard(off, len); + } } else { - image.discard(off, len); + std::cerr << "unrecognized tag byte " << (int)tag + << " in stream; aborting" << std::endl; + if (format == 2) { + ::lseek(fd, length, SEEK_CUR); + } else { + r = -EINVAL; + goto done; + } } - } else { - std::cerr << "unrecognized tag byte " << (int)tag - << " in stream; aborting" << std::endl; - r = -EINVAL; - goto done; } if (!from_stdin) { // progress through input