1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License version 2, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "include/int_types.h"
16 #include "include/rados/librados.h"
17 #include "include/rbd_types.h"
18 #include "include/rbd/librbd.h"
19 #include "include/rbd/librbd.hpp"
20 #include "include/event_type.h"
21 #include "include/err.h"
23 #include "gtest/gtest.h"
29 #include <sys/types.h>
35 #include <condition_variable>
43 #include "test/librados/test.h"
44 #include "test/librbd/test_support.h"
45 #include "common/event_socket.h"
46 #include "include/interval_set.h"
47 #include "include/stringify.h"
49 #include <boost/assign/list_of.hpp>
50 #include <boost/scope_exit.hpp>
53 #include <sys/eventfd.h>
58 using std::chrono::seconds
;
60 #define ASSERT_PASSED(x, args...) \
62 bool passed = false; \
64 ASSERT_TRUE(passed); \
67 void register_test_librbd() {
70 static int get_features(bool *old_format
, uint64_t *features
)
72 const char *c
= getenv("RBD_FEATURES");
80 cout
<< "using new format!" << std::endl
;
84 cout
<< "using old format" << std::endl
;
90 static int create_image_full(rados_ioctx_t ioctx
, const char *name
,
91 uint64_t size
, int *order
, int old_format
,
95 // ensure old-format tests actually use the old format
96 int r
= rados_conf_set(rados_ioctx_get_cluster(ioctx
),
97 "rbd_default_format", "1");
101 return rbd_create(ioctx
, name
, size
, order
);
102 } else if ((features
& RBD_FEATURE_STRIPINGV2
) != 0) {
103 uint64_t stripe_unit
= IMAGE_STRIPE_UNIT
;
105 // use a conservative stripe_unit for non default order
106 stripe_unit
= (1ull << (*order
-1));
109 printf("creating image with stripe unit: %" PRIu64
", "
110 "stripe count: %" PRIu64
"\n",
111 stripe_unit
, IMAGE_STRIPE_COUNT
);
112 return rbd_create3(ioctx
, name
, size
, features
, order
,
113 stripe_unit
, IMAGE_STRIPE_COUNT
);
115 return rbd_create2(ioctx
, name
, size
, features
, order
);
119 static int clone_image(rados_ioctx_t p_ioctx
,
120 rbd_image_t p_image
, const char *p_name
,
121 const char *p_snap_name
, rados_ioctx_t c_ioctx
,
122 const char *c_name
, uint64_t features
, int *c_order
)
124 uint64_t stripe_unit
, stripe_count
;
127 r
= rbd_get_stripe_unit(p_image
, &stripe_unit
);
132 r
= rbd_get_stripe_count(p_image
, &stripe_count
);
137 return rbd_clone2(p_ioctx
, p_name
, p_snap_name
, c_ioctx
,
138 c_name
, features
, c_order
, stripe_unit
, stripe_count
);
142 static int create_image(rados_ioctx_t ioctx
, const char *name
,
143 uint64_t size
, int *order
)
148 int r
= get_features(&old_format
, &features
);
151 return create_image_full(ioctx
, name
, size
, order
, old_format
, features
);
154 static int create_image_pp(librbd::RBD
&rbd
,
155 librados::IoCtx
&ioctx
,
157 uint64_t size
, int *order
) {
160 int r
= get_features(&old_format
, &features
);
164 librados::Rados
rados(ioctx
);
165 int r
= rados
.conf_set("rbd_default_format", "1");
169 return rbd
.create(ioctx
, name
, size
, order
);
171 return rbd
.create2(ioctx
, name
, size
, features
, order
);
175 class TestLibRBD
: public ::testing::Test
{
178 TestLibRBD() : m_pool_number() {
181 static void SetUpTestCase() {
182 static bool seeded
= false;
186 cout
<< "seed " << seed
<< std::endl
;
191 _unique_pool_names
.clear();
193 ASSERT_EQ("", connect_cluster(&_cluster
));
194 ASSERT_EQ("", connect_cluster_pp(_rados
));
196 create_optional_data_pool();
199 static void TearDownTestCase() {
200 rados_shutdown(_cluster
);
201 _rados
.wait_for_latest_osdmap();
202 _pool_names
.insert(_pool_names
.end(), _unique_pool_names
.begin(),
203 _unique_pool_names
.end());
204 for (size_t i
= 1; i
< _pool_names
.size(); ++i
) {
205 ASSERT_EQ(0, _rados
.pool_delete(_pool_names
[i
].c_str()));
207 if (!_pool_names
.empty()) {
208 ASSERT_EQ(0, destroy_one_pool_pp(_pool_names
[0], _rados
));
212 void SetUp() override
{
213 ASSERT_NE("", m_pool_name
= create_pool());
216 bool is_skip_partial_discard_enabled() {
218 EXPECT_EQ(0, _rados
.conf_get("rbd_skip_partial_discard", value
));
219 return value
== "true";
222 void validate_object_map(rbd_image_t image
, bool *passed
) {
224 ASSERT_EQ(0, rbd_get_flags(image
, &flags
));
225 *passed
= ((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) == 0);
228 void validate_object_map(librbd::Image
&image
, bool *passed
) {
230 ASSERT_EQ(0, image
.get_flags(&flags
));
231 *passed
= ((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) == 0);
234 std::string
get_temp_image_name() {
236 return "image" + stringify(_image_number
);
239 static void create_optional_data_pool() {
240 bool created
= false;
241 std::string data_pool
;
242 ASSERT_EQ(0, create_image_data_pool(_rados
, data_pool
, &created
));
243 if (!data_pool
.empty()) {
244 printf("using image data pool: %s\n", data_pool
.c_str());
246 _unique_pool_names
.push_back(data_pool
);
251 std::string
create_pool(bool unique
= false) {
252 librados::Rados rados
;
253 std::string pool_name
;
255 pool_name
= get_temp_pool_name("test-librbd-");
256 EXPECT_EQ("", create_one_pool_pp(pool_name
, rados
));
257 _unique_pool_names
.push_back(pool_name
);
258 } else if (m_pool_number
< _pool_names
.size()) {
259 pool_name
= _pool_names
[m_pool_number
];
261 pool_name
= get_temp_pool_name("test-librbd-");
262 EXPECT_EQ("", create_one_pool_pp(pool_name
, rados
));
263 _pool_names
.push_back(pool_name
);
269 static std::vector
<std::string
> _pool_names
;
270 static std::vector
<std::string
> _unique_pool_names
;
271 static rados_t _cluster
;
272 static librados::Rados _rados
;
273 static uint64_t _image_number
;
275 std::string m_pool_name
;
276 uint32_t m_pool_number
;
280 std::vector
<std::string
> TestLibRBD::_pool_names
;
281 std::vector
<std::string
> TestLibRBD::_unique_pool_names
;
282 rados_t
TestLibRBD::_cluster
;
283 librados::Rados
TestLibRBD::_rados
;
284 uint64_t TestLibRBD::_image_number
= 0;
286 TEST_F(TestLibRBD
, CreateAndStat
)
289 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
291 rbd_image_info_t info
;
294 std::string name
= get_temp_image_name();
295 uint64_t size
= 2 << 20;
297 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
298 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
299 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
300 printf("image has size %llu and order %d\n", (unsigned long long) info
.size
, info
.order
);
301 ASSERT_EQ(info
.size
, size
);
302 ASSERT_EQ(info
.order
, order
);
303 ASSERT_EQ(0, rbd_close(image
));
305 rados_ioctx_destroy(ioctx
);
308 TEST_F(TestLibRBD
, CreateWithSameDataPool
)
313 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
316 std::string name
= get_temp_image_name();
317 uint64_t size
= 2 << 20;
321 ASSERT_EQ(0, get_features(&old_format
, &features
));
322 ASSERT_FALSE(old_format
);
324 rbd_image_options_t image_options
;
325 rbd_image_options_create(&image_options
);
326 BOOST_SCOPE_EXIT( (&image_options
) ) {
327 rbd_image_options_destroy(image_options
);
328 } BOOST_SCOPE_EXIT_END
;
330 ASSERT_EQ(0, rbd_image_options_set_uint64(image_options
,
331 RBD_IMAGE_OPTION_FEATURES
,
333 ASSERT_EQ(0, rbd_image_options_set_string(image_options
,
334 RBD_IMAGE_OPTION_DATA_POOL
,
335 m_pool_name
.c_str()));
337 ASSERT_EQ(0, rbd_create4(ioctx
, name
.c_str(), size
, image_options
));
338 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
340 ASSERT_EQ(0, rbd_close(image
));
342 rados_ioctx_destroy(ioctx
);
345 TEST_F(TestLibRBD
, CreateAndStatPP
)
347 librados::IoCtx ioctx
;
348 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
352 librbd::image_info_t info
;
355 std::string name
= get_temp_image_name();
356 uint64_t size
= 2 << 20;
358 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
359 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
360 ASSERT_EQ(0, image
.stat(info
, sizeof(info
)));
361 ASSERT_EQ(info
.size
, size
);
362 ASSERT_EQ(info
.order
, order
);
368 TEST_F(TestLibRBD
, GetId
)
371 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
375 std::string name
= get_temp_image_name();
377 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), 0, &order
));
378 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
381 if (!is_feature_enabled(0)) {
383 ASSERT_EQ(-EINVAL
, rbd_get_id(image
, id
, sizeof(id
)));
385 ASSERT_EQ(-ERANGE
, rbd_get_id(image
, id
, 0));
386 ASSERT_EQ(0, rbd_get_id(image
, id
, sizeof(id
)));
387 ASSERT_LT(0U, strlen(id
));
390 ASSERT_EQ(0, rbd_close(image
));
391 rados_ioctx_destroy(ioctx
);
394 TEST_F(TestLibRBD
, GetIdPP
)
396 librados::IoCtx ioctx
;
397 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
402 std::string name
= get_temp_image_name();
405 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), 0, &order
));
406 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
407 if (!is_feature_enabled(0)) {
409 ASSERT_EQ(-EINVAL
, image
.get_id(&id
));
411 ASSERT_EQ(0, image
.get_id(&id
));
412 ASSERT_LT(0U, id
.size());
416 TEST_F(TestLibRBD
, GetBlockNamePrefix
)
419 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
423 std::string name
= get_temp_image_name();
425 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), 0, &order
));
426 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
429 ASSERT_EQ(-ERANGE
, rbd_get_block_name_prefix(image
, prefix
, 0));
430 ASSERT_EQ(0, rbd_get_block_name_prefix(image
, prefix
, sizeof(prefix
)));
431 ASSERT_LT(0U, strlen(prefix
));
433 ASSERT_EQ(0, rbd_close(image
));
434 rados_ioctx_destroy(ioctx
);
437 TEST_F(TestLibRBD
, GetBlockNamePrefixPP
)
439 librados::IoCtx ioctx
;
440 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
445 std::string name
= get_temp_image_name();
447 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), 0, &order
));
448 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
449 ASSERT_LT(0U, image
.get_block_name_prefix().size());
452 TEST_F(TestLibRBD
, TestGetCreateTimestamp
)
457 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
461 std::string name
= get_temp_image_name();
463 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), 0, &order
));
464 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
466 struct timespec timestamp
;
467 ASSERT_EQ(0, rbd_get_create_timestamp(image
, ×tamp
));
468 ASSERT_LT(0, timestamp
.tv_sec
);
470 ASSERT_EQ(0, rbd_close(image
));
472 rados_ioctx_destroy(ioctx
);
475 TEST_F(TestLibRBD
, GetCreateTimestampPP
)
479 librados::IoCtx ioctx
;
480 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
485 std::string name
= get_temp_image_name();
487 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), 0, &order
));
488 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
490 struct timespec timestamp
;
491 ASSERT_EQ(0, image
.get_create_timestamp(×tamp
));
492 ASSERT_LT(0, timestamp
.tv_sec
);
495 TEST_F(TestLibRBD
, OpenAio
)
498 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
500 rbd_image_info_t info
;
503 std::string name
= get_temp_image_name();
504 uint64_t size
= 2 << 20;
506 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
508 rbd_completion_t open_comp
;
509 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &open_comp
));
510 ASSERT_EQ(0, rbd_aio_open(ioctx
, name
.c_str(), &image
, NULL
, open_comp
));
511 ASSERT_EQ(0, rbd_aio_wait_for_complete(open_comp
));
512 ASSERT_EQ(1, rbd_aio_is_complete(open_comp
));
513 ASSERT_EQ(0, rbd_aio_get_return_value(open_comp
));
514 rbd_aio_release(open_comp
);
516 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
517 printf("image has size %llu and order %d\n", (unsigned long long) info
.size
, info
.order
);
518 ASSERT_EQ(info
.size
, size
);
519 ASSERT_EQ(info
.order
, order
);
521 rbd_completion_t close_comp
;
522 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &close_comp
));
523 ASSERT_EQ(0, rbd_aio_close(image
, close_comp
));
524 ASSERT_EQ(0, rbd_aio_wait_for_complete(close_comp
));
525 ASSERT_EQ(1, rbd_aio_is_complete(close_comp
));
526 ASSERT_EQ(0, rbd_aio_get_return_value(close_comp
));
527 rbd_aio_release(close_comp
);
529 rados_ioctx_destroy(ioctx
);
532 TEST_F(TestLibRBD
, OpenAioFail
)
535 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
537 std::string name
= get_temp_image_name();
539 rbd_completion_t open_comp
;
540 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &open_comp
));
541 ASSERT_EQ(0, rbd_aio_open(ioctx
, name
.c_str(), &image
, NULL
, open_comp
));
542 ASSERT_EQ(0, rbd_aio_wait_for_complete(open_comp
));
543 ASSERT_EQ(1, rbd_aio_is_complete(open_comp
));
544 ASSERT_EQ(-ENOENT
, rbd_aio_get_return_value(open_comp
));
545 rbd_aio_release(open_comp
);
547 rados_ioctx_destroy(ioctx
);
550 TEST_F(TestLibRBD
, OpenAioPP
)
552 librados::IoCtx ioctx
;
553 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
556 librbd::image_info_t info
;
559 std::string name
= get_temp_image_name();
560 uint64_t size
= 2 << 20;
562 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
564 librbd::RBD::AioCompletion
*open_comp
=
565 new librbd::RBD::AioCompletion(NULL
, NULL
);
566 ASSERT_EQ(0, rbd
.aio_open(ioctx
, image
, name
.c_str(), NULL
, open_comp
));
567 ASSERT_EQ(0, open_comp
->wait_for_complete());
568 ASSERT_EQ(1, open_comp
->is_complete());
569 ASSERT_EQ(0, open_comp
->get_return_value());
570 open_comp
->release();
572 ASSERT_EQ(0, image
.stat(info
, sizeof(info
)));
573 ASSERT_EQ(info
.size
, size
);
574 ASSERT_EQ(info
.order
, order
);
577 open_comp
= new librbd::RBD::AioCompletion(NULL
, NULL
);
578 ASSERT_EQ(0, rbd
.aio_open(ioctx
, image
, name
.c_str(), NULL
, open_comp
));
579 ASSERT_EQ(0, open_comp
->wait_for_complete());
580 ASSERT_EQ(1, open_comp
->is_complete());
581 ASSERT_EQ(0, open_comp
->get_return_value());
582 open_comp
->release();
585 librbd::RBD::AioCompletion
*close_comp
=
586 new librbd::RBD::AioCompletion(NULL
, NULL
);
587 ASSERT_EQ(0, image
.aio_close(close_comp
));
588 ASSERT_EQ(0, close_comp
->wait_for_complete());
589 ASSERT_EQ(1, close_comp
->is_complete());
590 ASSERT_EQ(0, close_comp
->get_return_value());
591 close_comp
->release();
593 // close closed image
594 close_comp
= new librbd::RBD::AioCompletion(NULL
, NULL
);
595 ASSERT_EQ(-EINVAL
, image
.aio_close(close_comp
));
596 close_comp
->release();
601 TEST_F(TestLibRBD
, OpenAioFailPP
)
603 librados::IoCtx ioctx
;
604 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
609 std::string name
= get_temp_image_name();
611 librbd::RBD::AioCompletion
*open_comp
=
612 new librbd::RBD::AioCompletion(NULL
, NULL
);
613 ASSERT_EQ(0, rbd
.aio_open(ioctx
, image
, name
.c_str(), NULL
, open_comp
));
614 ASSERT_EQ(0, open_comp
->wait_for_complete());
615 ASSERT_EQ(1, open_comp
->is_complete());
616 ASSERT_EQ(-ENOENT
, open_comp
->get_return_value());
617 open_comp
->release();
623 TEST_F(TestLibRBD
, ResizeAndStat
)
626 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
628 rbd_image_info_t info
;
631 std::string name
= get_temp_image_name();
632 uint64_t size
= 2 << 20;
634 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
635 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
637 ASSERT_EQ(0, rbd_resize(image
, size
* 4));
638 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
639 ASSERT_EQ(info
.size
, size
* 4);
641 ASSERT_EQ(0, rbd_resize(image
, size
/ 2));
642 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
643 ASSERT_EQ(info
.size
, size
/ 2);
645 // downsizing without allowing shrink should fail
646 // and image size should not change
647 ASSERT_EQ(-EINVAL
, rbd_resize2(image
, size
/ 4, false, NULL
, NULL
));
648 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
649 ASSERT_EQ(info
.size
, size
/ 2);
651 ASSERT_EQ(0, rbd_resize2(image
, size
/ 4, true, NULL
, NULL
));
652 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
653 ASSERT_EQ(info
.size
, size
/ 4);
655 ASSERT_PASSED(validate_object_map
, image
);
656 ASSERT_EQ(0, rbd_close(image
));
658 rados_ioctx_destroy(ioctx
);
661 TEST_F(TestLibRBD
, ResizeAndStatPP
)
663 librados::IoCtx ioctx
;
664 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
668 librbd::image_info_t info
;
671 std::string name
= get_temp_image_name();
672 uint64_t size
= 2 << 20;
674 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
675 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
677 ASSERT_EQ(0, image
.resize(size
* 4));
678 ASSERT_EQ(0, image
.stat(info
, sizeof(info
)));
679 ASSERT_EQ(info
.size
, size
* 4);
681 ASSERT_EQ(0, image
.resize(size
/ 2));
682 ASSERT_EQ(0, image
.stat(info
, sizeof(info
)));
683 ASSERT_EQ(info
.size
, size
/ 2);
684 ASSERT_PASSED(validate_object_map
, image
);
690 TEST_F(TestLibRBD
, UpdateWatchAndResize
)
693 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
697 std::string name
= get_temp_image_name();
698 uint64_t size
= 2 << 20;
700 rbd_image_t
&m_image
;
702 condition_variable m_cond
;
704 static void cb(void *arg
) {
705 Watcher
*watcher
= static_cast<Watcher
*>(arg
);
706 watcher
->handle_notify();
708 Watcher(rbd_image_t
&image
) : m_image(image
) {}
709 void handle_notify() {
710 rbd_image_info_t info
;
711 ASSERT_EQ(0, rbd_stat(m_image
, &info
, sizeof(info
)));
712 lock_guard
<mutex
> locker(m_lock
);
716 void wait_for_size(size_t size
) {
717 unique_lock
<mutex
> locker(m_lock
);
718 ASSERT_TRUE(m_cond
.wait_for(locker
, seconds(5),
720 return this->m_size
== size
;}));
725 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
726 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
728 ASSERT_EQ(0, rbd_update_watch(image
, &handle
, Watcher::cb
, &watcher
));
730 ASSERT_EQ(0, rbd_resize(image
, size
* 4));
731 watcher
.wait_for_size(size
* 4);
733 ASSERT_EQ(0, rbd_resize(image
, size
/ 2));
734 watcher
.wait_for_size(size
/ 2);
736 ASSERT_EQ(0, rbd_update_unwatch(image
, handle
));
738 ASSERT_EQ(0, rbd_close(image
));
739 rados_ioctx_destroy(ioctx
);
742 TEST_F(TestLibRBD
, UpdateWatchAndResizePP
)
744 librados::IoCtx ioctx
;
745 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
751 std::string name
= get_temp_image_name();
752 uint64_t size
= 2 << 20;
753 struct Watcher
: public librbd::UpdateWatchCtx
{
754 Watcher(librbd::Image
&image
) : m_image(image
) {
756 void handle_notify() override
{
757 librbd::image_info_t info
;
758 ASSERT_EQ(0, m_image
.stat(info
, sizeof(info
)));
759 lock_guard
<mutex
> locker(m_lock
);
763 void wait_for_size(size_t size
) {
764 unique_lock
<mutex
> locker(m_lock
);
765 ASSERT_TRUE(m_cond
.wait_for(locker
, seconds(5),
767 return this->m_size
== size
;}));
769 librbd::Image
&m_image
;
771 condition_variable m_cond
;
776 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
777 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
779 ASSERT_EQ(0, image
.update_watch(&watcher
, &handle
));
781 ASSERT_EQ(0, image
.resize(size
* 4));
782 watcher
.wait_for_size(size
* 4);
784 ASSERT_EQ(0, image
.resize(size
/ 2));
785 watcher
.wait_for_size(size
/ 2);
787 ASSERT_EQ(0, image
.update_unwatch(handle
));
793 int test_ls(rados_ioctx_t io_ctx
, size_t num_expected
, ...)
796 char *names
, *cur_name
;
798 size_t max_size
= 1024;
800 names
= (char *) malloc(sizeof(char) * 1024);
801 int len
= rbd_list(io_ctx
, names
, &max_size
);
803 std::set
<std::string
> image_names
;
804 for (i
= 0, num_images
= 0, cur_name
= names
; cur_name
< names
+ len
; i
++) {
805 printf("image: %s\n", cur_name
);
806 image_names
.insert(cur_name
);
807 cur_name
+= strlen(cur_name
) + 1;
812 va_start(ap
, num_expected
);
813 for (i
= num_expected
; i
> 0; i
--) {
814 char *expected
= va_arg(ap
, char *);
815 printf("expected = %s\n", expected
);
816 std::set
<std::string
>::iterator it
= image_names
.find(expected
);
817 if (it
!= image_names
.end()) {
818 printf("found %s\n", expected
);
819 image_names
.erase(it
);
820 printf("erased %s\n", expected
);
822 ADD_FAILURE() << "Unable to find image " << expected
;
829 if (!image_names
.empty()) {
830 ADD_FAILURE() << "Unexpected images discovered";
836 TEST_F(TestLibRBD
, TestCreateLsDelete
)
839 rados_ioctx_create(_cluster
, create_pool(true).c_str(), &ioctx
);
842 std::string name
= get_temp_image_name();
843 std::string name2
= get_temp_image_name();
844 uint64_t size
= 2 << 20;
846 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
847 ASSERT_EQ(1, test_ls(ioctx
, 1, name
.c_str()));
848 ASSERT_EQ(0, create_image(ioctx
, name2
.c_str(), size
, &order
));
849 ASSERT_EQ(2, test_ls(ioctx
, 2, name
.c_str(), name2
.c_str()));
850 ASSERT_EQ(0, rbd_remove(ioctx
, name
.c_str()));
851 ASSERT_EQ(1, test_ls(ioctx
, 1, name2
.c_str()));
853 ASSERT_EQ(-ENOENT
, rbd_remove(ioctx
, name
.c_str()));
855 rados_ioctx_destroy(ioctx
);
858 int test_ls_pp(librbd::RBD
& rbd
, librados::IoCtx
& io_ctx
, size_t num_expected
, ...)
863 vector
<string
> names
;
864 r
= rbd
.list(io_ctx
, names
);
868 cout
<< "num images is: " << names
.size() << std::endl
869 << "expected: " << num_expected
<< std::endl
;
870 int num
= names
.size();
872 for (i
= 0; i
< names
.size(); i
++) {
873 cout
<< "image: " << names
[i
] << std::endl
;
876 va_start(ap
, num_expected
);
877 for (i
= num_expected
; i
> 0; i
--) {
878 char *expected
= va_arg(ap
, char *);
879 cout
<< "expected = " << expected
<< std::endl
;
880 vector
<string
>::iterator listed_name
= find(names
.begin(), names
.end(), string(expected
));
881 if (listed_name
== names
.end()) {
882 ADD_FAILURE() << "Unable to find image " << expected
;
886 names
.erase(listed_name
);
890 if (!names
.empty()) {
891 ADD_FAILURE() << "Unexpected images discovered";
897 TEST_F(TestLibRBD
, TestCreateLsDeletePP
)
899 librados::IoCtx ioctx
;
900 ASSERT_EQ(0, _rados
.ioctx_create(create_pool(true).c_str(), ioctx
));
906 std::string name
= get_temp_image_name();
907 std::string name2
= get_temp_image_name();
908 uint64_t size
= 2 << 20;
910 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
911 ASSERT_EQ(1, test_ls_pp(rbd
, ioctx
, 1, name
.c_str()));
912 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name2
.c_str(), size
, &order
));
913 ASSERT_EQ(2, test_ls_pp(rbd
, ioctx
, 2, name
.c_str(), name2
.c_str()));
914 ASSERT_EQ(0, rbd
.remove(ioctx
, name
.c_str()));
915 ASSERT_EQ(1, test_ls_pp(rbd
, ioctx
, 1, name2
.c_str()));
922 static int print_progress_percent(uint64_t offset
, uint64_t src_size
,
925 float percent
= ((float)offset
* 100) / src_size
;
926 printf("%3.2f%% done\n", percent
);
930 TEST_F(TestLibRBD
, TestCopy
)
933 rados_ioctx_create(_cluster
, create_pool(true).c_str(), &ioctx
);
937 std::string name
= get_temp_image_name();
938 std::string name2
= get_temp_image_name();
939 std::string name3
= get_temp_image_name();
941 uint64_t size
= 2 << 20;
943 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
944 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
945 ASSERT_EQ(1, test_ls(ioctx
, 1, name
.c_str()));
946 ASSERT_EQ(0, rbd_copy(image
, ioctx
, name2
.c_str()));
947 ASSERT_EQ(2, test_ls(ioctx
, 2, name
.c_str(), name2
.c_str()));
948 ASSERT_EQ(0, rbd_copy_with_progress(image
, ioctx
, name3
.c_str(),
949 print_progress_percent
, NULL
));
950 ASSERT_EQ(3, test_ls(ioctx
, 3, name
.c_str(), name2
.c_str(), name3
.c_str()));
952 ASSERT_EQ(0, rbd_close(image
));
953 rados_ioctx_destroy(ioctx
);
956 class PrintProgress
: public librbd::ProgressContext
959 int update_progress(uint64_t offset
, uint64_t src_size
) override
961 float percent
= ((float)offset
* 100) / src_size
;
962 printf("%3.2f%% done\n", percent
);
967 TEST_F(TestLibRBD
, TestCopyPP
)
969 librados::IoCtx ioctx
;
970 ASSERT_EQ(0, _rados
.ioctx_create(create_pool(true).c_str(), ioctx
));
976 std::string name
= get_temp_image_name();
977 std::string name2
= get_temp_image_name();
978 std::string name3
= get_temp_image_name();
979 uint64_t size
= 2 << 20;
982 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
983 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
984 ASSERT_EQ(1, test_ls_pp(rbd
, ioctx
, 1, name
.c_str()));
985 ASSERT_EQ(0, image
.copy(ioctx
, name2
.c_str()));
986 ASSERT_EQ(2, test_ls_pp(rbd
, ioctx
, 2, name
.c_str(), name2
.c_str()));
987 ASSERT_EQ(0, image
.copy_with_progress(ioctx
, name3
.c_str(), pp
));
988 ASSERT_EQ(3, test_ls_pp(rbd
, ioctx
, 3, name
.c_str(), name2
.c_str(),
995 int test_ls_snaps(rbd_image_t image
, int num_expected
, ...)
997 int num_snaps
, i
, j
, max_size
= 10;
999 rbd_snap_info_t snaps
[max_size
];
1000 num_snaps
= rbd_snap_list(image
, snaps
, &max_size
);
1001 printf("num snaps is: %d\nexpected: %d\n", num_snaps
, num_expected
);
1003 for (i
= 0; i
< num_snaps
; i
++) {
1004 printf("snap: %s\n", snaps
[i
].name
);
1007 va_start(ap
, num_expected
);
1008 for (i
= num_expected
; i
> 0; i
--) {
1009 char *expected
= va_arg(ap
, char *);
1010 uint64_t expected_size
= va_arg(ap
, uint64_t);
1012 for (j
= 0; j
< num_snaps
; j
++) {
1013 if (snaps
[j
].name
== NULL
)
1015 if (strcmp(snaps
[j
].name
, expected
) == 0) {
1016 printf("found %s with size %llu\n", snaps
[j
].name
, (unsigned long long) snaps
[j
].size
);
1017 EXPECT_EQ(expected_size
, snaps
[j
].size
);
1018 free((void *) snaps
[j
].name
);
1019 snaps
[j
].name
= NULL
;
1028 for (i
= 0; i
< num_snaps
; i
++) {
1029 EXPECT_EQ((const char *)0, snaps
[i
].name
);
1035 TEST_F(TestLibRBD
, TestCreateLsDeleteSnap
)
1037 rados_ioctx_t ioctx
;
1038 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1042 std::string name
= get_temp_image_name();
1043 uint64_t size
= 2 << 20;
1044 uint64_t size2
= 4 << 20;
1046 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1047 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1049 ASSERT_EQ(0, rbd_snap_create(image
, "snap1"));
1050 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap1", size
));
1051 ASSERT_EQ(0, rbd_resize(image
, size2
));
1052 ASSERT_EQ(0, rbd_snap_create(image
, "snap2"));
1053 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1", size
, "snap2", size2
));
1054 ASSERT_EQ(0, rbd_snap_remove(image
, "snap1"));
1055 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap2", size2
));
1056 ASSERT_EQ(0, rbd_snap_remove(image
, "snap2"));
1057 ASSERT_EQ(0, test_ls_snaps(image
, 0));
1059 ASSERT_EQ(0, rbd_close(image
));
1061 rados_ioctx_destroy(ioctx
);
1064 int test_get_snapshot_timestamp(rbd_image_t image
, uint64_t snap_id
)
1066 struct timespec timestamp
;
1067 EXPECT_EQ(0, rbd_snap_get_timestamp(image
, snap_id
, ×tamp
));
1068 EXPECT_LT(0, timestamp
.tv_sec
);
1072 TEST_F(TestLibRBD
, TestGetSnapShotTimeStamp
)
1074 REQUIRE_FORMAT_V2();
1076 rados_ioctx_t ioctx
;
1077 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1081 std::string name
= get_temp_image_name();
1082 uint64_t size
= 2 << 20;
1083 int num_snaps
, max_size
= 10;
1084 rbd_snap_info_t snaps
[max_size
];
1086 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1087 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1089 ASSERT_EQ(0, rbd_snap_create(image
, "snap1"));
1090 num_snaps
= rbd_snap_list(image
, snaps
, &max_size
);
1091 ASSERT_EQ(1, num_snaps
);
1092 ASSERT_EQ(0, test_get_snapshot_timestamp(image
, snaps
[0].id
));
1093 free((void *)snaps
[0].name
);
1095 ASSERT_EQ(0, rbd_snap_create(image
, "snap2"));
1096 num_snaps
= rbd_snap_list(image
, snaps
, &max_size
);
1097 ASSERT_EQ(2, num_snaps
);
1098 ASSERT_EQ(0, test_get_snapshot_timestamp(image
, snaps
[0].id
));
1099 ASSERT_EQ(0, test_get_snapshot_timestamp(image
, snaps
[1].id
));
1100 free((void *)snaps
[0].name
);
1101 free((void *)snaps
[1].name
);
1103 ASSERT_EQ(0, rbd_close(image
));
1105 rados_ioctx_destroy(ioctx
);
1109 int test_ls_snaps(librbd::Image
& image
, size_t num_expected
, ...)
1114 vector
<librbd::snap_info_t
> snaps
;
1115 r
= image
.snap_list(snaps
);
1116 EXPECT_TRUE(r
>= 0);
1117 cout
<< "num snaps is: " << snaps
.size() << std::endl
1118 << "expected: " << num_expected
<< std::endl
;
1120 for (i
= 0; i
< snaps
.size(); i
++) {
1121 cout
<< "snap: " << snaps
[i
].name
<< std::endl
;
1124 va_start(ap
, num_expected
);
1125 for (i
= num_expected
; i
> 0; i
--) {
1126 char *expected
= va_arg(ap
, char *);
1127 uint64_t expected_size
= va_arg(ap
, uint64_t);
1129 for (j
= 0; j
< snaps
.size(); j
++) {
1130 if (snaps
[j
].name
== "")
1132 if (strcmp(snaps
[j
].name
.c_str(), expected
) == 0) {
1133 cout
<< "found " << snaps
[j
].name
<< " with size " << snaps
[j
].size
1135 EXPECT_EQ(expected_size
, snaps
[j
].size
);
1145 for (i
= 0; i
< snaps
.size(); i
++) {
1146 EXPECT_EQ("", snaps
[i
].name
);
1149 return snaps
.size();
1152 TEST_F(TestLibRBD
, TestCreateLsDeleteSnapPP
)
1154 librados::IoCtx ioctx
;
1155 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
1159 librbd::Image image
;
1161 std::string name
= get_temp_image_name();
1162 uint64_t size
= 2 << 20;
1163 uint64_t size2
= 4 << 20;
1165 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
1166 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
1169 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1170 ASSERT_FALSE(exists
);
1171 ASSERT_EQ(0, image
.snap_create("snap1"));
1172 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1173 ASSERT_TRUE(exists
);
1174 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap1", size
));
1175 ASSERT_EQ(0, image
.resize(size2
));
1176 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1177 ASSERT_FALSE(exists
);
1178 ASSERT_EQ(0, image
.snap_create("snap2"));
1179 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1180 ASSERT_TRUE(exists
);
1181 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1", size
, "snap2", size2
));
1182 ASSERT_EQ(0, image
.snap_remove("snap1"));
1183 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1184 ASSERT_FALSE(exists
);
1185 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap2", size2
));
1186 ASSERT_EQ(0, image
.snap_remove("snap2"));
1187 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1188 ASSERT_FALSE(exists
);
1189 ASSERT_EQ(0, test_ls_snaps(image
, 0));
1195 TEST_F(TestLibRBD
, TestCreateLsRenameSnapPP
)
1197 librados::IoCtx ioctx
;
1198 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
1202 librbd::Image image
;
1204 std::string name
= get_temp_image_name();
1205 uint64_t size
= 2 << 20;
1206 uint64_t size2
= 4 << 20;
1208 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
1209 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
1212 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1213 ASSERT_FALSE(exists
);
1214 ASSERT_EQ(0, image
.snap_create("snap1"));
1215 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1216 ASSERT_TRUE(exists
);
1217 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap1", size
));
1218 ASSERT_EQ(0, image
.resize(size2
));
1219 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1220 ASSERT_FALSE(exists
);
1221 ASSERT_EQ(0, image
.snap_create("snap2"));
1222 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1223 ASSERT_TRUE(exists
);
1224 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1", size
, "snap2", size2
));
1225 ASSERT_EQ(0, image
.snap_rename("snap1","snap1-rename"));
1226 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1-rename", size
, "snap2", size2
));
1227 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1228 ASSERT_FALSE(exists
);
1229 ASSERT_EQ(0, image
.snap_exists2("snap1-rename", &exists
));
1230 ASSERT_TRUE(exists
);
1231 ASSERT_EQ(0, image
.snap_remove("snap1-rename"));
1232 ASSERT_EQ(0, image
.snap_rename("snap2","snap2-rename"));
1233 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap2-rename", size2
));
1234 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1235 ASSERT_FALSE(exists
);
1236 ASSERT_EQ(0, image
.snap_exists2("snap2-rename", &exists
));
1237 ASSERT_TRUE(exists
);
1238 ASSERT_EQ(0, image
.snap_remove("snap2-rename"));
1239 ASSERT_EQ(0, test_ls_snaps(image
, 0));
1245 void simple_write_cb(rbd_completion_t cb
, void *arg
)
1247 printf("write completion cb called!\n");
1250 void simple_read_cb(rbd_completion_t cb
, void *arg
)
1252 printf("read completion cb called!\n");
1255 void aio_write_test_data_and_poll(rbd_image_t image
, int fd
, const char *test_data
,
1256 uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1258 rbd_completion_t comp
;
1259 uint64_t data
= 0x123;
1260 rbd_aio_create_completion((void*)&data
, (rbd_callback_t
) simple_write_cb
, &comp
);
1261 printf("created completion\n");
1262 printf("started write\n");
1264 rbd_aio_write2(image
, off
, len
, test_data
, comp
, iohint
);
1266 rbd_aio_write(image
, off
, len
, test_data
, comp
);
1270 pfd
.events
= POLLIN
;
1272 ASSERT_EQ(1, poll(&pfd
, 1, -1));
1273 ASSERT_TRUE(pfd
.revents
& POLLIN
);
1275 rbd_completion_t comps
[1];
1276 ASSERT_EQ(1, rbd_poll_io_events(image
, comps
, 1));
1278 ASSERT_EQ(static_cast<ssize_t
>(sizeof(count
)),
1279 read(fd
, &count
, sizeof(count
)));
1280 int r
= rbd_aio_get_return_value(comps
[0]);
1281 ASSERT_TRUE(rbd_aio_is_complete(comps
[0]));
1282 ASSERT_TRUE(*(uint64_t*)rbd_aio_get_arg(comps
[0]) == data
);
1283 printf("return value is: %d\n", r
);
1285 printf("finished write\n");
1286 rbd_aio_release(comps
[0]);
1290 void aio_write_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1292 rbd_completion_t comp
;
1293 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1294 printf("created completion\n");
1296 rbd_aio_write2(image
, off
, len
, test_data
, comp
, iohint
);
1298 rbd_aio_write(image
, off
, len
, test_data
, comp
);
1299 printf("started write\n");
1300 rbd_aio_wait_for_complete(comp
);
1301 int r
= rbd_aio_get_return_value(comp
);
1302 printf("return value is: %d\n", r
);
1304 printf("finished write\n");
1305 rbd_aio_release(comp
);
1309 void write_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1313 written
= rbd_write2(image
, off
, len
, test_data
, iohint
);
1315 written
= rbd_write(image
, off
, len
, test_data
);
1316 printf("wrote: %d\n", (int) written
);
1317 ASSERT_EQ(len
, static_cast<size_t>(written
));
1321 void aio_discard_test_data(rbd_image_t image
, uint64_t off
, uint64_t len
, bool *passed
)
1323 rbd_completion_t comp
;
1324 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1325 rbd_aio_discard(image
, off
, len
, comp
);
1326 rbd_aio_wait_for_complete(comp
);
1327 int r
= rbd_aio_get_return_value(comp
);
1329 printf("aio discard: %d~%d = %d\n", (int)off
, (int)len
, (int)r
);
1330 rbd_aio_release(comp
);
1334 void discard_test_data(rbd_image_t image
, uint64_t off
, size_t len
, bool *passed
)
1337 written
= rbd_discard(image
, off
, len
);
1338 printf("discard: %d~%d = %d\n", (int)off
, (int)len
, (int)written
);
1339 ASSERT_EQ(len
, static_cast<size_t>(written
));
1343 void aio_read_test_data_and_poll(rbd_image_t image
, int fd
, const char *expected
,
1344 uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1346 rbd_completion_t comp
;
1347 char *result
= (char *)malloc(len
+ 1);
1349 ASSERT_NE(static_cast<char *>(NULL
), result
);
1350 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1351 printf("created completion\n");
1352 printf("started read\n");
1354 rbd_aio_read2(image
, off
, len
, result
, comp
, iohint
);
1356 rbd_aio_read(image
, off
, len
, result
, comp
);
1360 pfd
.events
= POLLIN
;
1362 ASSERT_EQ(1, poll(&pfd
, 1, -1));
1363 ASSERT_TRUE(pfd
.revents
& POLLIN
);
1365 rbd_completion_t comps
[1];
1366 ASSERT_EQ(1, rbd_poll_io_events(image
, comps
, 1));
1368 ASSERT_EQ(static_cast<ssize_t
>(sizeof(count
)),
1369 read(fd
, &count
, sizeof(count
)));
1371 int r
= rbd_aio_get_return_value(comps
[0]);
1372 ASSERT_TRUE(rbd_aio_is_complete(comps
[0]));
1373 printf("return value is: %d\n", r
);
1374 ASSERT_EQ(len
, static_cast<size_t>(r
));
1375 rbd_aio_release(comps
[0]);
1376 if (memcmp(result
, expected
, len
)) {
1377 printf("read: %s\nexpected: %s\n", result
, expected
);
1378 ASSERT_EQ(0, memcmp(result
, expected
, len
));
1384 void aio_read_test_data(rbd_image_t image
, const char *expected
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1386 rbd_completion_t comp
;
1387 char *result
= (char *)malloc(len
+ 1);
1389 ASSERT_NE(static_cast<char *>(NULL
), result
);
1390 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1391 printf("created completion\n");
1393 rbd_aio_read2(image
, off
, len
, result
, comp
, iohint
);
1395 rbd_aio_read(image
, off
, len
, result
, comp
);
1396 printf("started read\n");
1397 rbd_aio_wait_for_complete(comp
);
1398 int r
= rbd_aio_get_return_value(comp
);
1399 printf("return value is: %d\n", r
);
1400 ASSERT_EQ(len
, static_cast<size_t>(r
));
1401 rbd_aio_release(comp
);
1402 if (memcmp(result
, expected
, len
)) {
1403 printf("read: %s\nexpected: %s\n", result
, expected
);
1404 ASSERT_EQ(0, memcmp(result
, expected
, len
));
1410 void read_test_data(rbd_image_t image
, const char *expected
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1413 char *result
= (char *)malloc(len
+ 1);
1415 ASSERT_NE(static_cast<char *>(NULL
), result
);
1417 read
= rbd_read2(image
, off
, len
, result
, iohint
);
1419 read
= rbd_read(image
, off
, len
, result
);
1420 printf("read: %d\n", (int) read
);
1421 ASSERT_EQ(len
, static_cast<size_t>(read
));
1423 if (memcmp(result
, expected
, len
)) {
1424 printf("read: %s\nexpected: %s\n", result
, expected
);
1425 ASSERT_EQ(0, memcmp(result
, expected
, len
));
1431 void aio_writesame_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, uint64_t len
,
1432 uint64_t data_len
, uint32_t iohint
, bool *passed
)
1434 rbd_completion_t comp
;
1435 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1436 printf("created completion\n");
1438 r
= rbd_aio_writesame(image
, off
, len
, test_data
, data_len
, comp
, iohint
);
1439 printf("started writesame\n");
1440 if (len
% data_len
) {
1441 ASSERT_EQ(-EINVAL
, r
);
1442 printf("expected fail, finished writesame\n");
1443 rbd_aio_release(comp
);
1448 rbd_aio_wait_for_complete(comp
);
1449 r
= rbd_aio_get_return_value(comp
);
1450 printf("return value is: %d\n", r
);
1452 printf("finished writesame\n");
1453 rbd_aio_release(comp
);
1456 printf("to verify the data\n");
1458 char *result
= (char *)malloc(data_len
+ 1);
1459 ASSERT_NE(static_cast<char *>(NULL
), result
);
1460 uint64_t left
= len
;
1462 read
= rbd_read(image
, off
, data_len
, result
);
1463 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
1464 result
[data_len
] = '\0';
1465 if (memcmp(result
, test_data
, data_len
)) {
1466 printf("read: %d ~ %d\n", (int) off
, (int) read
);
1467 printf("read: %s\nexpected: %s\n", result
, test_data
);
1468 ASSERT_EQ(0, memcmp(result
, test_data
, data_len
));
1473 ASSERT_EQ(0U, left
);
1475 printf("verified\n");
1480 void writesame_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, uint64_t len
,
1481 uint64_t data_len
, uint32_t iohint
, bool *passed
)
1484 written
= rbd_writesame(image
, off
, len
, test_data
, data_len
, iohint
);
1485 if (len
% data_len
) {
1486 ASSERT_EQ(-EINVAL
, written
);
1487 printf("expected fail, finished writesame\n");
1491 ASSERT_EQ(len
, static_cast<size_t>(written
));
1492 printf("wrote: %d\n", (int) written
);
1495 printf("to verify the data\n");
1497 char *result
= (char *)malloc(data_len
+ 1);
1498 ASSERT_NE(static_cast<char *>(NULL
), result
);
1499 uint64_t left
= len
;
1501 read
= rbd_read(image
, off
, data_len
, result
);
1502 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
1503 result
[data_len
] = '\0';
1504 if (memcmp(result
, test_data
, data_len
)) {
1505 printf("read: %d ~ %d\n", (int) off
, (int) read
);
1506 printf("read: %s\nexpected: %s\n", result
, test_data
);
1507 ASSERT_EQ(0, memcmp(result
, test_data
, data_len
));
1512 ASSERT_EQ(0U, left
);
1514 printf("verified\n");
1519 void aio_compare_and_write_test_data(rbd_image_t image
, const char *cmp_data
,
1520 const char *test_data
, uint64_t off
,
1521 size_t len
, uint32_t iohint
, bool *passed
)
1523 rbd_completion_t comp
;
1524 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1525 printf("created completion\n");
1527 uint64_t mismatch_offset
;
1528 rbd_aio_compare_and_write(image
, off
, len
, cmp_data
, test_data
, comp
, &mismatch_offset
, iohint
);
1529 printf("started aio compare and write\n");
1530 rbd_aio_wait_for_complete(comp
);
1531 int r
= rbd_aio_get_return_value(comp
);
1532 printf("return value is: %d\n", r
);
1534 printf("finished aio compare and write\n");
1535 rbd_aio_release(comp
);
1539 void compare_and_write_test_data(rbd_image_t image
, const char *cmp_data
,
1540 const char *test_data
, uint64_t off
, size_t len
,
1541 uint64_t *mismatch_off
, uint32_t iohint
, bool *passed
)
1543 printf("start compare and write\n");
1545 written
= rbd_compare_and_write(image
, off
, len
, cmp_data
, test_data
, mismatch_off
, iohint
);
1546 printf("compare and wrote: %d\n", (int) written
);
1547 ASSERT_EQ(len
, static_cast<size_t>(written
));
1552 TEST_F(TestLibRBD
, TestIO
)
1554 rados_ioctx_t ioctx
;
1555 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1557 bool skip_discard
= is_skip_partial_discard_enabled();
1561 std::string name
= get_temp_image_name();
1562 uint64_t size
= 2 << 20;
1564 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1565 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1567 char test_data
[TEST_IO_SIZE
+ 1];
1568 char zero_data
[TEST_IO_SIZE
+ 1];
1569 char mismatch_data
[TEST_IO_SIZE
+ 1];
1571 uint64_t mismatch_offset
;
1573 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
1574 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
1576 test_data
[TEST_IO_SIZE
] = '\0';
1577 memset(zero_data
, 0, sizeof(zero_data
));
1578 memset(mismatch_data
, 9, sizeof(mismatch_data
));
1580 for (i
= 0; i
< 5; ++i
)
1581 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1583 for (i
= 5; i
< 10; ++i
)
1584 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1586 for (i
= 0; i
< 5; ++i
)
1587 ASSERT_PASSED(compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, &mismatch_offset
, 0);
1589 for (i
= 5; i
< 10; ++i
)
1590 ASSERT_PASSED(aio_compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1592 for (i
= 0; i
< 5; ++i
)
1593 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1595 for (i
= 5; i
< 10; ++i
)
1596 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1598 // discard 2nd, 4th sections.
1599 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
1600 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
1602 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
, 0);
1603 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1604 TEST_IO_SIZE
, TEST_IO_SIZE
, 0);
1605 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
, 0);
1606 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1607 TEST_IO_SIZE
*3, TEST_IO_SIZE
, 0);
1608 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
1610 for (i
= 0; i
< 15; ++i
) {
1612 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1613 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1614 } else if (i
% 3 == 1) {
1615 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1616 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1618 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1619 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1622 for (i
= 0; i
< 15; ++i
) {
1624 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1625 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1626 } else if (i
% 3 == 1) {
1627 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1628 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1630 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1631 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1635 rbd_image_info_t info
;
1636 rbd_completion_t comp
;
1637 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
1638 // can't read or write starting past end
1639 ASSERT_EQ(-EINVAL
, rbd_write(image
, info
.size
, 1, test_data
));
1640 ASSERT_EQ(-EINVAL
, rbd_read(image
, info
.size
, 1, test_data
));
1641 // reading through end returns amount up to end
1642 ASSERT_EQ(10, rbd_read(image
, info
.size
- 10, 100, test_data
));
1643 // writing through end returns amount up to end
1644 ASSERT_EQ(10, rbd_write(image
, info
.size
- 10, 100, test_data
));
1646 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1647 ASSERT_EQ(0, rbd_aio_write(image
, info
.size
, 1, test_data
, comp
));
1648 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1649 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1650 rbd_aio_release(comp
);
1652 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1653 ASSERT_EQ(0, rbd_aio_read(image
, info
.size
, 1, test_data
, comp
));
1654 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1655 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1656 rbd_aio_release(comp
);
1658 ASSERT_PASSED(write_test_data
, image
, zero_data
, 0, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1659 ASSERT_EQ(-EILSEQ
, rbd_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
, &mismatch_offset
, 0));
1660 ASSERT_EQ(0U, mismatch_offset
);
1661 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1662 ASSERT_EQ(0, rbd_aio_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
, comp
, &mismatch_offset
, 0));
1663 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1664 ASSERT_EQ(0U, mismatch_offset
);
1665 rbd_aio_release(comp
);
1667 ASSERT_PASSED(validate_object_map
, image
);
1668 ASSERT_EQ(0, rbd_close(image
));
1670 rados_ioctx_destroy(ioctx
);
1673 TEST_F(TestLibRBD
, TestIOWithIOHint
)
1675 rados_ioctx_t ioctx
;
1676 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1678 bool skip_discard
= is_skip_partial_discard_enabled();
1682 std::string name
= get_temp_image_name();
1683 uint64_t size
= 2 << 20;
1685 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1686 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1688 char test_data
[TEST_IO_SIZE
+ 1];
1689 char zero_data
[TEST_IO_SIZE
+ 1];
1690 char mismatch_data
[TEST_IO_SIZE
+ 1];
1692 uint64_t mismatch_offset
;
1694 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
1695 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
1697 test_data
[TEST_IO_SIZE
] = '\0';
1698 memset(zero_data
, 0, sizeof(zero_data
));
1699 memset(mismatch_data
, 9, sizeof(mismatch_data
));
1701 for (i
= 0; i
< 5; ++i
)
1702 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
1703 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1705 for (i
= 5; i
< 10; ++i
)
1706 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
1707 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1709 for (i
= 0; i
< 5; ++i
)
1710 ASSERT_PASSED(compare_and_write_test_data
, image
, test_data
, test_data
,
1711 TEST_IO_SIZE
* i
, TEST_IO_SIZE
, &mismatch_offset
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1713 for (i
= 5; i
< 10; ++i
)
1714 ASSERT_PASSED(aio_compare_and_write_test_data
, image
, test_data
, test_data
,
1715 TEST_IO_SIZE
* i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1717 for (i
= 0; i
< 5; ++i
)
1718 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
,
1719 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1721 for (i
= 5; i
< 10; ++i
)
1722 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
1723 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
|LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1725 // discard 2nd, 4th sections.
1726 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
1727 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
1729 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
,
1730 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1731 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1732 TEST_IO_SIZE
, TEST_IO_SIZE
,
1733 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1734 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
,
1735 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1736 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1737 TEST_IO_SIZE
*3, TEST_IO_SIZE
,
1738 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1739 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
1741 for (i
= 0; i
< 15; ++i
) {
1743 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1744 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1745 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1746 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1747 } else if (i
% 3 == 1) {
1748 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1749 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1750 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1751 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1753 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1754 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1755 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1756 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1759 for (i
= 0; i
< 15; ++i
) {
1761 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1762 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1763 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1764 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1765 } else if (i
% 3 == 1) {
1766 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1767 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1768 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1769 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1771 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1772 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1773 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1774 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1778 rbd_image_info_t info
;
1779 rbd_completion_t comp
;
1780 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
1781 // can't read or write starting past end
1782 ASSERT_EQ(-EINVAL
, rbd_write(image
, info
.size
, 1, test_data
));
1783 ASSERT_EQ(-EINVAL
, rbd_read(image
, info
.size
, 1, test_data
));
1784 // reading through end returns amount up to end
1785 ASSERT_EQ(10, rbd_read2(image
, info
.size
- 10, 100, test_data
,
1786 LIBRADOS_OP_FLAG_FADVISE_NOCACHE
));
1787 // writing through end returns amount up to end
1788 ASSERT_EQ(10, rbd_write2(image
, info
.size
- 10, 100, test_data
,
1789 LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1791 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1792 ASSERT_EQ(0, rbd_aio_read2(image
, info
.size
, 1, test_data
, comp
,
1793 LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1794 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1795 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1796 rbd_aio_release(comp
);
1798 ASSERT_PASSED(write_test_data
, image
, zero_data
, 0, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1799 ASSERT_EQ(-EILSEQ
, rbd_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
,
1800 &mismatch_offset
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1801 ASSERT_EQ(0U, mismatch_offset
);
1802 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1803 ASSERT_EQ(0, rbd_aio_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
,
1804 comp
, &mismatch_offset
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1805 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1806 ASSERT_EQ(0U, mismatch_offset
);
1807 rbd_aio_release(comp
);
1809 ASSERT_PASSED(validate_object_map
, image
);
1810 ASSERT_EQ(0, rbd_close(image
));
1812 rados_ioctx_destroy(ioctx
);
1815 TEST_F(TestLibRBD
, TestDataPoolIO
)
1817 REQUIRE_FORMAT_V2();
1819 rados_ioctx_t ioctx
;
1820 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1822 std::string data_pool_name
= create_pool(true);
1824 bool skip_discard
= is_skip_partial_discard_enabled();
1827 std::string name
= get_temp_image_name();
1828 uint64_t size
= 2 << 20;
1832 ASSERT_EQ(0, get_features(&old_format
, &features
));
1833 ASSERT_FALSE(old_format
);
1835 rbd_image_options_t image_options
;
1836 rbd_image_options_create(&image_options
);
1837 BOOST_SCOPE_EXIT( (&image_options
) ) {
1838 rbd_image_options_destroy(image_options
);
1839 } BOOST_SCOPE_EXIT_END
;
1841 ASSERT_EQ(0, rbd_image_options_set_uint64(image_options
,
1842 RBD_IMAGE_OPTION_FEATURES
,
1844 ASSERT_EQ(0, rbd_image_options_set_string(image_options
,
1845 RBD_IMAGE_OPTION_DATA_POOL
,
1846 data_pool_name
.c_str()));
1848 ASSERT_EQ(0, rbd_create4(ioctx
, name
.c_str(), size
, image_options
));
1849 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1850 ASSERT_NE(-1, rbd_get_data_pool_id(image
));
1852 char test_data
[TEST_IO_SIZE
+ 1];
1853 char zero_data
[TEST_IO_SIZE
+ 1];
1856 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
1857 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
1859 test_data
[TEST_IO_SIZE
] = '\0';
1860 memset(zero_data
, 0, sizeof(zero_data
));
1862 for (i
= 0; i
< 5; ++i
)
1863 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1865 for (i
= 5; i
< 10; ++i
)
1866 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1868 for (i
= 0; i
< 5; ++i
)
1869 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1871 for (i
= 5; i
< 10; ++i
)
1872 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1874 // discard 2nd, 4th sections.
1875 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
1876 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
1878 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
, 0);
1879 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1880 TEST_IO_SIZE
, TEST_IO_SIZE
, 0);
1881 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
, 0);
1882 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1883 TEST_IO_SIZE
*3, TEST_IO_SIZE
, 0);
1884 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
1886 rbd_image_info_t info
;
1887 rbd_completion_t comp
;
1888 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
1889 // can't read or write starting past end
1890 ASSERT_EQ(-EINVAL
, rbd_write(image
, info
.size
, 1, test_data
));
1891 ASSERT_EQ(-EINVAL
, rbd_read(image
, info
.size
, 1, test_data
));
1892 // reading through end returns amount up to end
1893 ASSERT_EQ(10, rbd_read(image
, info
.size
- 10, 100, test_data
));
1894 // writing through end returns amount up to end
1895 ASSERT_EQ(10, rbd_write(image
, info
.size
- 10, 100, test_data
));
1897 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1898 ASSERT_EQ(0, rbd_aio_write(image
, info
.size
, 1, test_data
, comp
));
1899 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1900 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1901 rbd_aio_release(comp
);
1903 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1904 ASSERT_EQ(0, rbd_aio_read(image
, info
.size
, 1, test_data
, comp
));
1905 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1906 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1907 rbd_aio_release(comp
);
1909 ASSERT_PASSED(validate_object_map
, image
);
1910 ASSERT_EQ(0, rbd_close(image
));
1912 rados_ioctx_destroy(ioctx
);
1915 TEST_F(TestLibRBD
, TestScatterGatherIO
)
1917 rados_ioctx_t ioctx
;
1918 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1922 std::string name
= get_temp_image_name();
1923 uint64_t size
= 20 << 20;
1925 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1926 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1928 std::string
write_buffer("This is a test");
1929 struct iovec bad_iovs
[] = {
1930 {.iov_base
= NULL
, .iov_len
= static_cast<size_t>(-1)}
1932 struct iovec write_iovs
[] = {
1933 {.iov_base
= &write_buffer
[0], .iov_len
= 5},
1934 {.iov_base
= &write_buffer
[5], .iov_len
= 3},
1935 {.iov_base
= &write_buffer
[8], .iov_len
= 2},
1936 {.iov_base
= &write_buffer
[10], .iov_len
= 4}
1939 rbd_completion_t comp
;
1940 rbd_aio_create_completion(NULL
, NULL
, &comp
);
1941 ASSERT_EQ(-EINVAL
, rbd_aio_writev(image
, write_iovs
, 0, 0, comp
));
1942 ASSERT_EQ(-EINVAL
, rbd_aio_writev(image
, bad_iovs
, 1, 0, comp
));
1943 ASSERT_EQ(0, rbd_aio_writev(image
, write_iovs
,
1944 sizeof(write_iovs
) / sizeof(struct iovec
),
1946 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1947 ASSERT_EQ(0, rbd_aio_get_return_value(comp
));
1948 rbd_aio_release(comp
);
1950 std::string
read_buffer(write_buffer
.size(), '1');
1951 struct iovec read_iovs
[] = {
1952 {.iov_base
= &read_buffer
[0], .iov_len
= 4},
1953 {.iov_base
= &read_buffer
[8], .iov_len
= 4},
1954 {.iov_base
= &read_buffer
[12], .iov_len
= 2}
1957 rbd_aio_create_completion(NULL
, NULL
, &comp
);
1958 ASSERT_EQ(-EINVAL
, rbd_aio_readv(image
, read_iovs
, 0, 0, comp
));
1959 ASSERT_EQ(-EINVAL
, rbd_aio_readv(image
, bad_iovs
, 1, 0, comp
));
1960 ASSERT_EQ(0, rbd_aio_readv(image
, read_iovs
,
1961 sizeof(read_iovs
) / sizeof(struct iovec
),
1963 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1964 ASSERT_EQ(10, rbd_aio_get_return_value(comp
));
1965 rbd_aio_release(comp
);
1966 ASSERT_EQ("This1111 is a ", read_buffer
);
1968 std::string
linear_buffer(write_buffer
.size(), '1');
1969 struct iovec linear_iovs
[] = {
1970 {.iov_base
= &linear_buffer
[4], .iov_len
= 4}
1972 rbd_aio_create_completion(NULL
, NULL
, &comp
);
1973 ASSERT_EQ(0, rbd_aio_readv(image
, linear_iovs
,
1974 sizeof(linear_iovs
) / sizeof(struct iovec
),
1976 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1977 ASSERT_EQ(4, rbd_aio_get_return_value(comp
));
1978 rbd_aio_release(comp
);
1979 ASSERT_EQ("1111This111111", linear_buffer
);
1981 ASSERT_PASSED(validate_object_map
, image
);
1982 ASSERT_EQ(0, rbd_close(image
));
1984 rados_ioctx_destroy(ioctx
);
1987 TEST_F(TestLibRBD
, TestEmptyDiscard
)
1989 rados_ioctx_t ioctx
;
1990 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1994 std::string name
= get_temp_image_name();
1995 uint64_t size
= 20 << 20;
1997 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1998 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
2000 ASSERT_PASSED(aio_discard_test_data
, image
, 0, 1*1024*1024);
2001 ASSERT_PASSED(aio_discard_test_data
, image
, 0, 4*1024*1024);
2002 ASSERT_PASSED(aio_discard_test_data
, image
, 3*1024*1024, 1*1024*1024);
2004 ASSERT_PASSED(validate_object_map
, image
);
2005 ASSERT_EQ(0, rbd_close(image
));
2007 rados_ioctx_destroy(ioctx
);
2011 void simple_write_cb_pp(librbd::completion_t cb
, void *arg
)
2013 cout
<< "write completion cb called!" << std::endl
;
2016 void simple_read_cb_pp(librbd::completion_t cb
, void *arg
)
2018 cout
<< "read completion cb called!" << std::endl
;
2021 void aio_write_test_data(librbd::Image
& image
, const char *test_data
,
2022 off_t off
, uint32_t iohint
, bool *passed
)
2024 ceph::bufferlist bl
;
2025 bl
.append(test_data
, strlen(test_data
));
2026 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2027 printf("created completion\n");
2029 image
.aio_write2(off
, strlen(test_data
), bl
, comp
, iohint
);
2031 image
.aio_write(off
, strlen(test_data
), bl
, comp
);
2032 printf("started write\n");
2033 comp
->wait_for_complete();
2034 int r
= comp
->get_return_value();
2035 printf("return value is: %d\n", r
);
2037 printf("finished write\n");
2042 void aio_discard_test_data(librbd::Image
& image
, off_t off
, size_t len
, bool *passed
)
2044 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2045 image
.aio_discard(off
, len
, comp
);
2046 comp
->wait_for_complete();
2047 int r
= comp
->get_return_value();
2053 void write_test_data(librbd::Image
& image
, const char *test_data
, off_t off
, uint32_t iohint
, bool *passed
)
2056 size_t len
= strlen(test_data
);
2057 ceph::bufferlist bl
;
2058 bl
.append(test_data
, len
);
2060 written
= image
.write2(off
, len
, bl
, iohint
);
2062 written
= image
.write(off
, len
, bl
);
2063 printf("wrote: %u\n", (unsigned int) written
);
2064 ASSERT_EQ(bl
.length(), written
);
2068 void discard_test_data(librbd::Image
& image
, off_t off
, size_t len
, bool *passed
)
2071 written
= image
.discard(off
, len
);
2072 printf("discard: %u~%u\n", (unsigned)off
, (unsigned)len
);
2073 ASSERT_EQ(len
, written
);
2077 void aio_read_test_data(librbd::Image
& image
, const char *expected
, off_t off
, size_t expected_len
, uint32_t iohint
, bool *passed
)
2079 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_read_cb_pp
);
2080 ceph::bufferlist bl
;
2081 printf("created completion\n");
2083 image
.aio_read2(off
, expected_len
, bl
, comp
, iohint
);
2085 image
.aio_read(off
, expected_len
, bl
, comp
);
2086 printf("started read\n");
2087 comp
->wait_for_complete();
2088 int r
= comp
->get_return_value();
2089 printf("return value is: %d\n", r
);
2090 ASSERT_EQ(TEST_IO_SIZE
, r
);
2091 ASSERT_EQ(0, memcmp(expected
, bl
.c_str(), TEST_IO_SIZE
));
2092 printf("finished read\n");
2097 void read_test_data(librbd::Image
& image
, const char *expected
, off_t off
, size_t expected_len
, uint32_t iohint
, bool *passed
)
2100 size_t len
= expected_len
;
2101 ceph::bufferlist bl
;
2103 read
= image
.read2(off
, len
, bl
, iohint
);
2105 read
= image
.read(off
, len
, bl
);
2106 ASSERT_TRUE(read
>= 0);
2107 std::string
bl_str(bl
.c_str(), read
);
2109 printf("read: %u\n", (unsigned int) read
);
2110 int result
= memcmp(bl_str
.c_str(), expected
, expected_len
);
2112 printf("read: %s\nexpected: %s\n", bl_str
.c_str(), expected
);
2113 ASSERT_EQ(0, result
);
2118 void aio_writesame_test_data(librbd::Image
& image
, const char *test_data
, off_t off
,
2119 size_t len
, size_t data_len
, uint32_t iohint
, bool *passed
)
2121 ceph::bufferlist bl
;
2122 bl
.append(test_data
, data_len
);
2123 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2124 printf("created completion\n");
2126 r
= image
.aio_writesame(off
, len
, bl
, comp
, iohint
);
2127 printf("started writesame\n");
2128 if (len
% data_len
) {
2129 ASSERT_EQ(-EINVAL
, r
);
2130 printf("expected fail, finished writesame\n");
2136 comp
->wait_for_complete();
2137 r
= comp
->get_return_value();
2138 printf("return value is: %d\n", r
);
2140 printf("finished writesame\n");
2144 printf("to verify the data\n");
2146 uint64_t left
= len
;
2148 ceph::bufferlist bl
;
2149 read
= image
.read(off
, data_len
, bl
);
2150 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
2151 std::string
bl_str(bl
.c_str(), read
);
2152 int result
= memcmp(bl_str
.c_str(), test_data
, data_len
);
2154 printf("read: %u ~ %u\n", (unsigned int) off
, (unsigned int) read
);
2155 printf("read: %s\nexpected: %s\n", bl_str
.c_str(), test_data
);
2156 ASSERT_EQ(0, result
);
2161 ASSERT_EQ(0U, left
);
2162 printf("verified\n");
2167 void writesame_test_data(librbd::Image
& image
, const char *test_data
, off_t off
,
2168 ssize_t len
, size_t data_len
, uint32_t iohint
,
2172 ceph::bufferlist bl
;
2173 bl
.append(test_data
, data_len
);
2174 written
= image
.writesame(off
, len
, bl
, iohint
);
2175 if (len
% data_len
) {
2176 ASSERT_EQ(-EINVAL
, written
);
2177 printf("expected fail, finished writesame\n");
2181 ASSERT_EQ(len
, written
);
2182 printf("wrote: %u\n", (unsigned int) written
);
2186 printf("to verify the data\n");
2188 uint64_t left
= len
;
2190 ceph::bufferlist bl
;
2191 read
= image
.read(off
, data_len
, bl
);
2192 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
2193 std::string
bl_str(bl
.c_str(), read
);
2194 int result
= memcmp(bl_str
.c_str(), test_data
, data_len
);
2196 printf("read: %u ~ %u\n", (unsigned int) off
, (unsigned int) read
);
2197 printf("read: %s\nexpected: %s\n", bl_str
.c_str(), test_data
);
2198 ASSERT_EQ(0, result
);
2203 ASSERT_EQ(0U, left
);
2204 printf("verified\n");
2209 void aio_compare_and_write_test_data(librbd::Image
& image
, const char *cmp_data
,
2210 const char *test_data
, off_t off
, ssize_t len
,
2211 uint32_t iohint
, bool *passed
)
2213 ceph::bufferlist cmp_bl
;
2214 cmp_bl
.append(cmp_data
, strlen(cmp_data
));
2215 ceph::bufferlist test_bl
;
2216 test_bl
.append(test_data
, strlen(test_data
));
2217 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2218 printf("created completion\n");
2220 uint64_t mismatch_offset
;
2221 image
.aio_compare_and_write(off
, len
, cmp_bl
, test_bl
, comp
, &mismatch_offset
, iohint
);
2222 printf("started aio compare and write\n");
2223 comp
->wait_for_complete();
2224 int r
= comp
->get_return_value();
2225 printf("return value is: %d\n", r
);
2227 printf("finished aio compare and write\n");
2232 void compare_and_write_test_data(librbd::Image
& image
, const char *cmp_data
, const char *test_data
,
2233 off_t off
, ssize_t len
, uint64_t *mismatch_off
, uint32_t iohint
, bool *passed
)
2236 ceph::bufferlist cmp_bl
;
2237 cmp_bl
.append(cmp_data
, strlen(cmp_data
));
2238 ceph::bufferlist test_bl
;
2239 test_bl
.append(test_data
, strlen(test_data
));
2240 printf("start compare and write\n");
2241 written
= image
.compare_and_write(off
, len
, cmp_bl
, test_bl
, mismatch_off
, iohint
);
2242 printf("compare and wrote: %d\n", (int) written
);
2243 ASSERT_EQ(len
, static_cast<ssize_t
>(written
));
2247 TEST_F(TestLibRBD
, TestIOPP
)
2249 librados::IoCtx ioctx
;
2250 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
2252 bool skip_discard
= is_skip_partial_discard_enabled();
2256 librbd::Image image
;
2258 std::string name
= get_temp_image_name();
2259 uint64_t size
= 2 << 20;
2261 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
2262 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
2264 char test_data
[TEST_IO_SIZE
+ 1];
2265 char zero_data
[TEST_IO_SIZE
+ 1];
2267 uint64_t mismatch_offset
;
2269 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
2270 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
2272 test_data
[TEST_IO_SIZE
] = '\0';
2273 memset(zero_data
, 0, sizeof(zero_data
));
2275 for (i
= 0; i
< 5; ++i
)
2276 ASSERT_PASSED(write_test_data
, image
, test_data
, strlen(test_data
) * i
, 0);
2278 for (i
= 5; i
< 10; ++i
)
2279 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, strlen(test_data
) * i
, 0);
2281 for (i
= 0; i
< 5; ++i
)
2282 ASSERT_PASSED(compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
,
2283 TEST_IO_SIZE
, &mismatch_offset
, 0);
2285 for (i
= 5; i
< 10; ++i
)
2286 ASSERT_PASSED(aio_compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
,
2289 for (i
= 0; i
< 5; ++i
)
2290 ASSERT_PASSED(read_test_data
, image
, test_data
, strlen(test_data
) * i
, TEST_IO_SIZE
, 0);
2292 for (i
= 5; i
< 10; ++i
)
2293 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, strlen(test_data
) * i
, TEST_IO_SIZE
, 0);
2295 // discard 2nd, 4th sections.
2296 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
2297 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
2299 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
, 0);
2300 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
2301 TEST_IO_SIZE
, TEST_IO_SIZE
, 0);
2302 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
, 0);
2303 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
2304 TEST_IO_SIZE
*3, TEST_IO_SIZE
, 0);
2305 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
2307 for (i
= 0; i
< 15; ++i
) {
2309 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2310 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2311 } else if (i
% 3 == 1) {
2312 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2313 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2315 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2316 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2319 for (i
= 0; i
< 15; ++i
) {
2321 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2322 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2323 } else if (i
% 3 == 1) {
2324 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2325 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2327 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2328 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2332 ASSERT_PASSED(validate_object_map
, image
);
2338 TEST_F(TestLibRBD
, TestIOPPWithIOHint
)
2340 librados::IoCtx ioctx
;
2341 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
2345 librbd::Image image
;
2347 std::string name
= get_temp_image_name();
2348 uint64_t size
= 2 << 20;
2350 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
2351 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
2353 char test_data
[TEST_IO_SIZE
+ 1];
2354 char zero_data
[TEST_IO_SIZE
+ 1];
2355 test_data
[TEST_IO_SIZE
] = '\0';
2358 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
2359 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
2361 memset(zero_data
, 0, sizeof(zero_data
));
2363 for (i
= 0; i
< 5; ++i
)
2364 ASSERT_PASSED(write_test_data
, image
, test_data
, strlen(test_data
) * i
,
2365 LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2367 for (i
= 5; i
< 10; ++i
)
2368 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, strlen(test_data
) * i
,
2369 LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2371 ASSERT_PASSED(read_test_data
, image
, test_data
, strlen(test_data
),
2372 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_RANDOM
);
2374 for (i
= 5; i
< 10; ++i
)
2375 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, strlen(test_data
) * i
,
2376 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
|LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2378 for (i
= 0; i
< 15; ++i
) {
2380 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2381 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2382 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2383 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2384 } else if (i
% 3 == 1) {
2385 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
,
2386 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2387 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
,
2388 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2390 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2391 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2392 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2393 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2396 for (i
= 0; i
< 15; ++i
) {
2398 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2399 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2400 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2401 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2402 } else if (i
% 3 == 1) {
2403 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
,
2404 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2405 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
,
2406 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2408 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2409 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2410 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2411 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2415 ASSERT_PASSED(validate_object_map
, image
);
2423 TEST_F(TestLibRBD
, TestIOToSnapshot
)
2425 rados_ioctx_t ioctx
;
2426 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2430 std::string name
= get_temp_image_name();
2431 uint64_t isize
= 2 << 20;
2433 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), isize
, &order
));
2434 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
2437 rbd_image_t image_at_snap
;
2438 char orig_data
[TEST_IO_TO_SNAP_SIZE
+ 1];
2439 char test_data
[TEST_IO_TO_SNAP_SIZE
+ 1];
2441 for (i
= 0; i
< TEST_IO_TO_SNAP_SIZE
; ++i
)
2442 test_data
[i
] = (char) (i
+ 48);
2443 test_data
[TEST_IO_TO_SNAP_SIZE
] = '\0';
2444 orig_data
[TEST_IO_TO_SNAP_SIZE
] = '\0';
2446 r
= rbd_read(image
, 0, TEST_IO_TO_SNAP_SIZE
, orig_data
);
2447 ASSERT_EQ(r
, TEST_IO_TO_SNAP_SIZE
);
2449 ASSERT_EQ(0, test_ls_snaps(image
, 0));
2450 ASSERT_EQ(0, rbd_snap_create(image
, "orig"));
2451 ASSERT_EQ(1, test_ls_snaps(image
, 1, "orig", isize
));
2452 ASSERT_PASSED(read_test_data
, image
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2454 printf("write test data!\n");
2455 ASSERT_PASSED(write_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2456 ASSERT_EQ(0, rbd_snap_create(image
, "written"));
2457 ASSERT_EQ(2, test_ls_snaps(image
, 2, "orig", isize
, "written", isize
));
2459 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2461 rbd_snap_set(image
, "orig");
2462 ASSERT_PASSED(read_test_data
, image
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2464 rbd_snap_set(image
, "written");
2465 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2467 rbd_snap_set(image
, "orig");
2469 r
= rbd_write(image
, 0, TEST_IO_TO_SNAP_SIZE
, test_data
);
2470 printf("write to snapshot returned %d\n", r
);
2472 cout
<< strerror(-r
) << std::endl
;
2474 ASSERT_PASSED(read_test_data
, image
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2475 rbd_snap_set(image
, "written");
2476 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2478 r
= rbd_snap_rollback(image
, "orig");
2479 ASSERT_EQ(r
, -EROFS
);
2481 r
= rbd_snap_set(image
, NULL
);
2483 r
= rbd_snap_rollback(image
, "orig");
2486 ASSERT_PASSED(write_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2490 printf("opening testimg@orig\n");
2491 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image_at_snap
, "orig"));
2492 ASSERT_PASSED(read_test_data
, image_at_snap
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2493 r
= rbd_write(image_at_snap
, 0, TEST_IO_TO_SNAP_SIZE
, test_data
);
2494 printf("write to snapshot returned %d\n", r
);
2496 cout
<< strerror(-r
) << std::endl
;
2497 ASSERT_EQ(0, rbd_close(image_at_snap
));
2499 ASSERT_EQ(2, test_ls_snaps(image
, 2, "orig", isize
, "written", isize
));
2500 ASSERT_EQ(0, rbd_snap_remove(image
, "written"));
2501 ASSERT_EQ(1, test_ls_snaps(image
, 1, "orig", isize
));
2502 ASSERT_EQ(0, rbd_snap_remove(image
, "orig"));
2503 ASSERT_EQ(0, test_ls_snaps(image
, 0));
2505 ASSERT_PASSED(validate_object_map
, image
);
2506 ASSERT_EQ(0, rbd_close(image
));
2508 rados_ioctx_destroy(ioctx
);
2511 TEST_F(TestLibRBD
, TestClone
)
2513 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2515 rados_ioctx_t ioctx
;
2516 rbd_image_info_t pinfo
, cinfo
;
2517 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2521 rbd_image_t parent
, child
;
2524 ASSERT_EQ(0, get_features(&old_format
, &features
));
2525 ASSERT_FALSE(old_format
);
2527 std::string parent_name
= get_temp_image_name();
2528 std::string child_name
= get_temp_image_name();
2530 // make a parent to clone from
2531 ASSERT_EQ(0, create_image_full(ioctx
, parent_name
.c_str(), 4<<20, &order
,
2533 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, NULL
));
2534 printf("made parent image \"parent\"\n");
2536 char *data
= (char *)"testdata";
2537 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 0, strlen(data
), data
));
2539 // can't clone a non-snapshot, expect failure
2540 EXPECT_NE(0, clone_image(ioctx
, parent
, parent_name
.c_str(), NULL
, ioctx
,
2541 child_name
.c_str(), features
, &order
));
2543 // verify that there is no parent info on "parent"
2544 ASSERT_EQ(-ENOENT
, rbd_get_parent_info(parent
, NULL
, 0, NULL
, 0, NULL
, 0));
2545 printf("parent has no parent info\n");
2547 // create a snapshot, reopen as the parent we're interested in
2548 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2549 printf("made snapshot \"parent@parent_snap\"\n");
2550 ASSERT_EQ(0, rbd_close(parent
));
2551 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, "parent_snap"));
2553 ASSERT_EQ(-EINVAL
, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2554 ioctx
, child_name
.c_str(), features
, &order
));
2556 // unprotected image should fail unprotect
2557 ASSERT_EQ(-EINVAL
, rbd_snap_unprotect(parent
, "parent_snap"));
2558 printf("can't unprotect an unprotected snap\n");
2560 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2561 // protecting again should fail
2562 ASSERT_EQ(-EBUSY
, rbd_snap_protect(parent
, "parent_snap"));
2563 printf("can't protect a protected snap\n");
2565 // This clone and open should work
2566 ASSERT_EQ(0, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2567 ioctx
, child_name
.c_str(), features
, &order
));
2568 ASSERT_EQ(0, rbd_open(ioctx
, child_name
.c_str(), &child
, NULL
));
2569 printf("made and opened clone \"child\"\n");
2572 ASSERT_PASSED(read_test_data
, child
, data
, 0, strlen(data
), 0);
2575 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(child
, 20, strlen(data
), data
));
2576 ASSERT_PASSED(read_test_data
, child
, data
, 20, strlen(data
), 0);
2577 ASSERT_PASSED(read_test_data
, child
, data
, 0, strlen(data
), 0);
2580 ASSERT_EQ(0, rbd_stat(parent
, &pinfo
, sizeof(pinfo
)));
2581 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2582 EXPECT_EQ(cinfo
.size
, pinfo
.size
);
2584 rbd_get_overlap(child
, &overlap
);
2585 EXPECT_EQ(overlap
, pinfo
.size
);
2586 EXPECT_EQ(cinfo
.obj_size
, pinfo
.obj_size
);
2587 EXPECT_EQ(cinfo
.order
, pinfo
.order
);
2588 printf("sizes and overlaps are good between parent and child\n");
2590 // sizing down child results in changing overlap and size, not parent size
2591 ASSERT_EQ(0, rbd_resize(child
, 2UL<<20));
2592 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2593 rbd_get_overlap(child
, &overlap
);
2594 ASSERT_EQ(overlap
, 2UL<<20);
2595 ASSERT_EQ(cinfo
.size
, 2UL<<20);
2596 ASSERT_EQ(0, rbd_resize(child
, 4UL<<20));
2597 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2598 rbd_get_overlap(child
, &overlap
);
2599 ASSERT_EQ(overlap
, 2UL<<20);
2600 ASSERT_EQ(cinfo
.size
, 4UL<<20);
2601 printf("sized down clone, changed overlap\n");
2603 // sizing back up doesn't change that
2604 ASSERT_EQ(0, rbd_resize(child
, 5UL<<20));
2605 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2606 rbd_get_overlap(child
, &overlap
);
2607 ASSERT_EQ(overlap
, 2UL<<20);
2608 ASSERT_EQ(cinfo
.size
, 5UL<<20);
2609 ASSERT_EQ(0, rbd_stat(parent
, &pinfo
, sizeof(pinfo
)));
2610 printf("parent info: size %lld obj_size %lld parent_pool %lld\n",
2611 (unsigned long long)pinfo
.size
, (unsigned long long)pinfo
.obj_size
,
2612 (unsigned long long)pinfo
.parent_pool
);
2613 ASSERT_EQ(pinfo
.size
, 4UL<<20);
2614 printf("sized up clone, changed size but not overlap or parent's size\n");
2616 ASSERT_PASSED(validate_object_map
, child
);
2617 ASSERT_EQ(0, rbd_close(child
));
2619 ASSERT_PASSED(validate_object_map
, parent
);
2620 ASSERT_EQ(-EBUSY
, rbd_snap_remove(parent
, "parent_snap"));
2621 printf("can't remove parent while child still exists\n");
2622 ASSERT_EQ(0, rbd_remove(ioctx
, child_name
.c_str()));
2623 ASSERT_EQ(-EBUSY
, rbd_snap_remove(parent
, "parent_snap"));
2624 printf("can't remove parent while still protected\n");
2625 ASSERT_EQ(0, rbd_snap_unprotect(parent
, "parent_snap"));
2626 ASSERT_EQ(0, rbd_snap_remove(parent
, "parent_snap"));
2627 printf("removed parent snap after unprotecting\n");
2629 ASSERT_EQ(0, rbd_close(parent
));
2630 rados_ioctx_destroy(ioctx
);
2633 TEST_F(TestLibRBD
, TestClone2
)
2635 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2637 rados_ioctx_t ioctx
;
2638 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2642 rbd_image_t parent
, child
;
2645 ASSERT_EQ(0, get_features(&old_format
, &features
));
2646 ASSERT_FALSE(old_format
);
2648 std::string parent_name
= get_temp_image_name();
2649 std::string child_name
= get_temp_image_name();
2651 // make a parent to clone from
2652 ASSERT_EQ(0, create_image_full(ioctx
, parent_name
.c_str(), 4<<20, &order
,
2654 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, NULL
));
2655 printf("made parent image \"parent\"\n");
2657 char *data
= (char *)"testdata";
2658 char *childata
= (char *)"childata";
2659 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 0, strlen(data
), data
));
2660 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 12, strlen(data
), data
));
2662 // can't clone a non-snapshot, expect failure
2663 EXPECT_NE(0, clone_image(ioctx
, parent
, parent_name
.c_str(), NULL
, ioctx
,
2664 child_name
.c_str(), features
, &order
));
2666 // verify that there is no parent info on "parent"
2667 ASSERT_EQ(-ENOENT
, rbd_get_parent_info(parent
, NULL
, 0, NULL
, 0, NULL
, 0));
2668 printf("parent has no parent info\n");
2670 // create a snapshot, reopen as the parent we're interested in
2671 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2672 printf("made snapshot \"parent@parent_snap\"\n");
2673 ASSERT_EQ(0, rbd_close(parent
));
2674 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, "parent_snap"));
2676 ASSERT_EQ(-EINVAL
, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2677 ioctx
, child_name
.c_str(), features
, &order
));
2679 // unprotected image should fail unprotect
2680 ASSERT_EQ(-EINVAL
, rbd_snap_unprotect(parent
, "parent_snap"));
2681 printf("can't unprotect an unprotected snap\n");
2683 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2684 // protecting again should fail
2685 ASSERT_EQ(-EBUSY
, rbd_snap_protect(parent
, "parent_snap"));
2686 printf("can't protect a protected snap\n");
2688 // This clone and open should work
2689 ASSERT_EQ(0, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2690 ioctx
, child_name
.c_str(), features
, &order
));
2691 ASSERT_EQ(0, rbd_open(ioctx
, child_name
.c_str(), &child
, NULL
));
2692 printf("made and opened clone \"child\"\n");
2694 // write something in
2695 ASSERT_EQ((ssize_t
)strlen(childata
), rbd_write(child
, 20, strlen(childata
), childata
));
2697 char test
[strlen(data
) * 2];
2698 ASSERT_EQ((ssize_t
)strlen(data
), rbd_read(child
, 20, strlen(data
), test
));
2699 ASSERT_EQ(0, memcmp(test
, childata
, strlen(childata
)));
2702 ASSERT_EQ((ssize_t
)sizeof(test
), rbd_read(child
, 20 - strlen(data
), sizeof(test
), test
));
2703 ASSERT_EQ(0, memcmp(test
, data
, strlen(data
)));
2704 ASSERT_EQ(0, memcmp(test
+ strlen(data
), childata
, strlen(childata
)));
2707 ASSERT_EQ((ssize_t
)sizeof(test
), rbd_read(child
, 0, sizeof(test
), test
));
2708 ASSERT_EQ(0, memcmp(test
, data
, strlen(data
)));
2710 ASSERT_PASSED(validate_object_map
, child
);
2711 ASSERT_PASSED(validate_object_map
, parent
);
2713 ASSERT_EQ(0, rbd_close(child
));
2714 ASSERT_EQ(0, rbd_close(parent
));
2715 rados_ioctx_destroy(ioctx
);
2718 static void test_list_children(rbd_image_t image
, ssize_t num_expected
, ...)
2721 va_start(ap
, num_expected
);
2722 size_t pools_len
= 100;
2723 size_t children_len
= 100;
2725 char *children
= NULL
;
2726 ssize_t num_children
;
2731 pools
= (char *) malloc(pools_len
);
2732 children
= (char *) malloc(children_len
);
2733 num_children
= rbd_list_children(image
, pools
, &pools_len
,
2734 children
, &children_len
);
2735 } while (num_children
== -ERANGE
);
2737 ASSERT_EQ(num_expected
, num_children
);
2738 for (ssize_t i
= num_expected
; i
> 0; --i
) {
2739 char *expected_pool
= va_arg(ap
, char *);
2740 char *expected_image
= va_arg(ap
, char *);
2742 char *image
= children
;
2744 printf("\ntrying to find %s/%s\n", expected_pool
, expected_image
);
2745 for (ssize_t j
= 0; j
< num_children
; ++j
) {
2746 printf("checking %s/%s\n", pool
, image
);
2747 if (strcmp(expected_pool
, pool
) == 0 &&
2748 strcmp(expected_image
, image
) == 0) {
2749 printf("found child %s/%s\n\n", pool
, image
);
2753 pool
+= strlen(pool
) + 1;
2754 image
+= strlen(image
) + 1;
2755 if (j
== num_children
- 1) {
2756 ASSERT_EQ(pool
- pools
- 1, (ssize_t
) pools_len
);
2757 ASSERT_EQ(image
- children
- 1, (ssize_t
) children_len
);
2770 TEST_F(TestLibRBD
, ListChildren
)
2772 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2774 rados_ioctx_t ioctx1
, ioctx2
;
2775 string pool_name1
= create_pool(true);
2776 string pool_name2
= create_pool(true);
2777 ASSERT_NE("", pool_name2
);
2779 rados_ioctx_create(_cluster
, pool_name1
.c_str(), &ioctx1
);
2780 rados_ioctx_create(_cluster
, pool_name2
.c_str(), &ioctx2
);
2787 ASSERT_EQ(0, get_features(&old_format
, &features
));
2788 ASSERT_FALSE(old_format
);
2790 std::string parent_name
= get_temp_image_name();
2791 std::string child_name1
= get_temp_image_name();
2792 std::string child_name2
= get_temp_image_name();
2793 std::string child_name3
= get_temp_image_name();
2794 std::string child_name4
= get_temp_image_name();
2796 // make a parent to clone from
2797 ASSERT_EQ(0, create_image_full(ioctx1
, parent_name
.c_str(), 4<<20, &order
,
2799 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, NULL
));
2800 // create a snapshot, reopen as the parent we're interested in
2801 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2802 ASSERT_EQ(0, rbd_snap_set(parent
, "parent_snap"));
2803 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2805 ASSERT_EQ(0, rbd_close(parent
));
2806 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, "parent_snap"));
2808 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2809 ioctx2
, child_name1
.c_str(), features
, &order
));
2810 test_list_children(parent
, 1, pool_name2
.c_str(), child_name1
.c_str());
2812 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2813 ioctx1
, child_name2
.c_str(), features
, &order
));
2814 test_list_children(parent
, 2, pool_name2
.c_str(), child_name1
.c_str(),
2815 pool_name1
.c_str(), child_name2
.c_str());
2817 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2818 ioctx2
, child_name3
.c_str(), features
, &order
));
2819 test_list_children(parent
, 3, pool_name2
.c_str(), child_name1
.c_str(),
2820 pool_name1
.c_str(), child_name2
.c_str(),
2821 pool_name2
.c_str(), child_name3
.c_str());
2823 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2824 ioctx2
, child_name4
.c_str(), features
, &order
));
2825 test_list_children(parent
, 4, pool_name2
.c_str(), child_name1
.c_str(),
2826 pool_name1
.c_str(), child_name2
.c_str(),
2827 pool_name2
.c_str(), child_name3
.c_str(),
2828 pool_name2
.c_str(), child_name4
.c_str());
2830 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name1
.c_str()));
2831 test_list_children(parent
, 3,
2832 pool_name1
.c_str(), child_name2
.c_str(),
2833 pool_name2
.c_str(), child_name3
.c_str(),
2834 pool_name2
.c_str(), child_name4
.c_str());
2836 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name3
.c_str()));
2837 test_list_children(parent
, 2,
2838 pool_name1
.c_str(), child_name2
.c_str(),
2839 pool_name2
.c_str(), child_name4
.c_str());
2841 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name4
.c_str()));
2842 test_list_children(parent
, 1,
2843 pool_name1
.c_str(), child_name2
.c_str());
2845 ASSERT_EQ(0, rbd_remove(ioctx1
, child_name2
.c_str()));
2846 test_list_children(parent
, 0);
2848 ASSERT_EQ(0, rbd_snap_unprotect(parent
, "parent_snap"));
2849 ASSERT_EQ(0, rbd_snap_remove(parent
, "parent_snap"));
2850 ASSERT_EQ(0, rbd_close(parent
));
2851 ASSERT_EQ(0, rbd_remove(ioctx1
, parent_name
.c_str()));
2852 rados_ioctx_destroy(ioctx1
);
2853 rados_ioctx_destroy(ioctx2
);
2856 TEST_F(TestLibRBD
, ListChildrenTiered
)
2858 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2860 string pool_name1
= m_pool_name
;
2861 string pool_name2
= create_pool(true);
2862 string pool_name3
= create_pool(true);
2863 ASSERT_NE("", pool_name2
);
2864 ASSERT_NE("", pool_name3
);
2866 std::string cmdstr
= "{\"prefix\": \"osd tier add\", \"pool\": \"" +
2867 pool_name1
+ "\", \"tierpool\":\"" + pool_name3
+ "\", \"force_nonempty\":\"\"}";
2869 cmd
[0] = (char *)cmdstr
.c_str();
2870 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
2872 cmdstr
= "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" +
2873 pool_name3
+ "\", \"mode\":\"writeback\"}";
2874 cmd
[0] = (char *)cmdstr
.c_str();
2875 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
2877 cmdstr
= "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" +
2878 pool_name1
+ "\", \"overlaypool\":\"" + pool_name3
+ "\"}";
2879 cmd
[0] = (char *)cmdstr
.c_str();
2880 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
2882 EXPECT_EQ(0, rados_wait_for_latest_osdmap(_cluster
));
2884 string parent_name
= get_temp_image_name();
2885 string child_name1
= get_temp_image_name();
2886 string child_name2
= get_temp_image_name();
2887 string child_name3
= get_temp_image_name();
2888 string child_name4
= get_temp_image_name();
2890 rados_ioctx_t ioctx1
, ioctx2
;
2891 rados_ioctx_create(_cluster
, pool_name1
.c_str(), &ioctx1
);
2892 rados_ioctx_create(_cluster
, pool_name2
.c_str(), &ioctx2
);
2899 ASSERT_EQ(0, get_features(&old_format
, &features
));
2900 ASSERT_FALSE(old_format
);
2902 // make a parent to clone from
2903 ASSERT_EQ(0, create_image_full(ioctx1
, parent_name
.c_str(), 4<<20, &order
,
2905 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, NULL
));
2906 // create a snapshot, reopen as the parent we're interested in
2907 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2908 ASSERT_EQ(0, rbd_snap_set(parent
, "parent_snap"));
2909 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2911 ASSERT_EQ(0, rbd_close(parent
));
2912 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, "parent_snap"));
2914 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2915 ioctx2
, child_name1
.c_str(), features
, &order
));
2916 test_list_children(parent
, 1, pool_name2
.c_str(), child_name1
.c_str());
2918 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2919 ioctx1
, child_name2
.c_str(), features
, &order
));
2920 test_list_children(parent
, 2, pool_name2
.c_str(), child_name1
.c_str(),
2921 pool_name1
.c_str(), child_name2
.c_str());
2923 // read from the cache to populate it
2924 rbd_image_t tier_image
;
2925 ASSERT_EQ(0, rbd_open(ioctx1
, child_name2
.c_str(), &tier_image
, NULL
));
2926 size_t len
= 4 * 1024 * 1024;
2927 char* buf
= (char*)malloc(len
);
2928 ssize_t size
= rbd_read(tier_image
, 0, len
, buf
);
2931 ASSERT_EQ(0, rbd_close(tier_image
));
2933 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2934 ioctx2
, child_name3
.c_str(), features
, &order
));
2935 test_list_children(parent
, 3, pool_name2
.c_str(), child_name1
.c_str(),
2936 pool_name1
.c_str(), child_name2
.c_str(),
2937 pool_name2
.c_str(), child_name3
.c_str());
2939 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2940 ioctx2
, child_name4
.c_str(), features
, &order
));
2941 test_list_children(parent
, 4, pool_name2
.c_str(), child_name1
.c_str(),
2942 pool_name1
.c_str(), child_name2
.c_str(),
2943 pool_name2
.c_str(), child_name3
.c_str(),
2944 pool_name2
.c_str(), child_name4
.c_str());
2946 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name1
.c_str()));
2947 test_list_children(parent
, 3,
2948 pool_name1
.c_str(), child_name2
.c_str(),
2949 pool_name2
.c_str(), child_name3
.c_str(),
2950 pool_name2
.c_str(), child_name4
.c_str());
2952 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name3
.c_str()));
2953 test_list_children(parent
, 2,
2954 pool_name1
.c_str(), child_name2
.c_str(),
2955 pool_name2
.c_str(), child_name4
.c_str());
2957 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name4
.c_str()));
2958 test_list_children(parent
, 1,
2959 pool_name1
.c_str(), child_name2
.c_str());
2961 ASSERT_EQ(0, rbd_remove(ioctx1
, child_name2
.c_str()));
2962 test_list_children(parent
, 0);
2964 ASSERT_EQ(0, rbd_snap_unprotect(parent
, "parent_snap"));
2965 ASSERT_EQ(0, rbd_snap_remove(parent
, "parent_snap"));
2966 ASSERT_EQ(0, rbd_close(parent
));
2967 ASSERT_EQ(0, rbd_remove(ioctx1
, parent_name
.c_str()));
2968 rados_ioctx_destroy(ioctx1
);
2969 rados_ioctx_destroy(ioctx2
);
2970 cmdstr
= "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" +
2972 cmd
[0] = (char *)cmdstr
.c_str();
2973 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
2974 cmdstr
= "{\"prefix\": \"osd tier remove\", \"pool\": \"" +
2975 pool_name1
+ "\", \"tierpool\":\"" + pool_name3
+ "\"}";
2976 cmd
[0] = (char *)cmdstr
.c_str();
2977 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
2980 TEST_F(TestLibRBD
, LockingPP
)
2982 librados::IoCtx ioctx
;
2983 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
2987 librbd::Image image
;
2989 std::string name
= get_temp_image_name();
2990 uint64_t size
= 2 << 20;
2991 std::string cookie1
= "foo";
2992 std::string cookie2
= "bar";
2994 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
2995 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
2997 // no lockers initially
2998 std::list
<librbd::locker_t
> lockers
;
3001 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3002 ASSERT_EQ(0u, lockers
.size());
3005 // exclusive lock is exclusive
3006 ASSERT_EQ(0, image
.lock_exclusive(cookie1
));
3007 ASSERT_EQ(-EEXIST
, image
.lock_exclusive(cookie1
));
3008 ASSERT_EQ(-EBUSY
, image
.lock_exclusive(""));
3009 ASSERT_EQ(-EEXIST
, image
.lock_shared(cookie1
, ""));
3010 ASSERT_EQ(-EBUSY
, image
.lock_shared(cookie1
, "test"));
3011 ASSERT_EQ(-EBUSY
, image
.lock_shared("", "test"));
3012 ASSERT_EQ(-EBUSY
, image
.lock_shared("", ""));
3015 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3016 ASSERT_TRUE(exclusive
);
3018 ASSERT_EQ(1u, lockers
.size());
3019 ASSERT_EQ(cookie1
, lockers
.front().cookie
);
3022 ASSERT_EQ(-ENOENT
, image
.unlock(""));
3023 ASSERT_EQ(-ENOENT
, image
.unlock(cookie2
));
3024 ASSERT_EQ(0, image
.unlock(cookie1
));
3025 ASSERT_EQ(-ENOENT
, image
.unlock(cookie1
));
3026 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3027 ASSERT_EQ(0u, lockers
.size());
3029 ASSERT_EQ(0, image
.lock_shared(cookie1
, ""));
3030 ASSERT_EQ(-EEXIST
, image
.lock_shared(cookie1
, ""));
3031 ASSERT_EQ(0, image
.lock_shared(cookie2
, ""));
3032 ASSERT_EQ(-EEXIST
, image
.lock_shared(cookie2
, ""));
3033 ASSERT_EQ(-EEXIST
, image
.lock_exclusive(cookie1
));
3034 ASSERT_EQ(-EEXIST
, image
.lock_exclusive(cookie2
));
3035 ASSERT_EQ(-EBUSY
, image
.lock_exclusive(""));
3036 ASSERT_EQ(-EBUSY
, image
.lock_exclusive("test"));
3039 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3040 ASSERT_EQ(2u, lockers
.size());
3046 TEST_F(TestLibRBD
, FlushAio
)
3048 rados_ioctx_t ioctx
;
3049 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3053 std::string name
= get_temp_image_name();
3054 uint64_t size
= 2 << 20;
3055 size_t num_aios
= 256;
3057 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3058 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3060 char test_data
[TEST_IO_SIZE
+ 1];
3062 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
3063 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
3066 rbd_completion_t write_comps
[num_aios
];
3067 for (i
= 0; i
< num_aios
; ++i
) {
3068 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &write_comps
[i
]));
3069 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3070 ASSERT_EQ(0, rbd_aio_write(image
, offset
, TEST_IO_SIZE
, test_data
,
3074 rbd_completion_t flush_comp
;
3075 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &flush_comp
));
3076 ASSERT_EQ(0, rbd_aio_flush(image
, flush_comp
));
3077 ASSERT_EQ(0, rbd_aio_wait_for_complete(flush_comp
));
3078 ASSERT_EQ(1, rbd_aio_is_complete(flush_comp
));
3079 rbd_aio_release(flush_comp
);
3081 for (i
= 0; i
< num_aios
; ++i
) {
3082 ASSERT_EQ(1, rbd_aio_is_complete(write_comps
[i
]));
3083 rbd_aio_release(write_comps
[i
]);
3086 ASSERT_PASSED(validate_object_map
, image
);
3087 ASSERT_EQ(0, rbd_close(image
));
3088 ASSERT_EQ(0, rbd_remove(ioctx
, name
.c_str()));
3089 rados_ioctx_destroy(ioctx
);
3092 TEST_F(TestLibRBD
, FlushAioPP
)
3094 librados::IoCtx ioctx
;
3095 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3099 librbd::Image image
;
3101 std::string name
= get_temp_image_name();
3102 uint64_t size
= 2 << 20;
3103 const size_t num_aios
= 256;
3105 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3106 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3108 char test_data
[TEST_IO_SIZE
+ 1];
3110 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
3111 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
3113 test_data
[TEST_IO_SIZE
] = '\0';
3115 librbd::RBD::AioCompletion
*write_comps
[num_aios
];
3116 ceph::bufferlist bls
[num_aios
];
3117 for (i
= 0; i
< num_aios
; ++i
) {
3118 bls
[i
].append(test_data
, strlen(test_data
));
3119 write_comps
[i
] = new librbd::RBD::AioCompletion(NULL
, NULL
);
3120 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3121 ASSERT_EQ(0, image
.aio_write(offset
, TEST_IO_SIZE
, bls
[i
],
3125 librbd::RBD::AioCompletion
*flush_comp
=
3126 new librbd::RBD::AioCompletion(NULL
, NULL
);
3127 ASSERT_EQ(0, image
.aio_flush(flush_comp
));
3128 ASSERT_EQ(0, flush_comp
->wait_for_complete());
3129 ASSERT_EQ(1, flush_comp
->is_complete());
3130 flush_comp
->release();
3132 for (i
= 0; i
< num_aios
; ++i
) {
3133 librbd::RBD::AioCompletion
*comp
= write_comps
[i
];
3134 ASSERT_EQ(1, comp
->is_complete());
3137 ASSERT_PASSED(validate_object_map
, image
);
3144 int iterate_cb(uint64_t off
, size_t len
, int exists
, void *arg
)
3146 //cout << "iterate_cb " << off << "~" << len << std::endl;
3147 interval_set
<uint64_t> *diff
= static_cast<interval_set
<uint64_t> *>(arg
);
3148 diff
->insert(off
, len
);
3152 static int iterate_error_cb(uint64_t off
, size_t len
, int exists
, void *arg
)
3157 void scribble(librbd::Image
& image
, int n
, int max
, bool skip_discard
,
3158 interval_set
<uint64_t> *exists
,
3159 interval_set
<uint64_t> *what
)
3163 interval_set
<uint64_t> exists_at_start
= *exists
;
3165 for (int i
=0; i
<n
; i
++) {
3166 uint64_t off
= rand() % (size
- max
+ 1);
3167 uint64_t len
= 1 + rand() % max
;
3168 if (!skip_discard
&& rand() % 4 == 0) {
3169 ASSERT_EQ((int)len
, image
.discard(off
, len
));
3170 interval_set
<uint64_t> w
;
3173 // the zeroed bit no longer exists...
3174 w
.intersection_of(*exists
);
3175 exists
->subtract(w
);
3177 // the bits we discarded are no long written...
3178 interval_set
<uint64_t> w2
= w
;
3179 w2
.intersection_of(*what
);
3182 // except for the extents that existed at the start that we overwrote.
3183 interval_set
<uint64_t> w3
;
3184 w3
.insert(off
, len
);
3185 w3
.intersection_of(exists_at_start
);
3190 bl
.append(buffer::create(len
));
3192 ASSERT_EQ((int)len
, image
.write(off
, len
, bl
));
3193 interval_set
<uint64_t> w
;
3196 exists
->union_of(w
);
3201 interval_set
<uint64_t> round_diff_interval(const interval_set
<uint64_t>& diff
,
3202 uint64_t object_size
)
3204 if (object_size
== 0) {
3208 interval_set
<uint64_t> rounded_diff
;
3209 for (interval_set
<uint64_t>::const_iterator it
= diff
.begin();
3210 it
!= diff
.end(); ++it
) {
3211 uint64_t off
= it
.get_start();
3212 uint64_t len
= it
.get_len();
3213 off
-= off
% object_size
;
3214 len
+= (object_size
- (len
% object_size
));
3215 interval_set
<uint64_t> interval
;
3216 interval
.insert(off
, len
);
3217 rounded_diff
.union_of(interval
);
3219 return rounded_diff
;
3222 template <typename T
>
3223 class DiffIterateTest
: public TestLibRBD
{
3225 static const uint8_t whole_object
= T::whole_object
;
3228 template <bool _whole_object
>
3229 class DiffIterateParams
{
3231 static const uint8_t whole_object
= _whole_object
;
3234 typedef ::testing::Types
<DiffIterateParams
<false>,
3235 DiffIterateParams
<true> > DiffIterateTypes
;
3236 TYPED_TEST_CASE(DiffIterateTest
, DiffIterateTypes
);
3238 TYPED_TEST(DiffIterateTest
, DiffIterate
)
3240 librados::IoCtx ioctx
;
3241 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3243 bool skip_discard
= this->is_skip_partial_discard_enabled();
3247 librbd::Image image
;
3249 std::string name
= this->get_temp_image_name();
3250 uint64_t size
= 20 << 20;
3252 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3253 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3255 uint64_t object_size
= 0;
3256 if (this->whole_object
) {
3257 object_size
= 1 << order
;
3260 interval_set
<uint64_t> exists
;
3261 interval_set
<uint64_t> one
, two
;
3262 scribble(image
, 10, 102400, skip_discard
, &exists
, &one
);
3263 cout
<< " wrote " << one
<< std::endl
;
3264 ASSERT_EQ(0, image
.snap_create("one"));
3265 scribble(image
, 10, 102400, skip_discard
, &exists
, &two
);
3267 two
= round_diff_interval(two
, object_size
);
3268 cout
<< " wrote " << two
<< std::endl
;
3270 interval_set
<uint64_t> diff
;
3271 ASSERT_EQ(0, image
.diff_iterate2("one", 0, size
, true, this->whole_object
,
3272 iterate_cb
, (void *)&diff
));
3273 cout
<< " diff was " << diff
<< std::endl
;
3274 if (!two
.subset_of(diff
)) {
3275 interval_set
<uint64_t> i
;
3276 i
.intersection_of(two
, diff
);
3277 interval_set
<uint64_t> l
= two
;
3279 cout
<< " ... two - (two*diff) = " << l
<< std::endl
;
3281 ASSERT_TRUE(two
.subset_of(diff
));
3286 struct diff_extent
{
3287 diff_extent(uint64_t _offset
, uint64_t _length
, bool _exists
,
3288 uint64_t object_size
) :
3289 offset(_offset
), length(_length
), exists(_exists
)
3291 if (object_size
!= 0) {
3292 offset
-= offset
% object_size
;
3293 length
= object_size
;
3299 bool operator==(const diff_extent
& o
) const {
3300 return offset
== o
.offset
&& length
== o
.length
&& exists
== o
.exists
;
3304 ostream
& operator<<(ostream
& o
, const diff_extent
& e
) {
3305 return o
<< '(' << e
.offset
<< '~' << e
.length
<< ' ' << (e
.exists
? "true" : "false") << ')';
3308 int vector_iterate_cb(uint64_t off
, size_t len
, int exists
, void *arg
)
3310 cout
<< "iterate_cb " << off
<< "~" << len
<< std::endl
;
3311 vector
<diff_extent
> *diff
= static_cast<vector
<diff_extent
> *>(arg
);
3312 diff
->push_back(diff_extent(off
, len
, exists
, 0));
3316 TYPED_TEST(DiffIterateTest
, DiffIterateDiscard
)
3318 librados::IoCtx ioctx
;
3319 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3322 librbd::Image image
;
3324 std::string name
= this->get_temp_image_name();
3325 uint64_t size
= 20 << 20;
3327 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3328 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3330 uint64_t object_size
= 0;
3331 if (this->whole_object
) {
3332 object_size
= 1 << order
;
3334 vector
<diff_extent
> extents
;
3335 ceph::bufferlist bl
;
3337 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3338 vector_iterate_cb
, (void *) &extents
));
3339 ASSERT_EQ(0u, extents
.size());
3342 memset(data
, 1, sizeof(data
));
3343 bl
.append(data
, 256);
3344 ASSERT_EQ(256, image
.write(0, 256, bl
));
3345 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3346 vector_iterate_cb
, (void *) &extents
));
3347 ASSERT_EQ(1u, extents
.size());
3348 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3351 ASSERT_EQ(1 << order
, image
.discard(0, 1 << order
));
3354 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3355 vector_iterate_cb
, (void *) &extents
));
3356 ASSERT_EQ(0u, extents
.size());
3358 ASSERT_EQ(0, image
.snap_create("snap1"));
3359 ASSERT_EQ(256, image
.write(0, 256, bl
));
3360 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3361 vector_iterate_cb
, (void *) &extents
));
3362 ASSERT_EQ(1u, extents
.size());
3363 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3364 ASSERT_EQ(0, image
.snap_create("snap2"));
3366 ASSERT_EQ(obj_ofs
, image
.discard(0, obj_ofs
));
3369 ASSERT_EQ(0, image
.snap_set("snap2"));
3370 ASSERT_EQ(0, image
.diff_iterate2("snap1", 0, size
, true, this->whole_object
,
3371 vector_iterate_cb
, (void *) &extents
));
3372 ASSERT_EQ(1u, extents
.size());
3373 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3375 ASSERT_EQ(0, image
.snap_set(NULL
));
3376 ASSERT_EQ(1 << order
, image
.discard(0, 1 << order
));
3377 ASSERT_EQ(0, image
.snap_create("snap3"));
3378 ASSERT_EQ(0, image
.snap_set("snap3"));
3381 ASSERT_EQ(0, image
.diff_iterate2("snap1", 0, size
, true, this->whole_object
,
3382 vector_iterate_cb
, (void *) &extents
));
3383 ASSERT_EQ(1u, extents
.size());
3384 ASSERT_EQ(diff_extent(0, 256, false, object_size
), extents
[0]);
3385 ASSERT_PASSED(this->validate_object_map
, image
);
3388 TYPED_TEST(DiffIterateTest
, DiffIterateStress
)
3390 librados::IoCtx ioctx
;
3391 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3393 bool skip_discard
= this->is_skip_partial_discard_enabled();
3396 librbd::Image image
;
3398 std::string name
= this->get_temp_image_name();
3399 uint64_t size
= 400 << 20;
3401 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3402 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3404 uint64_t object_size
= 0;
3405 if (this->whole_object
) {
3406 object_size
= 1 << order
;
3409 interval_set
<uint64_t> curexists
;
3410 vector
<interval_set
<uint64_t> > wrote
;
3411 vector
<interval_set
<uint64_t> > exists
;
3412 vector
<string
> snap
;
3414 for (int i
=0; i
<n
; i
++) {
3415 interval_set
<uint64_t> w
;
3416 scribble(image
, 10, 8192000, skip_discard
, &curexists
, &w
);
3417 cout
<< " i=" << i
<< " exists " << curexists
<< " wrote " << w
<< std::endl
;
3418 string s
= "snap" + stringify(i
);
3419 ASSERT_EQ(0, image
.snap_create(s
.c_str()));
3421 exists
.push_back(curexists
);
3425 for (int h
=0; h
<n
-1; h
++) {
3426 for (int i
=0; i
<n
-h
-1; i
++) {
3427 for (int j
=(h
==0 ? i
+1 : n
-1); j
<n
; j
++) {
3428 interval_set
<uint64_t> diff
, actual
, uex
;
3429 for (int k
=i
+1; k
<=j
; k
++)
3430 diff
.union_of(wrote
[k
]);
3431 cout
<< "from " << i
<< " to "
3432 << (h
!= 0 ? string("HEAD") : stringify(j
)) << " diff "
3433 << round_diff_interval(diff
, object_size
) << std::endl
;
3435 // limit to extents that exists both at the beginning and at the end
3436 uex
.union_of(exists
[i
], exists
[j
]);
3437 diff
.intersection_of(uex
);
3438 diff
= round_diff_interval(diff
, object_size
);
3439 cout
<< " limited diff " << diff
<< std::endl
;
3441 ASSERT_EQ(0, image
.snap_set(h
==0 ? snap
[j
].c_str() : NULL
));
3442 ASSERT_EQ(0, image
.diff_iterate2(snap
[i
].c_str(), 0, size
, true,
3443 this->whole_object
, iterate_cb
,
3445 cout
<< " actual was " << actual
<< std::endl
;
3446 if (!diff
.subset_of(actual
)) {
3447 interval_set
<uint64_t> i
;
3448 i
.intersection_of(diff
, actual
);
3449 interval_set
<uint64_t> l
= diff
;
3451 cout
<< " ... diff - (actual*diff) = " << l
<< std::endl
;
3453 ASSERT_TRUE(diff
.subset_of(actual
));
3456 ASSERT_EQ(0, image
.snap_set(NULL
));
3457 ASSERT_EQ(0, image
.snap_remove(snap
[n
-h
-1].c_str()));
3460 ASSERT_PASSED(this->validate_object_map
, image
);
3463 TYPED_TEST(DiffIterateTest
, DiffIterateRegression6926
)
3465 librados::IoCtx ioctx
;
3466 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3469 librbd::Image image
;
3471 std::string name
= this->get_temp_image_name();
3472 uint64_t size
= 20 << 20;
3474 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3475 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3477 uint64_t object_size
= 0;
3478 if (this->whole_object
) {
3479 object_size
= 1 << order
;
3481 vector
<diff_extent
> extents
;
3482 ceph::bufferlist bl
;
3484 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3485 vector_iterate_cb
, (void *) &extents
));
3486 ASSERT_EQ(0u, extents
.size());
3488 ASSERT_EQ(0, image
.snap_create("snap1"));
3490 memset(data
, 1, sizeof(data
));
3491 bl
.append(data
, 256);
3492 ASSERT_EQ(256, image
.write(0, 256, bl
));
3495 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3496 vector_iterate_cb
, (void *) &extents
));
3497 ASSERT_EQ(1u, extents
.size());
3498 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3500 ASSERT_EQ(0, image
.snap_set("snap1"));
3502 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3503 vector_iterate_cb
, (void *) &extents
));
3504 ASSERT_EQ(static_cast<size_t>(0), extents
.size());
3507 TYPED_TEST(DiffIterateTest
, DiffIterateIgnoreParent
)
3509 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3511 librados::IoCtx ioctx
;
3512 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3514 bool skip_discard
= this->is_skip_partial_discard_enabled();
3517 librbd::Image image
;
3518 std::string name
= this->get_temp_image_name();
3519 uint64_t size
= 20 << 20;
3522 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3523 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3525 uint64_t object_size
= 0;
3526 if (this->whole_object
) {
3527 object_size
= 1 << order
;
3531 bl
.append(buffer::create(size
));
3533 interval_set
<uint64_t> one
;
3534 one
.insert(0, size
);
3535 ASSERT_EQ((int)size
, image
.write(0, size
, bl
));
3536 ASSERT_EQ(0, image
.snap_create("one"));
3537 ASSERT_EQ(0, image
.snap_protect("one"));
3539 std::string clone_name
= this->get_temp_image_name();
3540 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "one", ioctx
, clone_name
.c_str(),
3541 RBD_FEATURE_LAYERING
, &order
));
3542 ASSERT_EQ(0, rbd
.open(ioctx
, image
, clone_name
.c_str(), NULL
));
3544 interval_set
<uint64_t> exists
;
3545 interval_set
<uint64_t> two
;
3546 scribble(image
, 10, 102400, skip_discard
, &exists
, &two
);
3547 two
= round_diff_interval(two
, object_size
);
3548 cout
<< " wrote " << two
<< " to clone" << std::endl
;
3550 interval_set
<uint64_t> diff
;
3551 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, false, this->whole_object
,
3552 iterate_cb
, (void *)&diff
));
3553 cout
<< " diff was " << diff
<< std::endl
;
3554 if (!this->whole_object
) {
3555 ASSERT_FALSE(one
.subset_of(diff
));
3557 ASSERT_TRUE(two
.subset_of(diff
));
3560 TYPED_TEST(DiffIterateTest
, DiffIterateCallbackError
)
3562 librados::IoCtx ioctx
;
3563 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3565 bool skip_discard
= this->is_skip_partial_discard_enabled();
3569 librbd::Image image
;
3571 std::string name
= this->get_temp_image_name();
3572 uint64_t size
= 20 << 20;
3574 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3575 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3577 interval_set
<uint64_t> exists
;
3578 interval_set
<uint64_t> one
;
3579 scribble(image
, 10, 102400, skip_discard
, &exists
, &one
);
3580 cout
<< " wrote " << one
<< std::endl
;
3582 interval_set
<uint64_t> diff
;
3583 ASSERT_EQ(-EINVAL
, image
.diff_iterate2(NULL
, 0, size
, true,
3585 iterate_error_cb
, NULL
));
3590 TYPED_TEST(DiffIterateTest
, DiffIterateParentDiscard
)
3592 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3594 librados::IoCtx ioctx
;
3595 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3597 bool skip_discard
= this->is_skip_partial_discard_enabled();
3600 librbd::Image image
;
3601 std::string name
= this->get_temp_image_name();
3602 uint64_t size
= 20 << 20;
3605 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3606 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3608 uint64_t object_size
= 0;
3609 if (this->whole_object
) {
3610 object_size
= 1 << order
;
3613 interval_set
<uint64_t> exists
;
3614 interval_set
<uint64_t> one
;
3615 scribble(image
, 10, 102400, skip_discard
, &exists
, &one
);
3616 ASSERT_EQ(0, image
.snap_create("one"));
3618 ASSERT_EQ(1 << order
, image
.discard(0, 1 << order
));
3619 ASSERT_EQ(0, image
.snap_create("two"));
3620 ASSERT_EQ(0, image
.snap_protect("two"));
3624 std::string clone_name
= this->get_temp_image_name();
3625 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "two", ioctx
,
3626 clone_name
.c_str(), RBD_FEATURE_LAYERING
, &order
));
3627 ASSERT_EQ(0, rbd
.open(ioctx
, image
, clone_name
.c_str(), NULL
));
3629 interval_set
<uint64_t> two
;
3630 scribble(image
, 10, 102400, skip_discard
, &exists
, &two
);
3631 two
= round_diff_interval(two
, object_size
);
3633 interval_set
<uint64_t> diff
;
3634 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3635 iterate_cb
, (void *)&diff
));
3636 ASSERT_TRUE(two
.subset_of(diff
));
3639 TEST_F(TestLibRBD
, ZeroLengthWrite
)
3641 rados_ioctx_t ioctx
;
3642 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3646 std::string name
= get_temp_image_name();
3647 uint64_t size
= 2 << 20;
3649 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3650 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3653 ASSERT_EQ(0, rbd_write(image
, 0, 0, NULL
));
3654 ASSERT_EQ(1, rbd_read(image
, 0, 1, read_data
));
3655 ASSERT_EQ('\0', read_data
[0]);
3657 ASSERT_PASSED(validate_object_map
, image
);
3658 ASSERT_EQ(0, rbd_close(image
));
3660 rados_ioctx_destroy(ioctx
);
3664 TEST_F(TestLibRBD
, ZeroLengthDiscard
)
3666 rados_ioctx_t ioctx
;
3667 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3671 std::string name
= get_temp_image_name();
3672 uint64_t size
= 2 << 20;
3674 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3675 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3677 const char data
[] = "blah";
3678 char read_data
[sizeof(data
)];
3679 ASSERT_EQ((int)strlen(data
), rbd_write(image
, 0, strlen(data
), data
));
3680 ASSERT_EQ(0, rbd_discard(image
, 0, 0));
3681 ASSERT_EQ((int)strlen(data
), rbd_read(image
, 0, strlen(data
), read_data
));
3682 ASSERT_EQ(0, memcmp(data
, read_data
, strlen(data
)));
3684 ASSERT_PASSED(validate_object_map
, image
);
3685 ASSERT_EQ(0, rbd_close(image
));
3687 rados_ioctx_destroy(ioctx
);
3690 TEST_F(TestLibRBD
, ZeroLengthRead
)
3692 rados_ioctx_t ioctx
;
3693 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3697 std::string name
= get_temp_image_name();
3698 uint64_t size
= 2 << 20;
3700 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3701 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3704 ASSERT_EQ(0, rbd_read(image
, 0, 0, read_data
));
3706 ASSERT_EQ(0, rbd_close(image
));
3708 rados_ioctx_destroy(ioctx
);
3711 TEST_F(TestLibRBD
, LargeCacheRead
)
3713 std::string config_value
;
3714 ASSERT_EQ(0, _rados
.conf_get("rbd_cache", config_value
));
3715 if (config_value
== "false") {
3716 std::cout
<< "SKIPPING due to disabled cache" << std::endl
;
3720 rados_ioctx_t ioctx
;
3721 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3723 uint32_t new_cache_size
= 1 << 20;
3724 std::string orig_cache_size
;
3725 ASSERT_EQ(0, _rados
.conf_get("rbd_cache_size", orig_cache_size
));
3726 ASSERT_EQ(0, _rados
.conf_set("rbd_cache_size",
3727 stringify(new_cache_size
).c_str()));
3728 ASSERT_EQ(0, _rados
.conf_get("rbd_cache_size", config_value
));
3729 ASSERT_EQ(stringify(new_cache_size
), config_value
);
3730 BOOST_SCOPE_EXIT( (orig_cache_size
) ) {
3731 ASSERT_EQ(0, _rados
.conf_set("rbd_cache_size", orig_cache_size
.c_str()));
3732 } BOOST_SCOPE_EXIT_END
;
3736 std::string name
= get_temp_image_name();
3737 uint64_t size
= 1 << order
;
3739 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3740 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3742 std::string
buffer(1 << order
, '1');
3744 ASSERT_EQ(static_cast<ssize_t
>(buffer
.size()),
3745 rbd_write(image
, 0, buffer
.size(), buffer
.c_str()));
3747 ASSERT_EQ(0, rbd_invalidate_cache(image
));
3749 ASSERT_EQ(static_cast<ssize_t
>(buffer
.size()),
3750 rbd_read(image
, 0, buffer
.size(), &buffer
[0]));
3752 ASSERT_EQ(0, rbd_close(image
));
3754 rados_ioctx_destroy(ioctx
);
3757 TEST_F(TestLibRBD
, TestPendingAio
)
3759 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3761 rados_ioctx_t ioctx
;
3762 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3769 ASSERT_EQ(0, get_features(&old_format
, &features
));
3770 ASSERT_FALSE(old_format
);
3772 std::string name
= get_temp_image_name();
3774 uint64_t size
= 4 << 20;
3775 ASSERT_EQ(0, create_image_full(ioctx
, name
.c_str(), size
, &order
,
3777 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3779 char test_data
[TEST_IO_SIZE
];
3780 for (size_t i
= 0; i
< TEST_IO_SIZE
; ++i
) {
3781 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
3784 size_t num_aios
= 256;
3785 rbd_completion_t comps
[num_aios
];
3786 for (size_t i
= 0; i
< num_aios
; ++i
) {
3787 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &comps
[i
]));
3788 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3789 ASSERT_EQ(0, rbd_aio_write(image
, offset
, TEST_IO_SIZE
, test_data
,
3792 for (size_t i
= 0; i
< num_aios
; ++i
) {
3793 ASSERT_EQ(0, rbd_aio_wait_for_complete(comps
[i
]));
3794 rbd_aio_release(comps
[i
]);
3796 ASSERT_EQ(0, rbd_invalidate_cache(image
));
3798 for (size_t i
= 0; i
< num_aios
; ++i
) {
3799 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &comps
[i
]));
3800 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3801 ASSERT_LE(0, rbd_aio_read(image
, offset
, TEST_IO_SIZE
, test_data
,
3805 ASSERT_PASSED(validate_object_map
, image
);
3806 ASSERT_EQ(0, rbd_close(image
));
3807 for (size_t i
= 0; i
< num_aios
; ++i
) {
3808 ASSERT_EQ(1, rbd_aio_is_complete(comps
[i
]));
3809 rbd_aio_release(comps
[i
]);
3812 rados_ioctx_destroy(ioctx
);
3815 TEST_F(TestLibRBD
, Flatten
)
3817 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3819 librados::IoCtx ioctx
;
3820 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3823 std::string parent_name
= get_temp_image_name();
3824 uint64_t size
= 2 << 20;
3826 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, parent_name
.c_str(), size
, &order
));
3828 librbd::Image parent_image
;
3829 ASSERT_EQ(0, rbd
.open(ioctx
, parent_image
, parent_name
.c_str(), NULL
));
3832 bl
.append(std::string(4096, '1'));
3833 ASSERT_EQ((ssize_t
)bl
.length(), parent_image
.write(0, bl
.length(), bl
));
3835 ASSERT_EQ(0, parent_image
.snap_create("snap1"));
3836 ASSERT_EQ(0, parent_image
.snap_protect("snap1"));
3839 ASSERT_EQ(0, parent_image
.features(&features
));
3841 std::string clone_name
= get_temp_image_name();
3842 EXPECT_EQ(0, rbd
.clone(ioctx
, parent_name
.c_str(), "snap1", ioctx
,
3843 clone_name
.c_str(), features
, &order
));
3845 librbd::Image clone_image
;
3846 ASSERT_EQ(0, rbd
.open(ioctx
, clone_image
, clone_name
.c_str(), NULL
));
3847 ASSERT_EQ(0, clone_image
.flatten());
3849 librbd::RBD::AioCompletion
*read_comp
=
3850 new librbd::RBD::AioCompletion(NULL
, NULL
);
3852 clone_image
.aio_read(0, bl
.length(), read_bl
, read_comp
);
3853 ASSERT_EQ(0, read_comp
->wait_for_complete());
3854 ASSERT_EQ((ssize_t
)bl
.length(), read_comp
->get_return_value());
3855 read_comp
->release();
3856 ASSERT_TRUE(bl
.contents_equal(read_bl
));
3858 ASSERT_PASSED(validate_object_map
, clone_image
);
3861 TEST_F(TestLibRBD
, SnapshotLimit
)
3863 rados_ioctx_t ioctx
;
3864 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3868 std::string name
= get_temp_image_name();
3869 uint64_t size
= 2 << 20;
3872 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3873 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3875 ASSERT_EQ(0, rbd_snap_get_limit(image
, &limit
));
3876 ASSERT_EQ(UINT64_MAX
, limit
);
3877 ASSERT_EQ(0, rbd_snap_set_limit(image
, 2));
3878 ASSERT_EQ(0, rbd_snap_get_limit(image
, &limit
));
3879 ASSERT_EQ(2U, limit
);
3881 ASSERT_EQ(0, rbd_snap_create(image
, "snap1"));
3882 ASSERT_EQ(0, rbd_snap_create(image
, "snap2"));
3883 ASSERT_EQ(-EDQUOT
, rbd_snap_create(image
, "snap3"));
3884 ASSERT_EQ(0, rbd_snap_set_limit(image
, UINT64_MAX
));
3885 ASSERT_EQ(0, rbd_snap_create(image
, "snap3"));
3886 ASSERT_EQ(0, rbd_close(image
));
3888 rados_ioctx_destroy(ioctx
);
3892 TEST_F(TestLibRBD
, SnapshotLimitPP
)
3894 librados::IoCtx ioctx
;
3895 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3899 librbd::Image image
;
3900 std::string name
= get_temp_image_name();
3901 uint64_t size
= 2 << 20;
3905 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3906 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3908 ASSERT_EQ(0, image
.snap_get_limit(&limit
));
3909 ASSERT_EQ(UINT64_MAX
, limit
);
3910 ASSERT_EQ(0, image
.snap_set_limit(2));
3911 ASSERT_EQ(0, image
.snap_get_limit(&limit
));
3912 ASSERT_EQ(2U, limit
);
3914 ASSERT_EQ(0, image
.snap_create("snap1"));
3915 ASSERT_EQ(0, image
.snap_create("snap2"));
3916 ASSERT_EQ(-EDQUOT
, image
.snap_create("snap3"));
3917 ASSERT_EQ(0, image
.snap_set_limit(UINT64_MAX
));
3918 ASSERT_EQ(0, image
.snap_create("snap3"));
3924 TEST_F(TestLibRBD
, RebuildObjectMapViaLockOwner
)
3926 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_OBJECT_MAP
);
3928 librados::IoCtx ioctx
;
3929 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3932 std::string name
= get_temp_image_name();
3933 uint64_t size
= 2 << 20;
3935 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3937 std::string object_map_oid
;
3939 librbd::Image image
;
3940 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3942 std::string image_id
;
3943 ASSERT_EQ(0, get_image_id(image
, &image_id
));
3944 object_map_oid
= RBD_OBJECT_MAP_PREFIX
+ image_id
;
3947 // corrupt the object map
3950 ASSERT_EQ(0, ioctx
.write(object_map_oid
, bl
, bl
.length(), 0));
3952 librbd::Image image1
;
3953 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
3957 ASSERT_EQ(0, image1
.write(0, 0, bl
));
3958 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
3959 ASSERT_TRUE(lock_owner
);
3962 ASSERT_EQ(0, image1
.get_flags(&flags
));
3963 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0);
3965 librbd::Image image2
;
3966 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
3967 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
3968 ASSERT_FALSE(lock_owner
);
3970 PrintProgress prog_ctx
;
3971 ASSERT_EQ(0, image2
.rebuild_object_map(prog_ctx
));
3972 ASSERT_PASSED(validate_object_map
, image1
);
3973 ASSERT_PASSED(validate_object_map
, image2
);
3976 TEST_F(TestLibRBD
, RenameViaLockOwner
)
3978 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
3980 librados::IoCtx ioctx
;
3981 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3984 std::string name
= get_temp_image_name();
3985 uint64_t size
= 2 << 20;
3987 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3989 librbd::Image image1
;
3990 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
3993 ASSERT_EQ(0, image1
.write(0, 0, bl
));
3996 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
3997 ASSERT_TRUE(lock_owner
);
3999 std::string new_name
= get_temp_image_name();
4000 ASSERT_EQ(0, rbd
.rename(ioctx
, name
.c_str(), new_name
.c_str()));
4001 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4002 ASSERT_TRUE(lock_owner
);
4004 librbd::Image image2
;
4005 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, new_name
.c_str(), NULL
));
4008 TEST_F(TestLibRBD
, SnapCreateViaLockOwner
)
4010 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4012 librados::IoCtx ioctx
;
4013 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4016 std::string name
= get_temp_image_name();
4017 uint64_t size
= 2 << 20;
4019 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4021 librbd::Image image1
;
4022 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4024 // switch to writeback cache
4025 ASSERT_EQ(0, image1
.flush());
4028 bl
.append(std::string(4096, '1'));
4029 ASSERT_EQ((ssize_t
)bl
.length(), image1
.write(0, bl
.length(), bl
));
4032 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4033 ASSERT_TRUE(lock_owner
);
4035 librbd::Image image2
;
4036 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4038 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4039 ASSERT_FALSE(lock_owner
);
4041 ASSERT_EQ(0, image2
.snap_create("snap1"));
4043 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4044 ASSERT_TRUE(exists
);
4045 ASSERT_EQ(0, image2
.snap_exists2("snap1", &exists
));
4046 ASSERT_TRUE(exists
);
4048 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4049 ASSERT_TRUE(lock_owner
);
4052 TEST_F(TestLibRBD
, SnapRemoveViaLockOwner
)
4054 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4056 librados::IoCtx ioctx
;
4057 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4060 std::string name
= get_temp_image_name();
4061 uint64_t size
= 2 << 20;
4063 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4065 librbd::Image image1
;
4066 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4069 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4070 ASSERT_EQ(0, image1
.snap_create("snap1"));
4073 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4074 ASSERT_TRUE(lock_owner
);
4076 librbd::Image image2
;
4077 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4079 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4080 ASSERT_FALSE(lock_owner
);
4082 ASSERT_EQ(0, image2
.snap_remove("snap1"));
4084 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4085 ASSERT_FALSE(exists
);
4086 ASSERT_EQ(0, image2
.snap_exists2("snap1", &exists
));
4087 ASSERT_FALSE(exists
);
4089 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4090 ASSERT_TRUE(lock_owner
);
4093 TEST_F(TestLibRBD
, SnapRemove2
)
4095 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4097 librados::IoCtx ioctx
;
4098 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4101 std::string name
= get_temp_image_name();
4102 uint64_t size
= 2 << 20;
4104 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4106 librbd::Image image1
;
4107 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4110 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4111 ASSERT_EQ(0, image1
.snap_create("snap1"));
4113 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4114 ASSERT_TRUE(exists
);
4115 ASSERT_EQ(0, image1
.snap_protect("snap1"));
4117 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4118 ASSERT_TRUE(is_protected
);
4121 ASSERT_EQ(0, image1
.features(&features
));
4123 std::string child_name
= get_temp_image_name();
4124 EXPECT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "snap1", ioctx
,
4125 child_name
.c_str(), features
, &order
));
4127 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4128 ASSERT_TRUE(exists
);
4129 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4130 ASSERT_TRUE(is_protected
);
4132 ASSERT_EQ(-EBUSY
, image1
.snap_remove("snap1"));
4134 ASSERT_EQ(0, image1
.snap_remove2("snap1", RBD_SNAP_REMOVE_FORCE
, pp
));
4135 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4136 ASSERT_FALSE(exists
);
4139 TEST_F(TestLibRBD
, SnapRenameViaLockOwner
)
4141 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4143 librados::IoCtx ioctx
;
4144 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4147 std::string name
= get_temp_image_name();
4148 uint64_t size
= 2 << 20;
4150 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4152 librbd::Image image1
;
4153 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4156 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4157 ASSERT_EQ(0, image1
.snap_create("snap1"));
4160 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4161 ASSERT_TRUE(lock_owner
);
4163 librbd::Image image2
;
4164 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4166 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4167 ASSERT_FALSE(lock_owner
);
4169 ASSERT_EQ(0, image2
.snap_rename("snap1", "snap1-rename"));
4171 ASSERT_EQ(0, image1
.snap_exists2("snap1-rename", &exists
));
4172 ASSERT_TRUE(exists
);
4173 ASSERT_EQ(0, image2
.snap_exists2("snap1-rename", &exists
));
4174 ASSERT_TRUE(exists
);
4176 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4177 ASSERT_TRUE(lock_owner
);
4180 TEST_F(TestLibRBD
, SnapProtectViaLockOwner
)
4182 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4184 librados::IoCtx ioctx
;
4185 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4188 std::string name
= get_temp_image_name();
4189 uint64_t size
= 2 << 20;
4191 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4193 librbd::Image image1
;
4194 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4197 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4200 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4201 ASSERT_TRUE(lock_owner
);
4202 ASSERT_EQ(0, image1
.snap_create("snap1"));
4204 librbd::Image image2
;
4205 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4207 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4208 ASSERT_FALSE(lock_owner
);
4210 ASSERT_EQ(0, image2
.snap_protect("snap1"));
4212 ASSERT_EQ(0, image2
.snap_is_protected("snap1", &is_protected
));
4213 ASSERT_TRUE(is_protected
);
4214 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4215 ASSERT_TRUE(is_protected
);
4217 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4218 ASSERT_TRUE(lock_owner
);
4221 TEST_F(TestLibRBD
, SnapUnprotectViaLockOwner
)
4223 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4225 librados::IoCtx ioctx
;
4226 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4229 std::string name
= get_temp_image_name();
4230 uint64_t size
= 2 << 20;
4232 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4234 librbd::Image image1
;
4235 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4238 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4241 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4242 ASSERT_TRUE(lock_owner
);
4243 ASSERT_EQ(0, image1
.snap_create("snap1"));
4244 ASSERT_EQ(0, image1
.snap_protect("snap1"));
4246 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4247 ASSERT_TRUE(is_protected
);
4249 librbd::Image image2
;
4250 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4252 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4253 ASSERT_FALSE(lock_owner
);
4255 ASSERT_EQ(0, image2
.snap_unprotect("snap1"));
4256 ASSERT_EQ(0, image2
.snap_is_protected("snap1", &is_protected
));
4257 ASSERT_FALSE(is_protected
);
4258 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4259 ASSERT_FALSE(is_protected
);
4261 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4262 ASSERT_TRUE(lock_owner
);
4265 TEST_F(TestLibRBD
, FlattenViaLockOwner
)
4267 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
4269 librados::IoCtx ioctx
;
4270 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4273 std::string parent_name
= get_temp_image_name();
4274 uint64_t size
= 2 << 20;
4276 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, parent_name
.c_str(), size
, &order
));
4278 librbd::Image parent_image
;
4279 ASSERT_EQ(0, rbd
.open(ioctx
, parent_image
, parent_name
.c_str(), NULL
));
4280 ASSERT_EQ(0, parent_image
.snap_create("snap1"));
4281 ASSERT_EQ(0, parent_image
.snap_protect("snap1"));
4284 ASSERT_EQ(0, parent_image
.features(&features
));
4286 std::string name
= get_temp_image_name();
4287 EXPECT_EQ(0, rbd
.clone(ioctx
, parent_name
.c_str(), "snap1", ioctx
,
4288 name
.c_str(), features
, &order
));
4290 librbd::Image image1
;
4291 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4294 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4297 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4298 ASSERT_TRUE(lock_owner
);
4300 librbd::Image image2
;
4301 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4303 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4304 ASSERT_FALSE(lock_owner
);
4306 ASSERT_EQ(0, image2
.flatten());
4308 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4309 ASSERT_TRUE(lock_owner
);
4310 ASSERT_PASSED(validate_object_map
, image1
);
4313 TEST_F(TestLibRBD
, ResizeViaLockOwner
)
4315 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
4317 librados::IoCtx ioctx
;
4318 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4321 std::string name
= get_temp_image_name();
4322 uint64_t size
= 2 << 20;
4324 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4326 librbd::Image image1
;
4327 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4330 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4333 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4334 ASSERT_TRUE(lock_owner
);
4336 librbd::Image image2
;
4337 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4339 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4340 ASSERT_FALSE(lock_owner
);
4342 ASSERT_EQ(0, image2
.resize(0));
4344 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4345 ASSERT_TRUE(lock_owner
);
4346 ASSERT_PASSED(validate_object_map
, image1
);
4349 TEST_F(TestLibRBD
, ObjectMapConsistentSnap
)
4351 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
4353 librados::IoCtx ioctx
;
4354 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4357 std::string name
= get_temp_image_name();
4358 uint64_t size
= 1 << 20;
4360 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4362 librbd::Image image1
;
4363 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4366 for (int i
= 0; i
< num_snaps
; ++i
) {
4367 std::string snap_name
= "snap" + stringify(i
);
4368 ASSERT_EQ(0, image1
.snap_create(snap_name
.c_str()));
4372 thread
writer([&image1
](){
4373 librbd::image_info_t info
;
4374 int r
= image1
.stat(info
, sizeof(info
));
4378 for (unsigned i
= 0; i
< info
.num_objs
; ++i
) {
4379 r
= image1
.write((1 << info
.order
) * i
, bl
.length(), bl
);
4380 assert(r
== (int) bl
.length());
4385 for (int i
= 0; i
< num_snaps
; ++i
) {
4386 std::string snap_name
= "snap" + stringify(i
);
4387 ASSERT_EQ(0, image1
.snap_set(snap_name
.c_str()));
4388 ASSERT_PASSED(validate_object_map
, image1
);
4391 ASSERT_EQ(0, image1
.snap_set(NULL
));
4392 ASSERT_PASSED(validate_object_map
, image1
);
4395 void memset_rand(char *buf
, size_t len
) {
4396 for (size_t i
= 0; i
< len
; ++i
) {
4397 buf
[i
] = (char) (rand() % (126 - 33) + 33);
4401 TEST_F(TestLibRBD
, Metadata
)
4403 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4405 rados_ioctx_t ioctx
;
4406 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
4408 std::string name
= get_temp_image_name();
4409 uint64_t size
= 2 << 20;
4411 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
4414 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
4417 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image1
, NULL
));
4421 size_t keys_len
= sizeof(keys
);
4422 size_t vals_len
= sizeof(vals
);
4424 memset_rand(keys
, keys_len
);
4425 memset_rand(vals
, vals_len
);
4427 ASSERT_EQ(0, rbd_metadata_list(image
, "", 0, keys
, &keys_len
, vals
,
4429 ASSERT_EQ(0U, keys_len
);
4430 ASSERT_EQ(0U, vals_len
);
4433 size_t value_len
= sizeof(value
);
4434 memset_rand(value
, value_len
);
4436 ASSERT_EQ(0, rbd_metadata_set(image1
, "key1", "value1"));
4437 ASSERT_EQ(0, rbd_metadata_set(image1
, "key2", "value2"));
4438 ASSERT_EQ(0, rbd_metadata_get(image1
, "key1", value
, &value_len
));
4439 ASSERT_STREQ(value
, "value1");
4441 ASSERT_EQ(-ERANGE
, rbd_metadata_get(image1
, "key1", value
, &value_len
));
4442 ASSERT_EQ(value_len
, strlen("value1") + 1);
4444 ASSERT_EQ(-ERANGE
, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4446 keys_len
= sizeof(keys
);
4447 vals_len
= sizeof(vals
);
4448 memset_rand(keys
, keys_len
);
4449 memset_rand(vals
, vals_len
);
4450 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4452 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1);
4453 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1);
4454 ASSERT_STREQ(keys
, "key1");
4455 ASSERT_STREQ(keys
+ strlen(keys
) + 1, "key2");
4456 ASSERT_STREQ(vals
, "value1");
4457 ASSERT_STREQ(vals
+ strlen(vals
) + 1, "value2");
4459 ASSERT_EQ(0, rbd_metadata_remove(image1
, "key1"));
4460 ASSERT_EQ(0, rbd_metadata_remove(image1
, "key3"));
4461 value_len
= sizeof(value
);
4462 ASSERT_EQ(-ENOENT
, rbd_metadata_get(image1
, "key3", value
, &value_len
));
4463 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4465 ASSERT_EQ(keys_len
, strlen("key2") + 1);
4466 ASSERT_EQ(vals_len
, strlen("value2") + 1);
4467 ASSERT_STREQ(keys
, "key2");
4468 ASSERT_STREQ(vals
, "value2");
4470 // test config setting
4471 ASSERT_EQ(0, rbd_metadata_set(image1
, "conf_rbd_cache", "false"));
4472 ASSERT_EQ(-EINVAL
, rbd_metadata_set(image1
, "conf_rbd_cache", "INVALID_VAL"));
4473 ASSERT_EQ(0, rbd_metadata_remove(image1
, "conf_rbd_cache"));
4475 // test metadata with snapshot adding
4476 ASSERT_EQ(0, rbd_snap_create(image1
, "snap1"));
4477 ASSERT_EQ(0, rbd_snap_protect(image1
, "snap1"));
4478 ASSERT_EQ(0, rbd_snap_set(image1
, "snap1"));
4480 ASSERT_EQ(0, rbd_metadata_set(image1
, "key1", "value1"));
4481 ASSERT_EQ(0, rbd_metadata_set(image1
, "key3", "value3"));
4483 keys_len
= sizeof(keys
);
4484 vals_len
= sizeof(vals
);
4485 memset_rand(keys
, keys_len
);
4486 memset_rand(vals
, vals_len
);
4487 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4490 strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1);
4492 strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1);
4493 ASSERT_STREQ(keys
, "key1");
4494 ASSERT_STREQ(keys
+ strlen("key1") + 1, "key2");
4495 ASSERT_STREQ(keys
+ strlen("key1") + 1 + strlen("key2") + 1, "key3");
4496 ASSERT_STREQ(vals
, "value1");
4497 ASSERT_STREQ(vals
+ strlen("value1") + 1, "value2");
4498 ASSERT_STREQ(vals
+ strlen("value1") + 1 + strlen("value2") + 1, "value3");
4500 ASSERT_EQ(0, rbd_snap_set(image1
, NULL
));
4501 keys_len
= sizeof(keys
);
4502 vals_len
= sizeof(vals
);
4503 memset_rand(keys
, keys_len
);
4504 memset_rand(vals
, vals_len
);
4505 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4508 strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1);
4510 strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1);
4511 ASSERT_STREQ(keys
, "key1");
4512 ASSERT_STREQ(keys
+ strlen("key1") + 1, "key2");
4513 ASSERT_STREQ(keys
+ strlen("key1") + 1 + strlen("key2") + 1, "key3");
4514 ASSERT_STREQ(vals
, "value1");
4515 ASSERT_STREQ(vals
+ strlen("value1") + 1, "value2");
4516 ASSERT_STREQ(vals
+ strlen("value1") + 1 + strlen("value2") + 1, "value3");
4518 // test metadata with cloning
4520 ASSERT_EQ(0, rbd_get_features(image1
, &features
));
4522 string cname
= get_temp_image_name();
4523 EXPECT_EQ(0, rbd_clone(ioctx
, name
.c_str(), "snap1", ioctx
,
4524 cname
.c_str(), features
, &order
));
4526 ASSERT_EQ(0, rbd_open(ioctx
, cname
.c_str(), &image2
, NULL
));
4527 ASSERT_EQ(0, rbd_metadata_set(image2
, "key4", "value4"));
4529 keys_len
= sizeof(keys
);
4530 vals_len
= sizeof(vals
);
4531 memset_rand(keys
, keys_len
);
4532 memset_rand(vals
, vals_len
);
4533 ASSERT_EQ(0, rbd_metadata_list(image2
, "", 0, keys
, &keys_len
, vals
,
4535 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") +
4536 1 + strlen("key4") + 1);
4537 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1 +
4538 strlen("value3") + 1 + strlen("value4") + 1);
4539 ASSERT_STREQ(keys
+ strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") +
4541 ASSERT_STREQ(vals
+ strlen("value1") + 1 + strlen("value2") + 1 +
4542 strlen("value3") + 1, "value4");
4544 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4547 strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1);
4549 strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1);
4550 ASSERT_EQ(-ENOENT
, rbd_metadata_get(image1
, "key4", value
, &value_len
));
4552 // test short buffer cases
4553 keys_len
= strlen("key1") + 1;
4554 vals_len
= strlen("value1") + 1;
4555 memset_rand(keys
, keys_len
);
4556 memset_rand(vals
, vals_len
);
4557 ASSERT_EQ(0, rbd_metadata_list(image2
, "", 1, keys
, &keys_len
, vals
,
4559 ASSERT_EQ(keys_len
, strlen("key1") + 1);
4560 ASSERT_EQ(vals_len
, strlen("value1") + 1);
4561 ASSERT_STREQ(keys
, "key1");
4562 ASSERT_STREQ(vals
, "value1");
4564 ASSERT_EQ(-ERANGE
, rbd_metadata_list(image2
, "", 2, keys
, &keys_len
, vals
,
4566 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1);
4567 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1);
4569 ASSERT_EQ(-ERANGE
, rbd_metadata_list(image2
, "", 0, keys
, &keys_len
, vals
,
4571 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") +
4572 1 + strlen("key4") + 1);
4573 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1 +
4574 strlen("value3") + 1 + strlen("value4") + 1);
4576 // test `start` param
4577 keys_len
= sizeof(keys
);
4578 vals_len
= sizeof(vals
);
4579 memset_rand(keys
, keys_len
);
4580 memset_rand(vals
, vals_len
);
4581 ASSERT_EQ(0, rbd_metadata_list(image2
, "key2", 0, keys
, &keys_len
, vals
,
4583 ASSERT_EQ(keys_len
, strlen("key3") + 1 + strlen("key4") + 1);
4584 ASSERT_EQ(vals_len
, strlen("value3") + 1 + strlen("value4") + 1);
4585 ASSERT_STREQ(keys
, "key3");
4586 ASSERT_STREQ(vals
, "value3");
4588 ASSERT_EQ(0, rbd_close(image
));
4589 ASSERT_EQ(0, rbd_close(image1
));
4590 ASSERT_EQ(0, rbd_close(image2
));
4591 rados_ioctx_destroy(ioctx
);
4594 TEST_F(TestLibRBD
, MetadataPP
)
4596 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4598 librados::IoCtx ioctx
;
4599 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4602 string name
= get_temp_image_name();
4603 uint64_t size
= 2 << 20;
4607 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4609 librbd::Image image1
;
4610 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4611 map
<string
, bufferlist
> pairs
;
4612 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4613 ASSERT_TRUE(pairs
.empty());
4615 ASSERT_EQ(0, image1
.metadata_set("key1", "value1"));
4616 ASSERT_EQ(0, image1
.metadata_set("key2", "value2"));
4617 ASSERT_EQ(0, image1
.metadata_get("key1", &value
));
4618 ASSERT_EQ(0, strcmp("value1", value
.c_str()));
4619 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4620 ASSERT_EQ(2U, pairs
.size());
4621 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
4622 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4625 ASSERT_EQ(0, image1
.metadata_remove("key1"));
4626 ASSERT_EQ(0, image1
.metadata_remove("key3"));
4627 ASSERT_TRUE(image1
.metadata_get("key3", &value
) < 0);
4628 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4629 ASSERT_EQ(1U, pairs
.size());
4630 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4632 // test config setting
4633 ASSERT_EQ(0, image1
.metadata_set("conf_rbd_cache", "false"));
4634 ASSERT_EQ(-EINVAL
, image1
.metadata_set("conf_rbd_cache", "INVALID_VALUE"));
4635 ASSERT_EQ(0, image1
.metadata_remove("conf_rbd_cache"));
4637 // test metadata with snapshot adding
4638 ASSERT_EQ(0, image1
.snap_create("snap1"));
4639 ASSERT_EQ(0, image1
.snap_protect("snap1"));
4640 ASSERT_EQ(0, image1
.snap_set("snap1"));
4643 ASSERT_EQ(0, image1
.metadata_set("key1", "value1"));
4644 ASSERT_EQ(0, image1
.metadata_set("key3", "value3"));
4645 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4646 ASSERT_EQ(3U, pairs
.size());
4647 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
4648 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4649 ASSERT_EQ(0, strncmp("value3", pairs
["key3"].c_str(), 6));
4651 ASSERT_EQ(0, image1
.snap_set(NULL
));
4652 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4653 ASSERT_EQ(3U, pairs
.size());
4654 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
4655 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4656 ASSERT_EQ(0, strncmp("value3", pairs
["key3"].c_str(), 6));
4658 // test metadata with cloning
4659 string cname
= get_temp_image_name();
4660 librbd::Image image2
;
4661 ASSERT_EQ(0, image1
.features(&features
));
4662 EXPECT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "snap1", ioctx
,
4663 cname
.c_str(), features
, &order
));
4664 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, cname
.c_str(), NULL
));
4665 ASSERT_EQ(0, image2
.metadata_set("key4", "value4"));
4667 ASSERT_EQ(0, image2
.metadata_list("", 0, &pairs
));
4668 ASSERT_EQ(4U, pairs
.size());
4670 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4671 ASSERT_EQ(3U, pairs
.size());
4672 ASSERT_EQ(-ENOENT
, image1
.metadata_get("key4", &value
));
4675 TEST_F(TestLibRBD
, UpdateFeatures
)
4677 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4679 librados::IoCtx ioctx
;
4680 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4683 std::string name
= get_temp_image_name();
4684 uint64_t size
= 1 << 20;
4686 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4688 librbd::Image image
;
4689 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4692 ASSERT_EQ(0, image
.old_format(&old_format
));
4694 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, true));
4699 ASSERT_EQ(0, image
.features(&features
));
4701 // must provide a single feature
4702 ASSERT_EQ(-EINVAL
, image
.update_features(0, true));
4704 uint64_t disable_features
;
4705 disable_features
= features
& (RBD_FEATURE_EXCLUSIVE_LOCK
|
4706 RBD_FEATURE_OBJECT_MAP
|
4707 RBD_FEATURE_FAST_DIFF
|
4708 RBD_FEATURE_JOURNALING
);
4709 if (disable_features
!= 0) {
4710 ASSERT_EQ(0, image
.update_features(disable_features
, false));
4713 ASSERT_EQ(0, image
.features(&features
));
4714 ASSERT_EQ(0U, features
& disable_features
);
4716 // cannot enable object map nor journaling w/o exclusive lock
4717 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_OBJECT_MAP
, true));
4718 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_JOURNALING
, true));
4719 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, true));
4721 ASSERT_EQ(0, image
.features(&features
));
4722 ASSERT_NE(0U, features
& RBD_FEATURE_EXCLUSIVE_LOCK
);
4724 // cannot enable fast diff w/o object map
4725 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_FAST_DIFF
, true));
4726 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
, true));
4727 ASSERT_EQ(0, image
.features(&features
));
4728 ASSERT_NE(0U, features
& RBD_FEATURE_OBJECT_MAP
);
4730 uint64_t expected_flags
= RBD_FLAG_OBJECT_MAP_INVALID
;
4732 ASSERT_EQ(0, image
.get_flags(&flags
));
4733 ASSERT_EQ(expected_flags
, flags
);
4735 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
, false));
4736 ASSERT_EQ(0, image
.features(&features
));
4737 ASSERT_EQ(0U, features
& RBD_FEATURE_OBJECT_MAP
);
4739 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
|
4740 RBD_FEATURE_FAST_DIFF
|
4741 RBD_FEATURE_JOURNALING
, true));
4743 expected_flags
= RBD_FLAG_OBJECT_MAP_INVALID
| RBD_FLAG_FAST_DIFF_INVALID
;
4744 ASSERT_EQ(0, image
.get_flags(&flags
));
4745 ASSERT_EQ(expected_flags
, flags
);
4747 // cannot disable object map w/ fast diff
4748 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_OBJECT_MAP
, false));
4749 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_FAST_DIFF
, false));
4750 ASSERT_EQ(0, image
.features(&features
));
4751 ASSERT_EQ(0U, features
& RBD_FEATURE_FAST_DIFF
);
4753 expected_flags
= RBD_FLAG_OBJECT_MAP_INVALID
;
4754 ASSERT_EQ(0, image
.get_flags(&flags
));
4755 ASSERT_EQ(expected_flags
, flags
);
4757 // cannot disable exclusive lock w/ object map
4758 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, false));
4759 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
, false));
4761 // cannot disable exclusive lock w/ journaling
4762 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, false));
4763 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_JOURNALING
, false));
4765 ASSERT_EQ(0, image
.get_flags(&flags
));
4766 ASSERT_EQ(0U, flags
);
4768 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, false));
4770 ASSERT_EQ(0, image
.features(&features
));
4771 if ((features
& RBD_FEATURE_DEEP_FLATTEN
) != 0) {
4772 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_DEEP_FLATTEN
, false));
4774 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_DEEP_FLATTEN
, true));
4777 TEST_F(TestLibRBD
, RebuildObjectMap
)
4779 librados::IoCtx ioctx
;
4780 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4783 std::string name
= get_temp_image_name();
4784 uint64_t size
= 1 << 20;
4786 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4788 PrintProgress prog_ctx
;
4789 std::string object_map_oid
;
4793 librbd::Image image
;
4794 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4797 ASSERT_EQ(0, image
.features(&features
));
4798 if ((features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
4799 ASSERT_EQ(-EINVAL
, image
.rebuild_object_map(prog_ctx
));
4803 ASSERT_EQ((ssize_t
)bl
.length(), image
.write(0, bl
.length(), bl
));
4805 ASSERT_EQ(0, image
.snap_create("snap1"));
4806 ASSERT_EQ((ssize_t
)bl
.length(), image
.write(1<<order
, bl
.length(), bl
));
4808 std::string image_id
;
4809 ASSERT_EQ(0, get_image_id(image
, &image_id
));
4810 object_map_oid
= RBD_OBJECT_MAP_PREFIX
+ image_id
;
4813 // corrupt the object map
4814 ASSERT_EQ(0, ioctx
.write(object_map_oid
, bl
, bl
.length(), 0));
4816 librbd::Image image1
;
4817 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4821 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4822 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4823 ASSERT_TRUE(lock_owner
);
4826 ASSERT_EQ(0, image1
.get_flags(&flags
));
4827 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0);
4829 ASSERT_EQ(0, image1
.rebuild_object_map(prog_ctx
));
4831 librbd::Image image2
;
4832 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4835 ASSERT_EQ((ssize_t
)bl
.length(), image2
.read(0, bl
.length(), read_bl
));
4836 ASSERT_TRUE(bl
.contents_equal(read_bl
));
4839 ASSERT_EQ((ssize_t
)bl
.length(), image2
.read(1<<order
, bl
.length(), read_bl
));
4840 ASSERT_TRUE(bl
.contents_equal(read_bl
));
4842 ASSERT_PASSED(validate_object_map
, image1
);
4843 ASSERT_PASSED(validate_object_map
, image2
);
4846 TEST_F(TestLibRBD
, RebuildNewObjectMap
)
4848 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
4850 rados_ioctx_t ioctx
;
4851 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
4853 std::string name
= get_temp_image_name();
4854 uint64_t size
= 1 << 20;
4856 uint64_t features
= RBD_FEATURE_EXCLUSIVE_LOCK
;
4857 ASSERT_EQ(0, create_image_full(ioctx
, name
.c_str(), size
, &order
,
4861 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
4862 ASSERT_EQ(0, rbd_update_features(image
, RBD_FEATURE_OBJECT_MAP
, true));
4863 ASSERT_EQ(0, rbd_rebuild_object_map(image
, print_progress_percent
, NULL
));
4865 ASSERT_PASSED(validate_object_map
, image
);
4867 ASSERT_EQ(0, rbd_close(image
));
4868 rados_ioctx_destroy(ioctx
);
4871 TEST_F(TestLibRBD
, CheckObjectMap
)
4873 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
4875 librados::IoCtx ioctx
;
4876 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4879 std::string name
= get_temp_image_name();
4880 uint64_t size
= 1 << 20;
4882 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4884 PrintProgress prog_ctx
;
4889 librbd::Image image
;
4890 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4893 ASSERT_EQ(0, image
.features(&features
));
4895 ASSERT_EQ((ssize_t
)bl1
.length(), image
.write(0, bl1
.length(), bl1
));
4897 ASSERT_EQ(0, image
.snap_create("snap1"));
4898 ASSERT_EQ((ssize_t
)bl1
.length(), image
.write(1<<order
, bl1
.length(), bl1
));
4901 librbd::Image image1
;
4902 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4904 std::string image_id
;
4905 ASSERT_EQ(0, get_image_id(image1
, &image_id
));
4907 std::string object_map_oid
= RBD_OBJECT_MAP_PREFIX
+ image_id
;
4909 ASSERT_LT(0, ioctx
.read(object_map_oid
, bl2
, 1024, 0));
4912 ASSERT_EQ((ssize_t
)bl1
.length(), image1
.write(3 * (1 << 18), bl1
.length(), bl1
));
4913 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4914 ASSERT_TRUE(lock_owner
);
4916 //reopen image to reread now corrupt object map from disk
4920 ASSERT_LT(0, ioctx
.read(object_map_oid
, bl1
, 1024, 0));
4921 ASSERT_FALSE(bl1
.contents_equal(bl2
));
4923 ASSERT_EQ(0, ioctx
.write_full(object_map_oid
, bl2
));
4924 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4927 ASSERT_EQ(0, image1
.get_flags(&flags
));
4928 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) == 0);
4930 ASSERT_EQ(0, image1
.check_object_map(prog_ctx
));
4932 ASSERT_EQ(0, image1
.get_flags(&flags
));
4933 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0);
4936 TEST_F(TestLibRBD
, BlockingAIO
)
4938 librados::IoCtx ioctx
;
4939 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4941 bool skip_discard
= is_skip_partial_discard_enabled();
4944 std::string name
= get_temp_image_name();
4945 uint64_t size
= 1 << 20;
4947 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4949 std::string non_blocking_aio
;
4950 ASSERT_EQ(0, _rados
.conf_get("rbd_non_blocking_aio", non_blocking_aio
));
4951 ASSERT_EQ(0, _rados
.conf_set("rbd_non_blocking_aio", "0"));
4952 BOOST_SCOPE_EXIT( (non_blocking_aio
) ) {
4953 ASSERT_EQ(0, _rados
.conf_set("rbd_non_blocking_aio",
4954 non_blocking_aio
.c_str()));
4955 } BOOST_SCOPE_EXIT_END
;
4957 librbd::Image image
;
4958 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4961 ASSERT_EQ(0, image
.write(0, bl
.length(), bl
));
4963 bl
.append(std::string(256, '1'));
4964 librbd::RBD::AioCompletion
*write_comp
=
4965 new librbd::RBD::AioCompletion(NULL
, NULL
);
4966 ASSERT_EQ(0, image
.aio_write(0, bl
.length(), bl
, write_comp
));
4968 librbd::RBD::AioCompletion
*flush_comp
=
4969 new librbd::RBD::AioCompletion(NULL
, NULL
);
4970 ASSERT_EQ(0, image
.aio_flush(flush_comp
));
4971 ASSERT_EQ(0, flush_comp
->wait_for_complete());
4972 ASSERT_EQ(0, flush_comp
->get_return_value());
4973 flush_comp
->release();
4975 ASSERT_EQ(1, write_comp
->is_complete());
4976 ASSERT_EQ(0, write_comp
->get_return_value());
4977 write_comp
->release();
4979 librbd::RBD::AioCompletion
*discard_comp
=
4980 new librbd::RBD::AioCompletion(NULL
, NULL
);
4981 ASSERT_EQ(0, image
.aio_discard(128, 128, discard_comp
));
4982 ASSERT_EQ(0, discard_comp
->wait_for_complete());
4983 discard_comp
->release();
4985 librbd::RBD::AioCompletion
*read_comp
=
4986 new librbd::RBD::AioCompletion(NULL
, NULL
);
4988 image
.aio_read(0, bl
.length(), read_bl
, read_comp
);
4989 ASSERT_EQ(0, read_comp
->wait_for_complete());
4990 ASSERT_EQ((ssize_t
)bl
.length(), read_comp
->get_return_value());
4991 read_comp
->release();
4993 bufferlist expected_bl
;
4994 expected_bl
.append(std::string(128, '1'));
4995 expected_bl
.append(std::string(128, skip_discard
? '1' : '\0'));
4996 ASSERT_TRUE(expected_bl
.contents_equal(read_bl
));
4999 TEST_F(TestLibRBD
, ExclusiveLockTransition
)
5001 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
5003 librados::IoCtx ioctx
;
5004 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5007 std::string name
= get_temp_image_name();
5009 uint64_t size
= 1 << 18;
5011 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5013 librbd::Image image1
;
5014 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5016 librbd::Image image2
;
5017 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5019 std::list
<librbd::RBD::AioCompletion
*> comps
;
5020 ceph::bufferlist bl
;
5021 bl
.append(std::string(1 << order
, '1'));
5022 for (size_t object_no
= 0; object_no
< (size
>> 12); ++object_no
) {
5023 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
,
5025 comps
.push_back(comp
);
5026 if (object_no
% 2 == 0) {
5027 ASSERT_EQ(0, image1
.aio_write(object_no
<< order
, bl
.length(), bl
, comp
));
5029 ASSERT_EQ(0, image2
.aio_write(object_no
<< order
, bl
.length(), bl
, comp
));
5033 while (!comps
.empty()) {
5034 librbd::RBD::AioCompletion
*comp
= comps
.front();
5036 ASSERT_EQ(0, comp
->wait_for_complete());
5037 ASSERT_EQ(1, comp
->is_complete());
5041 librbd::Image image3
;
5042 ASSERT_EQ(0, rbd
.open(ioctx
, image3
, name
.c_str(), NULL
));
5043 for (size_t object_no
= 0; object_no
< (size
>> 12); ++object_no
) {
5045 ASSERT_EQ((ssize_t
)bl
.length(), image3
.read(object_no
<< order
, bl
.length(),
5047 ASSERT_TRUE(bl
.contents_equal(read_bl
));
5050 ASSERT_PASSED(validate_object_map
, image1
);
5051 ASSERT_PASSED(validate_object_map
, image2
);
5052 ASSERT_PASSED(validate_object_map
, image3
);
5055 TEST_F(TestLibRBD
, ExclusiveLockReadTransition
)
5057 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
5059 librados::IoCtx ioctx
;
5060 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5063 std::string name
= get_temp_image_name();
5065 uint64_t size
= 1 << 18;
5067 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5069 librbd::Image image1
;
5070 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5073 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
5074 ASSERT_FALSE(lock_owner
);
5076 // journaling should force read ops to acquire the lock
5078 ASSERT_EQ(0, image1
.read(0, 0, read_bl
));
5080 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
5081 ASSERT_TRUE(lock_owner
);
5083 librbd::Image image2
;
5084 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5086 std::list
<librbd::RBD::AioCompletion
*> comps
;
5087 std::list
<bufferlist
> read_bls
;
5088 for (size_t object_no
= 0; object_no
< (size
>> 12); ++object_no
) {
5089 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
,
5091 comps
.push_back(comp
);
5092 read_bls
.emplace_back();
5093 if (object_no
% 2 == 0) {
5094 ASSERT_EQ(0, image1
.aio_read(object_no
<< order
, 1 << order
, read_bls
.back(), comp
));
5096 ASSERT_EQ(0, image2
.aio_read(object_no
<< order
, 1 << order
, read_bls
.back(), comp
));
5100 while (!comps
.empty()) {
5101 librbd::RBD::AioCompletion
*comp
= comps
.front();
5103 ASSERT_EQ(0, comp
->wait_for_complete());
5104 ASSERT_EQ(1, comp
->is_complete());
5109 TEST_F(TestLibRBD
, CacheMayCopyOnWrite
) {
5110 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
5112 librados::IoCtx ioctx
;
5113 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5116 std::string name
= get_temp_image_name();
5118 uint64_t size
= 1 << 18;
5120 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5122 librbd::Image image
;
5123 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5124 ASSERT_EQ(0, image
.snap_create("one"));
5125 ASSERT_EQ(0, image
.snap_protect("one"));
5127 std::string clone_name
= this->get_temp_image_name();
5128 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "one", ioctx
, clone_name
.c_str(),
5129 RBD_FEATURE_LAYERING
, &order
));
5131 librbd::Image clone
;
5132 ASSERT_EQ(0, rbd
.open(ioctx
, clone
, clone_name
.c_str(), NULL
));
5133 ASSERT_EQ(0, clone
.flush());
5135 bufferlist expect_bl
;
5136 expect_bl
.append(std::string(1024, '\0'));
5138 // test double read path
5140 uint64_t offset
= 0;
5141 ASSERT_EQ(1024, clone
.read(offset
+ 2048, 1024, read_bl
));
5142 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
5144 bufferlist write_bl
;
5145 write_bl
.append(std::string(1024, '1'));
5146 ASSERT_EQ(1024, clone
.write(offset
, write_bl
.length(), write_bl
));
5149 ASSERT_EQ(1024, clone
.read(offset
+ 2048, 1024, read_bl
));
5150 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
5152 // test read retry path
5153 offset
= 1 << order
;
5154 ASSERT_EQ(1024, clone
.write(offset
, write_bl
.length(), write_bl
));
5157 ASSERT_EQ(1024, clone
.read(offset
+ 2048, 1024, read_bl
));
5158 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
5161 TEST_F(TestLibRBD
, FlushEmptyOpsOnExternalSnapshot
) {
5162 std::string cache_enabled
;
5163 ASSERT_EQ(0, _rados
.conf_get("rbd_cache", cache_enabled
));
5164 ASSERT_EQ(0, _rados
.conf_set("rbd_cache", "false"));
5165 BOOST_SCOPE_EXIT( (cache_enabled
) ) {
5166 ASSERT_EQ(0, _rados
.conf_set("rbd_cache", cache_enabled
.c_str()));
5167 } BOOST_SCOPE_EXIT_END
;
5169 librados::IoCtx ioctx
;
5170 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5173 std::string name
= get_temp_image_name();
5174 uint64_t size
= 1 << 18;
5176 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5178 librbd::Image image1
;
5179 librbd::Image image2
;
5180 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5181 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5182 ASSERT_EQ(0, image1
.snap_create("snap1"));
5184 librbd::RBD::AioCompletion
*read_comp
=
5185 new librbd::RBD::AioCompletion(NULL
, NULL
);
5187 image2
.aio_read(0, 1024, read_bl
, read_comp
);
5188 ASSERT_EQ(0, read_comp
->wait_for_complete());
5189 read_comp
->release();
5192 TEST_F(TestLibRBD
, TestImageOptions
)
5194 rados_ioctx_t ioctx
;
5195 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5197 //make create image options
5198 uint64_t features
= RBD_FEATURE_LAYERING
| RBD_FEATURE_STRIPINGV2
;
5200 uint64_t stripe_unit
= IMAGE_STRIPE_UNIT
;
5201 uint64_t stripe_count
= IMAGE_STRIPE_COUNT
;
5202 rbd_image_options_t opts
;
5203 rbd_image_options_create(&opts
);
5206 ASSERT_EQ(-EINVAL
, rbd_image_options_is_set(opts
, 12345, &is_set
));
5207 ASSERT_EQ(0, rbd_image_options_is_set(opts
, RBD_IMAGE_OPTION_FORMAT
,
5209 ASSERT_FALSE(is_set
);
5211 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_FORMAT
,
5213 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_FEATURES
,
5215 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_ORDER
,
5217 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_STRIPE_UNIT
,
5219 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_STRIPE_COUNT
,
5222 ASSERT_EQ(0, rbd_image_options_is_set(opts
, RBD_IMAGE_OPTION_FORMAT
,
5224 ASSERT_TRUE(is_set
);
5226 std::string parent_name
= get_temp_image_name();
5229 ASSERT_EQ(0, rbd_create4(ioctx
, parent_name
.c_str(), 4<<20, opts
));
5231 // check order is returned in opts
5232 ASSERT_EQ(0, rbd_image_options_get_uint64(opts
, RBD_IMAGE_OPTION_ORDER
,
5234 ASSERT_NE((uint64_t)0, order
);
5236 // write some data to parent
5238 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, NULL
));
5239 char *data
= (char *)"testdata";
5240 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 0, strlen(data
), data
));
5241 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 12, strlen(data
), data
));
5243 // create a snapshot, reopen as the parent we're interested in
5244 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
5245 ASSERT_EQ(0, rbd_close(parent
));
5246 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, "parent_snap"));
5249 std::string child_name
= get_temp_image_name();
5250 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
5251 ASSERT_EQ(0, rbd_clone3(ioctx
, parent_name
.c_str(), "parent_snap", ioctx
,
5252 child_name
.c_str(), opts
));
5255 std::string copy1_name
= get_temp_image_name();
5256 ASSERT_EQ(0, rbd_copy3(parent
, ioctx
, copy1_name
.c_str(), opts
));
5257 std::string copy2_name
= get_temp_image_name();
5258 ASSERT_EQ(0, rbd_copy_with_progress3(parent
, ioctx
, copy2_name
.c_str(), opts
,
5259 print_progress_percent
, NULL
));
5261 ASSERT_EQ(0, rbd_close(parent
));
5263 rbd_image_options_destroy(opts
);
5265 rados_ioctx_destroy(ioctx
);
5268 TEST_F(TestLibRBD
, TestImageOptionsPP
)
5270 librados::IoCtx ioctx
;
5271 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5273 //make create image options
5274 uint64_t features
= RBD_FEATURE_LAYERING
| RBD_FEATURE_STRIPINGV2
;
5276 uint64_t stripe_unit
= IMAGE_STRIPE_UNIT
;
5277 uint64_t stripe_count
= IMAGE_STRIPE_COUNT
;
5278 librbd::ImageOptions opts
;
5279 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_FORMAT
, static_cast<uint64_t>(2)));
5280 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_FEATURES
, features
));
5281 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_ORDER
, order
));
5282 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_STRIPE_UNIT
, stripe_unit
));
5283 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_STRIPE_COUNT
, stripe_count
));
5286 std::string parent_name
= get_temp_image_name();
5289 ASSERT_EQ(0, rbd
.create4(ioctx
, parent_name
.c_str(), 4<<20, opts
));
5291 // check order is returned in opts
5292 ASSERT_EQ(0, opts
.get(RBD_IMAGE_OPTION_ORDER
, &order
));
5293 ASSERT_NE((uint64_t)0, order
);
5295 // write some data to parent
5296 librbd::Image parent
;
5297 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), NULL
));
5301 bl
.append(buffer::create(len
));
5303 ASSERT_EQ(len
, parent
.write(0, len
, bl
));
5304 ASSERT_EQ(len
, parent
.write(len
, len
, bl
));
5306 // create a snapshot, reopen as the parent we're interested in
5307 ASSERT_EQ(0, parent
.snap_create("parent_snap"));
5308 ASSERT_EQ(0, parent
.close());
5309 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), "parent_snap"));
5312 std::string child_name
= get_temp_image_name();
5313 ASSERT_EQ(0, parent
.snap_protect("parent_snap"));
5314 ASSERT_EQ(0, rbd
.clone3(ioctx
, parent_name
.c_str(), "parent_snap", ioctx
,
5315 child_name
.c_str(), opts
));
5318 std::string copy1_name
= get_temp_image_name();
5319 ASSERT_EQ(0, parent
.copy3(ioctx
, copy1_name
.c_str(), opts
));
5320 std::string copy2_name
= get_temp_image_name();
5322 ASSERT_EQ(0, parent
.copy_with_progress3(ioctx
, copy2_name
.c_str(), opts
, pp
));
5324 ASSERT_EQ(0, parent
.close());
5327 TEST_F(TestLibRBD
, EventSocketPipe
)
5329 EventSocket event_sock
;
5330 int pipe_fd
[2]; // read and write fd
5333 ASSERT_EQ(0, pipe(pipe_fd
));
5335 ASSERT_FALSE(event_sock
.is_valid());
5337 ASSERT_EQ(-EINVAL
, event_sock
.init(pipe_fd
[1], EVENT_SOCKET_TYPE_NONE
));
5338 ASSERT_FALSE(event_sock
.is_valid());
5340 ASSERT_EQ(-EINVAL
, event_sock
.init(pipe_fd
[1], 44));
5341 ASSERT_FALSE(event_sock
.is_valid());
5343 #ifndef HAVE_EVENTFD
5344 ASSERT_EQ(-EINVAL
, event_sock
.init(pipe_fd
[1], EVENT_SOCKET_TYPE_EVENTFD
));
5345 ASSERT_FALSE(event_sock
.is_valid());
5348 ASSERT_EQ(0, event_sock
.init(pipe_fd
[1], EVENT_SOCKET_TYPE_PIPE
));
5349 ASSERT_TRUE(event_sock
.is_valid());
5350 ASSERT_EQ(0, event_sock
.notify());
5351 ASSERT_EQ(1, read(pipe_fd
[0], buf
, 32));
5352 ASSERT_EQ('i', buf
[0]);
5358 TEST_F(TestLibRBD
, EventSocketEventfd
)
5361 EventSocket event_sock
;
5363 struct pollfd poll_fd
;
5366 event_fd
= eventfd(0, EFD_NONBLOCK
);
5367 ASSERT_NE(-1, event_fd
);
5369 ASSERT_FALSE(event_sock
.is_valid());
5371 ASSERT_EQ(-EINVAL
, event_sock
.init(event_fd
, EVENT_SOCKET_TYPE_NONE
));
5372 ASSERT_FALSE(event_sock
.is_valid());
5374 ASSERT_EQ(-EINVAL
, event_sock
.init(event_fd
, 44));
5375 ASSERT_FALSE(event_sock
.is_valid());
5377 ASSERT_EQ(0, event_sock
.init(event_fd
, EVENT_SOCKET_TYPE_EVENTFD
));
5378 ASSERT_TRUE(event_sock
.is_valid());
5379 ASSERT_EQ(0, event_sock
.notify());
5381 poll_fd
.fd
= event_fd
;
5382 poll_fd
.events
= POLLIN
;
5383 ASSERT_EQ(1, poll(&poll_fd
, 1, -1));
5384 ASSERT_TRUE(poll_fd
.revents
& POLLIN
);
5386 ASSERT_EQ(static_cast<ssize_t
>(sizeof(uint64_t)), read(event_fd
, buf
, 32));
5387 ASSERT_EQ(1U, *reinterpret_cast<uint64_t *>(buf
));
5393 TEST_F(TestLibRBD
, ImagePollIO
)
5396 rados_ioctx_t ioctx
;
5397 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5401 std::string name
= get_temp_image_name();
5402 uint64_t size
= 2 << 20;
5403 int fd
= eventfd(0, EFD_NONBLOCK
);
5405 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
5406 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
5408 ASSERT_EQ(0, rbd_set_image_notification(image
, fd
, EVENT_SOCKET_TYPE_EVENTFD
));
5410 char test_data
[TEST_IO_SIZE
+ 1];
5411 char zero_data
[TEST_IO_SIZE
+ 1];
5414 for (i
= 0; i
< TEST_IO_SIZE
; ++i
)
5415 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
5416 test_data
[TEST_IO_SIZE
] = '\0';
5417 memset(zero_data
, 0, sizeof(zero_data
));
5419 for (i
= 0; i
< 5; ++i
)
5420 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
5422 for (i
= 5; i
< 10; ++i
)
5423 ASSERT_PASSED(aio_write_test_data_and_poll
, image
, fd
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
5425 for (i
= 5; i
< 10; ++i
)
5426 ASSERT_PASSED(aio_read_test_data_and_poll
, image
, fd
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
5428 ASSERT_EQ(0, rbd_close(image
));
5429 rados_ioctx_destroy(ioctx
);
5435 static bool operator==(const mirror_peer_t
&lhs
, const mirror_peer_t
&rhs
) {
5436 return (lhs
.uuid
== rhs
.uuid
&&
5437 lhs
.cluster_name
== rhs
.cluster_name
&&
5438 lhs
.client_name
== rhs
.client_name
);
5441 static std::ostream
& operator<<(std::ostream
&os
, const mirror_peer_t
&peer
) {
5442 os
<< "uuid=" << peer
.uuid
<< ", "
5443 << "cluster=" << peer
.cluster_name
<< ", "
5444 << "client=" << peer
.client_name
;
5448 } // namespace librbd
5450 TEST_F(TestLibRBD
, Mirror
) {
5451 librados::IoCtx ioctx
;
5452 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5456 std::vector
<librbd::mirror_peer_t
> expected_peers
;
5457 std::vector
<librbd::mirror_peer_t
> peers
;
5458 ASSERT_EQ(0, rbd
.mirror_peer_list(ioctx
, &peers
));
5459 ASSERT_EQ(expected_peers
, peers
);
5462 ASSERT_EQ(-EINVAL
, rbd
.mirror_peer_add(ioctx
, &uuid1
, "cluster1", "client"));
5464 rbd_mirror_mode_t mirror_mode
;
5465 ASSERT_EQ(0, rbd
.mirror_mode_get(ioctx
, &mirror_mode
));
5466 ASSERT_EQ(RBD_MIRROR_MODE_DISABLED
, mirror_mode
);
5468 ASSERT_EQ(0, rbd
.mirror_mode_set(ioctx
, RBD_MIRROR_MODE_IMAGE
));
5469 ASSERT_EQ(0, rbd
.mirror_mode_get(ioctx
, &mirror_mode
));
5471 // Add some images to the pool
5473 std::string parent_name
= get_temp_image_name();
5474 std::string child_name
= get_temp_image_name();
5475 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, parent_name
.c_str(), 2 << 20,
5479 ASSERT_EQ(0, get_features(&old_format
, &features
));
5480 if ((features
& RBD_FEATURE_LAYERING
) != 0) {
5481 librbd::Image parent
;
5482 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), NULL
));
5483 ASSERT_EQ(0, parent
.snap_create("parent_snap"));
5484 ASSERT_EQ(0, parent
.close());
5485 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), "parent_snap"));
5486 ASSERT_EQ(0, parent
.snap_protect("parent_snap"));
5487 ASSERT_EQ(0, parent
.close());
5488 ASSERT_EQ(0, rbd
.clone(ioctx
, parent_name
.c_str(), "parent_snap", ioctx
,
5489 child_name
.c_str(), features
, &order
));
5492 ASSERT_EQ(RBD_MIRROR_MODE_IMAGE
, mirror_mode
);
5494 ASSERT_EQ(0, rbd
.mirror_mode_set(ioctx
, RBD_MIRROR_MODE_POOL
));
5495 ASSERT_EQ(0, rbd
.mirror_mode_get(ioctx
, &mirror_mode
));
5496 ASSERT_EQ(RBD_MIRROR_MODE_POOL
, mirror_mode
);
5500 ASSERT_EQ(0, rbd
.mirror_peer_add(ioctx
, &uuid1
, "cluster1", "client"));
5501 ASSERT_EQ(0, rbd
.mirror_peer_add(ioctx
, &uuid2
, "cluster2", "admin"));
5502 ASSERT_EQ(-EEXIST
, rbd
.mirror_peer_add(ioctx
, &uuid3
, "cluster1", "foo"));
5503 ASSERT_EQ(0, rbd
.mirror_peer_add(ioctx
, &uuid3
, "cluster3", "admin"));
5505 ASSERT_EQ(0, rbd
.mirror_peer_list(ioctx
, &peers
));
5506 auto sort_peers
= [](const librbd::mirror_peer_t
&lhs
,
5507 const librbd::mirror_peer_t
&rhs
) {
5508 return lhs
.uuid
< rhs
.uuid
;
5511 {uuid1
, "cluster1", "client"},
5512 {uuid2
, "cluster2", "admin"},
5513 {uuid3
, "cluster3", "admin"}};
5514 std::sort(expected_peers
.begin(), expected_peers
.end(), sort_peers
);
5515 ASSERT_EQ(expected_peers
, peers
);
5517 ASSERT_EQ(0, rbd
.mirror_peer_remove(ioctx
, "uuid4"));
5518 ASSERT_EQ(0, rbd
.mirror_peer_remove(ioctx
, uuid2
));
5520 ASSERT_EQ(-ENOENT
, rbd
.mirror_peer_set_client(ioctx
, "uuid4", "new client"));
5521 ASSERT_EQ(0, rbd
.mirror_peer_set_client(ioctx
, uuid1
, "new client"));
5523 ASSERT_EQ(-ENOENT
, rbd
.mirror_peer_set_cluster(ioctx
, "uuid4",
5525 ASSERT_EQ(0, rbd
.mirror_peer_set_cluster(ioctx
, uuid3
, "new cluster"));
5527 ASSERT_EQ(0, rbd
.mirror_peer_list(ioctx
, &peers
));
5529 {uuid1
, "cluster1", "new client"},
5530 {uuid3
, "new cluster", "admin"}};
5531 std::sort(expected_peers
.begin(), expected_peers
.end(), sort_peers
);
5532 ASSERT_EQ(expected_peers
, peers
);
5534 ASSERT_EQ(-EBUSY
, rbd
.mirror_mode_set(ioctx
, RBD_MIRROR_MODE_DISABLED
));
5537 TEST_F(TestLibRBD
, FlushCacheWithCopyupOnExternalSnapshot
) {
5538 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
5540 librados::IoCtx ioctx
;
5541 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5544 librbd::Image image
;
5545 std::string name
= get_temp_image_name();
5547 uint64_t size
= 1 << 18;
5550 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5551 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5554 bl
.append(std::string(size
, '1'));
5555 ASSERT_EQ((int)size
, image
.write(0, size
, bl
));
5556 ASSERT_EQ(0, image
.snap_create("one"));
5557 ASSERT_EQ(0, image
.snap_protect("one"));
5559 std::string clone_name
= this->get_temp_image_name();
5560 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "one", ioctx
, clone_name
.c_str(),
5561 RBD_FEATURE_LAYERING
, &order
));
5562 ASSERT_EQ(0, rbd
.open(ioctx
, image
, clone_name
.c_str(), NULL
));
5564 librbd::Image image2
;
5565 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, clone_name
.c_str(), NULL
));
5567 // prepare CoW writeback that will be flushed on next op
5569 bl
.append(std::string(1, '1'));
5570 ASSERT_EQ(0, image
.flush());
5571 ASSERT_EQ(1, image
.write(0, 1, bl
));
5572 ASSERT_EQ(0, image2
.snap_create("snap1"));
5574 librbd::RBD::AioCompletion
*read_comp
=
5575 new librbd::RBD::AioCompletion(NULL
, NULL
);
5577 image
.aio_read(0, 1024, read_bl
, read_comp
);
5578 ASSERT_EQ(0, read_comp
->wait_for_complete());
5579 read_comp
->release();
5582 TEST_F(TestLibRBD
, ExclusiveLock
)
5584 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
5586 static char buf
[10];
5588 rados_ioctx_t ioctx
;
5589 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5591 std::string name
= get_temp_image_name();
5592 uint64_t size
= 2 << 20;
5594 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
5597 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image1
, NULL
));
5600 ASSERT_EQ(0, rbd_lock_acquire(image1
, RBD_LOCK_MODE_EXCLUSIVE
));
5601 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5602 ASSERT_TRUE(lock_owner
);
5604 rbd_lock_mode_t lock_mode
;
5605 char *lock_owners
[1];
5606 size_t max_lock_owners
= 0;
5607 ASSERT_EQ(-ERANGE
, rbd_lock_get_owners(image1
, &lock_mode
, lock_owners
,
5609 ASSERT_EQ(1U, max_lock_owners
);
5611 max_lock_owners
= 2;
5612 ASSERT_EQ(0, rbd_lock_get_owners(image1
, &lock_mode
, lock_owners
,
5614 ASSERT_EQ(RBD_LOCK_MODE_EXCLUSIVE
, lock_mode
);
5615 ASSERT_STRNE("", lock_owners
[0]);
5616 ASSERT_EQ(1U, max_lock_owners
);
5619 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image2
, NULL
));
5621 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5622 ASSERT_FALSE(lock_owner
);
5624 ASSERT_EQ(-EOPNOTSUPP
, rbd_lock_break(image1
, RBD_LOCK_MODE_SHARED
, ""));
5625 ASSERT_EQ(-EBUSY
, rbd_lock_break(image1
, RBD_LOCK_MODE_EXCLUSIVE
,
5628 ASSERT_EQ(0, rbd_lock_release(image1
));
5629 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5630 ASSERT_FALSE(lock_owner
);
5632 ASSERT_EQ(-ENOENT
, rbd_lock_break(image1
, RBD_LOCK_MODE_EXCLUSIVE
,
5634 rbd_lock_get_owners_cleanup(lock_owners
, max_lock_owners
);
5636 ASSERT_EQ(-EROFS
, rbd_write(image1
, 0, sizeof(buf
), buf
));
5637 ASSERT_EQ((ssize_t
)sizeof(buf
), rbd_write(image2
, 0, sizeof(buf
), buf
));
5639 ASSERT_EQ(0, rbd_lock_acquire(image2
, RBD_LOCK_MODE_EXCLUSIVE
));
5640 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5641 ASSERT_TRUE(lock_owner
);
5643 ASSERT_EQ(0, rbd_lock_release(image2
));
5644 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5645 ASSERT_FALSE(lock_owner
);
5647 ASSERT_EQ(0, rbd_lock_acquire(image1
, RBD_LOCK_MODE_EXCLUSIVE
));
5648 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5649 ASSERT_TRUE(lock_owner
);
5651 ASSERT_EQ((ssize_t
)sizeof(buf
), rbd_write(image1
, 0, sizeof(buf
), buf
));
5652 ASSERT_EQ(-EROFS
, rbd_write(image2
, 0, sizeof(buf
), buf
));
5654 ASSERT_EQ(0, rbd_lock_release(image1
));
5655 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5656 ASSERT_FALSE(lock_owner
);
5660 const auto pingpong
= [&,this](int m_id
, rbd_image_t
&m_image
) {
5661 for (int i
= 0; i
< 10; i
++) {
5663 lock_guard
<mutex
> locker(lock
);
5664 if (owner_id
== m_id
) {
5665 std::cout
<< m_id
<< ": releasing exclusive lock" << std::endl
;
5666 EXPECT_EQ(0, rbd_lock_release(m_image
));
5668 EXPECT_EQ(0, rbd_is_exclusive_lock_owner(m_image
, &lock_owner
));
5669 EXPECT_FALSE(lock_owner
);
5671 std::cout
<< m_id
<< ": exclusive lock released" << std::endl
;
5676 std::cout
<< m_id
<< ": acquiring exclusive lock" << std::endl
;
5679 r
= rbd_lock_acquire(m_image
, RBD_LOCK_MODE_EXCLUSIVE
);
5683 } while (r
== -EROFS
);
5687 EXPECT_EQ(0, rbd_is_exclusive_lock_owner(m_image
, &lock_owner
));
5688 EXPECT_TRUE(lock_owner
);
5689 std::cout
<< m_id
<< ": exclusive lock acquired" << std::endl
;
5691 lock_guard
<mutex
> locker(lock
);
5694 usleep(rand() % 50000);
5697 lock_guard
<mutex
> locker(lock
);
5698 if (owner_id
== m_id
) {
5699 EXPECT_EQ(0, rbd_lock_release(m_image
));
5701 EXPECT_EQ(0, rbd_is_exclusive_lock_owner(m_image
, &lock_owner
));
5702 EXPECT_FALSE(lock_owner
);
5706 thread
ping(bind(pingpong
, 1, ref(image1
)));
5707 thread
pong(bind(pingpong
, 2, ref(image2
)));
5712 ASSERT_EQ(0, rbd_lock_acquire(image2
, RBD_LOCK_MODE_EXCLUSIVE
));
5713 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5714 ASSERT_TRUE(lock_owner
);
5716 ASSERT_EQ(0, rbd_close(image2
));
5718 ASSERT_EQ(0, rbd_lock_acquire(image1
, RBD_LOCK_MODE_EXCLUSIVE
));
5719 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5720 ASSERT_TRUE(lock_owner
);
5722 ASSERT_EQ(0, rbd_close(image1
));
5723 rados_ioctx_destroy(ioctx
);
5726 TEST_F(TestLibRBD
, BreakLock
)
5728 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
5730 static char buf
[10];
5732 rados_t blacklist_cluster
;
5733 ASSERT_EQ("", connect_cluster(&blacklist_cluster
));
5735 rados_ioctx_t ioctx
, blacklist_ioctx
;
5736 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
5737 ASSERT_EQ(0, rados_ioctx_create(blacklist_cluster
, m_pool_name
.c_str(),
5740 std::string name
= get_temp_image_name();
5741 uint64_t size
= 2 << 20;
5743 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
5745 rbd_image_t image
, blacklist_image
;
5746 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
5747 ASSERT_EQ(0, rbd_open(blacklist_ioctx
, name
.c_str(), &blacklist_image
, NULL
));
5749 ASSERT_EQ(0, rbd_metadata_set(image
, "rbd_blacklist_on_break_lock", "true"));
5750 ASSERT_EQ(0, rbd_lock_acquire(blacklist_image
, RBD_LOCK_MODE_EXCLUSIVE
));
5752 rbd_lock_mode_t lock_mode
;
5753 char *lock_owners
[1];
5754 size_t max_lock_owners
= 1;
5755 ASSERT_EQ(0, rbd_lock_get_owners(image
, &lock_mode
, lock_owners
,
5757 ASSERT_EQ(RBD_LOCK_MODE_EXCLUSIVE
, lock_mode
);
5758 ASSERT_STRNE("", lock_owners
[0]);
5759 ASSERT_EQ(1U, max_lock_owners
);
5761 ASSERT_EQ(0, rbd_lock_break(image
, RBD_LOCK_MODE_EXCLUSIVE
, lock_owners
[0]));
5762 ASSERT_EQ(0, rbd_lock_acquire(image
, RBD_LOCK_MODE_EXCLUSIVE
));
5763 EXPECT_EQ(0, rados_wait_for_latest_osdmap(blacklist_cluster
));
5765 ASSERT_EQ((ssize_t
)sizeof(buf
), rbd_write(image
, 0, sizeof(buf
), buf
));
5766 ASSERT_EQ(-EBLACKLISTED
, rbd_write(blacklist_image
, 0, sizeof(buf
), buf
));
5768 ASSERT_EQ(0, rbd_close(image
));
5769 ASSERT_EQ(0, rbd_close(blacklist_image
));
5771 rbd_lock_get_owners_cleanup(lock_owners
, max_lock_owners
);
5773 rados_ioctx_destroy(ioctx
);
5774 rados_ioctx_destroy(blacklist_ioctx
);
5775 rados_shutdown(blacklist_cluster
);
5778 TEST_F(TestLibRBD
, DiscardAfterWrite
)
5780 REQUIRE(!is_skip_partial_discard_enabled());
5782 librados::IoCtx ioctx
;
5783 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5786 std::string name
= get_temp_image_name();
5787 uint64_t size
= 1 << 20;
5789 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5791 librbd::Image image
;
5792 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5794 // enable writeback cache
5795 ASSERT_EQ(0, image
.flush());
5798 bl
.append(std::string(256, '1'));
5800 librbd::RBD::AioCompletion
*write_comp
=
5801 new librbd::RBD::AioCompletion(NULL
, NULL
);
5802 ASSERT_EQ(0, image
.aio_write(0, bl
.length(), bl
, write_comp
));
5803 ASSERT_EQ(0, write_comp
->wait_for_complete());
5804 write_comp
->release();
5806 librbd::RBD::AioCompletion
*discard_comp
=
5807 new librbd::RBD::AioCompletion(NULL
, NULL
);
5808 ASSERT_EQ(0, image
.aio_discard(0, 256, discard_comp
));
5809 ASSERT_EQ(0, discard_comp
->wait_for_complete());
5810 discard_comp
->release();
5812 librbd::RBD::AioCompletion
*read_comp
=
5813 new librbd::RBD::AioCompletion(NULL
, NULL
);
5815 image
.aio_read(0, bl
.length(), read_bl
, read_comp
);
5816 ASSERT_EQ(0, read_comp
->wait_for_complete());
5817 ASSERT_EQ(bl
.length(), read_comp
->get_return_value());
5818 ASSERT_TRUE(read_bl
.is_zero());
5819 read_comp
->release();
5822 TEST_F(TestLibRBD
, DefaultFeatures
) {
5823 std::string orig_default_features
;
5824 ASSERT_EQ(0, _rados
.conf_get("rbd_default_features", orig_default_features
));
5825 BOOST_SCOPE_EXIT_ALL(orig_default_features
) {
5826 ASSERT_EQ(0, _rados
.conf_set("rbd_default_features",
5827 orig_default_features
.c_str()));
5830 std::list
<std::pair
<std::string
, std::string
> > feature_names_to_bitmask
= {
5831 {"", orig_default_features
},
5833 {"layering, exclusive-lock", "5"},
5834 {"exclusive-lock,journaling", "68"},
5838 for (auto &pair
: feature_names_to_bitmask
) {
5839 ASSERT_EQ(0, _rados
.conf_set("rbd_default_features", pair
.first
.c_str()));
5840 std::string features
;
5841 ASSERT_EQ(0, _rados
.conf_get("rbd_default_features", features
));
5842 ASSERT_EQ(pair
.second
, features
);
5846 TEST_F(TestLibRBD
, TestTrashMoveAndPurge
) {
5847 librados::IoCtx ioctx
;
5848 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5851 std::string name
= get_temp_image_name();
5853 uint64_t size
= 1 << 18;
5855 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5857 librbd::Image image
;
5858 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), nullptr));
5860 ASSERT_EQ(0, image
.old_format(&old_format
));
5863 ASSERT_EQ(-EOPNOTSUPP
, rbd
.trash_move(ioctx
, name
.c_str(), 0));
5867 std::string image_id
;
5868 ASSERT_EQ(0, image
.get_id(&image_id
));
5871 ASSERT_EQ(0, rbd
.trash_move(ioctx
, name
.c_str(), 0));
5873 std::vector
<std::string
> images
;
5874 ASSERT_EQ(0, rbd
.list(ioctx
, images
));
5875 for (const auto& image
: images
) {
5876 ASSERT_TRUE(image
!= name
);
5879 librbd::trash_image_info_t info
;
5880 ASSERT_EQ(-ENOENT
, rbd
.trash_get(ioctx
, "dummy image id", &info
));
5881 ASSERT_EQ(0, rbd
.trash_get(ioctx
, image_id
.c_str(), &info
));
5882 ASSERT_EQ(image_id
, info
.id
);
5884 std::vector
<librbd::trash_image_info_t
> entries
;
5885 ASSERT_EQ(0, rbd
.trash_list(ioctx
, entries
));
5886 ASSERT_FALSE(entries
.empty());
5887 ASSERT_EQ(entries
.begin()->id
, image_id
);
5891 ASSERT_EQ(0, rbd
.trash_remove_with_progress(ioctx
, image_id
.c_str(),
5893 ASSERT_EQ(0, rbd
.trash_list(ioctx
, entries
));
5894 ASSERT_TRUE(entries
.empty());
5897 TEST_F(TestLibRBD
, TestTrashMoveAndPurgeNonExpiredDelay
) {
5898 librados::IoCtx ioctx
;
5899 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5902 std::string name
= get_temp_image_name();
5904 uint64_t size
= 1 << 18;
5906 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5908 librbd::Image image
;
5909 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), nullptr));
5911 ASSERT_EQ(0, image
.old_format(&old_format
));
5914 ASSERT_EQ(-EOPNOTSUPP
, rbd
.trash_move(ioctx
, name
.c_str(), 0));
5918 std::string image_id
;
5919 ASSERT_EQ(0, image
.get_id(&image_id
));
5922 ASSERT_EQ(0, rbd
.trash_move(ioctx
, name
.c_str(), 100));
5925 ASSERT_EQ(-EPERM
, rbd
.trash_remove_with_progress(ioctx
, image_id
.c_str(),
5929 ASSERT_EQ(0, rbd
.trash_remove_with_progress(ioctx
, image_id
.c_str(),
5933 TEST_F(TestLibRBD
, TestTrashMoveAndRestore
) {
5934 librados::IoCtx ioctx
;
5935 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5938 std::string name
= get_temp_image_name();
5940 uint64_t size
= 1 << 18;
5942 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5944 librbd::Image image
;
5945 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), nullptr));
5947 ASSERT_EQ(0, image
.old_format(&old_format
));
5950 ASSERT_EQ(-EOPNOTSUPP
, rbd
.trash_move(ioctx
, name
.c_str(), 0));
5954 std::string image_id
;
5955 ASSERT_EQ(0, image
.get_id(&image_id
));
5958 ASSERT_EQ(0, rbd
.trash_move(ioctx
, name
.c_str(), 10));
5960 std::vector
<std::string
> images
;
5961 ASSERT_EQ(0, rbd
.list(ioctx
, images
));
5962 for (const auto& image
: images
) {
5963 ASSERT_TRUE(image
!= name
);
5966 std::vector
<librbd::trash_image_info_t
> entries
;
5967 ASSERT_EQ(0, rbd
.trash_list(ioctx
, entries
));
5968 ASSERT_FALSE(entries
.empty());
5969 ASSERT_EQ(entries
.begin()->id
, image_id
);
5972 ASSERT_EQ(0, rbd
.trash_restore(ioctx
, image_id
.c_str(), ""));
5973 ASSERT_EQ(0, rbd
.list(ioctx
, images
));
5974 ASSERT_FALSE(images
.empty());
5976 for (const auto& image
: images
) {
5977 if (image
== name
) {
5985 // poorman's assert()
5987 void __ceph_assert_fail(const char *assertion
, const char *file
, int line
,