Skip to content

Commit 8914b25

Browse files
authored
Merge pull request ceph#58180 from guojidan/format
rbd: add the validate of the format and clone_format Reviewed-by: Ilya Dryomov <[email protected]>
2 parents a88356b + 165869f commit 8914b25

File tree

5 files changed

+185
-4
lines changed

5 files changed

+185
-4
lines changed

src/librbd/api/Image.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,8 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx,
570570
if (opts.get(RBD_IMAGE_OPTION_FORMAT, &format) != 0) {
571571
opts.set(RBD_IMAGE_OPTION_FORMAT, format);
572572
}
573-
if (format == 1) {
574-
lderr(cct) << "old format not supported for destination image" << dendl;
573+
if (format != 2) {
574+
lderr(cct) << "unsupported destination image format: " << format << dendl;
575575
return -EINVAL;
576576
}
577577
uint64_t stripe_unit = src->stripe_unit;

src/librbd/image/CloneRequest.cc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ void CloneRequest<I>::validate_options() {
8787

8888
uint64_t format = 0;
8989
m_opts.get(RBD_IMAGE_OPTION_FORMAT, &format);
90-
if (format < 2) {
91-
lderr(m_cct) << "format 2 or later required for clone" << dendl;
90+
if (format != 2) {
91+
lderr(m_cct) << "unsupported format for clone: " << format << dendl;
9292
complete(-EINVAL);
9393
return;
9494
}
@@ -124,6 +124,12 @@ void CloneRequest<I>::validate_options() {
124124
}
125125
}
126126

127+
if (m_clone_format < 1 || m_clone_format > 2) {
128+
lderr(m_cct) << "unsupported clone format: " << m_clone_format << dendl;
129+
complete(-EINVAL);
130+
return;
131+
}
132+
127133
if (m_clone_format == 1 &&
128134
m_parent_io_ctx.get_namespace() != m_ioctx.get_namespace()) {
129135
ldout(m_cct, 1) << "clone v2 required for cross-namespace clones" << dendl;

src/librbd/internal.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,11 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
638638
uint64_t format;
639639
if (opts.get(RBD_IMAGE_OPTION_FORMAT, &format) != 0)
640640
format = cct->_conf.get_val<uint64_t>("rbd_default_format");
641+
642+
if (format < 1 || format > 2) {
643+
lderr(cct) << "unsupported format: " << format << dendl;
644+
return -EINVAL;
645+
}
641646
bool old_format = format == 1;
642647

643648
// make sure it doesn't already exist, in either format

src/test/librbd/test_librbd.cc

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13625,6 +13625,171 @@ TEST_F(TestLibRBD, ConcurrentOperations)
1362513625
ioctx.close();
1362613626
}
1362713627

13628+
TEST_F(TestLibRBD, FormatAndCloneFormatOptions)
13629+
{
13630+
REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
13631+
13632+
librados::IoCtx ioctx;
13633+
ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx));
13634+
13635+
librbd::ImageOptions opts_with_0;
13636+
ASSERT_EQ(0, opts_with_0.set(RBD_IMAGE_OPTION_FORMAT, 0));
13637+
librbd::ImageOptions opts_with_1;
13638+
ASSERT_EQ(0, opts_with_1.set(RBD_IMAGE_OPTION_FORMAT, 1));
13639+
librbd::ImageOptions opts_with_2;
13640+
ASSERT_EQ(0, opts_with_2.set(RBD_IMAGE_OPTION_FORMAT, 2));
13641+
librbd::ImageOptions opts_with_3;
13642+
ASSERT_EQ(0, opts_with_3.set(RBD_IMAGE_OPTION_FORMAT, 3));
13643+
13644+
uint64_t features;
13645+
ASSERT_TRUE(get_features(&features));
13646+
ASSERT_EQ(0, opts_with_2.set(RBD_IMAGE_OPTION_FEATURES, features));
13647+
13648+
// create
13649+
librbd::RBD rbd;
13650+
std::string name1 = get_temp_image_name();
13651+
std::string name2 = get_temp_image_name();
13652+
auto do_create = [&rbd, &ioctx](const auto& name, const auto& opts) {
13653+
auto mod_opts = opts;
13654+
return rbd.create4(ioctx, name.c_str(), 2 << 20, mod_opts);
13655+
};
13656+
ASSERT_EQ(-EINVAL, do_create(name1, opts_with_0));
13657+
ASSERT_EQ(-EINVAL, do_create(name1, opts_with_3));
13658+
ASSERT_EQ(0, do_create(name1, opts_with_1));
13659+
auto verify_format_1 = [&rbd, &ioctx](const auto& name) {
13660+
librbd::Image image;
13661+
ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
13662+
uint8_t old_format;
13663+
ASSERT_EQ(0, image.old_format(&old_format));
13664+
ASSERT_TRUE(old_format);
13665+
};
13666+
ASSERT_NO_FATAL_FAILURE(verify_format_1(name1));
13667+
ASSERT_EQ(0, do_create(name2, opts_with_2));
13668+
auto verify_format_2 = [&rbd, &ioctx](const auto& name) {
13669+
librbd::Image image;
13670+
ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
13671+
uint8_t old_format;
13672+
ASSERT_EQ(0, image.old_format(&old_format));
13673+
ASSERT_FALSE(old_format);
13674+
};
13675+
ASSERT_NO_FATAL_FAILURE(verify_format_2(name2));
13676+
13677+
{
13678+
librbd::Image image;
13679+
ASSERT_EQ(0, rbd.open(ioctx, image, name2.c_str(), NULL));
13680+
ASSERT_EQ(0, image.snap_create("parent_snap"));
13681+
ASSERT_EQ(0, image.snap_protect("parent_snap"));
13682+
}
13683+
13684+
// clone
13685+
std::string clone_name1 = get_temp_image_name();
13686+
std::string clone_name2 = get_temp_image_name();
13687+
auto do_clone = [&rbd, &ioctx, &name2](const auto& clone_name,
13688+
const auto& opts) {
13689+
auto mod_opts = opts;
13690+
return rbd.clone3(ioctx, name2.c_str(), "parent_snap", ioctx,
13691+
clone_name.c_str(), mod_opts);
13692+
};
13693+
ASSERT_EQ(-EINVAL, do_clone(clone_name1, opts_with_0));
13694+
ASSERT_EQ(-EINVAL, do_clone(clone_name1, opts_with_1));
13695+
ASSERT_EQ(-EINVAL, do_clone(clone_name1, opts_with_3));
13696+
// if RBD_IMAGE_OPTION_CLONE_FORMAT isn't set, rbd_default_clone_format
13697+
// config option kicks in -- we aren't interested in its behavior here
13698+
ASSERT_EQ(0, do_clone(clone_name1, opts_with_2));
13699+
ASSERT_EQ(0, rbd.remove(ioctx, clone_name1.c_str()));
13700+
13701+
auto clone_opts_with_0 = opts_with_2;
13702+
ASSERT_EQ(0, clone_opts_with_0.set(RBD_IMAGE_OPTION_CLONE_FORMAT, 0));
13703+
auto clone_opts_with_1 = opts_with_2;
13704+
ASSERT_EQ(0, clone_opts_with_1.set(RBD_IMAGE_OPTION_CLONE_FORMAT, 1));
13705+
auto clone_opts_with_2 = opts_with_2;
13706+
ASSERT_EQ(0, clone_opts_with_2.set(RBD_IMAGE_OPTION_CLONE_FORMAT, 2));
13707+
auto clone_opts_with_3 = opts_with_2;
13708+
ASSERT_EQ(0, clone_opts_with_3.set(RBD_IMAGE_OPTION_CLONE_FORMAT, 3));
13709+
13710+
ASSERT_EQ(-EINVAL, do_clone(clone_name1, clone_opts_with_0));
13711+
ASSERT_EQ(-EINVAL, do_clone(clone_name1, clone_opts_with_3));
13712+
ASSERT_EQ(0, do_clone(clone_name1, clone_opts_with_1));
13713+
{
13714+
librbd::Image image;
13715+
ASSERT_EQ(0, rbd.open(ioctx, image, clone_name1.c_str(), NULL));
13716+
uint64_t op_features;
13717+
ASSERT_EQ(0, image.get_op_features(&op_features));
13718+
ASSERT_EQ(op_features, 0);
13719+
}
13720+
ASSERT_EQ(0, do_clone(clone_name2, clone_opts_with_2));
13721+
{
13722+
librbd::Image image;
13723+
ASSERT_EQ(0, rbd.open(ioctx, image, clone_name2.c_str(), NULL));
13724+
uint64_t op_features;
13725+
ASSERT_EQ(0, image.get_op_features(&op_features));
13726+
ASSERT_EQ(op_features, RBD_OPERATION_FEATURE_CLONE_CHILD);
13727+
}
13728+
13729+
librbd::Image image;
13730+
ASSERT_EQ(0, rbd.open(ioctx, image, name1.c_str(), NULL));
13731+
13732+
// copy
13733+
std::string copy_name1 = get_temp_image_name();
13734+
std::string copy_name2 = get_temp_image_name();
13735+
auto do_copy = [&image, &ioctx](const auto& copy_name, const auto& opts) {
13736+
auto mod_opts = opts;
13737+
return image.copy3(ioctx, copy_name.c_str(), mod_opts);
13738+
};
13739+
ASSERT_EQ(-EINVAL, do_copy(copy_name1, opts_with_0));
13740+
ASSERT_EQ(-EINVAL, do_copy(copy_name1, opts_with_3));
13741+
ASSERT_EQ(0, do_copy(copy_name1, opts_with_1));
13742+
ASSERT_NO_FATAL_FAILURE(verify_format_1(copy_name1));
13743+
ASSERT_EQ(0, do_copy(copy_name2, opts_with_2));
13744+
ASSERT_NO_FATAL_FAILURE(verify_format_2(copy_name2));
13745+
13746+
// deep copy
13747+
std::string deep_copy_name = get_temp_image_name();
13748+
auto do_deep_copy = [&image, &ioctx, &deep_copy_name](const auto& opts) {
13749+
auto mod_opts = opts;
13750+
return image.deep_copy(ioctx, deep_copy_name.c_str(), mod_opts);
13751+
};
13752+
ASSERT_EQ(-EINVAL, do_deep_copy(opts_with_0));
13753+
ASSERT_EQ(-EINVAL, do_deep_copy(opts_with_1));
13754+
ASSERT_EQ(-EINVAL, do_deep_copy(opts_with_3));
13755+
ASSERT_EQ(0, do_deep_copy(opts_with_2));
13756+
ASSERT_NO_FATAL_FAILURE(verify_format_2(deep_copy_name));
13757+
13758+
ASSERT_EQ(0, image.close());
13759+
13760+
// migration
13761+
std::string migrate_name = get_temp_image_name();
13762+
auto do_migrate = [&rbd, &ioctx, &name1, &migrate_name](const auto& opts) {
13763+
auto mod_opts = opts;
13764+
return rbd.migration_prepare(ioctx, name1.c_str(), ioctx,
13765+
migrate_name.c_str(), mod_opts);
13766+
};
13767+
ASSERT_EQ(-EINVAL, do_migrate(opts_with_0));
13768+
ASSERT_EQ(-EINVAL, do_migrate(opts_with_1));
13769+
ASSERT_EQ(-EINVAL, do_migrate(opts_with_3));
13770+
ASSERT_EQ(0, do_migrate(opts_with_2));
13771+
ASSERT_NO_FATAL_FAILURE(verify_format_2(migrate_name));
13772+
13773+
// import-only migration
13774+
std::string source_spec = R"({
13775+
"type": "native",
13776+
"pool_name": ")" + m_pool_name + R"(",
13777+
"image_name": ")" + name2 + R"(",
13778+
"snap_name": "parent_snap"
13779+
})";
13780+
std::string import_name = get_temp_image_name();
13781+
auto do_migrate_import = [&rbd, &ioctx, &source_spec, &import_name](
13782+
const auto& opts) {
13783+
auto mod_opts = opts;
13784+
return rbd.migration_prepare_import(source_spec.c_str(), ioctx,
13785+
import_name.c_str(), mod_opts);
13786+
};
13787+
ASSERT_EQ(-EINVAL, do_migrate_import(opts_with_0));
13788+
ASSERT_EQ(-EINVAL, do_migrate_import(opts_with_1));
13789+
ASSERT_EQ(-EINVAL, do_migrate_import(opts_with_3));
13790+
ASSERT_EQ(0, do_migrate_import(opts_with_2));
13791+
ASSERT_NO_FATAL_FAILURE(verify_format_2(import_name));
13792+
}
1362813793

1362913794
// poorman's ceph_assert()
1363013795
namespace ceph {

src/test/pybind/test_rbd.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,11 @@ def test_stripe_unit_and_count(self):
17301730

17311731
def test_clone_format(self):
17321732
clone_name2 = get_temp_image_name()
1733+
assert_raises(InvalidArgument, self.rbd.clone, ioctx, image_name,
1734+
'snap1', ioctx, clone_name2, features, clone_format=0)
1735+
assert_raises(InvalidArgument, self.rbd.clone, ioctx, image_name,
1736+
'snap1', ioctx, clone_name2, features, clone_format=3)
1737+
17331738
self.rbd.clone(ioctx, image_name, 'snap1', ioctx, clone_name2,
17341739
features, clone_format=1)
17351740
with Image(ioctx, clone_name2) as clone2:

0 commit comments

Comments
 (0)