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) {
}
};
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() {
}
static int export_diff_cb(uint64_t offset, size_t length, int exists,
- void *arg) {
+ void *arg) {
ExportDiffContext *edc = reinterpret_cast<ExportDiffContext *>(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();
}
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);
}
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);
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);
}
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);
}
}
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) {
while (true) {
__u8 tag;
+ uint64_t length = 0;
r = safe_read_exact(fd, &tag, 1);
if (r < 0) {
goto done;
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