return nullptr;
}
- m_image_ctx->init_layout();
+ send_v2_get_data_pool();
+ return nullptr;
+}
+
+template <typename I>
+void OpenRequest<I>::send_v2_get_data_pool() {
+ CephContext *cct = m_image_ctx->cct;
+ ldout(cct, 10) << this << " " << __func__ << dendl;
+ librados::ObjectReadOperation op;
+ cls_client::get_data_pool_start(&op);
+
+ using klass = OpenRequest<I>;
+ librados::AioCompletion *comp = create_rados_ack_callback<
+ klass, &klass::handle_v2_get_data_pool>(this);
+ m_out_bl.clear();
+ m_image_ctx->md_ctx.aio_operate(m_image_ctx->header_oid, comp, &op,
+ &m_out_bl);
+ comp->release();
+}
+
+template <typename I>
+Context *OpenRequest<I>::handle_v2_get_data_pool(int *result) {
+ CephContext *cct = m_image_ctx->cct;
+ ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
+
+ int64_t data_pool_id = -1;
+ if (*result == 0) {
+ bufferlist::iterator it = m_out_bl.begin();
+ *result = cls_client::get_data_pool_finish(&it, &data_pool_id);
+ } else if (*result == -ENOEXEC) {
+ *result = 0;
+ }
+
+ if (*result < 0) {
+ lderr(cct) << "failed to read data pool: " << cpp_strerror(*result)
+ << dendl;
+ send_close_image(*result);
+ return nullptr;
+ }
+
+ if (data_pool_id != -1) {
+ librados::Rados rados(m_image_ctx->md_ctx);
+ *result = rados.ioctx_create2(data_pool_id, m_image_ctx->data_ctx);
+ if (*result < 0) {
+ lderr(cct) << "failed to initialize data pool IO context: "
+ << cpp_strerror(*result) << dendl;
+ send_close_image(*result);
+ return nullptr;
+ }
+ }
+
+ m_image_ctx->init_layout();
send_v2_apply_metadata();
return nullptr;
}
rados_ioctx_destroy(ioctx);
}
+TEST_F(TestLibRBD, TestDataPoolIO)
+{
+ REQUIRE_FORMAT_V2();
+
+ rados_ioctx_t ioctx;
+ rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx);
+
+ std::string data_pool_name = create_pool(true);
+
+ CephContext* cct = reinterpret_cast<CephContext*>(_rados.cct());
+ bool skip_discard = cct->_conf->rbd_skip_partial_discard;
+
+ rbd_image_t image;
+ std::string name = get_temp_image_name();
+ uint64_t size = 2 << 20;
+
+ bool old_format;
+ uint64_t features;
+ ASSERT_EQ(0, get_features(&old_format, &features));
+ ASSERT_FALSE(old_format);
+
+ rbd_image_options_t image_options;
+ rbd_image_options_create(&image_options);
+ BOOST_SCOPE_EXIT( (&image_options) ) {
+ rbd_image_options_destroy(image_options);
+ } BOOST_SCOPE_EXIT_END;
+
+ ASSERT_EQ(0, rbd_image_options_set_uint64(image_options,
+ RBD_IMAGE_OPTION_FEATURES,
+ features));
+ ASSERT_EQ(0, rbd_image_options_set_string(image_options,
+ RBD_IMAGE_OPTION_DATA_POOL,
+ data_pool_name.c_str()));
+
+ ASSERT_EQ(0, rbd_create4(ioctx, name.c_str(), size, image_options));
+ ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
+ ASSERT_NE(-1, rbd_get_data_pool_id(image));
+
+ char test_data[TEST_IO_SIZE + 1];
+ char zero_data[TEST_IO_SIZE + 1];
+ int i;
+
+ for (i = 0; i < TEST_IO_SIZE; ++i) {
+ test_data[i] = (char) (rand() % (126 - 33) + 33);
+ }
+ test_data[TEST_IO_SIZE] = '\0';
+ memset(zero_data, 0, sizeof(zero_data));
+
+ for (i = 0; i < 5; ++i)
+ ASSERT_PASSED(write_test_data, image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE, 0);
+
+ for (i = 5; i < 10; ++i)
+ ASSERT_PASSED(aio_write_test_data, image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE, 0);
+
+ for (i = 0; i < 5; ++i)
+ ASSERT_PASSED(read_test_data, image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE, 0);
+
+ for (i = 5; i < 10; ++i)
+ ASSERT_PASSED(aio_read_test_data, image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE, 0);
+
+ // discard 2nd, 4th sections.
+ ASSERT_PASSED(discard_test_data, image, TEST_IO_SIZE, TEST_IO_SIZE);
+ ASSERT_PASSED(aio_discard_test_data, image, TEST_IO_SIZE*3, TEST_IO_SIZE);
+
+ ASSERT_PASSED(read_test_data, image, test_data, 0, TEST_IO_SIZE, 0);
+ ASSERT_PASSED(read_test_data, image, skip_discard ? test_data : zero_data,
+ TEST_IO_SIZE, TEST_IO_SIZE, 0);
+ ASSERT_PASSED(read_test_data, image, test_data, TEST_IO_SIZE*2, TEST_IO_SIZE, 0);
+ ASSERT_PASSED(read_test_data, image, skip_discard ? test_data : zero_data,
+ TEST_IO_SIZE*3, TEST_IO_SIZE, 0);
+ ASSERT_PASSED(read_test_data, image, test_data, TEST_IO_SIZE*4, TEST_IO_SIZE, 0);
+
+ rbd_image_info_t info;
+ rbd_completion_t comp;
+ ASSERT_EQ(0, rbd_stat(image, &info, sizeof(info)));
+ // can't read or write starting past end
+ ASSERT_EQ(-EINVAL, rbd_write(image, info.size, 1, test_data));
+ ASSERT_EQ(-EINVAL, rbd_read(image, info.size, 1, test_data));
+ // reading through end returns amount up to end
+ ASSERT_EQ(10, rbd_read(image, info.size - 10, 100, test_data));
+ // writing through end returns amount up to end
+ ASSERT_EQ(10, rbd_write(image, info.size - 10, 100, test_data));
+
+ rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
+ ASSERT_EQ(0, rbd_aio_write(image, info.size, 1, test_data, comp));
+ ASSERT_EQ(0, rbd_aio_wait_for_complete(comp));
+ ASSERT_EQ(-EINVAL, rbd_aio_get_return_value(comp));
+ rbd_aio_release(comp);
+
+ rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
+ ASSERT_EQ(0, rbd_aio_read(image, info.size, 1, test_data, comp));
+ ASSERT_EQ(0, rbd_aio_wait_for_complete(comp));
+ ASSERT_EQ(-EINVAL, rbd_aio_get_return_value(comp));
+ rbd_aio_release(comp);
+
+ ASSERT_PASSED(validate_object_map, image);
+ ASSERT_EQ(0, rbd_close(image));
+
+ rados_ioctx_destroy(ioctx);
+}
TEST_F(TestLibRBD, TestEmptyDiscard)
{
rados_ioctx_t ioctx;