rbd: refactor do_import_diff to accept fd.

Signed-off-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
This commit is contained in:
Dongsheng Yang 2016-10-11 07:18:07 -04:00
parent bc80b147ac
commit 58c8e8cd00

View File

@ -20,10 +20,10 @@
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;
@ -31,16 +31,8 @@ int do_import_diff(librbd::Image &image, const char *path,
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;
@ -53,7 +45,7 @@ int do_import_diff(librbd::Image &image, const char *path,
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;
}
@ -70,43 +62,43 @@ int do_import_diff(librbd::Image &image, const char *path,
} 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();
@ -114,17 +106,16 @@ int do_import_diff(librbd::Image &image, const char *path,
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();
@ -132,19 +123,19 @@ int do_import_diff(librbd::Image &image, const char *path,
::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;
}
@ -163,12 +154,33 @@ int do_import_diff(librbd::Image &image, const char *path,
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;
}