namespace rbd {
namespace action {
-int do_import_diff(librbd::Image &image, const char *path,
- bool no_progress)
+int do_import_diff_fd(librbd::Image &image, int fd,
+ bool no_progress)
{
- int fd, r;
+ int r;
struct stat stat_buf;
utils::ProgressContext pc("Importing image diff", no_progress);
uint64_t size = 0;
string from, to;
char buf[utils::RBD_DIFF_BANNER.size() + 1];
- bool from_stdin = !strcmp(path, "-");
- if (from_stdin) {
- fd = 0;
- } else {
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- r = -errno;
- std::cerr << "rbd: error opening " << path << std::endl;
- return r;
- }
+ bool from_stdin = (fd == 0);
+ if (!from_stdin) {
r = ::fstat(fd, &stat_buf);
if (r < 0)
goto done;
buf[utils::RBD_DIFF_BANNER.size()] = '\0';
if (strcmp(buf, utils::RBD_DIFF_BANNER.c_str())) {
std::cerr << "invalid banner '" << buf << "', expected '"
- << utils::RBD_DIFF_BANNER << "'" << std::endl;
+ << utils::RBD_DIFF_BANNER << "'" << std::endl;
r = -EINVAL;
goto done;
}
} 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;
+ goto done;
bool exists;
r = image.snap_exists2(from.c_str(), &exists);
if (r < 0)
- goto done;
+ goto done;
if (!exists) {
- std::cerr << "start snapshot '" << from
- << "' does not exist in the image, aborting" << std::endl;
- r = -EINVAL;
- goto done;
+ 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;
+ goto done;
// verify this snap isn't already present
bool exists;
r = image.snap_exists2(to.c_str(), &exists);
if (r < 0)
- goto done;
+ goto done;
if (exists) {
- std::cerr << "end snapshot '" << to
- << "' already exists, aborting" << std::endl;
- r = -EEXIST;
- goto done;
+ 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;
+ goto done;
bufferlist bl;
bl.append(buf, 8);
bufferlist::iterator p = bl.begin();
uint64_t cur_size;
image.size(&cur_size);
if (cur_size != end_size) {
- image.resize(end_size);
- } else {
+ image.resize(end_size);
}
if (from_stdin)
- size = end_size;
+ 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;
+ goto done;
bufferlist bl;
bl.append(buf, 16);
bufferlist::iterator p = bl.begin();
::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);
+ 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);
+ image.discard(off, len);
}
} else {
std::cerr << "unrecognized tag byte " << (int)tag
- << " in stream; aborting" << std::endl;
+ << " in stream; aborting" << std::endl;
r = -EINVAL;
goto done;
}
r = image.snap_create(to.c_str());
}
- done:
+done:
if (r < 0)
pc.fail();
else
pc.finish();
- if (!from_stdin)
+ return r;
+}
+
+int do_import_diff(librbd::Image &image, const char *path,
+ bool no_progress)
+{
+ int r;
+ int fd;
+
+ if (strcmp(path, "-") == 0) {
+ fd = 0;
+ } else {
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ r = -errno;
+ std::cerr << "rbd: error opening " << path << std::endl;
+ return r;
+ }
+ }
+ r = do_import_diff_fd(image, fd, no_progress);
+
+ if (fd != 0)
close(fd);
return r;
}