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
);
939 std::string name
= get_temp_image_name();
940 std::string name2
= get_temp_image_name();
941 std::string name3
= get_temp_image_name();
943 uint64_t size
= 2 << 20;
945 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
946 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
947 ASSERT_EQ(1, test_ls(ioctx
, 1, name
.c_str()));
949 size_t sum_key_len
= 0;
950 size_t sum_value_len
= 0;
953 for (int i
= 1; i
<= 70; i
++) {
954 key
= "key" + stringify(i
);
955 val
= "value" + stringify(i
);
956 ASSERT_EQ(0, rbd_metadata_set(image
, key
.c_str(), val
.c_str()));
958 sum_key_len
+= (key
.size() + 1);
959 sum_value_len
+= (val
.size() + 1);
964 size_t keys_len
= sizeof(keys
);
965 size_t vals_len
= sizeof(vals
);
968 size_t value_len
= sizeof(value
);
970 ASSERT_EQ(0, rbd_copy(image
, ioctx
, name2
.c_str()));
971 ASSERT_EQ(2, test_ls(ioctx
, 2, name
.c_str(), name2
.c_str()));
972 ASSERT_EQ(0, rbd_open(ioctx
, name2
.c_str(), &image2
, NULL
));
973 ASSERT_EQ(0, rbd_metadata_list(image2
, "", 70, keys
, &keys_len
, vals
,
975 ASSERT_EQ(keys_len
, sum_key_len
);
976 ASSERT_EQ(vals_len
, sum_value_len
);
978 for (int i
= 1; i
<= 70; i
++) {
979 key
= "key" + stringify(i
);
980 val
= "value" + stringify(i
);
981 ASSERT_EQ(0, rbd_metadata_get(image2
, key
.c_str(), value
, &value_len
));
982 ASSERT_STREQ(val
.c_str(), value
);
984 value_len
= sizeof(value
);
987 ASSERT_EQ(0, rbd_copy_with_progress(image
, ioctx
, name3
.c_str(),
988 print_progress_percent
, NULL
));
989 ASSERT_EQ(3, test_ls(ioctx
, 3, name
.c_str(), name2
.c_str(), name3
.c_str()));
991 keys_len
= sizeof(keys
);
992 vals_len
= sizeof(vals
);
993 ASSERT_EQ(0, rbd_open(ioctx
, name3
.c_str(), &image3
, NULL
));
994 ASSERT_EQ(0, rbd_metadata_list(image3
, "", 70, keys
, &keys_len
, vals
,
996 ASSERT_EQ(keys_len
, sum_key_len
);
997 ASSERT_EQ(vals_len
, sum_value_len
);
999 for (int i
= 1; i
<= 70; i
++) {
1000 key
= "key" + stringify(i
);
1001 val
= "value" + stringify(i
);
1002 ASSERT_EQ(0, rbd_metadata_get(image3
, key
.c_str(), value
, &value_len
));
1003 ASSERT_STREQ(val
.c_str(), value
);
1005 value_len
= sizeof(value
);
1008 ASSERT_EQ(0, rbd_close(image
));
1009 ASSERT_EQ(0, rbd_close(image2
));
1010 ASSERT_EQ(0, rbd_close(image3
));
1011 rados_ioctx_destroy(ioctx
);
1014 class PrintProgress
: public librbd::ProgressContext
1017 int update_progress(uint64_t offset
, uint64_t src_size
) override
1019 float percent
= ((float)offset
* 100) / src_size
;
1020 printf("%3.2f%% done\n", percent
);
1025 TEST_F(TestLibRBD
, TestCopyPP
)
1027 librados::IoCtx ioctx
;
1028 ASSERT_EQ(0, _rados
.ioctx_create(create_pool(true).c_str(), ioctx
));
1032 librbd::Image image
;
1033 librbd::Image image2
;
1034 librbd::Image image3
;
1036 std::string name
= get_temp_image_name();
1037 std::string name2
= get_temp_image_name();
1038 std::string name3
= get_temp_image_name();
1039 uint64_t size
= 2 << 20;
1042 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
1043 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
1047 for (int i
= 1; i
<= 70; i
++) {
1048 key
= "key" + stringify(i
);
1049 val
= "value" + stringify(i
);
1050 ASSERT_EQ(0, image
.metadata_set(key
, val
));
1053 ASSERT_EQ(1, test_ls_pp(rbd
, ioctx
, 1, name
.c_str()));
1054 ASSERT_EQ(0, image
.copy(ioctx
, name2
.c_str()));
1055 ASSERT_EQ(2, test_ls_pp(rbd
, ioctx
, 2, name
.c_str(), name2
.c_str()));
1056 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name2
.c_str(), NULL
));
1058 map
<string
, bufferlist
> pairs
;
1060 ASSERT_EQ(0, image2
.metadata_list("", 70, &pairs
));
1061 ASSERT_EQ(70U, pairs
.size());
1063 for (int i
= 1; i
<= 70; i
++) {
1064 key
= "key" + stringify(i
);
1065 val
= "value" + stringify(i
);
1066 ASSERT_EQ(0, image2
.metadata_get(key
.c_str(), &value
));
1067 ASSERT_STREQ(val
.c_str(), value
.c_str());
1070 ASSERT_EQ(0, image
.copy_with_progress(ioctx
, name3
.c_str(), pp
));
1071 ASSERT_EQ(3, test_ls_pp(rbd
, ioctx
, 3, name
.c_str(), name2
.c_str(),
1073 ASSERT_EQ(0, rbd
.open(ioctx
, image3
, name3
.c_str(), NULL
));
1076 ASSERT_EQ(0, image3
.metadata_list("", 70, &pairs
));
1077 ASSERT_EQ(70U, pairs
.size());
1079 for (int i
= 1; i
<= 70; i
++) {
1080 key
= "key" + stringify(i
);
1081 val
= "value" + stringify(i
);
1082 ASSERT_EQ(0, image3
.metadata_get(key
.c_str(), &value
));
1083 ASSERT_STREQ(val
.c_str(), value
.c_str());
1090 int test_ls_snaps(rbd_image_t image
, int num_expected
, ...)
1092 int num_snaps
, i
, j
, max_size
= 10;
1094 rbd_snap_info_t snaps
[max_size
];
1095 num_snaps
= rbd_snap_list(image
, snaps
, &max_size
);
1096 printf("num snaps is: %d\nexpected: %d\n", num_snaps
, num_expected
);
1098 for (i
= 0; i
< num_snaps
; i
++) {
1099 printf("snap: %s\n", snaps
[i
].name
);
1102 va_start(ap
, num_expected
);
1103 for (i
= num_expected
; i
> 0; i
--) {
1104 char *expected
= va_arg(ap
, char *);
1105 uint64_t expected_size
= va_arg(ap
, uint64_t);
1107 for (j
= 0; j
< num_snaps
; j
++) {
1108 if (snaps
[j
].name
== NULL
)
1110 if (strcmp(snaps
[j
].name
, expected
) == 0) {
1111 printf("found %s with size %llu\n", snaps
[j
].name
, (unsigned long long) snaps
[j
].size
);
1112 EXPECT_EQ(expected_size
, snaps
[j
].size
);
1113 free((void *) snaps
[j
].name
);
1114 snaps
[j
].name
= NULL
;
1123 for (i
= 0; i
< num_snaps
; i
++) {
1124 EXPECT_EQ((const char *)0, snaps
[i
].name
);
1130 TEST_F(TestLibRBD
, TestCreateLsDeleteSnap
)
1132 rados_ioctx_t ioctx
;
1133 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1137 std::string name
= get_temp_image_name();
1138 uint64_t size
= 2 << 20;
1139 uint64_t size2
= 4 << 20;
1141 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1142 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1144 ASSERT_EQ(0, rbd_snap_create(image
, "snap1"));
1145 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap1", size
));
1146 ASSERT_EQ(0, rbd_resize(image
, size2
));
1147 ASSERT_EQ(0, rbd_snap_create(image
, "snap2"));
1148 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1", size
, "snap2", size2
));
1149 ASSERT_EQ(0, rbd_snap_remove(image
, "snap1"));
1150 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap2", size2
));
1151 ASSERT_EQ(0, rbd_snap_remove(image
, "snap2"));
1152 ASSERT_EQ(0, test_ls_snaps(image
, 0));
1154 ASSERT_EQ(0, rbd_close(image
));
1156 rados_ioctx_destroy(ioctx
);
1159 int test_get_snapshot_timestamp(rbd_image_t image
, uint64_t snap_id
)
1161 struct timespec timestamp
;
1162 EXPECT_EQ(0, rbd_snap_get_timestamp(image
, snap_id
, ×tamp
));
1163 EXPECT_LT(0, timestamp
.tv_sec
);
1167 TEST_F(TestLibRBD
, TestGetSnapShotTimeStamp
)
1169 REQUIRE_FORMAT_V2();
1171 rados_ioctx_t ioctx
;
1172 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1176 std::string name
= get_temp_image_name();
1177 uint64_t size
= 2 << 20;
1178 int num_snaps
, max_size
= 10;
1179 rbd_snap_info_t snaps
[max_size
];
1181 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1182 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1184 ASSERT_EQ(0, rbd_snap_create(image
, "snap1"));
1185 num_snaps
= rbd_snap_list(image
, snaps
, &max_size
);
1186 ASSERT_EQ(1, num_snaps
);
1187 ASSERT_EQ(0, test_get_snapshot_timestamp(image
, snaps
[0].id
));
1188 free((void *)snaps
[0].name
);
1190 ASSERT_EQ(0, rbd_snap_create(image
, "snap2"));
1191 num_snaps
= rbd_snap_list(image
, snaps
, &max_size
);
1192 ASSERT_EQ(2, num_snaps
);
1193 ASSERT_EQ(0, test_get_snapshot_timestamp(image
, snaps
[0].id
));
1194 ASSERT_EQ(0, test_get_snapshot_timestamp(image
, snaps
[1].id
));
1195 free((void *)snaps
[0].name
);
1196 free((void *)snaps
[1].name
);
1198 ASSERT_EQ(0, rbd_close(image
));
1200 rados_ioctx_destroy(ioctx
);
1204 int test_ls_snaps(librbd::Image
& image
, size_t num_expected
, ...)
1209 vector
<librbd::snap_info_t
> snaps
;
1210 r
= image
.snap_list(snaps
);
1211 EXPECT_TRUE(r
>= 0);
1212 cout
<< "num snaps is: " << snaps
.size() << std::endl
1213 << "expected: " << num_expected
<< std::endl
;
1215 for (i
= 0; i
< snaps
.size(); i
++) {
1216 cout
<< "snap: " << snaps
[i
].name
<< std::endl
;
1219 va_start(ap
, num_expected
);
1220 for (i
= num_expected
; i
> 0; i
--) {
1221 char *expected
= va_arg(ap
, char *);
1222 uint64_t expected_size
= va_arg(ap
, uint64_t);
1224 for (j
= 0; j
< snaps
.size(); j
++) {
1225 if (snaps
[j
].name
== "")
1227 if (strcmp(snaps
[j
].name
.c_str(), expected
) == 0) {
1228 cout
<< "found " << snaps
[j
].name
<< " with size " << snaps
[j
].size
1230 EXPECT_EQ(expected_size
, snaps
[j
].size
);
1240 for (i
= 0; i
< snaps
.size(); i
++) {
1241 EXPECT_EQ("", snaps
[i
].name
);
1244 return snaps
.size();
1247 TEST_F(TestLibRBD
, TestCreateLsDeleteSnapPP
)
1249 librados::IoCtx ioctx
;
1250 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
1254 librbd::Image image
;
1256 std::string name
= get_temp_image_name();
1257 uint64_t size
= 2 << 20;
1258 uint64_t size2
= 4 << 20;
1260 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
1261 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
1264 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1265 ASSERT_FALSE(exists
);
1266 ASSERT_EQ(0, image
.snap_create("snap1"));
1267 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1268 ASSERT_TRUE(exists
);
1269 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap1", size
));
1270 ASSERT_EQ(0, image
.resize(size2
));
1271 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1272 ASSERT_FALSE(exists
);
1273 ASSERT_EQ(0, image
.snap_create("snap2"));
1274 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1275 ASSERT_TRUE(exists
);
1276 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1", size
, "snap2", size2
));
1277 ASSERT_EQ(0, image
.snap_remove("snap1"));
1278 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1279 ASSERT_FALSE(exists
);
1280 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap2", size2
));
1281 ASSERT_EQ(0, image
.snap_remove("snap2"));
1282 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1283 ASSERT_FALSE(exists
);
1284 ASSERT_EQ(0, test_ls_snaps(image
, 0));
1290 TEST_F(TestLibRBD
, TestCreateLsRenameSnapPP
)
1292 librados::IoCtx ioctx
;
1293 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
1297 librbd::Image image
;
1299 std::string name
= get_temp_image_name();
1300 uint64_t size
= 2 << 20;
1301 uint64_t size2
= 4 << 20;
1303 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
1304 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
1307 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1308 ASSERT_FALSE(exists
);
1309 ASSERT_EQ(0, image
.snap_create("snap1"));
1310 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1311 ASSERT_TRUE(exists
);
1312 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap1", size
));
1313 ASSERT_EQ(0, image
.resize(size2
));
1314 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1315 ASSERT_FALSE(exists
);
1316 ASSERT_EQ(0, image
.snap_create("snap2"));
1317 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1318 ASSERT_TRUE(exists
);
1319 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1", size
, "snap2", size2
));
1320 ASSERT_EQ(0, image
.snap_rename("snap1","snap1-rename"));
1321 ASSERT_EQ(2, test_ls_snaps(image
, 2, "snap1-rename", size
, "snap2", size2
));
1322 ASSERT_EQ(0, image
.snap_exists2("snap1", &exists
));
1323 ASSERT_FALSE(exists
);
1324 ASSERT_EQ(0, image
.snap_exists2("snap1-rename", &exists
));
1325 ASSERT_TRUE(exists
);
1326 ASSERT_EQ(0, image
.snap_remove("snap1-rename"));
1327 ASSERT_EQ(0, image
.snap_rename("snap2","snap2-rename"));
1328 ASSERT_EQ(1, test_ls_snaps(image
, 1, "snap2-rename", size2
));
1329 ASSERT_EQ(0, image
.snap_exists2("snap2", &exists
));
1330 ASSERT_FALSE(exists
);
1331 ASSERT_EQ(0, image
.snap_exists2("snap2-rename", &exists
));
1332 ASSERT_TRUE(exists
);
1333 ASSERT_EQ(0, image
.snap_remove("snap2-rename"));
1334 ASSERT_EQ(0, test_ls_snaps(image
, 0));
1340 void simple_write_cb(rbd_completion_t cb
, void *arg
)
1342 printf("write completion cb called!\n");
1345 void simple_read_cb(rbd_completion_t cb
, void *arg
)
1347 printf("read completion cb called!\n");
1350 void aio_write_test_data_and_poll(rbd_image_t image
, int fd
, const char *test_data
,
1351 uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1353 rbd_completion_t comp
;
1354 uint64_t data
= 0x123;
1355 rbd_aio_create_completion((void*)&data
, (rbd_callback_t
) simple_write_cb
, &comp
);
1356 printf("created completion\n");
1357 printf("started write\n");
1359 rbd_aio_write2(image
, off
, len
, test_data
, comp
, iohint
);
1361 rbd_aio_write(image
, off
, len
, test_data
, comp
);
1365 pfd
.events
= POLLIN
;
1367 ASSERT_EQ(1, poll(&pfd
, 1, -1));
1368 ASSERT_TRUE(pfd
.revents
& POLLIN
);
1370 rbd_completion_t comps
[1];
1371 ASSERT_EQ(1, rbd_poll_io_events(image
, comps
, 1));
1373 ASSERT_EQ(static_cast<ssize_t
>(sizeof(count
)),
1374 read(fd
, &count
, sizeof(count
)));
1375 int r
= rbd_aio_get_return_value(comps
[0]);
1376 ASSERT_TRUE(rbd_aio_is_complete(comps
[0]));
1377 ASSERT_TRUE(*(uint64_t*)rbd_aio_get_arg(comps
[0]) == data
);
1378 printf("return value is: %d\n", r
);
1380 printf("finished write\n");
1381 rbd_aio_release(comps
[0]);
1385 void aio_write_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1387 rbd_completion_t comp
;
1388 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1389 printf("created completion\n");
1391 rbd_aio_write2(image
, off
, len
, test_data
, comp
, iohint
);
1393 rbd_aio_write(image
, off
, len
, test_data
, comp
);
1394 printf("started write\n");
1395 rbd_aio_wait_for_complete(comp
);
1396 int r
= rbd_aio_get_return_value(comp
);
1397 printf("return value is: %d\n", r
);
1399 printf("finished write\n");
1400 rbd_aio_release(comp
);
1404 void write_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1408 written
= rbd_write2(image
, off
, len
, test_data
, iohint
);
1410 written
= rbd_write(image
, off
, len
, test_data
);
1411 printf("wrote: %d\n", (int) written
);
1412 ASSERT_EQ(len
, static_cast<size_t>(written
));
1416 void aio_discard_test_data(rbd_image_t image
, uint64_t off
, uint64_t len
, bool *passed
)
1418 rbd_completion_t comp
;
1419 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1420 rbd_aio_discard(image
, off
, len
, comp
);
1421 rbd_aio_wait_for_complete(comp
);
1422 int r
= rbd_aio_get_return_value(comp
);
1424 printf("aio discard: %d~%d = %d\n", (int)off
, (int)len
, (int)r
);
1425 rbd_aio_release(comp
);
1429 void discard_test_data(rbd_image_t image
, uint64_t off
, size_t len
, bool *passed
)
1432 written
= rbd_discard(image
, off
, len
);
1433 printf("discard: %d~%d = %d\n", (int)off
, (int)len
, (int)written
);
1434 ASSERT_EQ(len
, static_cast<size_t>(written
));
1438 void aio_read_test_data_and_poll(rbd_image_t image
, int fd
, const char *expected
,
1439 uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1441 rbd_completion_t comp
;
1442 char *result
= (char *)malloc(len
+ 1);
1444 ASSERT_NE(static_cast<char *>(NULL
), result
);
1445 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1446 printf("created completion\n");
1447 printf("started read\n");
1449 rbd_aio_read2(image
, off
, len
, result
, comp
, iohint
);
1451 rbd_aio_read(image
, off
, len
, result
, comp
);
1455 pfd
.events
= POLLIN
;
1457 ASSERT_EQ(1, poll(&pfd
, 1, -1));
1458 ASSERT_TRUE(pfd
.revents
& POLLIN
);
1460 rbd_completion_t comps
[1];
1461 ASSERT_EQ(1, rbd_poll_io_events(image
, comps
, 1));
1463 ASSERT_EQ(static_cast<ssize_t
>(sizeof(count
)),
1464 read(fd
, &count
, sizeof(count
)));
1466 int r
= rbd_aio_get_return_value(comps
[0]);
1467 ASSERT_TRUE(rbd_aio_is_complete(comps
[0]));
1468 printf("return value is: %d\n", r
);
1469 ASSERT_EQ(len
, static_cast<size_t>(r
));
1470 rbd_aio_release(comps
[0]);
1471 if (memcmp(result
, expected
, len
)) {
1472 printf("read: %s\nexpected: %s\n", result
, expected
);
1473 ASSERT_EQ(0, memcmp(result
, expected
, len
));
1479 void aio_read_test_data(rbd_image_t image
, const char *expected
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1481 rbd_completion_t comp
;
1482 char *result
= (char *)malloc(len
+ 1);
1484 ASSERT_NE(static_cast<char *>(NULL
), result
);
1485 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1486 printf("created completion\n");
1488 rbd_aio_read2(image
, off
, len
, result
, comp
, iohint
);
1490 rbd_aio_read(image
, off
, len
, result
, comp
);
1491 printf("started read\n");
1492 rbd_aio_wait_for_complete(comp
);
1493 int r
= rbd_aio_get_return_value(comp
);
1494 printf("return value is: %d\n", r
);
1495 ASSERT_EQ(len
, static_cast<size_t>(r
));
1496 rbd_aio_release(comp
);
1497 if (memcmp(result
, expected
, len
)) {
1498 printf("read: %s\nexpected: %s\n", result
, expected
);
1499 ASSERT_EQ(0, memcmp(result
, expected
, len
));
1505 void read_test_data(rbd_image_t image
, const char *expected
, uint64_t off
, size_t len
, uint32_t iohint
, bool *passed
)
1508 char *result
= (char *)malloc(len
+ 1);
1510 ASSERT_NE(static_cast<char *>(NULL
), result
);
1512 read
= rbd_read2(image
, off
, len
, result
, iohint
);
1514 read
= rbd_read(image
, off
, len
, result
);
1515 printf("read: %d\n", (int) read
);
1516 ASSERT_EQ(len
, static_cast<size_t>(read
));
1518 if (memcmp(result
, expected
, len
)) {
1519 printf("read: %s\nexpected: %s\n", result
, expected
);
1520 ASSERT_EQ(0, memcmp(result
, expected
, len
));
1526 void aio_writesame_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, uint64_t len
,
1527 uint64_t data_len
, uint32_t iohint
, bool *passed
)
1529 rbd_completion_t comp
;
1530 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1531 printf("created completion\n");
1533 r
= rbd_aio_writesame(image
, off
, len
, test_data
, data_len
, comp
, iohint
);
1534 printf("started writesame\n");
1535 if (len
% data_len
) {
1536 ASSERT_EQ(-EINVAL
, r
);
1537 printf("expected fail, finished writesame\n");
1538 rbd_aio_release(comp
);
1543 rbd_aio_wait_for_complete(comp
);
1544 r
= rbd_aio_get_return_value(comp
);
1545 printf("return value is: %d\n", r
);
1547 printf("finished writesame\n");
1548 rbd_aio_release(comp
);
1551 printf("to verify the data\n");
1553 char *result
= (char *)malloc(data_len
+ 1);
1554 ASSERT_NE(static_cast<char *>(NULL
), result
);
1555 uint64_t left
= len
;
1557 read
= rbd_read(image
, off
, data_len
, result
);
1558 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
1559 result
[data_len
] = '\0';
1560 if (memcmp(result
, test_data
, data_len
)) {
1561 printf("read: %d ~ %d\n", (int) off
, (int) read
);
1562 printf("read: %s\nexpected: %s\n", result
, test_data
);
1563 ASSERT_EQ(0, memcmp(result
, test_data
, data_len
));
1568 ASSERT_EQ(0U, left
);
1570 printf("verified\n");
1575 void writesame_test_data(rbd_image_t image
, const char *test_data
, uint64_t off
, uint64_t len
,
1576 uint64_t data_len
, uint32_t iohint
, bool *passed
)
1579 written
= rbd_writesame(image
, off
, len
, test_data
, data_len
, iohint
);
1580 if (len
% data_len
) {
1581 ASSERT_EQ(-EINVAL
, written
);
1582 printf("expected fail, finished writesame\n");
1586 ASSERT_EQ(len
, static_cast<size_t>(written
));
1587 printf("wrote: %d\n", (int) written
);
1590 printf("to verify the data\n");
1592 char *result
= (char *)malloc(data_len
+ 1);
1593 ASSERT_NE(static_cast<char *>(NULL
), result
);
1594 uint64_t left
= len
;
1596 read
= rbd_read(image
, off
, data_len
, result
);
1597 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
1598 result
[data_len
] = '\0';
1599 if (memcmp(result
, test_data
, data_len
)) {
1600 printf("read: %d ~ %d\n", (int) off
, (int) read
);
1601 printf("read: %s\nexpected: %s\n", result
, test_data
);
1602 ASSERT_EQ(0, memcmp(result
, test_data
, data_len
));
1607 ASSERT_EQ(0U, left
);
1609 printf("verified\n");
1614 void aio_compare_and_write_test_data(rbd_image_t image
, const char *cmp_data
,
1615 const char *test_data
, uint64_t off
,
1616 size_t len
, uint32_t iohint
, bool *passed
)
1618 rbd_completion_t comp
;
1619 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_write_cb
, &comp
);
1620 printf("created completion\n");
1622 uint64_t mismatch_offset
;
1623 rbd_aio_compare_and_write(image
, off
, len
, cmp_data
, test_data
, comp
, &mismatch_offset
, iohint
);
1624 printf("started aio compare and write\n");
1625 rbd_aio_wait_for_complete(comp
);
1626 int r
= rbd_aio_get_return_value(comp
);
1627 printf("return value is: %d\n", r
);
1629 printf("finished aio compare and write\n");
1630 rbd_aio_release(comp
);
1634 void compare_and_write_test_data(rbd_image_t image
, const char *cmp_data
,
1635 const char *test_data
, uint64_t off
, size_t len
,
1636 uint64_t *mismatch_off
, uint32_t iohint
, bool *passed
)
1638 printf("start compare and write\n");
1640 written
= rbd_compare_and_write(image
, off
, len
, cmp_data
, test_data
, mismatch_off
, iohint
);
1641 printf("compare and wrote: %d\n", (int) written
);
1642 ASSERT_EQ(len
, static_cast<size_t>(written
));
1647 TEST_F(TestLibRBD
, TestIO
)
1649 rados_ioctx_t ioctx
;
1650 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1652 bool skip_discard
= is_skip_partial_discard_enabled();
1656 std::string name
= get_temp_image_name();
1657 uint64_t size
= 2 << 20;
1659 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1660 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1662 char test_data
[TEST_IO_SIZE
+ 1];
1663 char zero_data
[TEST_IO_SIZE
+ 1];
1664 char mismatch_data
[TEST_IO_SIZE
+ 1];
1666 uint64_t mismatch_offset
;
1668 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
1669 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
1671 test_data
[TEST_IO_SIZE
] = '\0';
1672 memset(zero_data
, 0, sizeof(zero_data
));
1673 memset(mismatch_data
, 9, sizeof(mismatch_data
));
1675 for (i
= 0; i
< 5; ++i
)
1676 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1678 for (i
= 5; i
< 10; ++i
)
1679 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1681 for (i
= 0; i
< 5; ++i
)
1682 ASSERT_PASSED(compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, &mismatch_offset
, 0);
1684 for (i
= 5; i
< 10; ++i
)
1685 ASSERT_PASSED(aio_compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1687 for (i
= 0; i
< 5; ++i
)
1688 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1690 for (i
= 5; i
< 10; ++i
)
1691 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1693 // discard 2nd, 4th sections.
1694 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
1695 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
1697 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
, 0);
1698 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1699 TEST_IO_SIZE
, TEST_IO_SIZE
, 0);
1700 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
, 0);
1701 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1702 TEST_IO_SIZE
*3, TEST_IO_SIZE
, 0);
1703 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
1705 for (i
= 0; i
< 15; ++i
) {
1707 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1708 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1709 } else if (i
% 3 == 1) {
1710 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1711 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1713 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1714 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1717 for (i
= 0; i
< 15; ++i
) {
1719 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1720 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
1721 } else if (i
% 3 == 1) {
1722 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1723 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1725 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1726 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
1730 rbd_image_info_t info
;
1731 rbd_completion_t comp
;
1732 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
1733 // can't read or write starting past end
1734 ASSERT_EQ(-EINVAL
, rbd_write(image
, info
.size
, 1, test_data
));
1735 ASSERT_EQ(-EINVAL
, rbd_read(image
, info
.size
, 1, test_data
));
1736 // reading through end returns amount up to end
1737 ASSERT_EQ(10, rbd_read(image
, info
.size
- 10, 100, test_data
));
1738 // writing through end returns amount up to end
1739 ASSERT_EQ(10, rbd_write(image
, info
.size
- 10, 100, test_data
));
1741 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1742 ASSERT_EQ(0, rbd_aio_write(image
, info
.size
, 1, test_data
, comp
));
1743 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1744 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1745 rbd_aio_release(comp
);
1747 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1748 ASSERT_EQ(0, rbd_aio_read(image
, info
.size
, 1, test_data
, comp
));
1749 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1750 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1751 rbd_aio_release(comp
);
1753 ASSERT_PASSED(write_test_data
, image
, zero_data
, 0, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1754 ASSERT_EQ(-EILSEQ
, rbd_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
, &mismatch_offset
, 0));
1755 ASSERT_EQ(0U, mismatch_offset
);
1756 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1757 ASSERT_EQ(0, rbd_aio_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
, comp
, &mismatch_offset
, 0));
1758 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1759 ASSERT_EQ(0U, mismatch_offset
);
1760 rbd_aio_release(comp
);
1762 ASSERT_PASSED(validate_object_map
, image
);
1763 ASSERT_EQ(0, rbd_close(image
));
1765 rados_ioctx_destroy(ioctx
);
1768 TEST_F(TestLibRBD
, TestIOWithIOHint
)
1770 rados_ioctx_t ioctx
;
1771 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1773 bool skip_discard
= is_skip_partial_discard_enabled();
1777 std::string name
= get_temp_image_name();
1778 uint64_t size
= 2 << 20;
1780 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
1781 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1783 char test_data
[TEST_IO_SIZE
+ 1];
1784 char zero_data
[TEST_IO_SIZE
+ 1];
1785 char mismatch_data
[TEST_IO_SIZE
+ 1];
1787 uint64_t mismatch_offset
;
1789 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
1790 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
1792 test_data
[TEST_IO_SIZE
] = '\0';
1793 memset(zero_data
, 0, sizeof(zero_data
));
1794 memset(mismatch_data
, 9, sizeof(mismatch_data
));
1796 for (i
= 0; i
< 5; ++i
)
1797 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
1798 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1800 for (i
= 5; i
< 10; ++i
)
1801 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
1802 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1804 for (i
= 0; i
< 5; ++i
)
1805 ASSERT_PASSED(compare_and_write_test_data
, image
, test_data
, test_data
,
1806 TEST_IO_SIZE
* i
, TEST_IO_SIZE
, &mismatch_offset
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1808 for (i
= 5; i
< 10; ++i
)
1809 ASSERT_PASSED(aio_compare_and_write_test_data
, image
, test_data
, test_data
,
1810 TEST_IO_SIZE
* i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1812 for (i
= 0; i
< 5; ++i
)
1813 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
,
1814 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1816 for (i
= 5; i
< 10; ++i
)
1817 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
1818 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
|LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1820 // discard 2nd, 4th sections.
1821 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
1822 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
1824 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
,
1825 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1826 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1827 TEST_IO_SIZE
, TEST_IO_SIZE
,
1828 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1829 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
,
1830 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1831 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1832 TEST_IO_SIZE
*3, TEST_IO_SIZE
,
1833 LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
);
1834 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
1836 for (i
= 0; i
< 15; ++i
) {
1838 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1839 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1840 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1841 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1842 } else if (i
% 3 == 1) {
1843 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1844 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1845 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1846 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1848 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1849 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1850 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1851 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1854 for (i
= 0; i
< 15; ++i
) {
1856 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1857 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1858 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
,
1859 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1860 } else if (i
% 3 == 1) {
1861 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1862 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1863 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32,
1864 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1866 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1867 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1868 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32,
1869 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
1873 rbd_image_info_t info
;
1874 rbd_completion_t comp
;
1875 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
1876 // can't read or write starting past end
1877 ASSERT_EQ(-EINVAL
, rbd_write(image
, info
.size
, 1, test_data
));
1878 ASSERT_EQ(-EINVAL
, rbd_read(image
, info
.size
, 1, test_data
));
1879 // reading through end returns amount up to end
1880 ASSERT_EQ(10, rbd_read2(image
, info
.size
- 10, 100, test_data
,
1881 LIBRADOS_OP_FLAG_FADVISE_NOCACHE
));
1882 // writing through end returns amount up to end
1883 ASSERT_EQ(10, rbd_write2(image
, info
.size
- 10, 100, test_data
,
1884 LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1886 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1887 ASSERT_EQ(0, rbd_aio_read2(image
, info
.size
, 1, test_data
, comp
,
1888 LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1889 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1890 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1891 rbd_aio_release(comp
);
1893 ASSERT_PASSED(write_test_data
, image
, zero_data
, 0, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
1894 ASSERT_EQ(-EILSEQ
, rbd_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
,
1895 &mismatch_offset
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1896 ASSERT_EQ(0U, mismatch_offset
);
1897 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1898 ASSERT_EQ(0, rbd_aio_compare_and_write(image
, 0, TEST_IO_SIZE
, mismatch_data
, mismatch_data
,
1899 comp
, &mismatch_offset
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
));
1900 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1901 ASSERT_EQ(0U, mismatch_offset
);
1902 rbd_aio_release(comp
);
1904 ASSERT_PASSED(validate_object_map
, image
);
1905 ASSERT_EQ(0, rbd_close(image
));
1907 rados_ioctx_destroy(ioctx
);
1910 TEST_F(TestLibRBD
, TestDataPoolIO
)
1912 REQUIRE_FORMAT_V2();
1914 rados_ioctx_t ioctx
;
1915 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
1917 std::string data_pool_name
= create_pool(true);
1919 bool skip_discard
= is_skip_partial_discard_enabled();
1922 std::string name
= get_temp_image_name();
1923 uint64_t size
= 2 << 20;
1927 ASSERT_EQ(0, get_features(&old_format
, &features
));
1928 ASSERT_FALSE(old_format
);
1930 rbd_image_options_t image_options
;
1931 rbd_image_options_create(&image_options
);
1932 BOOST_SCOPE_EXIT( (&image_options
) ) {
1933 rbd_image_options_destroy(image_options
);
1934 } BOOST_SCOPE_EXIT_END
;
1936 ASSERT_EQ(0, rbd_image_options_set_uint64(image_options
,
1937 RBD_IMAGE_OPTION_FEATURES
,
1939 ASSERT_EQ(0, rbd_image_options_set_string(image_options
,
1940 RBD_IMAGE_OPTION_DATA_POOL
,
1941 data_pool_name
.c_str()));
1943 ASSERT_EQ(0, rbd_create4(ioctx
, name
.c_str(), size
, image_options
));
1944 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
1945 ASSERT_NE(-1, rbd_get_data_pool_id(image
));
1947 char test_data
[TEST_IO_SIZE
+ 1];
1948 char zero_data
[TEST_IO_SIZE
+ 1];
1951 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
1952 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
1954 test_data
[TEST_IO_SIZE
] = '\0';
1955 memset(zero_data
, 0, sizeof(zero_data
));
1957 for (i
= 0; i
< 5; ++i
)
1958 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1960 for (i
= 5; i
< 10; ++i
)
1961 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1963 for (i
= 0; i
< 5; ++i
)
1964 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1966 for (i
= 5; i
< 10; ++i
)
1967 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
1969 // discard 2nd, 4th sections.
1970 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
1971 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
1973 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
, 0);
1974 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1975 TEST_IO_SIZE
, TEST_IO_SIZE
, 0);
1976 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
, 0);
1977 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
1978 TEST_IO_SIZE
*3, TEST_IO_SIZE
, 0);
1979 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
1981 rbd_image_info_t info
;
1982 rbd_completion_t comp
;
1983 ASSERT_EQ(0, rbd_stat(image
, &info
, sizeof(info
)));
1984 // can't read or write starting past end
1985 ASSERT_EQ(-EINVAL
, rbd_write(image
, info
.size
, 1, test_data
));
1986 ASSERT_EQ(-EINVAL
, rbd_read(image
, info
.size
, 1, test_data
));
1987 // reading through end returns amount up to end
1988 ASSERT_EQ(10, rbd_read(image
, info
.size
- 10, 100, test_data
));
1989 // writing through end returns amount up to end
1990 ASSERT_EQ(10, rbd_write(image
, info
.size
- 10, 100, test_data
));
1992 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1993 ASSERT_EQ(0, rbd_aio_write(image
, info
.size
, 1, test_data
, comp
));
1994 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
1995 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
1996 rbd_aio_release(comp
);
1998 rbd_aio_create_completion(NULL
, (rbd_callback_t
) simple_read_cb
, &comp
);
1999 ASSERT_EQ(0, rbd_aio_read(image
, info
.size
, 1, test_data
, comp
));
2000 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
2001 ASSERT_EQ(-EINVAL
, rbd_aio_get_return_value(comp
));
2002 rbd_aio_release(comp
);
2004 ASSERT_PASSED(validate_object_map
, image
);
2005 ASSERT_EQ(0, rbd_close(image
));
2007 rados_ioctx_destroy(ioctx
);
2010 TEST_F(TestLibRBD
, TestScatterGatherIO
)
2012 rados_ioctx_t ioctx
;
2013 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2017 std::string name
= get_temp_image_name();
2018 uint64_t size
= 20 << 20;
2020 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
2021 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
2023 std::string
write_buffer("This is a test");
2024 struct iovec bad_iovs
[] = {
2025 {.iov_base
= NULL
, .iov_len
= static_cast<size_t>(-1)}
2027 struct iovec write_iovs
[] = {
2028 {.iov_base
= &write_buffer
[0], .iov_len
= 5},
2029 {.iov_base
= &write_buffer
[5], .iov_len
= 3},
2030 {.iov_base
= &write_buffer
[8], .iov_len
= 2},
2031 {.iov_base
= &write_buffer
[10], .iov_len
= 4}
2034 rbd_completion_t comp
;
2035 rbd_aio_create_completion(NULL
, NULL
, &comp
);
2036 ASSERT_EQ(-EINVAL
, rbd_aio_writev(image
, write_iovs
, 0, 0, comp
));
2037 ASSERT_EQ(-EINVAL
, rbd_aio_writev(image
, bad_iovs
, 1, 0, comp
));
2038 ASSERT_EQ(0, rbd_aio_writev(image
, write_iovs
,
2039 sizeof(write_iovs
) / sizeof(struct iovec
),
2041 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
2042 ASSERT_EQ(0, rbd_aio_get_return_value(comp
));
2043 rbd_aio_release(comp
);
2045 std::string
read_buffer(write_buffer
.size(), '1');
2046 struct iovec read_iovs
[] = {
2047 {.iov_base
= &read_buffer
[0], .iov_len
= 4},
2048 {.iov_base
= &read_buffer
[8], .iov_len
= 4},
2049 {.iov_base
= &read_buffer
[12], .iov_len
= 2}
2052 rbd_aio_create_completion(NULL
, NULL
, &comp
);
2053 ASSERT_EQ(-EINVAL
, rbd_aio_readv(image
, read_iovs
, 0, 0, comp
));
2054 ASSERT_EQ(-EINVAL
, rbd_aio_readv(image
, bad_iovs
, 1, 0, comp
));
2055 ASSERT_EQ(0, rbd_aio_readv(image
, read_iovs
,
2056 sizeof(read_iovs
) / sizeof(struct iovec
),
2058 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
2059 ASSERT_EQ(10, rbd_aio_get_return_value(comp
));
2060 rbd_aio_release(comp
);
2061 ASSERT_EQ("This1111 is a ", read_buffer
);
2063 std::string
linear_buffer(write_buffer
.size(), '1');
2064 struct iovec linear_iovs
[] = {
2065 {.iov_base
= &linear_buffer
[4], .iov_len
= 4}
2067 rbd_aio_create_completion(NULL
, NULL
, &comp
);
2068 ASSERT_EQ(0, rbd_aio_readv(image
, linear_iovs
,
2069 sizeof(linear_iovs
) / sizeof(struct iovec
),
2071 ASSERT_EQ(0, rbd_aio_wait_for_complete(comp
));
2072 ASSERT_EQ(4, rbd_aio_get_return_value(comp
));
2073 rbd_aio_release(comp
);
2074 ASSERT_EQ("1111This111111", linear_buffer
);
2076 ASSERT_PASSED(validate_object_map
, image
);
2077 ASSERT_EQ(0, rbd_close(image
));
2079 rados_ioctx_destroy(ioctx
);
2082 TEST_F(TestLibRBD
, TestEmptyDiscard
)
2084 rados_ioctx_t ioctx
;
2085 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2089 std::string name
= get_temp_image_name();
2090 uint64_t size
= 20 << 20;
2092 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
2093 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
2095 ASSERT_PASSED(aio_discard_test_data
, image
, 0, 1*1024*1024);
2096 ASSERT_PASSED(aio_discard_test_data
, image
, 0, 4*1024*1024);
2097 ASSERT_PASSED(aio_discard_test_data
, image
, 3*1024*1024, 1*1024*1024);
2099 ASSERT_PASSED(validate_object_map
, image
);
2100 ASSERT_EQ(0, rbd_close(image
));
2102 rados_ioctx_destroy(ioctx
);
2106 void simple_write_cb_pp(librbd::completion_t cb
, void *arg
)
2108 cout
<< "write completion cb called!" << std::endl
;
2111 void simple_read_cb_pp(librbd::completion_t cb
, void *arg
)
2113 cout
<< "read completion cb called!" << std::endl
;
2116 void aio_write_test_data(librbd::Image
& image
, const char *test_data
,
2117 off_t off
, uint32_t iohint
, bool *passed
)
2119 ceph::bufferlist bl
;
2120 bl
.append(test_data
, strlen(test_data
));
2121 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2122 printf("created completion\n");
2124 image
.aio_write2(off
, strlen(test_data
), bl
, comp
, iohint
);
2126 image
.aio_write(off
, strlen(test_data
), bl
, comp
);
2127 printf("started write\n");
2128 comp
->wait_for_complete();
2129 int r
= comp
->get_return_value();
2130 printf("return value is: %d\n", r
);
2132 printf("finished write\n");
2137 void aio_discard_test_data(librbd::Image
& image
, off_t off
, size_t len
, bool *passed
)
2139 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2140 image
.aio_discard(off
, len
, comp
);
2141 comp
->wait_for_complete();
2142 int r
= comp
->get_return_value();
2148 void write_test_data(librbd::Image
& image
, const char *test_data
, off_t off
, uint32_t iohint
, bool *passed
)
2151 size_t len
= strlen(test_data
);
2152 ceph::bufferlist bl
;
2153 bl
.append(test_data
, len
);
2155 written
= image
.write2(off
, len
, bl
, iohint
);
2157 written
= image
.write(off
, len
, bl
);
2158 printf("wrote: %u\n", (unsigned int) written
);
2159 ASSERT_EQ(bl
.length(), written
);
2163 void discard_test_data(librbd::Image
& image
, off_t off
, size_t len
, bool *passed
)
2166 written
= image
.discard(off
, len
);
2167 printf("discard: %u~%u\n", (unsigned)off
, (unsigned)len
);
2168 ASSERT_EQ(len
, written
);
2172 void aio_read_test_data(librbd::Image
& image
, const char *expected
, off_t off
, size_t expected_len
, uint32_t iohint
, bool *passed
)
2174 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_read_cb_pp
);
2175 ceph::bufferlist bl
;
2176 printf("created completion\n");
2178 image
.aio_read2(off
, expected_len
, bl
, comp
, iohint
);
2180 image
.aio_read(off
, expected_len
, bl
, comp
);
2181 printf("started read\n");
2182 comp
->wait_for_complete();
2183 int r
= comp
->get_return_value();
2184 printf("return value is: %d\n", r
);
2185 ASSERT_EQ(TEST_IO_SIZE
, r
);
2186 ASSERT_EQ(0, memcmp(expected
, bl
.c_str(), TEST_IO_SIZE
));
2187 printf("finished read\n");
2192 void read_test_data(librbd::Image
& image
, const char *expected
, off_t off
, size_t expected_len
, uint32_t iohint
, bool *passed
)
2195 size_t len
= expected_len
;
2196 ceph::bufferlist bl
;
2198 read
= image
.read2(off
, len
, bl
, iohint
);
2200 read
= image
.read(off
, len
, bl
);
2201 ASSERT_TRUE(read
>= 0);
2202 std::string
bl_str(bl
.c_str(), read
);
2204 printf("read: %u\n", (unsigned int) read
);
2205 int result
= memcmp(bl_str
.c_str(), expected
, expected_len
);
2207 printf("read: %s\nexpected: %s\n", bl_str
.c_str(), expected
);
2208 ASSERT_EQ(0, result
);
2213 void aio_writesame_test_data(librbd::Image
& image
, const char *test_data
, off_t off
,
2214 size_t len
, size_t data_len
, uint32_t iohint
, bool *passed
)
2216 ceph::bufferlist bl
;
2217 bl
.append(test_data
, data_len
);
2218 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2219 printf("created completion\n");
2221 r
= image
.aio_writesame(off
, len
, bl
, comp
, iohint
);
2222 printf("started writesame\n");
2223 if (len
% data_len
) {
2224 ASSERT_EQ(-EINVAL
, r
);
2225 printf("expected fail, finished writesame\n");
2231 comp
->wait_for_complete();
2232 r
= comp
->get_return_value();
2233 printf("return value is: %d\n", r
);
2235 printf("finished writesame\n");
2239 printf("to verify the data\n");
2241 uint64_t left
= len
;
2243 ceph::bufferlist bl
;
2244 read
= image
.read(off
, data_len
, bl
);
2245 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
2246 std::string
bl_str(bl
.c_str(), read
);
2247 int result
= memcmp(bl_str
.c_str(), test_data
, data_len
);
2249 printf("read: %u ~ %u\n", (unsigned int) off
, (unsigned int) read
);
2250 printf("read: %s\nexpected: %s\n", bl_str
.c_str(), test_data
);
2251 ASSERT_EQ(0, result
);
2256 ASSERT_EQ(0U, left
);
2257 printf("verified\n");
2262 void writesame_test_data(librbd::Image
& image
, const char *test_data
, off_t off
,
2263 ssize_t len
, size_t data_len
, uint32_t iohint
,
2267 ceph::bufferlist bl
;
2268 bl
.append(test_data
, data_len
);
2269 written
= image
.writesame(off
, len
, bl
, iohint
);
2270 if (len
% data_len
) {
2271 ASSERT_EQ(-EINVAL
, written
);
2272 printf("expected fail, finished writesame\n");
2276 ASSERT_EQ(len
, written
);
2277 printf("wrote: %u\n", (unsigned int) written
);
2281 printf("to verify the data\n");
2283 uint64_t left
= len
;
2285 ceph::bufferlist bl
;
2286 read
= image
.read(off
, data_len
, bl
);
2287 ASSERT_EQ(data_len
, static_cast<size_t>(read
));
2288 std::string
bl_str(bl
.c_str(), read
);
2289 int result
= memcmp(bl_str
.c_str(), test_data
, data_len
);
2291 printf("read: %u ~ %u\n", (unsigned int) off
, (unsigned int) read
);
2292 printf("read: %s\nexpected: %s\n", bl_str
.c_str(), test_data
);
2293 ASSERT_EQ(0, result
);
2298 ASSERT_EQ(0U, left
);
2299 printf("verified\n");
2304 void aio_compare_and_write_test_data(librbd::Image
& image
, const char *cmp_data
,
2305 const char *test_data
, off_t off
, ssize_t len
,
2306 uint32_t iohint
, bool *passed
)
2308 ceph::bufferlist cmp_bl
;
2309 cmp_bl
.append(cmp_data
, strlen(cmp_data
));
2310 ceph::bufferlist test_bl
;
2311 test_bl
.append(test_data
, strlen(test_data
));
2312 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
, (librbd::callback_t
) simple_write_cb_pp
);
2313 printf("created completion\n");
2315 uint64_t mismatch_offset
;
2316 image
.aio_compare_and_write(off
, len
, cmp_bl
, test_bl
, comp
, &mismatch_offset
, iohint
);
2317 printf("started aio compare and write\n");
2318 comp
->wait_for_complete();
2319 int r
= comp
->get_return_value();
2320 printf("return value is: %d\n", r
);
2322 printf("finished aio compare and write\n");
2327 void compare_and_write_test_data(librbd::Image
& image
, const char *cmp_data
, const char *test_data
,
2328 off_t off
, ssize_t len
, uint64_t *mismatch_off
, uint32_t iohint
, bool *passed
)
2331 ceph::bufferlist cmp_bl
;
2332 cmp_bl
.append(cmp_data
, strlen(cmp_data
));
2333 ceph::bufferlist test_bl
;
2334 test_bl
.append(test_data
, strlen(test_data
));
2335 printf("start compare and write\n");
2336 written
= image
.compare_and_write(off
, len
, cmp_bl
, test_bl
, mismatch_off
, iohint
);
2337 printf("compare and wrote: %d\n", (int) written
);
2338 ASSERT_EQ(len
, static_cast<ssize_t
>(written
));
2342 TEST_F(TestLibRBD
, TestIOPP
)
2344 librados::IoCtx ioctx
;
2345 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
2347 bool skip_discard
= is_skip_partial_discard_enabled();
2351 librbd::Image image
;
2353 std::string name
= get_temp_image_name();
2354 uint64_t size
= 2 << 20;
2356 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
2357 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
2359 char test_data
[TEST_IO_SIZE
+ 1];
2360 char zero_data
[TEST_IO_SIZE
+ 1];
2362 uint64_t mismatch_offset
;
2364 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
2365 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
2367 test_data
[TEST_IO_SIZE
] = '\0';
2368 memset(zero_data
, 0, sizeof(zero_data
));
2370 for (i
= 0; i
< 5; ++i
)
2371 ASSERT_PASSED(write_test_data
, image
, test_data
, strlen(test_data
) * i
, 0);
2373 for (i
= 5; i
< 10; ++i
)
2374 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, strlen(test_data
) * i
, 0);
2376 for (i
= 0; i
< 5; ++i
)
2377 ASSERT_PASSED(compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
,
2378 TEST_IO_SIZE
, &mismatch_offset
, 0);
2380 for (i
= 5; i
< 10; ++i
)
2381 ASSERT_PASSED(aio_compare_and_write_test_data
, image
, test_data
, test_data
, TEST_IO_SIZE
* i
,
2384 for (i
= 0; i
< 5; ++i
)
2385 ASSERT_PASSED(read_test_data
, image
, test_data
, strlen(test_data
) * i
, TEST_IO_SIZE
, 0);
2387 for (i
= 5; i
< 10; ++i
)
2388 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, strlen(test_data
) * i
, TEST_IO_SIZE
, 0);
2390 // discard 2nd, 4th sections.
2391 ASSERT_PASSED(discard_test_data
, image
, TEST_IO_SIZE
, TEST_IO_SIZE
);
2392 ASSERT_PASSED(aio_discard_test_data
, image
, TEST_IO_SIZE
*3, TEST_IO_SIZE
);
2394 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_SIZE
, 0);
2395 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
2396 TEST_IO_SIZE
, TEST_IO_SIZE
, 0);
2397 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*2, TEST_IO_SIZE
, 0);
2398 ASSERT_PASSED(read_test_data
, image
, skip_discard
? test_data
: zero_data
,
2399 TEST_IO_SIZE
*3, TEST_IO_SIZE
, 0);
2400 ASSERT_PASSED(read_test_data
, image
, test_data
, TEST_IO_SIZE
*4, TEST_IO_SIZE
, 0);
2402 for (i
= 0; i
< 15; ++i
) {
2404 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2405 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2406 } else if (i
% 3 == 1) {
2407 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2408 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2410 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2411 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2414 for (i
= 0; i
< 15; ++i
) {
2416 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2417 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, 0);
2418 } else if (i
% 3 == 1) {
2419 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2420 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2422 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2423 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, 0);
2427 ASSERT_PASSED(validate_object_map
, image
);
2433 TEST_F(TestLibRBD
, TestIOPPWithIOHint
)
2435 librados::IoCtx ioctx
;
2436 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
2440 librbd::Image image
;
2442 std::string name
= get_temp_image_name();
2443 uint64_t size
= 2 << 20;
2445 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
2446 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
2448 char test_data
[TEST_IO_SIZE
+ 1];
2449 char zero_data
[TEST_IO_SIZE
+ 1];
2450 test_data
[TEST_IO_SIZE
] = '\0';
2453 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
2454 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
2456 memset(zero_data
, 0, sizeof(zero_data
));
2458 for (i
= 0; i
< 5; ++i
)
2459 ASSERT_PASSED(write_test_data
, image
, test_data
, strlen(test_data
) * i
,
2460 LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2462 for (i
= 5; i
< 10; ++i
)
2463 ASSERT_PASSED(aio_write_test_data
, image
, test_data
, strlen(test_data
) * i
,
2464 LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2466 ASSERT_PASSED(read_test_data
, image
, test_data
, strlen(test_data
),
2467 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_RANDOM
);
2469 for (i
= 5; i
< 10; ++i
)
2470 ASSERT_PASSED(aio_read_test_data
, image
, test_data
, strlen(test_data
) * i
,
2471 TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
|LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2473 for (i
= 0; i
< 15; ++i
) {
2475 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2476 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2477 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2478 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2479 } else if (i
% 3 == 1) {
2480 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
,
2481 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2482 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
,
2483 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2485 ASSERT_PASSED(writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2486 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2487 ASSERT_PASSED(writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2488 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_NOCACHE
);
2491 for (i
= 0; i
< 15; ++i
) {
2493 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2494 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2495 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2496 TEST_IO_SIZE
* i
* 32 + i
, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2497 } else if (i
% 3 == 1) {
2498 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
+ i
,
2499 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2500 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
+ i
,
2501 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2503 ASSERT_PASSED(aio_writesame_test_data
, image
, test_data
, TEST_IO_SIZE
* i
,
2504 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2505 ASSERT_PASSED(aio_writesame_test_data
, image
, zero_data
, TEST_IO_SIZE
* i
,
2506 TEST_IO_SIZE
* i
* 32, TEST_IO_SIZE
, LIBRADOS_OP_FLAG_FADVISE_DONTNEED
);
2510 ASSERT_PASSED(validate_object_map
, image
);
2518 TEST_F(TestLibRBD
, TestIOToSnapshot
)
2520 rados_ioctx_t ioctx
;
2521 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2525 std::string name
= get_temp_image_name();
2526 uint64_t isize
= 2 << 20;
2528 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), isize
, &order
));
2529 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
2532 rbd_image_t image_at_snap
;
2533 char orig_data
[TEST_IO_TO_SNAP_SIZE
+ 1];
2534 char test_data
[TEST_IO_TO_SNAP_SIZE
+ 1];
2536 for (i
= 0; i
< TEST_IO_TO_SNAP_SIZE
; ++i
)
2537 test_data
[i
] = (char) (i
+ 48);
2538 test_data
[TEST_IO_TO_SNAP_SIZE
] = '\0';
2539 orig_data
[TEST_IO_TO_SNAP_SIZE
] = '\0';
2541 r
= rbd_read(image
, 0, TEST_IO_TO_SNAP_SIZE
, orig_data
);
2542 ASSERT_EQ(r
, TEST_IO_TO_SNAP_SIZE
);
2544 ASSERT_EQ(0, test_ls_snaps(image
, 0));
2545 ASSERT_EQ(0, rbd_snap_create(image
, "orig"));
2546 ASSERT_EQ(1, test_ls_snaps(image
, 1, "orig", isize
));
2547 ASSERT_PASSED(read_test_data
, image
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2549 printf("write test data!\n");
2550 ASSERT_PASSED(write_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2551 ASSERT_EQ(0, rbd_snap_create(image
, "written"));
2552 ASSERT_EQ(2, test_ls_snaps(image
, 2, "orig", isize
, "written", isize
));
2554 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2556 rbd_snap_set(image
, "orig");
2557 ASSERT_PASSED(read_test_data
, image
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2559 rbd_snap_set(image
, "written");
2560 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2562 rbd_snap_set(image
, "orig");
2564 r
= rbd_write(image
, 0, TEST_IO_TO_SNAP_SIZE
, test_data
);
2565 printf("write to snapshot returned %d\n", r
);
2567 cout
<< strerror(-r
) << std::endl
;
2569 ASSERT_PASSED(read_test_data
, image
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2570 rbd_snap_set(image
, "written");
2571 ASSERT_PASSED(read_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2573 r
= rbd_snap_rollback(image
, "orig");
2574 ASSERT_EQ(r
, -EROFS
);
2576 r
= rbd_snap_set(image
, NULL
);
2578 r
= rbd_snap_rollback(image
, "orig");
2581 ASSERT_PASSED(write_test_data
, image
, test_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2585 printf("opening testimg@orig\n");
2586 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image_at_snap
, "orig"));
2587 ASSERT_PASSED(read_test_data
, image_at_snap
, orig_data
, 0, TEST_IO_TO_SNAP_SIZE
, 0);
2588 r
= rbd_write(image_at_snap
, 0, TEST_IO_TO_SNAP_SIZE
, test_data
);
2589 printf("write to snapshot returned %d\n", r
);
2591 cout
<< strerror(-r
) << std::endl
;
2592 ASSERT_EQ(0, rbd_close(image_at_snap
));
2594 ASSERT_EQ(2, test_ls_snaps(image
, 2, "orig", isize
, "written", isize
));
2595 ASSERT_EQ(0, rbd_snap_remove(image
, "written"));
2596 ASSERT_EQ(1, test_ls_snaps(image
, 1, "orig", isize
));
2597 ASSERT_EQ(0, rbd_snap_remove(image
, "orig"));
2598 ASSERT_EQ(0, test_ls_snaps(image
, 0));
2600 ASSERT_PASSED(validate_object_map
, image
);
2601 ASSERT_EQ(0, rbd_close(image
));
2603 rados_ioctx_destroy(ioctx
);
2606 TEST_F(TestLibRBD
, TestClone
)
2608 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2610 rados_ioctx_t ioctx
;
2611 rbd_image_info_t pinfo
, cinfo
;
2612 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2616 rbd_image_t parent
, child
;
2619 ASSERT_EQ(0, get_features(&old_format
, &features
));
2620 ASSERT_FALSE(old_format
);
2622 std::string parent_name
= get_temp_image_name();
2623 std::string child_name
= get_temp_image_name();
2625 // make a parent to clone from
2626 ASSERT_EQ(0, create_image_full(ioctx
, parent_name
.c_str(), 4<<20, &order
,
2628 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, NULL
));
2629 printf("made parent image \"parent\"\n");
2631 char *data
= (char *)"testdata";
2632 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 0, strlen(data
), data
));
2634 // can't clone a non-snapshot, expect failure
2635 EXPECT_NE(0, clone_image(ioctx
, parent
, parent_name
.c_str(), NULL
, ioctx
,
2636 child_name
.c_str(), features
, &order
));
2638 // verify that there is no parent info on "parent"
2639 ASSERT_EQ(-ENOENT
, rbd_get_parent_info(parent
, NULL
, 0, NULL
, 0, NULL
, 0));
2640 printf("parent has no parent info\n");
2642 // create 70 metadatas to verify we can clone all key/value pairs
2645 size_t sum_key_len
= 0;
2646 size_t sum_value_len
= 0;
2647 for (int i
= 1; i
<= 70; i
++) {
2648 key
= "key" + stringify(i
);
2649 val
= "value" + stringify(i
);
2650 ASSERT_EQ(0, rbd_metadata_set(parent
, key
.c_str(), val
.c_str()));
2652 sum_key_len
+= (key
.size() + 1);
2653 sum_value_len
+= (val
.size() + 1);
2658 size_t keys_len
= sizeof(keys
);
2659 size_t vals_len
= sizeof(vals
);
2662 size_t value_len
= sizeof(value
);
2664 // create a snapshot, reopen as the parent we're interested in
2665 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2666 printf("made snapshot \"parent@parent_snap\"\n");
2667 ASSERT_EQ(0, rbd_close(parent
));
2668 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, "parent_snap"));
2670 ASSERT_EQ(-EINVAL
, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2671 ioctx
, child_name
.c_str(), features
, &order
));
2673 // unprotected image should fail unprotect
2674 ASSERT_EQ(-EINVAL
, rbd_snap_unprotect(parent
, "parent_snap"));
2675 printf("can't unprotect an unprotected snap\n");
2677 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2678 // protecting again should fail
2679 ASSERT_EQ(-EBUSY
, rbd_snap_protect(parent
, "parent_snap"));
2680 printf("can't protect a protected snap\n");
2682 // This clone and open should work
2683 ASSERT_EQ(0, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2684 ioctx
, child_name
.c_str(), features
, &order
));
2685 ASSERT_EQ(0, rbd_open(ioctx
, child_name
.c_str(), &child
, NULL
));
2686 printf("made and opened clone \"child\"\n");
2689 ASSERT_PASSED(read_test_data
, child
, data
, 0, strlen(data
), 0);
2692 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(child
, 20, strlen(data
), data
));
2693 ASSERT_PASSED(read_test_data
, child
, data
, 20, strlen(data
), 0);
2694 ASSERT_PASSED(read_test_data
, child
, data
, 0, strlen(data
), 0);
2697 ASSERT_EQ(0, rbd_stat(parent
, &pinfo
, sizeof(pinfo
)));
2698 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2699 EXPECT_EQ(cinfo
.size
, pinfo
.size
);
2701 rbd_get_overlap(child
, &overlap
);
2702 EXPECT_EQ(overlap
, pinfo
.size
);
2703 EXPECT_EQ(cinfo
.obj_size
, pinfo
.obj_size
);
2704 EXPECT_EQ(cinfo
.order
, pinfo
.order
);
2705 printf("sizes and overlaps are good between parent and child\n");
2707 // check key/value pairs in child image
2708 ASSERT_EQ(0, rbd_metadata_list(child
, "", 70, keys
, &keys_len
, vals
,
2710 ASSERT_EQ(sum_key_len
, keys_len
);
2711 ASSERT_EQ(sum_value_len
, vals_len
);
2713 for (int i
= 1; i
<= 70; i
++) {
2714 key
= "key" + stringify(i
);
2715 val
= "value" + stringify(i
);
2716 ASSERT_EQ(0, rbd_metadata_get(child
, key
.c_str(), value
, &value_len
));
2717 ASSERT_STREQ(val
.c_str(), value
);
2719 value_len
= sizeof(value
);
2721 printf("child image successfully cloned all image-meta pairs\n");
2723 // sizing down child results in changing overlap and size, not parent size
2724 ASSERT_EQ(0, rbd_resize(child
, 2UL<<20));
2725 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2726 rbd_get_overlap(child
, &overlap
);
2727 ASSERT_EQ(overlap
, 2UL<<20);
2728 ASSERT_EQ(cinfo
.size
, 2UL<<20);
2729 ASSERT_EQ(0, rbd_resize(child
, 4UL<<20));
2730 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2731 rbd_get_overlap(child
, &overlap
);
2732 ASSERT_EQ(overlap
, 2UL<<20);
2733 ASSERT_EQ(cinfo
.size
, 4UL<<20);
2734 printf("sized down clone, changed overlap\n");
2736 // sizing back up doesn't change that
2737 ASSERT_EQ(0, rbd_resize(child
, 5UL<<20));
2738 ASSERT_EQ(0, rbd_stat(child
, &cinfo
, sizeof(cinfo
)));
2739 rbd_get_overlap(child
, &overlap
);
2740 ASSERT_EQ(overlap
, 2UL<<20);
2741 ASSERT_EQ(cinfo
.size
, 5UL<<20);
2742 ASSERT_EQ(0, rbd_stat(parent
, &pinfo
, sizeof(pinfo
)));
2743 printf("parent info: size %lld obj_size %lld parent_pool %lld\n",
2744 (unsigned long long)pinfo
.size
, (unsigned long long)pinfo
.obj_size
,
2745 (unsigned long long)pinfo
.parent_pool
);
2746 ASSERT_EQ(pinfo
.size
, 4UL<<20);
2747 printf("sized up clone, changed size but not overlap or parent's size\n");
2749 ASSERT_PASSED(validate_object_map
, child
);
2750 ASSERT_EQ(0, rbd_close(child
));
2752 ASSERT_PASSED(validate_object_map
, parent
);
2753 ASSERT_EQ(-EBUSY
, rbd_snap_remove(parent
, "parent_snap"));
2754 printf("can't remove parent while child still exists\n");
2755 ASSERT_EQ(0, rbd_remove(ioctx
, child_name
.c_str()));
2756 ASSERT_EQ(-EBUSY
, rbd_snap_remove(parent
, "parent_snap"));
2757 printf("can't remove parent while still protected\n");
2758 ASSERT_EQ(0, rbd_snap_unprotect(parent
, "parent_snap"));
2759 ASSERT_EQ(0, rbd_snap_remove(parent
, "parent_snap"));
2760 printf("removed parent snap after unprotecting\n");
2762 ASSERT_EQ(0, rbd_close(parent
));
2763 rados_ioctx_destroy(ioctx
);
2766 TEST_F(TestLibRBD
, TestClone2
)
2768 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2770 rados_ioctx_t ioctx
;
2771 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
2775 rbd_image_t parent
, child
;
2778 ASSERT_EQ(0, get_features(&old_format
, &features
));
2779 ASSERT_FALSE(old_format
);
2781 std::string parent_name
= get_temp_image_name();
2782 std::string child_name
= get_temp_image_name();
2784 // make a parent to clone from
2785 ASSERT_EQ(0, create_image_full(ioctx
, parent_name
.c_str(), 4<<20, &order
,
2787 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, NULL
));
2788 printf("made parent image \"parent\"\n");
2790 char *data
= (char *)"testdata";
2791 char *childata
= (char *)"childata";
2792 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 0, strlen(data
), data
));
2793 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 12, strlen(data
), data
));
2795 // can't clone a non-snapshot, expect failure
2796 EXPECT_NE(0, clone_image(ioctx
, parent
, parent_name
.c_str(), NULL
, ioctx
,
2797 child_name
.c_str(), features
, &order
));
2799 // verify that there is no parent info on "parent"
2800 ASSERT_EQ(-ENOENT
, rbd_get_parent_info(parent
, NULL
, 0, NULL
, 0, NULL
, 0));
2801 printf("parent has no parent info\n");
2803 // create 70 metadatas to verify we can clone all key/value pairs
2806 size_t sum_key_len
= 0;
2807 size_t sum_value_len
= 0;
2808 for (int i
= 1; i
<= 70; i
++) {
2809 key
= "key" + stringify(i
);
2810 val
= "value" + stringify(i
);
2811 ASSERT_EQ(0, rbd_metadata_set(parent
, key
.c_str(), val
.c_str()));
2813 sum_key_len
+= (key
.size() + 1);
2814 sum_value_len
+= (val
.size() + 1);
2819 size_t keys_len
= sizeof(keys
);
2820 size_t vals_len
= sizeof(vals
);
2823 size_t value_len
= sizeof(value
);
2825 // create a snapshot, reopen as the parent we're interested in
2826 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2827 printf("made snapshot \"parent@parent_snap\"\n");
2828 ASSERT_EQ(0, rbd_close(parent
));
2829 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, "parent_snap"));
2831 ASSERT_EQ(-EINVAL
, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2832 ioctx
, child_name
.c_str(), features
, &order
));
2834 // unprotected image should fail unprotect
2835 ASSERT_EQ(-EINVAL
, rbd_snap_unprotect(parent
, "parent_snap"));
2836 printf("can't unprotect an unprotected snap\n");
2838 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2839 // protecting again should fail
2840 ASSERT_EQ(-EBUSY
, rbd_snap_protect(parent
, "parent_snap"));
2841 printf("can't protect a protected snap\n");
2843 // This clone and open should work
2844 ASSERT_EQ(0, clone_image(ioctx
, parent
, parent_name
.c_str(), "parent_snap",
2845 ioctx
, child_name
.c_str(), features
, &order
));
2846 ASSERT_EQ(0, rbd_open(ioctx
, child_name
.c_str(), &child
, NULL
));
2847 printf("made and opened clone \"child\"\n");
2849 // check key/value pairs in child image
2850 ASSERT_EQ(0, rbd_metadata_list(child
, "", 70, keys
, &keys_len
, vals
,
2852 ASSERT_EQ(sum_key_len
, keys_len
);
2853 ASSERT_EQ(sum_value_len
, vals_len
);
2855 for (int i
= 1; i
<= 70; i
++) {
2856 key
= "key" + stringify(i
);
2857 val
= "value" + stringify(i
);
2858 ASSERT_EQ(0, rbd_metadata_get(child
, key
.c_str(), value
, &value_len
));
2859 ASSERT_STREQ(val
.c_str(), value
);
2861 value_len
= sizeof(value
);
2863 printf("child image successfully cloned all image-meta pairs\n");
2865 // write something in
2866 ASSERT_EQ((ssize_t
)strlen(childata
), rbd_write(child
, 20, strlen(childata
), childata
));
2868 char test
[strlen(data
) * 2];
2869 ASSERT_EQ((ssize_t
)strlen(data
), rbd_read(child
, 20, strlen(data
), test
));
2870 ASSERT_EQ(0, memcmp(test
, childata
, strlen(childata
)));
2873 ASSERT_EQ((ssize_t
)sizeof(test
), rbd_read(child
, 20 - strlen(data
), sizeof(test
), test
));
2874 ASSERT_EQ(0, memcmp(test
, data
, strlen(data
)));
2875 ASSERT_EQ(0, memcmp(test
+ strlen(data
), childata
, strlen(childata
)));
2878 ASSERT_EQ((ssize_t
)sizeof(test
), rbd_read(child
, 0, sizeof(test
), test
));
2879 ASSERT_EQ(0, memcmp(test
, data
, strlen(data
)));
2881 ASSERT_PASSED(validate_object_map
, child
);
2882 ASSERT_PASSED(validate_object_map
, parent
);
2884 ASSERT_EQ(0, rbd_close(child
));
2885 ASSERT_EQ(0, rbd_close(parent
));
2886 rados_ioctx_destroy(ioctx
);
2889 static void test_list_children(rbd_image_t image
, ssize_t num_expected
, ...)
2892 va_start(ap
, num_expected
);
2893 size_t pools_len
= 100;
2894 size_t children_len
= 100;
2896 char *children
= NULL
;
2897 ssize_t num_children
;
2902 pools
= (char *) malloc(pools_len
);
2903 children
= (char *) malloc(children_len
);
2904 num_children
= rbd_list_children(image
, pools
, &pools_len
,
2905 children
, &children_len
);
2906 } while (num_children
== -ERANGE
);
2908 ASSERT_EQ(num_expected
, num_children
);
2909 for (ssize_t i
= num_expected
; i
> 0; --i
) {
2910 char *expected_pool
= va_arg(ap
, char *);
2911 char *expected_image
= va_arg(ap
, char *);
2913 char *image
= children
;
2915 printf("\ntrying to find %s/%s\n", expected_pool
, expected_image
);
2916 for (ssize_t j
= 0; j
< num_children
; ++j
) {
2917 printf("checking %s/%s\n", pool
, image
);
2918 if (strcmp(expected_pool
, pool
) == 0 &&
2919 strcmp(expected_image
, image
) == 0) {
2920 printf("found child %s/%s\n\n", pool
, image
);
2924 pool
+= strlen(pool
) + 1;
2925 image
+= strlen(image
) + 1;
2926 if (j
== num_children
- 1) {
2927 ASSERT_EQ(pool
- pools
- 1, (ssize_t
) pools_len
);
2928 ASSERT_EQ(image
- children
- 1, (ssize_t
) children_len
);
2941 TEST_F(TestLibRBD
, ListChildren
)
2943 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
2945 rados_ioctx_t ioctx1
, ioctx2
;
2946 string pool_name1
= create_pool(true);
2947 string pool_name2
= create_pool(true);
2948 ASSERT_NE("", pool_name2
);
2950 rados_ioctx_create(_cluster
, pool_name1
.c_str(), &ioctx1
);
2951 rados_ioctx_create(_cluster
, pool_name2
.c_str(), &ioctx2
);
2958 ASSERT_EQ(0, get_features(&old_format
, &features
));
2959 ASSERT_FALSE(old_format
);
2961 std::string parent_name
= get_temp_image_name();
2962 std::string child_name1
= get_temp_image_name();
2963 std::string child_name2
= get_temp_image_name();
2964 std::string child_name3
= get_temp_image_name();
2965 std::string child_name4
= get_temp_image_name();
2967 // make a parent to clone from
2968 ASSERT_EQ(0, create_image_full(ioctx1
, parent_name
.c_str(), 4<<20, &order
,
2970 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, NULL
));
2971 // create a snapshot, reopen as the parent we're interested in
2972 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
2973 ASSERT_EQ(0, rbd_snap_set(parent
, "parent_snap"));
2974 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
2976 ASSERT_EQ(0, rbd_close(parent
));
2977 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, "parent_snap"));
2979 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2980 ioctx2
, child_name1
.c_str(), features
, &order
));
2981 test_list_children(parent
, 1, pool_name2
.c_str(), child_name1
.c_str());
2983 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2984 ioctx1
, child_name2
.c_str(), features
, &order
));
2985 test_list_children(parent
, 2, pool_name2
.c_str(), child_name1
.c_str(),
2986 pool_name1
.c_str(), child_name2
.c_str());
2988 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2989 ioctx2
, child_name3
.c_str(), features
, &order
));
2990 test_list_children(parent
, 3, pool_name2
.c_str(), child_name1
.c_str(),
2991 pool_name1
.c_str(), child_name2
.c_str(),
2992 pool_name2
.c_str(), child_name3
.c_str());
2994 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
2995 ioctx2
, child_name4
.c_str(), features
, &order
));
2996 test_list_children(parent
, 4, pool_name2
.c_str(), child_name1
.c_str(),
2997 pool_name1
.c_str(), child_name2
.c_str(),
2998 pool_name2
.c_str(), child_name3
.c_str(),
2999 pool_name2
.c_str(), child_name4
.c_str());
3001 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name1
.c_str()));
3002 test_list_children(parent
, 3,
3003 pool_name1
.c_str(), child_name2
.c_str(),
3004 pool_name2
.c_str(), child_name3
.c_str(),
3005 pool_name2
.c_str(), child_name4
.c_str());
3007 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name3
.c_str()));
3008 test_list_children(parent
, 2,
3009 pool_name1
.c_str(), child_name2
.c_str(),
3010 pool_name2
.c_str(), child_name4
.c_str());
3012 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name4
.c_str()));
3013 test_list_children(parent
, 1,
3014 pool_name1
.c_str(), child_name2
.c_str());
3016 ASSERT_EQ(0, rbd_remove(ioctx1
, child_name2
.c_str()));
3017 test_list_children(parent
, 0);
3019 ASSERT_EQ(0, rbd_snap_unprotect(parent
, "parent_snap"));
3020 ASSERT_EQ(0, rbd_snap_remove(parent
, "parent_snap"));
3021 ASSERT_EQ(0, rbd_close(parent
));
3022 ASSERT_EQ(0, rbd_remove(ioctx1
, parent_name
.c_str()));
3023 rados_ioctx_destroy(ioctx1
);
3024 rados_ioctx_destroy(ioctx2
);
3027 TEST_F(TestLibRBD
, ListChildrenTiered
)
3029 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3031 string pool_name1
= create_pool(true);
3032 string pool_name2
= create_pool(true);
3033 string pool_name3
= create_pool(true);
3034 ASSERT_NE("", pool_name1
);
3035 ASSERT_NE("", pool_name2
);
3036 ASSERT_NE("", pool_name3
);
3038 std::string cmdstr
= "{\"prefix\": \"osd tier add\", \"pool\": \"" +
3039 pool_name1
+ "\", \"tierpool\":\"" + pool_name3
+ "\", \"force_nonempty\":\"\"}";
3041 cmd
[0] = (char *)cmdstr
.c_str();
3042 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
3044 cmdstr
= "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" +
3045 pool_name3
+ "\", \"mode\":\"writeback\"}";
3046 cmd
[0] = (char *)cmdstr
.c_str();
3047 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
3049 cmdstr
= "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" +
3050 pool_name1
+ "\", \"overlaypool\":\"" + pool_name3
+ "\"}";
3051 cmd
[0] = (char *)cmdstr
.c_str();
3052 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
3054 EXPECT_EQ(0, rados_wait_for_latest_osdmap(_cluster
));
3056 string parent_name
= get_temp_image_name();
3057 string child_name1
= get_temp_image_name();
3058 string child_name2
= get_temp_image_name();
3059 string child_name3
= get_temp_image_name();
3060 string child_name4
= get_temp_image_name();
3062 rados_ioctx_t ioctx1
, ioctx2
;
3063 rados_ioctx_create(_cluster
, pool_name1
.c_str(), &ioctx1
);
3064 rados_ioctx_create(_cluster
, pool_name2
.c_str(), &ioctx2
);
3071 ASSERT_EQ(0, get_features(&old_format
, &features
));
3072 ASSERT_FALSE(old_format
);
3074 // make a parent to clone from
3075 ASSERT_EQ(0, create_image_full(ioctx1
, parent_name
.c_str(), 4<<20, &order
,
3077 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, NULL
));
3078 // create a snapshot, reopen as the parent we're interested in
3079 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
3080 ASSERT_EQ(0, rbd_snap_set(parent
, "parent_snap"));
3081 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
3083 ASSERT_EQ(0, rbd_close(parent
));
3084 ASSERT_EQ(0, rbd_open(ioctx1
, parent_name
.c_str(), &parent
, "parent_snap"));
3086 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
3087 ioctx2
, child_name1
.c_str(), features
, &order
));
3088 test_list_children(parent
, 1, pool_name2
.c_str(), child_name1
.c_str());
3090 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
3091 ioctx1
, child_name2
.c_str(), features
, &order
));
3092 test_list_children(parent
, 2, pool_name2
.c_str(), child_name1
.c_str(),
3093 pool_name1
.c_str(), child_name2
.c_str());
3095 // read from the cache to populate it
3096 rbd_image_t tier_image
;
3097 ASSERT_EQ(0, rbd_open(ioctx1
, child_name2
.c_str(), &tier_image
, NULL
));
3098 size_t len
= 4 * 1024 * 1024;
3099 char* buf
= (char*)malloc(len
);
3100 ssize_t size
= rbd_read(tier_image
, 0, len
, buf
);
3103 ASSERT_EQ(0, rbd_close(tier_image
));
3105 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
3106 ioctx2
, child_name3
.c_str(), features
, &order
));
3107 test_list_children(parent
, 3, pool_name2
.c_str(), child_name1
.c_str(),
3108 pool_name1
.c_str(), child_name2
.c_str(),
3109 pool_name2
.c_str(), child_name3
.c_str());
3111 ASSERT_EQ(0, clone_image(ioctx1
, parent
, parent_name
.c_str(), "parent_snap",
3112 ioctx2
, child_name4
.c_str(), features
, &order
));
3113 test_list_children(parent
, 4, pool_name2
.c_str(), child_name1
.c_str(),
3114 pool_name1
.c_str(), child_name2
.c_str(),
3115 pool_name2
.c_str(), child_name3
.c_str(),
3116 pool_name2
.c_str(), child_name4
.c_str());
3118 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name1
.c_str()));
3119 test_list_children(parent
, 3,
3120 pool_name1
.c_str(), child_name2
.c_str(),
3121 pool_name2
.c_str(), child_name3
.c_str(),
3122 pool_name2
.c_str(), child_name4
.c_str());
3124 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name3
.c_str()));
3125 test_list_children(parent
, 2,
3126 pool_name1
.c_str(), child_name2
.c_str(),
3127 pool_name2
.c_str(), child_name4
.c_str());
3129 ASSERT_EQ(0, rbd_remove(ioctx2
, child_name4
.c_str()));
3130 test_list_children(parent
, 1,
3131 pool_name1
.c_str(), child_name2
.c_str());
3133 ASSERT_EQ(0, rbd_remove(ioctx1
, child_name2
.c_str()));
3134 test_list_children(parent
, 0);
3136 ASSERT_EQ(0, rbd_snap_unprotect(parent
, "parent_snap"));
3137 ASSERT_EQ(0, rbd_snap_remove(parent
, "parent_snap"));
3138 ASSERT_EQ(0, rbd_close(parent
));
3139 ASSERT_EQ(0, rbd_remove(ioctx1
, parent_name
.c_str()));
3140 rados_ioctx_destroy(ioctx1
);
3141 rados_ioctx_destroy(ioctx2
);
3142 cmdstr
= "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" +
3144 cmd
[0] = (char *)cmdstr
.c_str();
3145 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
3146 cmdstr
= "{\"prefix\": \"osd tier remove\", \"pool\": \"" +
3147 pool_name1
+ "\", \"tierpool\":\"" + pool_name3
+ "\"}";
3148 cmd
[0] = (char *)cmdstr
.c_str();
3149 ASSERT_EQ(0, rados_mon_command(_cluster
, (const char **)cmd
, 1, "", 0, NULL
, 0, NULL
, 0));
3152 TEST_F(TestLibRBD
, LockingPP
)
3154 librados::IoCtx ioctx
;
3155 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3159 librbd::Image image
;
3161 std::string name
= get_temp_image_name();
3162 uint64_t size
= 2 << 20;
3163 std::string cookie1
= "foo";
3164 std::string cookie2
= "bar";
3166 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3167 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3169 // no lockers initially
3170 std::list
<librbd::locker_t
> lockers
;
3173 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3174 ASSERT_EQ(0u, lockers
.size());
3177 // exclusive lock is exclusive
3178 ASSERT_EQ(0, image
.lock_exclusive(cookie1
));
3179 ASSERT_EQ(-EEXIST
, image
.lock_exclusive(cookie1
));
3180 ASSERT_EQ(-EBUSY
, image
.lock_exclusive(""));
3181 ASSERT_EQ(-EEXIST
, image
.lock_shared(cookie1
, ""));
3182 ASSERT_EQ(-EBUSY
, image
.lock_shared(cookie1
, "test"));
3183 ASSERT_EQ(-EBUSY
, image
.lock_shared("", "test"));
3184 ASSERT_EQ(-EBUSY
, image
.lock_shared("", ""));
3187 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3188 ASSERT_TRUE(exclusive
);
3190 ASSERT_EQ(1u, lockers
.size());
3191 ASSERT_EQ(cookie1
, lockers
.front().cookie
);
3194 ASSERT_EQ(-ENOENT
, image
.unlock(""));
3195 ASSERT_EQ(-ENOENT
, image
.unlock(cookie2
));
3196 ASSERT_EQ(0, image
.unlock(cookie1
));
3197 ASSERT_EQ(-ENOENT
, image
.unlock(cookie1
));
3198 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3199 ASSERT_EQ(0u, lockers
.size());
3201 ASSERT_EQ(0, image
.lock_shared(cookie1
, ""));
3202 ASSERT_EQ(-EEXIST
, image
.lock_shared(cookie1
, ""));
3203 ASSERT_EQ(0, image
.lock_shared(cookie2
, ""));
3204 ASSERT_EQ(-EEXIST
, image
.lock_shared(cookie2
, ""));
3205 ASSERT_EQ(-EEXIST
, image
.lock_exclusive(cookie1
));
3206 ASSERT_EQ(-EEXIST
, image
.lock_exclusive(cookie2
));
3207 ASSERT_EQ(-EBUSY
, image
.lock_exclusive(""));
3208 ASSERT_EQ(-EBUSY
, image
.lock_exclusive("test"));
3211 ASSERT_EQ(0, image
.list_lockers(&lockers
, &exclusive
, &tag
));
3212 ASSERT_EQ(2u, lockers
.size());
3218 TEST_F(TestLibRBD
, FlushAio
)
3220 rados_ioctx_t ioctx
;
3221 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3225 std::string name
= get_temp_image_name();
3226 uint64_t size
= 2 << 20;
3227 size_t num_aios
= 256;
3229 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3230 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3232 char test_data
[TEST_IO_SIZE
+ 1];
3234 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
3235 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
3238 rbd_completion_t write_comps
[num_aios
];
3239 for (i
= 0; i
< num_aios
; ++i
) {
3240 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &write_comps
[i
]));
3241 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3242 ASSERT_EQ(0, rbd_aio_write(image
, offset
, TEST_IO_SIZE
, test_data
,
3246 rbd_completion_t flush_comp
;
3247 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &flush_comp
));
3248 ASSERT_EQ(0, rbd_aio_flush(image
, flush_comp
));
3249 ASSERT_EQ(0, rbd_aio_wait_for_complete(flush_comp
));
3250 ASSERT_EQ(1, rbd_aio_is_complete(flush_comp
));
3251 rbd_aio_release(flush_comp
);
3253 for (i
= 0; i
< num_aios
; ++i
) {
3254 ASSERT_EQ(1, rbd_aio_is_complete(write_comps
[i
]));
3255 rbd_aio_release(write_comps
[i
]);
3258 ASSERT_PASSED(validate_object_map
, image
);
3259 ASSERT_EQ(0, rbd_close(image
));
3260 ASSERT_EQ(0, rbd_remove(ioctx
, name
.c_str()));
3261 rados_ioctx_destroy(ioctx
);
3264 TEST_F(TestLibRBD
, FlushAioPP
)
3266 librados::IoCtx ioctx
;
3267 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3271 librbd::Image image
;
3273 std::string name
= get_temp_image_name();
3274 uint64_t size
= 2 << 20;
3275 const size_t num_aios
= 256;
3277 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3278 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3280 char test_data
[TEST_IO_SIZE
+ 1];
3282 for (i
= 0; i
< TEST_IO_SIZE
; ++i
) {
3283 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
3285 test_data
[TEST_IO_SIZE
] = '\0';
3287 librbd::RBD::AioCompletion
*write_comps
[num_aios
];
3288 ceph::bufferlist bls
[num_aios
];
3289 for (i
= 0; i
< num_aios
; ++i
) {
3290 bls
[i
].append(test_data
, strlen(test_data
));
3291 write_comps
[i
] = new librbd::RBD::AioCompletion(NULL
, NULL
);
3292 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3293 ASSERT_EQ(0, image
.aio_write(offset
, TEST_IO_SIZE
, bls
[i
],
3297 librbd::RBD::AioCompletion
*flush_comp
=
3298 new librbd::RBD::AioCompletion(NULL
, NULL
);
3299 ASSERT_EQ(0, image
.aio_flush(flush_comp
));
3300 ASSERT_EQ(0, flush_comp
->wait_for_complete());
3301 ASSERT_EQ(1, flush_comp
->is_complete());
3302 flush_comp
->release();
3304 for (i
= 0; i
< num_aios
; ++i
) {
3305 librbd::RBD::AioCompletion
*comp
= write_comps
[i
];
3306 ASSERT_EQ(1, comp
->is_complete());
3309 ASSERT_PASSED(validate_object_map
, image
);
3316 int iterate_cb(uint64_t off
, size_t len
, int exists
, void *arg
)
3318 //cout << "iterate_cb " << off << "~" << len << std::endl;
3319 interval_set
<uint64_t> *diff
= static_cast<interval_set
<uint64_t> *>(arg
);
3320 diff
->insert(off
, len
);
3324 static int iterate_error_cb(uint64_t off
, size_t len
, int exists
, void *arg
)
3329 void scribble(librbd::Image
& image
, int n
, int max
, bool skip_discard
,
3330 interval_set
<uint64_t> *exists
,
3331 interval_set
<uint64_t> *what
)
3335 interval_set
<uint64_t> exists_at_start
= *exists
;
3337 for (int i
=0; i
<n
; i
++) {
3338 uint64_t off
= rand() % (size
- max
+ 1);
3339 uint64_t len
= 1 + rand() % max
;
3340 if (!skip_discard
&& rand() % 4 == 0) {
3341 ASSERT_EQ((int)len
, image
.discard(off
, len
));
3342 interval_set
<uint64_t> w
;
3345 // the zeroed bit no longer exists...
3346 w
.intersection_of(*exists
);
3347 exists
->subtract(w
);
3349 // the bits we discarded are no long written...
3350 interval_set
<uint64_t> w2
= w
;
3351 w2
.intersection_of(*what
);
3354 // except for the extents that existed at the start that we overwrote.
3355 interval_set
<uint64_t> w3
;
3356 w3
.insert(off
, len
);
3357 w3
.intersection_of(exists_at_start
);
3362 bl
.append(buffer::create(len
));
3364 ASSERT_EQ((int)len
, image
.write(off
, len
, bl
));
3365 interval_set
<uint64_t> w
;
3368 exists
->union_of(w
);
3373 interval_set
<uint64_t> round_diff_interval(const interval_set
<uint64_t>& diff
,
3374 uint64_t object_size
)
3376 if (object_size
== 0) {
3380 interval_set
<uint64_t> rounded_diff
;
3381 for (interval_set
<uint64_t>::const_iterator it
= diff
.begin();
3382 it
!= diff
.end(); ++it
) {
3383 uint64_t off
= it
.get_start();
3384 uint64_t len
= it
.get_len();
3385 off
-= off
% object_size
;
3386 len
+= (object_size
- (len
% object_size
));
3387 interval_set
<uint64_t> interval
;
3388 interval
.insert(off
, len
);
3389 rounded_diff
.union_of(interval
);
3391 return rounded_diff
;
3394 template <typename T
>
3395 class DiffIterateTest
: public TestLibRBD
{
3397 static const uint8_t whole_object
= T::whole_object
;
3400 template <bool _whole_object
>
3401 class DiffIterateParams
{
3403 static const uint8_t whole_object
= _whole_object
;
3406 typedef ::testing::Types
<DiffIterateParams
<false>,
3407 DiffIterateParams
<true> > DiffIterateTypes
;
3408 TYPED_TEST_CASE(DiffIterateTest
, DiffIterateTypes
);
3410 TYPED_TEST(DiffIterateTest
, DiffIterate
)
3412 librados::IoCtx ioctx
;
3413 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3415 bool skip_discard
= this->is_skip_partial_discard_enabled();
3419 librbd::Image image
;
3421 std::string name
= this->get_temp_image_name();
3422 uint64_t size
= 20 << 20;
3424 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3425 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3427 uint64_t object_size
= 0;
3428 if (this->whole_object
) {
3429 object_size
= 1 << order
;
3432 interval_set
<uint64_t> exists
;
3433 interval_set
<uint64_t> one
, two
;
3434 scribble(image
, 10, 102400, skip_discard
, &exists
, &one
);
3435 cout
<< " wrote " << one
<< std::endl
;
3436 ASSERT_EQ(0, image
.snap_create("one"));
3437 scribble(image
, 10, 102400, skip_discard
, &exists
, &two
);
3439 two
= round_diff_interval(two
, object_size
);
3440 cout
<< " wrote " << two
<< std::endl
;
3442 interval_set
<uint64_t> diff
;
3443 ASSERT_EQ(0, image
.diff_iterate2("one", 0, size
, true, this->whole_object
,
3444 iterate_cb
, (void *)&diff
));
3445 cout
<< " diff was " << diff
<< std::endl
;
3446 if (!two
.subset_of(diff
)) {
3447 interval_set
<uint64_t> i
;
3448 i
.intersection_of(two
, diff
);
3449 interval_set
<uint64_t> l
= two
;
3451 cout
<< " ... two - (two*diff) = " << l
<< std::endl
;
3453 ASSERT_TRUE(two
.subset_of(diff
));
3458 struct diff_extent
{
3459 diff_extent(uint64_t _offset
, uint64_t _length
, bool _exists
,
3460 uint64_t object_size
) :
3461 offset(_offset
), length(_length
), exists(_exists
)
3463 if (object_size
!= 0) {
3464 offset
-= offset
% object_size
;
3465 length
= object_size
;
3471 bool operator==(const diff_extent
& o
) const {
3472 return offset
== o
.offset
&& length
== o
.length
&& exists
== o
.exists
;
3476 ostream
& operator<<(ostream
& o
, const diff_extent
& e
) {
3477 return o
<< '(' << e
.offset
<< '~' << e
.length
<< ' ' << (e
.exists
? "true" : "false") << ')';
3480 int vector_iterate_cb(uint64_t off
, size_t len
, int exists
, void *arg
)
3482 cout
<< "iterate_cb " << off
<< "~" << len
<< std::endl
;
3483 vector
<diff_extent
> *diff
= static_cast<vector
<diff_extent
> *>(arg
);
3484 diff
->push_back(diff_extent(off
, len
, exists
, 0));
3488 TYPED_TEST(DiffIterateTest
, DiffIterateDiscard
)
3490 librados::IoCtx ioctx
;
3491 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3494 librbd::Image image
;
3496 std::string name
= this->get_temp_image_name();
3497 uint64_t size
= 20 << 20;
3499 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3500 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3502 uint64_t object_size
= 0;
3503 if (this->whole_object
) {
3504 object_size
= 1 << order
;
3506 vector
<diff_extent
> extents
;
3507 ceph::bufferlist bl
;
3509 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3510 vector_iterate_cb
, (void *) &extents
));
3511 ASSERT_EQ(0u, extents
.size());
3514 memset(data
, 1, sizeof(data
));
3515 bl
.append(data
, 256);
3516 ASSERT_EQ(256, image
.write(0, 256, bl
));
3517 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3518 vector_iterate_cb
, (void *) &extents
));
3519 ASSERT_EQ(1u, extents
.size());
3520 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3523 ASSERT_EQ(1 << order
, image
.discard(0, 1 << order
));
3526 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3527 vector_iterate_cb
, (void *) &extents
));
3528 ASSERT_EQ(0u, extents
.size());
3530 ASSERT_EQ(0, image
.snap_create("snap1"));
3531 ASSERT_EQ(256, image
.write(0, 256, bl
));
3532 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3533 vector_iterate_cb
, (void *) &extents
));
3534 ASSERT_EQ(1u, extents
.size());
3535 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3536 ASSERT_EQ(0, image
.snap_create("snap2"));
3538 ASSERT_EQ(obj_ofs
, image
.discard(0, obj_ofs
));
3541 ASSERT_EQ(0, image
.snap_set("snap2"));
3542 ASSERT_EQ(0, image
.diff_iterate2("snap1", 0, size
, true, this->whole_object
,
3543 vector_iterate_cb
, (void *) &extents
));
3544 ASSERT_EQ(1u, extents
.size());
3545 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3547 ASSERT_EQ(0, image
.snap_set(NULL
));
3548 ASSERT_EQ(1 << order
, image
.discard(0, 1 << order
));
3549 ASSERT_EQ(0, image
.snap_create("snap3"));
3550 ASSERT_EQ(0, image
.snap_set("snap3"));
3553 ASSERT_EQ(0, image
.diff_iterate2("snap1", 0, size
, true, this->whole_object
,
3554 vector_iterate_cb
, (void *) &extents
));
3555 ASSERT_EQ(1u, extents
.size());
3556 ASSERT_EQ(diff_extent(0, 256, false, object_size
), extents
[0]);
3557 ASSERT_PASSED(this->validate_object_map
, image
);
3560 TYPED_TEST(DiffIterateTest
, DiffIterateStress
)
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();
3568 librbd::Image image
;
3570 std::string name
= this->get_temp_image_name();
3571 uint64_t size
= 400 << 20;
3573 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3574 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3576 uint64_t object_size
= 0;
3577 if (this->whole_object
) {
3578 object_size
= 1 << order
;
3581 interval_set
<uint64_t> curexists
;
3582 vector
<interval_set
<uint64_t> > wrote
;
3583 vector
<interval_set
<uint64_t> > exists
;
3584 vector
<string
> snap
;
3586 for (int i
=0; i
<n
; i
++) {
3587 interval_set
<uint64_t> w
;
3588 scribble(image
, 10, 8192000, skip_discard
, &curexists
, &w
);
3589 cout
<< " i=" << i
<< " exists " << curexists
<< " wrote " << w
<< std::endl
;
3590 string s
= "snap" + stringify(i
);
3591 ASSERT_EQ(0, image
.snap_create(s
.c_str()));
3593 exists
.push_back(curexists
);
3597 for (int h
=0; h
<n
-1; h
++) {
3598 for (int i
=0; i
<n
-h
-1; i
++) {
3599 for (int j
=(h
==0 ? i
+1 : n
-1); j
<n
; j
++) {
3600 interval_set
<uint64_t> diff
, actual
, uex
;
3601 for (int k
=i
+1; k
<=j
; k
++)
3602 diff
.union_of(wrote
[k
]);
3603 cout
<< "from " << i
<< " to "
3604 << (h
!= 0 ? string("HEAD") : stringify(j
)) << " diff "
3605 << round_diff_interval(diff
, object_size
) << std::endl
;
3607 // limit to extents that exists both at the beginning and at the end
3608 uex
.union_of(exists
[i
], exists
[j
]);
3609 diff
.intersection_of(uex
);
3610 diff
= round_diff_interval(diff
, object_size
);
3611 cout
<< " limited diff " << diff
<< std::endl
;
3613 ASSERT_EQ(0, image
.snap_set(h
==0 ? snap
[j
].c_str() : NULL
));
3614 ASSERT_EQ(0, image
.diff_iterate2(snap
[i
].c_str(), 0, size
, true,
3615 this->whole_object
, iterate_cb
,
3617 cout
<< " actual was " << actual
<< std::endl
;
3618 if (!diff
.subset_of(actual
)) {
3619 interval_set
<uint64_t> i
;
3620 i
.intersection_of(diff
, actual
);
3621 interval_set
<uint64_t> l
= diff
;
3623 cout
<< " ... diff - (actual*diff) = " << l
<< std::endl
;
3625 ASSERT_TRUE(diff
.subset_of(actual
));
3628 ASSERT_EQ(0, image
.snap_set(NULL
));
3629 ASSERT_EQ(0, image
.snap_remove(snap
[n
-h
-1].c_str()));
3632 ASSERT_PASSED(this->validate_object_map
, image
);
3635 TYPED_TEST(DiffIterateTest
, DiffIterateRegression6926
)
3637 librados::IoCtx ioctx
;
3638 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3641 librbd::Image image
;
3643 std::string name
= this->get_temp_image_name();
3644 uint64_t size
= 20 << 20;
3646 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3647 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3649 uint64_t object_size
= 0;
3650 if (this->whole_object
) {
3651 object_size
= 1 << order
;
3653 vector
<diff_extent
> extents
;
3654 ceph::bufferlist bl
;
3656 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3657 vector_iterate_cb
, (void *) &extents
));
3658 ASSERT_EQ(0u, extents
.size());
3660 ASSERT_EQ(0, image
.snap_create("snap1"));
3662 memset(data
, 1, sizeof(data
));
3663 bl
.append(data
, 256);
3664 ASSERT_EQ(256, image
.write(0, 256, bl
));
3667 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3668 vector_iterate_cb
, (void *) &extents
));
3669 ASSERT_EQ(1u, extents
.size());
3670 ASSERT_EQ(diff_extent(0, 256, true, object_size
), extents
[0]);
3672 ASSERT_EQ(0, image
.snap_set("snap1"));
3674 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3675 vector_iterate_cb
, (void *) &extents
));
3676 ASSERT_EQ(static_cast<size_t>(0), extents
.size());
3679 TYPED_TEST(DiffIterateTest
, DiffIterateIgnoreParent
)
3681 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3683 librados::IoCtx ioctx
;
3684 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3686 bool skip_discard
= this->is_skip_partial_discard_enabled();
3689 librbd::Image image
;
3690 std::string name
= this->get_temp_image_name();
3691 uint64_t size
= 20 << 20;
3694 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3695 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3697 uint64_t object_size
= 0;
3698 if (this->whole_object
) {
3699 object_size
= 1 << order
;
3703 bl
.append(buffer::create(size
));
3705 interval_set
<uint64_t> one
;
3706 one
.insert(0, size
);
3707 ASSERT_EQ((int)size
, image
.write(0, size
, bl
));
3708 ASSERT_EQ(0, image
.snap_create("one"));
3709 ASSERT_EQ(0, image
.snap_protect("one"));
3711 std::string clone_name
= this->get_temp_image_name();
3712 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "one", ioctx
, clone_name
.c_str(),
3713 RBD_FEATURE_LAYERING
, &order
));
3714 ASSERT_EQ(0, rbd
.open(ioctx
, image
, clone_name
.c_str(), NULL
));
3716 interval_set
<uint64_t> exists
;
3717 interval_set
<uint64_t> two
;
3718 scribble(image
, 10, 102400, skip_discard
, &exists
, &two
);
3719 two
= round_diff_interval(two
, object_size
);
3720 cout
<< " wrote " << two
<< " to clone" << std::endl
;
3722 interval_set
<uint64_t> diff
;
3723 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, false, this->whole_object
,
3724 iterate_cb
, (void *)&diff
));
3725 cout
<< " diff was " << diff
<< std::endl
;
3726 if (!this->whole_object
) {
3727 ASSERT_FALSE(one
.subset_of(diff
));
3729 ASSERT_TRUE(two
.subset_of(diff
));
3732 TYPED_TEST(DiffIterateTest
, DiffIterateCallbackError
)
3734 librados::IoCtx ioctx
;
3735 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3737 bool skip_discard
= this->is_skip_partial_discard_enabled();
3741 librbd::Image image
;
3743 std::string name
= this->get_temp_image_name();
3744 uint64_t size
= 20 << 20;
3746 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3747 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3749 interval_set
<uint64_t> exists
;
3750 interval_set
<uint64_t> one
;
3751 scribble(image
, 10, 102400, skip_discard
, &exists
, &one
);
3752 cout
<< " wrote " << one
<< std::endl
;
3754 interval_set
<uint64_t> diff
;
3755 ASSERT_EQ(-EINVAL
, image
.diff_iterate2(NULL
, 0, size
, true,
3757 iterate_error_cb
, NULL
));
3762 TYPED_TEST(DiffIterateTest
, DiffIterateParentDiscard
)
3764 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3766 librados::IoCtx ioctx
;
3767 ASSERT_EQ(0, this->_rados
.ioctx_create(this->m_pool_name
.c_str(), ioctx
));
3769 bool skip_discard
= this->is_skip_partial_discard_enabled();
3772 librbd::Image image
;
3773 std::string name
= this->get_temp_image_name();
3774 uint64_t size
= 20 << 20;
3777 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
3778 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
3780 uint64_t object_size
= 0;
3781 if (this->whole_object
) {
3782 object_size
= 1 << order
;
3785 interval_set
<uint64_t> exists
;
3786 interval_set
<uint64_t> one
;
3787 scribble(image
, 10, 102400, skip_discard
, &exists
, &one
);
3788 ASSERT_EQ(0, image
.snap_create("one"));
3790 ASSERT_EQ(1 << order
, image
.discard(0, 1 << order
));
3791 ASSERT_EQ(0, image
.snap_create("two"));
3792 ASSERT_EQ(0, image
.snap_protect("two"));
3796 std::string clone_name
= this->get_temp_image_name();
3797 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "two", ioctx
,
3798 clone_name
.c_str(), RBD_FEATURE_LAYERING
, &order
));
3799 ASSERT_EQ(0, rbd
.open(ioctx
, image
, clone_name
.c_str(), NULL
));
3801 interval_set
<uint64_t> two
;
3802 scribble(image
, 10, 102400, skip_discard
, &exists
, &two
);
3803 two
= round_diff_interval(two
, object_size
);
3805 interval_set
<uint64_t> diff
;
3806 ASSERT_EQ(0, image
.diff_iterate2(NULL
, 0, size
, true, this->whole_object
,
3807 iterate_cb
, (void *)&diff
));
3808 ASSERT_TRUE(two
.subset_of(diff
));
3811 TEST_F(TestLibRBD
, ZeroLengthWrite
)
3813 rados_ioctx_t ioctx
;
3814 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3818 std::string name
= get_temp_image_name();
3819 uint64_t size
= 2 << 20;
3821 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3822 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3825 ASSERT_EQ(0, rbd_write(image
, 0, 0, NULL
));
3826 ASSERT_EQ(1, rbd_read(image
, 0, 1, read_data
));
3827 ASSERT_EQ('\0', read_data
[0]);
3829 ASSERT_PASSED(validate_object_map
, image
);
3830 ASSERT_EQ(0, rbd_close(image
));
3832 rados_ioctx_destroy(ioctx
);
3836 TEST_F(TestLibRBD
, ZeroLengthDiscard
)
3838 rados_ioctx_t ioctx
;
3839 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3843 std::string name
= get_temp_image_name();
3844 uint64_t size
= 2 << 20;
3846 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3847 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3849 const char data
[] = "blah";
3850 char read_data
[sizeof(data
)];
3851 ASSERT_EQ((int)strlen(data
), rbd_write(image
, 0, strlen(data
), data
));
3852 ASSERT_EQ(0, rbd_discard(image
, 0, 0));
3853 ASSERT_EQ((int)strlen(data
), rbd_read(image
, 0, strlen(data
), read_data
));
3854 ASSERT_EQ(0, memcmp(data
, read_data
, strlen(data
)));
3856 ASSERT_PASSED(validate_object_map
, image
);
3857 ASSERT_EQ(0, rbd_close(image
));
3859 rados_ioctx_destroy(ioctx
);
3862 TEST_F(TestLibRBD
, ZeroLengthRead
)
3864 rados_ioctx_t ioctx
;
3865 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3869 std::string name
= get_temp_image_name();
3870 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
));
3876 ASSERT_EQ(0, rbd_read(image
, 0, 0, read_data
));
3878 ASSERT_EQ(0, rbd_close(image
));
3880 rados_ioctx_destroy(ioctx
);
3883 TEST_F(TestLibRBD
, LargeCacheRead
)
3885 std::string config_value
;
3886 ASSERT_EQ(0, _rados
.conf_get("rbd_cache", config_value
));
3887 if (config_value
== "false") {
3888 std::cout
<< "SKIPPING due to disabled cache" << std::endl
;
3892 rados_ioctx_t ioctx
;
3893 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3895 uint32_t new_cache_size
= 1 << 20;
3896 std::string orig_cache_size
;
3897 ASSERT_EQ(0, _rados
.conf_get("rbd_cache_size", orig_cache_size
));
3898 ASSERT_EQ(0, _rados
.conf_set("rbd_cache_size",
3899 stringify(new_cache_size
).c_str()));
3900 ASSERT_EQ(0, _rados
.conf_get("rbd_cache_size", config_value
));
3901 ASSERT_EQ(stringify(new_cache_size
), config_value
);
3902 BOOST_SCOPE_EXIT( (orig_cache_size
) ) {
3903 ASSERT_EQ(0, _rados
.conf_set("rbd_cache_size", orig_cache_size
.c_str()));
3904 } BOOST_SCOPE_EXIT_END
;
3908 std::string name
= get_temp_image_name();
3909 uint64_t size
= 1 << order
;
3911 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
3912 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3914 std::string
buffer(1 << order
, '1');
3916 ASSERT_EQ(static_cast<ssize_t
>(buffer
.size()),
3917 rbd_write(image
, 0, buffer
.size(), buffer
.c_str()));
3919 ASSERT_EQ(0, rbd_invalidate_cache(image
));
3921 ASSERT_EQ(static_cast<ssize_t
>(buffer
.size()),
3922 rbd_read(image
, 0, buffer
.size(), &buffer
[0]));
3924 ASSERT_EQ(0, rbd_close(image
));
3926 rados_ioctx_destroy(ioctx
);
3929 TEST_F(TestLibRBD
, TestPendingAio
)
3931 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3933 rados_ioctx_t ioctx
;
3934 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
3941 ASSERT_EQ(0, get_features(&old_format
, &features
));
3942 ASSERT_FALSE(old_format
);
3944 std::string name
= get_temp_image_name();
3946 uint64_t size
= 4 << 20;
3947 ASSERT_EQ(0, create_image_full(ioctx
, name
.c_str(), size
, &order
,
3949 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
3951 char test_data
[TEST_IO_SIZE
];
3952 for (size_t i
= 0; i
< TEST_IO_SIZE
; ++i
) {
3953 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
3956 size_t num_aios
= 256;
3957 rbd_completion_t comps
[num_aios
];
3958 for (size_t i
= 0; i
< num_aios
; ++i
) {
3959 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &comps
[i
]));
3960 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3961 ASSERT_EQ(0, rbd_aio_write(image
, offset
, TEST_IO_SIZE
, test_data
,
3964 for (size_t i
= 0; i
< num_aios
; ++i
) {
3965 ASSERT_EQ(0, rbd_aio_wait_for_complete(comps
[i
]));
3966 rbd_aio_release(comps
[i
]);
3968 ASSERT_EQ(0, rbd_invalidate_cache(image
));
3970 for (size_t i
= 0; i
< num_aios
; ++i
) {
3971 ASSERT_EQ(0, rbd_aio_create_completion(NULL
, NULL
, &comps
[i
]));
3972 uint64_t offset
= rand() % (size
- TEST_IO_SIZE
);
3973 ASSERT_LE(0, rbd_aio_read(image
, offset
, TEST_IO_SIZE
, test_data
,
3977 ASSERT_PASSED(validate_object_map
, image
);
3978 ASSERT_EQ(0, rbd_close(image
));
3979 for (size_t i
= 0; i
< num_aios
; ++i
) {
3980 ASSERT_EQ(1, rbd_aio_is_complete(comps
[i
]));
3981 rbd_aio_release(comps
[i
]);
3984 rados_ioctx_destroy(ioctx
);
3987 TEST_F(TestLibRBD
, Flatten
)
3989 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
3991 librados::IoCtx ioctx
;
3992 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
3995 std::string parent_name
= get_temp_image_name();
3996 uint64_t size
= 2 << 20;
3998 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, parent_name
.c_str(), size
, &order
));
4000 librbd::Image parent_image
;
4001 ASSERT_EQ(0, rbd
.open(ioctx
, parent_image
, parent_name
.c_str(), NULL
));
4004 bl
.append(std::string(4096, '1'));
4005 ASSERT_EQ((ssize_t
)bl
.length(), parent_image
.write(0, bl
.length(), bl
));
4007 ASSERT_EQ(0, parent_image
.snap_create("snap1"));
4008 ASSERT_EQ(0, parent_image
.snap_protect("snap1"));
4011 ASSERT_EQ(0, parent_image
.features(&features
));
4013 std::string clone_name
= get_temp_image_name();
4014 EXPECT_EQ(0, rbd
.clone(ioctx
, parent_name
.c_str(), "snap1", ioctx
,
4015 clone_name
.c_str(), features
, &order
));
4017 librbd::Image clone_image
;
4018 ASSERT_EQ(0, rbd
.open(ioctx
, clone_image
, clone_name
.c_str(), NULL
));
4019 ASSERT_EQ(0, clone_image
.flatten());
4021 librbd::RBD::AioCompletion
*read_comp
=
4022 new librbd::RBD::AioCompletion(NULL
, NULL
);
4024 clone_image
.aio_read(0, bl
.length(), read_bl
, read_comp
);
4025 ASSERT_EQ(0, read_comp
->wait_for_complete());
4026 ASSERT_EQ((ssize_t
)bl
.length(), read_comp
->get_return_value());
4027 read_comp
->release();
4028 ASSERT_TRUE(bl
.contents_equal(read_bl
));
4030 ASSERT_PASSED(validate_object_map
, clone_image
);
4033 TEST_F(TestLibRBD
, SnapshotLimit
)
4035 rados_ioctx_t ioctx
;
4036 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
4040 std::string name
= get_temp_image_name();
4041 uint64_t size
= 2 << 20;
4044 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
4045 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
4047 ASSERT_EQ(0, rbd_snap_get_limit(image
, &limit
));
4048 ASSERT_EQ(UINT64_MAX
, limit
);
4049 ASSERT_EQ(0, rbd_snap_set_limit(image
, 2));
4050 ASSERT_EQ(0, rbd_snap_get_limit(image
, &limit
));
4051 ASSERT_EQ(2U, limit
);
4053 ASSERT_EQ(0, rbd_snap_create(image
, "snap1"));
4054 ASSERT_EQ(0, rbd_snap_create(image
, "snap2"));
4055 ASSERT_EQ(-EDQUOT
, rbd_snap_create(image
, "snap3"));
4056 ASSERT_EQ(0, rbd_snap_set_limit(image
, UINT64_MAX
));
4057 ASSERT_EQ(0, rbd_snap_create(image
, "snap3"));
4058 ASSERT_EQ(0, rbd_close(image
));
4060 rados_ioctx_destroy(ioctx
);
4064 TEST_F(TestLibRBD
, SnapshotLimitPP
)
4066 librados::IoCtx ioctx
;
4067 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4071 librbd::Image image
;
4072 std::string name
= get_temp_image_name();
4073 uint64_t size
= 2 << 20;
4077 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4078 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4080 ASSERT_EQ(0, image
.snap_get_limit(&limit
));
4081 ASSERT_EQ(UINT64_MAX
, limit
);
4082 ASSERT_EQ(0, image
.snap_set_limit(2));
4083 ASSERT_EQ(0, image
.snap_get_limit(&limit
));
4084 ASSERT_EQ(2U, limit
);
4086 ASSERT_EQ(0, image
.snap_create("snap1"));
4087 ASSERT_EQ(0, image
.snap_create("snap2"));
4088 ASSERT_EQ(-EDQUOT
, image
.snap_create("snap3"));
4089 ASSERT_EQ(0, image
.snap_set_limit(UINT64_MAX
));
4090 ASSERT_EQ(0, image
.snap_create("snap3"));
4096 TEST_F(TestLibRBD
, RebuildObjectMapViaLockOwner
)
4098 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_OBJECT_MAP
);
4100 librados::IoCtx ioctx
;
4101 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4104 std::string name
= get_temp_image_name();
4105 uint64_t size
= 2 << 20;
4107 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4109 std::string object_map_oid
;
4111 librbd::Image image
;
4112 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4114 std::string image_id
;
4115 ASSERT_EQ(0, get_image_id(image
, &image_id
));
4116 object_map_oid
= RBD_OBJECT_MAP_PREFIX
+ image_id
;
4119 // corrupt the object map
4122 ASSERT_EQ(0, ioctx
.write(object_map_oid
, bl
, bl
.length(), 0));
4124 librbd::Image image1
;
4125 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4129 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4130 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4131 ASSERT_TRUE(lock_owner
);
4134 ASSERT_EQ(0, image1
.get_flags(&flags
));
4135 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0);
4137 librbd::Image image2
;
4138 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4139 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4140 ASSERT_FALSE(lock_owner
);
4142 PrintProgress prog_ctx
;
4143 ASSERT_EQ(0, image2
.rebuild_object_map(prog_ctx
));
4144 ASSERT_PASSED(validate_object_map
, image1
);
4145 ASSERT_PASSED(validate_object_map
, image2
);
4148 TEST_F(TestLibRBD
, RenameViaLockOwner
)
4150 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
4152 librados::IoCtx ioctx
;
4153 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4156 std::string name
= get_temp_image_name();
4157 uint64_t size
= 2 << 20;
4159 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4161 librbd::Image image1
;
4162 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4165 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4168 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4169 ASSERT_TRUE(lock_owner
);
4171 std::string new_name
= get_temp_image_name();
4172 ASSERT_EQ(0, rbd
.rename(ioctx
, name
.c_str(), new_name
.c_str()));
4173 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4174 ASSERT_TRUE(lock_owner
);
4176 librbd::Image image2
;
4177 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, new_name
.c_str(), NULL
));
4180 TEST_F(TestLibRBD
, SnapCreateViaLockOwner
)
4182 REQUIRE_FEATURE(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
));
4196 // switch to writeback cache
4197 ASSERT_EQ(0, image1
.flush());
4200 bl
.append(std::string(4096, '1'));
4201 ASSERT_EQ((ssize_t
)bl
.length(), image1
.write(0, bl
.length(), bl
));
4204 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4205 ASSERT_TRUE(lock_owner
);
4207 librbd::Image image2
;
4208 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4210 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4211 ASSERT_FALSE(lock_owner
);
4213 ASSERT_EQ(0, image2
.snap_create("snap1"));
4215 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4216 ASSERT_TRUE(exists
);
4217 ASSERT_EQ(0, image2
.snap_exists2("snap1", &exists
));
4218 ASSERT_TRUE(exists
);
4220 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4221 ASSERT_TRUE(lock_owner
);
4224 TEST_F(TestLibRBD
, SnapRemoveViaLockOwner
)
4226 REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF
);
4228 librados::IoCtx ioctx
;
4229 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4232 std::string name
= get_temp_image_name();
4233 uint64_t size
= 2 << 20;
4235 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4237 librbd::Image image1
;
4238 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4241 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4242 ASSERT_EQ(0, image1
.snap_create("snap1"));
4245 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4246 ASSERT_TRUE(lock_owner
);
4248 librbd::Image image2
;
4249 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4251 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4252 ASSERT_FALSE(lock_owner
);
4254 ASSERT_EQ(0, image2
.snap_remove("snap1"));
4256 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4257 ASSERT_FALSE(exists
);
4258 ASSERT_EQ(0, image2
.snap_exists2("snap1", &exists
));
4259 ASSERT_FALSE(exists
);
4261 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4262 ASSERT_TRUE(lock_owner
);
4265 TEST_F(TestLibRBD
, EnableJournalingViaLockOwner
)
4267 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
4269 librados::IoCtx ioctx
;
4270 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4273 std::string name
= get_temp_image_name();
4274 uint64_t size
= 2 << 20;
4276 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4278 librbd::Image image1
;
4279 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4282 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4285 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4286 ASSERT_TRUE(lock_owner
);
4288 librbd::Image image2
;
4289 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4291 ASSERT_EQ(0, image2
.update_features(RBD_FEATURE_JOURNALING
, false));
4293 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4294 ASSERT_TRUE(lock_owner
);
4295 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4296 ASSERT_FALSE(lock_owner
);
4298 ASSERT_EQ(0, image2
.update_features(RBD_FEATURE_JOURNALING
, true));
4300 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4301 ASSERT_FALSE(lock_owner
);
4302 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4303 ASSERT_TRUE(lock_owner
);
4306 TEST_F(TestLibRBD
, SnapRemove2
)
4308 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4310 librados::IoCtx ioctx
;
4311 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4314 std::string name
= get_temp_image_name();
4315 uint64_t size
= 2 << 20;
4317 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4319 librbd::Image image1
;
4320 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4323 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4324 ASSERT_EQ(0, image1
.snap_create("snap1"));
4326 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4327 ASSERT_TRUE(exists
);
4328 ASSERT_EQ(0, image1
.snap_protect("snap1"));
4330 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4331 ASSERT_TRUE(is_protected
);
4334 ASSERT_EQ(0, image1
.features(&features
));
4336 std::string child_name
= get_temp_image_name();
4337 EXPECT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "snap1", ioctx
,
4338 child_name
.c_str(), features
, &order
));
4340 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4341 ASSERT_TRUE(exists
);
4342 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4343 ASSERT_TRUE(is_protected
);
4345 ASSERT_EQ(-EBUSY
, image1
.snap_remove("snap1"));
4347 ASSERT_EQ(0, image1
.snap_remove2("snap1", RBD_SNAP_REMOVE_FORCE
, pp
));
4348 ASSERT_EQ(0, image1
.snap_exists2("snap1", &exists
));
4349 ASSERT_FALSE(exists
);
4352 TEST_F(TestLibRBD
, SnapRenameViaLockOwner
)
4354 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4356 librados::IoCtx ioctx
;
4357 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4360 std::string name
= get_temp_image_name();
4361 uint64_t size
= 2 << 20;
4363 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4365 librbd::Image image1
;
4366 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4369 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4370 ASSERT_EQ(0, image1
.snap_create("snap1"));
4373 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4374 ASSERT_TRUE(lock_owner
);
4376 librbd::Image image2
;
4377 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4379 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4380 ASSERT_FALSE(lock_owner
);
4382 ASSERT_EQ(0, image2
.snap_rename("snap1", "snap1-rename"));
4384 ASSERT_EQ(0, image1
.snap_exists2("snap1-rename", &exists
));
4385 ASSERT_TRUE(exists
);
4386 ASSERT_EQ(0, image2
.snap_exists2("snap1-rename", &exists
));
4387 ASSERT_TRUE(exists
);
4389 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4390 ASSERT_TRUE(lock_owner
);
4393 TEST_F(TestLibRBD
, SnapProtectViaLockOwner
)
4395 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4397 librados::IoCtx ioctx
;
4398 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4401 std::string name
= get_temp_image_name();
4402 uint64_t size
= 2 << 20;
4404 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4406 librbd::Image image1
;
4407 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4410 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4413 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4414 ASSERT_TRUE(lock_owner
);
4415 ASSERT_EQ(0, image1
.snap_create("snap1"));
4417 librbd::Image image2
;
4418 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4420 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4421 ASSERT_FALSE(lock_owner
);
4423 ASSERT_EQ(0, image2
.snap_protect("snap1"));
4425 ASSERT_EQ(0, image2
.snap_is_protected("snap1", &is_protected
));
4426 ASSERT_TRUE(is_protected
);
4427 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4428 ASSERT_TRUE(is_protected
);
4430 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4431 ASSERT_TRUE(lock_owner
);
4434 TEST_F(TestLibRBD
, SnapUnprotectViaLockOwner
)
4436 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_EXCLUSIVE_LOCK
);
4438 librados::IoCtx ioctx
;
4439 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4442 std::string name
= get_temp_image_name();
4443 uint64_t size
= 2 << 20;
4445 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4447 librbd::Image image1
;
4448 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4451 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4454 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4455 ASSERT_TRUE(lock_owner
);
4456 ASSERT_EQ(0, image1
.snap_create("snap1"));
4457 ASSERT_EQ(0, image1
.snap_protect("snap1"));
4459 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4460 ASSERT_TRUE(is_protected
);
4462 librbd::Image image2
;
4463 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4465 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4466 ASSERT_FALSE(lock_owner
);
4468 ASSERT_EQ(0, image2
.snap_unprotect("snap1"));
4469 ASSERT_EQ(0, image2
.snap_is_protected("snap1", &is_protected
));
4470 ASSERT_FALSE(is_protected
);
4471 ASSERT_EQ(0, image1
.snap_is_protected("snap1", &is_protected
));
4472 ASSERT_FALSE(is_protected
);
4474 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4475 ASSERT_TRUE(lock_owner
);
4478 TEST_F(TestLibRBD
, FlattenViaLockOwner
)
4480 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
4482 librados::IoCtx ioctx
;
4483 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4486 std::string parent_name
= get_temp_image_name();
4487 uint64_t size
= 2 << 20;
4489 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, parent_name
.c_str(), size
, &order
));
4491 librbd::Image parent_image
;
4492 ASSERT_EQ(0, rbd
.open(ioctx
, parent_image
, parent_name
.c_str(), NULL
));
4493 ASSERT_EQ(0, parent_image
.snap_create("snap1"));
4494 ASSERT_EQ(0, parent_image
.snap_protect("snap1"));
4497 ASSERT_EQ(0, parent_image
.features(&features
));
4499 std::string name
= get_temp_image_name();
4500 EXPECT_EQ(0, rbd
.clone(ioctx
, parent_name
.c_str(), "snap1", ioctx
,
4501 name
.c_str(), features
, &order
));
4503 librbd::Image image1
;
4504 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4507 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4510 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4511 ASSERT_TRUE(lock_owner
);
4513 librbd::Image image2
;
4514 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4516 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4517 ASSERT_FALSE(lock_owner
);
4519 ASSERT_EQ(0, image2
.flatten());
4521 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4522 ASSERT_TRUE(lock_owner
);
4523 ASSERT_PASSED(validate_object_map
, image1
);
4526 TEST_F(TestLibRBD
, ResizeViaLockOwner
)
4528 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
4530 librados::IoCtx ioctx
;
4531 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4534 std::string name
= get_temp_image_name();
4535 uint64_t size
= 2 << 20;
4537 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4539 librbd::Image image1
;
4540 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4543 ASSERT_EQ(0, image1
.write(0, 0, bl
));
4546 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4547 ASSERT_TRUE(lock_owner
);
4549 librbd::Image image2
;
4550 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
4552 ASSERT_EQ(0, image2
.is_exclusive_lock_owner(&lock_owner
));
4553 ASSERT_FALSE(lock_owner
);
4555 ASSERT_EQ(0, image2
.resize(0));
4557 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
4558 ASSERT_TRUE(lock_owner
);
4559 ASSERT_PASSED(validate_object_map
, image1
);
4562 TEST_F(TestLibRBD
, ObjectMapConsistentSnap
)
4564 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
4566 librados::IoCtx ioctx
;
4567 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4570 std::string name
= get_temp_image_name();
4571 uint64_t size
= 1 << 20;
4573 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4575 librbd::Image image1
;
4576 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4579 for (int i
= 0; i
< num_snaps
; ++i
) {
4580 std::string snap_name
= "snap" + stringify(i
);
4581 ASSERT_EQ(0, image1
.snap_create(snap_name
.c_str()));
4585 thread
writer([&image1
](){
4586 librbd::image_info_t info
;
4587 int r
= image1
.stat(info
, sizeof(info
));
4591 for (unsigned i
= 0; i
< info
.num_objs
; ++i
) {
4592 r
= image1
.write((1 << info
.order
) * i
, bl
.length(), bl
);
4593 assert(r
== (int) bl
.length());
4598 for (int i
= 0; i
< num_snaps
; ++i
) {
4599 std::string snap_name
= "snap" + stringify(i
);
4600 ASSERT_EQ(0, image1
.snap_set(snap_name
.c_str()));
4601 ASSERT_PASSED(validate_object_map
, image1
);
4604 ASSERT_EQ(0, image1
.snap_set(NULL
));
4605 ASSERT_PASSED(validate_object_map
, image1
);
4608 void memset_rand(char *buf
, size_t len
) {
4609 for (size_t i
= 0; i
< len
; ++i
) {
4610 buf
[i
] = (char) (rand() % (126 - 33) + 33);
4614 TEST_F(TestLibRBD
, Metadata
)
4616 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4618 rados_ioctx_t ioctx
;
4619 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
4621 std::string name
= get_temp_image_name();
4622 uint64_t size
= 2 << 20;
4624 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
4627 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
4630 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image1
, NULL
));
4634 size_t keys_len
= sizeof(keys
);
4635 size_t vals_len
= sizeof(vals
);
4637 memset_rand(keys
, keys_len
);
4638 memset_rand(vals
, vals_len
);
4640 ASSERT_EQ(0, rbd_metadata_list(image
, "", 0, keys
, &keys_len
, vals
,
4642 ASSERT_EQ(0U, keys_len
);
4643 ASSERT_EQ(0U, vals_len
);
4646 size_t value_len
= sizeof(value
);
4647 memset_rand(value
, value_len
);
4649 ASSERT_EQ(0, rbd_metadata_set(image1
, "key1", "value1"));
4650 ASSERT_EQ(0, rbd_metadata_set(image1
, "key2", "value2"));
4651 ASSERT_EQ(0, rbd_metadata_get(image1
, "key1", value
, &value_len
));
4652 ASSERT_STREQ(value
, "value1");
4654 ASSERT_EQ(-ERANGE
, rbd_metadata_get(image1
, "key1", value
, &value_len
));
4655 ASSERT_EQ(value_len
, strlen("value1") + 1);
4657 ASSERT_EQ(-ERANGE
, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4659 keys_len
= sizeof(keys
);
4660 vals_len
= sizeof(vals
);
4661 memset_rand(keys
, keys_len
);
4662 memset_rand(vals
, vals_len
);
4663 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4665 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1);
4666 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1);
4667 ASSERT_STREQ(keys
, "key1");
4668 ASSERT_STREQ(keys
+ strlen(keys
) + 1, "key2");
4669 ASSERT_STREQ(vals
, "value1");
4670 ASSERT_STREQ(vals
+ strlen(vals
) + 1, "value2");
4672 ASSERT_EQ(0, rbd_metadata_remove(image1
, "key1"));
4673 ASSERT_EQ(-ENOENT
, rbd_metadata_remove(image1
, "key3"));
4674 value_len
= sizeof(value
);
4675 ASSERT_EQ(-ENOENT
, rbd_metadata_get(image1
, "key3", value
, &value_len
));
4676 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4678 ASSERT_EQ(keys_len
, strlen("key2") + 1);
4679 ASSERT_EQ(vals_len
, strlen("value2") + 1);
4680 ASSERT_STREQ(keys
, "key2");
4681 ASSERT_STREQ(vals
, "value2");
4683 // test config setting
4684 ASSERT_EQ(0, rbd_metadata_set(image1
, "conf_rbd_cache", "false"));
4685 ASSERT_EQ(-EINVAL
, rbd_metadata_set(image1
, "conf_rbd_cache", "INVALID_VAL"));
4686 ASSERT_EQ(0, rbd_metadata_remove(image1
, "conf_rbd_cache"));
4688 // test metadata with snapshot adding
4689 ASSERT_EQ(0, rbd_snap_create(image1
, "snap1"));
4690 ASSERT_EQ(0, rbd_snap_protect(image1
, "snap1"));
4691 ASSERT_EQ(0, rbd_snap_set(image1
, "snap1"));
4693 ASSERT_EQ(0, rbd_metadata_set(image1
, "key1", "value1"));
4694 ASSERT_EQ(0, rbd_metadata_set(image1
, "key3", "value3"));
4696 keys_len
= sizeof(keys
);
4697 vals_len
= sizeof(vals
);
4698 memset_rand(keys
, keys_len
);
4699 memset_rand(vals
, vals_len
);
4700 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4703 strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1);
4705 strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1);
4706 ASSERT_STREQ(keys
, "key1");
4707 ASSERT_STREQ(keys
+ strlen("key1") + 1, "key2");
4708 ASSERT_STREQ(keys
+ strlen("key1") + 1 + strlen("key2") + 1, "key3");
4709 ASSERT_STREQ(vals
, "value1");
4710 ASSERT_STREQ(vals
+ strlen("value1") + 1, "value2");
4711 ASSERT_STREQ(vals
+ strlen("value1") + 1 + strlen("value2") + 1, "value3");
4713 ASSERT_EQ(0, rbd_snap_set(image1
, NULL
));
4714 keys_len
= sizeof(keys
);
4715 vals_len
= sizeof(vals
);
4716 memset_rand(keys
, keys_len
);
4717 memset_rand(vals
, vals_len
);
4718 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4721 strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1);
4723 strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1);
4724 ASSERT_STREQ(keys
, "key1");
4725 ASSERT_STREQ(keys
+ strlen("key1") + 1, "key2");
4726 ASSERT_STREQ(keys
+ strlen("key1") + 1 + strlen("key2") + 1, "key3");
4727 ASSERT_STREQ(vals
, "value1");
4728 ASSERT_STREQ(vals
+ strlen("value1") + 1, "value2");
4729 ASSERT_STREQ(vals
+ strlen("value1") + 1 + strlen("value2") + 1, "value3");
4731 // test metadata with cloning
4733 ASSERT_EQ(0, rbd_get_features(image1
, &features
));
4735 string cname
= get_temp_image_name();
4736 EXPECT_EQ(0, rbd_clone(ioctx
, name
.c_str(), "snap1", ioctx
,
4737 cname
.c_str(), features
, &order
));
4739 ASSERT_EQ(0, rbd_open(ioctx
, cname
.c_str(), &image2
, NULL
));
4740 ASSERT_EQ(0, rbd_metadata_set(image2
, "key4", "value4"));
4742 keys_len
= sizeof(keys
);
4743 vals_len
= sizeof(vals
);
4744 memset_rand(keys
, keys_len
);
4745 memset_rand(vals
, vals_len
);
4746 ASSERT_EQ(0, rbd_metadata_list(image2
, "", 0, keys
, &keys_len
, vals
,
4748 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") +
4749 1 + strlen("key4") + 1);
4750 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1 +
4751 strlen("value3") + 1 + strlen("value4") + 1);
4752 ASSERT_STREQ(keys
+ strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") +
4754 ASSERT_STREQ(vals
+ strlen("value1") + 1 + strlen("value2") + 1 +
4755 strlen("value3") + 1, "value4");
4757 ASSERT_EQ(0, rbd_metadata_list(image1
, "", 0, keys
, &keys_len
, vals
,
4760 strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") + 1);
4762 strlen("value1") + 1 + strlen("value2") + 1 + strlen("value3") + 1);
4763 ASSERT_EQ(-ENOENT
, rbd_metadata_get(image1
, "key4", value
, &value_len
));
4765 // test short buffer cases
4766 keys_len
= strlen("key1") + 1;
4767 vals_len
= strlen("value1") + 1;
4768 memset_rand(keys
, keys_len
);
4769 memset_rand(vals
, vals_len
);
4770 ASSERT_EQ(0, rbd_metadata_list(image2
, "", 1, keys
, &keys_len
, vals
,
4772 ASSERT_EQ(keys_len
, strlen("key1") + 1);
4773 ASSERT_EQ(vals_len
, strlen("value1") + 1);
4774 ASSERT_STREQ(keys
, "key1");
4775 ASSERT_STREQ(vals
, "value1");
4777 ASSERT_EQ(-ERANGE
, rbd_metadata_list(image2
, "", 2, keys
, &keys_len
, vals
,
4779 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1);
4780 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1);
4782 ASSERT_EQ(-ERANGE
, rbd_metadata_list(image2
, "", 0, keys
, &keys_len
, vals
,
4784 ASSERT_EQ(keys_len
, strlen("key1") + 1 + strlen("key2") + 1 + strlen("key3") +
4785 1 + strlen("key4") + 1);
4786 ASSERT_EQ(vals_len
, strlen("value1") + 1 + strlen("value2") + 1 +
4787 strlen("value3") + 1 + strlen("value4") + 1);
4789 // test `start` param
4790 keys_len
= sizeof(keys
);
4791 vals_len
= sizeof(vals
);
4792 memset_rand(keys
, keys_len
);
4793 memset_rand(vals
, vals_len
);
4794 ASSERT_EQ(0, rbd_metadata_list(image2
, "key2", 0, keys
, &keys_len
, vals
,
4796 ASSERT_EQ(keys_len
, strlen("key3") + 1 + strlen("key4") + 1);
4797 ASSERT_EQ(vals_len
, strlen("value3") + 1 + strlen("value4") + 1);
4798 ASSERT_STREQ(keys
, "key3");
4799 ASSERT_STREQ(vals
, "value3");
4801 ASSERT_EQ(0, rbd_close(image
));
4802 ASSERT_EQ(0, rbd_close(image1
));
4803 ASSERT_EQ(0, rbd_close(image2
));
4804 rados_ioctx_destroy(ioctx
);
4807 TEST_F(TestLibRBD
, MetadataPP
)
4809 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4811 librados::IoCtx ioctx
;
4812 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4815 string name
= get_temp_image_name();
4816 uint64_t size
= 2 << 20;
4820 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4822 librbd::Image image1
;
4823 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
4824 map
<string
, bufferlist
> pairs
;
4825 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4826 ASSERT_TRUE(pairs
.empty());
4828 ASSERT_EQ(0, image1
.metadata_set("key1", "value1"));
4829 ASSERT_EQ(0, image1
.metadata_set("key2", "value2"));
4830 ASSERT_EQ(0, image1
.metadata_get("key1", &value
));
4831 ASSERT_EQ(0, strcmp("value1", value
.c_str()));
4832 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4833 ASSERT_EQ(2U, pairs
.size());
4834 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
4835 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4838 ASSERT_EQ(0, image1
.metadata_remove("key1"));
4839 ASSERT_EQ(-ENOENT
, image1
.metadata_remove("key3"));
4840 ASSERT_TRUE(image1
.metadata_get("key3", &value
) < 0);
4841 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4842 ASSERT_EQ(1U, pairs
.size());
4843 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4845 // test config setting
4846 ASSERT_EQ(0, image1
.metadata_set("conf_rbd_cache", "false"));
4847 ASSERT_EQ(-EINVAL
, image1
.metadata_set("conf_rbd_cache", "INVALID_VALUE"));
4848 ASSERT_EQ(0, image1
.metadata_remove("conf_rbd_cache"));
4850 // test metadata with snapshot adding
4851 ASSERT_EQ(0, image1
.snap_create("snap1"));
4852 ASSERT_EQ(0, image1
.snap_protect("snap1"));
4853 ASSERT_EQ(0, image1
.snap_set("snap1"));
4856 ASSERT_EQ(0, image1
.metadata_set("key1", "value1"));
4857 ASSERT_EQ(0, image1
.metadata_set("key3", "value3"));
4858 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4859 ASSERT_EQ(3U, pairs
.size());
4860 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
4861 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4862 ASSERT_EQ(0, strncmp("value3", pairs
["key3"].c_str(), 6));
4864 ASSERT_EQ(0, image1
.snap_set(NULL
));
4865 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4866 ASSERT_EQ(3U, pairs
.size());
4867 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
4868 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
4869 ASSERT_EQ(0, strncmp("value3", pairs
["key3"].c_str(), 6));
4871 // test metadata with cloning
4872 string cname
= get_temp_image_name();
4873 librbd::Image image2
;
4874 ASSERT_EQ(0, image1
.features(&features
));
4875 EXPECT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "snap1", ioctx
,
4876 cname
.c_str(), features
, &order
));
4877 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, cname
.c_str(), NULL
));
4878 ASSERT_EQ(0, image2
.metadata_set("key4", "value4"));
4880 ASSERT_EQ(0, image2
.metadata_list("", 0, &pairs
));
4881 ASSERT_EQ(4U, pairs
.size());
4883 ASSERT_EQ(0, image1
.metadata_list("", 0, &pairs
));
4884 ASSERT_EQ(3U, pairs
.size());
4885 ASSERT_EQ(-ENOENT
, image1
.metadata_get("key4", &value
));
4888 TEST_F(TestLibRBD
, UpdateFeatures
)
4890 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
4892 librados::IoCtx ioctx
;
4893 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4896 std::string name
= get_temp_image_name();
4897 uint64_t size
= 1 << 20;
4899 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
4901 librbd::Image image
;
4902 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
4905 ASSERT_EQ(0, image
.old_format(&old_format
));
4907 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, true));
4912 ASSERT_EQ(0, image
.features(&features
));
4914 // must provide a single feature
4915 ASSERT_EQ(-EINVAL
, image
.update_features(0, true));
4917 uint64_t disable_features
;
4918 disable_features
= features
& (RBD_FEATURE_EXCLUSIVE_LOCK
|
4919 RBD_FEATURE_OBJECT_MAP
|
4920 RBD_FEATURE_FAST_DIFF
|
4921 RBD_FEATURE_JOURNALING
);
4922 if (disable_features
!= 0) {
4923 ASSERT_EQ(0, image
.update_features(disable_features
, false));
4926 ASSERT_EQ(0, image
.features(&features
));
4927 ASSERT_EQ(0U, features
& disable_features
);
4929 // cannot enable object map nor journaling w/o exclusive lock
4930 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_OBJECT_MAP
, true));
4931 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_JOURNALING
, true));
4932 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, true));
4934 ASSERT_EQ(0, image
.features(&features
));
4935 ASSERT_NE(0U, features
& RBD_FEATURE_EXCLUSIVE_LOCK
);
4937 // cannot enable fast diff w/o object map
4938 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_FAST_DIFF
, true));
4939 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
, true));
4940 ASSERT_EQ(0, image
.features(&features
));
4941 ASSERT_NE(0U, features
& RBD_FEATURE_OBJECT_MAP
);
4943 uint64_t expected_flags
= RBD_FLAG_OBJECT_MAP_INVALID
;
4945 ASSERT_EQ(0, image
.get_flags(&flags
));
4946 ASSERT_EQ(expected_flags
, flags
);
4948 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
, false));
4949 ASSERT_EQ(0, image
.features(&features
));
4950 ASSERT_EQ(0U, features
& RBD_FEATURE_OBJECT_MAP
);
4952 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
|
4953 RBD_FEATURE_FAST_DIFF
|
4954 RBD_FEATURE_JOURNALING
, true));
4956 expected_flags
= RBD_FLAG_OBJECT_MAP_INVALID
| RBD_FLAG_FAST_DIFF_INVALID
;
4957 ASSERT_EQ(0, image
.get_flags(&flags
));
4958 ASSERT_EQ(expected_flags
, flags
);
4960 // cannot disable object map w/ fast diff
4961 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_OBJECT_MAP
, false));
4962 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_FAST_DIFF
, false));
4963 ASSERT_EQ(0, image
.features(&features
));
4964 ASSERT_EQ(0U, features
& RBD_FEATURE_FAST_DIFF
);
4966 expected_flags
= RBD_FLAG_OBJECT_MAP_INVALID
;
4967 ASSERT_EQ(0, image
.get_flags(&flags
));
4968 ASSERT_EQ(expected_flags
, flags
);
4970 // cannot disable exclusive lock w/ object map
4971 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, false));
4972 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_OBJECT_MAP
, false));
4974 // cannot disable exclusive lock w/ journaling
4975 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, false));
4976 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_JOURNALING
, false));
4978 ASSERT_EQ(0, image
.get_flags(&flags
));
4979 ASSERT_EQ(0U, flags
);
4981 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_EXCLUSIVE_LOCK
, false));
4983 ASSERT_EQ(0, image
.features(&features
));
4984 if ((features
& RBD_FEATURE_DEEP_FLATTEN
) != 0) {
4985 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_DEEP_FLATTEN
, false));
4987 ASSERT_EQ(-EINVAL
, image
.update_features(RBD_FEATURE_DEEP_FLATTEN
, true));
4990 TEST_F(TestLibRBD
, RebuildObjectMap
)
4992 librados::IoCtx ioctx
;
4993 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
4996 std::string name
= get_temp_image_name();
4997 uint64_t size
= 1 << 20;
4999 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5001 PrintProgress prog_ctx
;
5002 std::string object_map_oid
;
5006 librbd::Image image
;
5007 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5010 ASSERT_EQ(0, image
.features(&features
));
5011 if ((features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
5012 ASSERT_EQ(-EINVAL
, image
.rebuild_object_map(prog_ctx
));
5016 ASSERT_EQ((ssize_t
)bl
.length(), image
.write(0, bl
.length(), bl
));
5018 ASSERT_EQ(0, image
.snap_create("snap1"));
5019 ASSERT_EQ((ssize_t
)bl
.length(), image
.write(1<<order
, bl
.length(), bl
));
5021 std::string image_id
;
5022 ASSERT_EQ(0, get_image_id(image
, &image_id
));
5023 object_map_oid
= RBD_OBJECT_MAP_PREFIX
+ image_id
;
5026 // corrupt the object map
5027 ASSERT_EQ(0, ioctx
.write(object_map_oid
, bl
, bl
.length(), 0));
5029 librbd::Image image1
;
5030 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5034 ASSERT_EQ(0, image1
.write(0, 0, bl
));
5035 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
5036 ASSERT_TRUE(lock_owner
);
5039 ASSERT_EQ(0, image1
.get_flags(&flags
));
5040 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0);
5042 ASSERT_EQ(0, image1
.rebuild_object_map(prog_ctx
));
5044 librbd::Image image2
;
5045 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5048 ASSERT_EQ((ssize_t
)bl
.length(), image2
.read(0, bl
.length(), read_bl
));
5049 ASSERT_TRUE(bl
.contents_equal(read_bl
));
5052 ASSERT_EQ((ssize_t
)bl
.length(), image2
.read(1<<order
, bl
.length(), read_bl
));
5053 ASSERT_TRUE(bl
.contents_equal(read_bl
));
5055 ASSERT_PASSED(validate_object_map
, image1
);
5056 ASSERT_PASSED(validate_object_map
, image2
);
5059 TEST_F(TestLibRBD
, RebuildNewObjectMap
)
5061 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
5063 rados_ioctx_t ioctx
;
5064 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5066 std::string name
= get_temp_image_name();
5067 uint64_t size
= 1 << 20;
5069 uint64_t features
= RBD_FEATURE_EXCLUSIVE_LOCK
;
5070 ASSERT_EQ(0, create_image_full(ioctx
, name
.c_str(), size
, &order
,
5074 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
5075 ASSERT_EQ(0, rbd_update_features(image
, RBD_FEATURE_OBJECT_MAP
, true));
5076 ASSERT_EQ(0, rbd_rebuild_object_map(image
, print_progress_percent
, NULL
));
5078 ASSERT_PASSED(validate_object_map
, image
);
5080 ASSERT_EQ(0, rbd_close(image
));
5081 rados_ioctx_destroy(ioctx
);
5084 TEST_F(TestLibRBD
, CheckObjectMap
)
5086 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
5088 librados::IoCtx ioctx
;
5089 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5092 std::string name
= get_temp_image_name();
5093 uint64_t size
= 1 << 20;
5095 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5097 PrintProgress prog_ctx
;
5102 librbd::Image image
;
5103 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5106 ASSERT_EQ(0, image
.features(&features
));
5108 ASSERT_EQ((ssize_t
)bl1
.length(), image
.write(0, bl1
.length(), bl1
));
5110 ASSERT_EQ(0, image
.snap_create("snap1"));
5111 ASSERT_EQ((ssize_t
)bl1
.length(), image
.write(1<<order
, bl1
.length(), bl1
));
5114 librbd::Image image1
;
5115 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5117 std::string image_id
;
5118 ASSERT_EQ(0, get_image_id(image1
, &image_id
));
5120 std::string object_map_oid
= RBD_OBJECT_MAP_PREFIX
+ image_id
;
5122 ASSERT_LT(0, ioctx
.read(object_map_oid
, bl2
, 1024, 0));
5125 ASSERT_EQ((ssize_t
)bl1
.length(), image1
.write(3 * (1 << 18), bl1
.length(), bl1
));
5126 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
5127 ASSERT_TRUE(lock_owner
);
5129 //reopen image to reread now corrupt object map from disk
5133 ASSERT_LT(0, ioctx
.read(object_map_oid
, bl1
, 1024, 0));
5134 ASSERT_FALSE(bl1
.contents_equal(bl2
));
5136 ASSERT_EQ(0, ioctx
.write_full(object_map_oid
, bl2
));
5137 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5140 ASSERT_EQ(0, image1
.get_flags(&flags
));
5141 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) == 0);
5143 ASSERT_EQ(0, image1
.check_object_map(prog_ctx
));
5145 ASSERT_EQ(0, image1
.get_flags(&flags
));
5146 ASSERT_TRUE((flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0);
5149 TEST_F(TestLibRBD
, BlockingAIO
)
5151 librados::IoCtx ioctx
;
5152 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5154 bool skip_discard
= is_skip_partial_discard_enabled();
5157 std::string name
= get_temp_image_name();
5158 uint64_t size
= 1 << 20;
5160 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5162 std::string non_blocking_aio
;
5163 ASSERT_EQ(0, _rados
.conf_get("rbd_non_blocking_aio", non_blocking_aio
));
5164 ASSERT_EQ(0, _rados
.conf_set("rbd_non_blocking_aio", "0"));
5165 BOOST_SCOPE_EXIT( (non_blocking_aio
) ) {
5166 ASSERT_EQ(0, _rados
.conf_set("rbd_non_blocking_aio",
5167 non_blocking_aio
.c_str()));
5168 } BOOST_SCOPE_EXIT_END
;
5170 librbd::Image image
;
5171 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5174 ASSERT_EQ(0, image
.write(0, bl
.length(), bl
));
5176 bl
.append(std::string(256, '1'));
5177 librbd::RBD::AioCompletion
*write_comp
=
5178 new librbd::RBD::AioCompletion(NULL
, NULL
);
5179 ASSERT_EQ(0, image
.aio_write(0, bl
.length(), bl
, write_comp
));
5181 librbd::RBD::AioCompletion
*flush_comp
=
5182 new librbd::RBD::AioCompletion(NULL
, NULL
);
5183 ASSERT_EQ(0, image
.aio_flush(flush_comp
));
5184 ASSERT_EQ(0, flush_comp
->wait_for_complete());
5185 ASSERT_EQ(0, flush_comp
->get_return_value());
5186 flush_comp
->release();
5188 ASSERT_EQ(1, write_comp
->is_complete());
5189 ASSERT_EQ(0, write_comp
->get_return_value());
5190 write_comp
->release();
5192 librbd::RBD::AioCompletion
*discard_comp
=
5193 new librbd::RBD::AioCompletion(NULL
, NULL
);
5194 ASSERT_EQ(0, image
.aio_discard(128, 128, discard_comp
));
5195 ASSERT_EQ(0, discard_comp
->wait_for_complete());
5196 discard_comp
->release();
5198 librbd::RBD::AioCompletion
*read_comp
=
5199 new librbd::RBD::AioCompletion(NULL
, NULL
);
5201 image
.aio_read(0, bl
.length(), read_bl
, read_comp
);
5202 ASSERT_EQ(0, read_comp
->wait_for_complete());
5203 ASSERT_EQ((ssize_t
)bl
.length(), read_comp
->get_return_value());
5204 read_comp
->release();
5206 bufferlist expected_bl
;
5207 expected_bl
.append(std::string(128, '1'));
5208 expected_bl
.append(std::string(128, skip_discard
? '1' : '\0'));
5209 ASSERT_TRUE(expected_bl
.contents_equal(read_bl
));
5212 TEST_F(TestLibRBD
, ExclusiveLockTransition
)
5214 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
5216 librados::IoCtx ioctx
;
5217 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5220 std::string name
= get_temp_image_name();
5222 uint64_t size
= 1 << 18;
5224 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5226 librbd::Image image1
;
5227 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5229 librbd::Image image2
;
5230 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5232 std::list
<librbd::RBD::AioCompletion
*> comps
;
5233 ceph::bufferlist bl
;
5234 bl
.append(std::string(1 << order
, '1'));
5235 for (size_t object_no
= 0; object_no
< (size
>> 12); ++object_no
) {
5236 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
,
5238 comps
.push_back(comp
);
5239 if (object_no
% 2 == 0) {
5240 ASSERT_EQ(0, image1
.aio_write(object_no
<< order
, bl
.length(), bl
, comp
));
5242 ASSERT_EQ(0, image2
.aio_write(object_no
<< order
, bl
.length(), bl
, comp
));
5246 while (!comps
.empty()) {
5247 librbd::RBD::AioCompletion
*comp
= comps
.front();
5249 ASSERT_EQ(0, comp
->wait_for_complete());
5250 ASSERT_EQ(1, comp
->is_complete());
5254 librbd::Image image3
;
5255 ASSERT_EQ(0, rbd
.open(ioctx
, image3
, name
.c_str(), NULL
));
5256 for (size_t object_no
= 0; object_no
< (size
>> 12); ++object_no
) {
5258 ASSERT_EQ((ssize_t
)bl
.length(), image3
.read(object_no
<< order
, bl
.length(),
5260 ASSERT_TRUE(bl
.contents_equal(read_bl
));
5263 ASSERT_PASSED(validate_object_map
, image1
);
5264 ASSERT_PASSED(validate_object_map
, image2
);
5265 ASSERT_PASSED(validate_object_map
, image3
);
5268 TEST_F(TestLibRBD
, ExclusiveLockReadTransition
)
5270 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
5272 librados::IoCtx ioctx
;
5273 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5276 std::string name
= get_temp_image_name();
5278 uint64_t size
= 1 << 18;
5280 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5282 librbd::Image image1
;
5283 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5286 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
5287 ASSERT_FALSE(lock_owner
);
5289 // journaling should force read ops to acquire the lock
5291 ASSERT_EQ(0, image1
.read(0, 0, read_bl
));
5293 ASSERT_EQ(0, image1
.is_exclusive_lock_owner(&lock_owner
));
5294 ASSERT_TRUE(lock_owner
);
5296 librbd::Image image2
;
5297 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5299 std::list
<librbd::RBD::AioCompletion
*> comps
;
5300 std::list
<bufferlist
> read_bls
;
5301 for (size_t object_no
= 0; object_no
< (size
>> 12); ++object_no
) {
5302 librbd::RBD::AioCompletion
*comp
= new librbd::RBD::AioCompletion(NULL
,
5304 comps
.push_back(comp
);
5305 read_bls
.emplace_back();
5306 if (object_no
% 2 == 0) {
5307 ASSERT_EQ(0, image1
.aio_read(object_no
<< order
, 1 << order
, read_bls
.back(), comp
));
5309 ASSERT_EQ(0, image2
.aio_read(object_no
<< order
, 1 << order
, read_bls
.back(), comp
));
5313 while (!comps
.empty()) {
5314 librbd::RBD::AioCompletion
*comp
= comps
.front();
5316 ASSERT_EQ(0, comp
->wait_for_complete());
5317 ASSERT_EQ(1, comp
->is_complete());
5322 TEST_F(TestLibRBD
, CacheMayCopyOnWrite
) {
5323 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
5325 librados::IoCtx ioctx
;
5326 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5329 std::string name
= get_temp_image_name();
5331 uint64_t size
= 1 << 18;
5333 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5335 librbd::Image image
;
5336 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5337 ASSERT_EQ(0, image
.snap_create("one"));
5338 ASSERT_EQ(0, image
.snap_protect("one"));
5340 std::string clone_name
= this->get_temp_image_name();
5341 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "one", ioctx
, clone_name
.c_str(),
5342 RBD_FEATURE_LAYERING
, &order
));
5344 librbd::Image clone
;
5345 ASSERT_EQ(0, rbd
.open(ioctx
, clone
, clone_name
.c_str(), NULL
));
5346 ASSERT_EQ(0, clone
.flush());
5348 bufferlist expect_bl
;
5349 expect_bl
.append(std::string(1024, '\0'));
5351 // test double read path
5353 uint64_t offset
= 0;
5354 ASSERT_EQ(1024, clone
.read(offset
+ 2048, 1024, read_bl
));
5355 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
5357 bufferlist write_bl
;
5358 write_bl
.append(std::string(1024, '1'));
5359 ASSERT_EQ(1024, clone
.write(offset
, write_bl
.length(), write_bl
));
5362 ASSERT_EQ(1024, clone
.read(offset
+ 2048, 1024, read_bl
));
5363 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
5365 // test read retry path
5366 offset
= 1 << order
;
5367 ASSERT_EQ(1024, clone
.write(offset
, write_bl
.length(), write_bl
));
5370 ASSERT_EQ(1024, clone
.read(offset
+ 2048, 1024, read_bl
));
5371 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
5374 TEST_F(TestLibRBD
, FlushEmptyOpsOnExternalSnapshot
) {
5375 std::string cache_enabled
;
5376 ASSERT_EQ(0, _rados
.conf_get("rbd_cache", cache_enabled
));
5377 ASSERT_EQ(0, _rados
.conf_set("rbd_cache", "false"));
5378 BOOST_SCOPE_EXIT( (cache_enabled
) ) {
5379 ASSERT_EQ(0, _rados
.conf_set("rbd_cache", cache_enabled
.c_str()));
5380 } BOOST_SCOPE_EXIT_END
;
5382 librados::IoCtx ioctx
;
5383 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5386 std::string name
= get_temp_image_name();
5387 uint64_t size
= 1 << 18;
5389 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5391 librbd::Image image1
;
5392 librbd::Image image2
;
5393 ASSERT_EQ(0, rbd
.open(ioctx
, image1
, name
.c_str(), NULL
));
5394 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, name
.c_str(), NULL
));
5395 ASSERT_EQ(0, image1
.snap_create("snap1"));
5397 librbd::RBD::AioCompletion
*read_comp
=
5398 new librbd::RBD::AioCompletion(NULL
, NULL
);
5400 image2
.aio_read(0, 1024, read_bl
, read_comp
);
5401 ASSERT_EQ(0, read_comp
->wait_for_complete());
5402 read_comp
->release();
5405 TEST_F(TestLibRBD
, TestImageOptions
)
5407 rados_ioctx_t ioctx
;
5408 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5410 //make create image options
5411 uint64_t features
= RBD_FEATURE_LAYERING
| RBD_FEATURE_STRIPINGV2
;
5413 uint64_t stripe_unit
= IMAGE_STRIPE_UNIT
;
5414 uint64_t stripe_count
= IMAGE_STRIPE_COUNT
;
5415 rbd_image_options_t opts
;
5416 rbd_image_options_create(&opts
);
5419 ASSERT_EQ(-EINVAL
, rbd_image_options_is_set(opts
, 12345, &is_set
));
5420 ASSERT_EQ(0, rbd_image_options_is_set(opts
, RBD_IMAGE_OPTION_FORMAT
,
5422 ASSERT_FALSE(is_set
);
5424 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_FORMAT
,
5426 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_FEATURES
,
5428 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_ORDER
,
5430 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_STRIPE_UNIT
,
5432 ASSERT_EQ(0, rbd_image_options_set_uint64(opts
, RBD_IMAGE_OPTION_STRIPE_COUNT
,
5435 ASSERT_EQ(0, rbd_image_options_is_set(opts
, RBD_IMAGE_OPTION_FORMAT
,
5437 ASSERT_TRUE(is_set
);
5439 std::string parent_name
= get_temp_image_name();
5442 ASSERT_EQ(0, rbd_create4(ioctx
, parent_name
.c_str(), 4<<20, opts
));
5444 // check order is returned in opts
5445 ASSERT_EQ(0, rbd_image_options_get_uint64(opts
, RBD_IMAGE_OPTION_ORDER
,
5447 ASSERT_NE((uint64_t)0, order
);
5449 // write some data to parent
5451 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, NULL
));
5452 char *data
= (char *)"testdata";
5453 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 0, strlen(data
), data
));
5454 ASSERT_EQ((ssize_t
)strlen(data
), rbd_write(parent
, 12, strlen(data
), data
));
5456 // create a snapshot, reopen as the parent we're interested in
5457 ASSERT_EQ(0, rbd_snap_create(parent
, "parent_snap"));
5458 ASSERT_EQ(0, rbd_close(parent
));
5459 ASSERT_EQ(0, rbd_open(ioctx
, parent_name
.c_str(), &parent
, "parent_snap"));
5462 std::string child_name
= get_temp_image_name();
5463 ASSERT_EQ(0, rbd_snap_protect(parent
, "parent_snap"));
5464 ASSERT_EQ(0, rbd_clone3(ioctx
, parent_name
.c_str(), "parent_snap", ioctx
,
5465 child_name
.c_str(), opts
));
5468 std::string copy1_name
= get_temp_image_name();
5469 ASSERT_EQ(0, rbd_copy3(parent
, ioctx
, copy1_name
.c_str(), opts
));
5470 std::string copy2_name
= get_temp_image_name();
5471 ASSERT_EQ(0, rbd_copy_with_progress3(parent
, ioctx
, copy2_name
.c_str(), opts
,
5472 print_progress_percent
, NULL
));
5474 ASSERT_EQ(0, rbd_close(parent
));
5476 rbd_image_options_destroy(opts
);
5478 rados_ioctx_destroy(ioctx
);
5481 TEST_F(TestLibRBD
, TestImageOptionsPP
)
5483 librados::IoCtx ioctx
;
5484 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5486 //make create image options
5487 uint64_t features
= RBD_FEATURE_LAYERING
| RBD_FEATURE_STRIPINGV2
;
5489 uint64_t stripe_unit
= IMAGE_STRIPE_UNIT
;
5490 uint64_t stripe_count
= IMAGE_STRIPE_COUNT
;
5491 librbd::ImageOptions opts
;
5492 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_FORMAT
, static_cast<uint64_t>(2)));
5493 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_FEATURES
, features
));
5494 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_ORDER
, order
));
5495 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_STRIPE_UNIT
, stripe_unit
));
5496 ASSERT_EQ(0, opts
.set(RBD_IMAGE_OPTION_STRIPE_COUNT
, stripe_count
));
5499 std::string parent_name
= get_temp_image_name();
5502 ASSERT_EQ(0, rbd
.create4(ioctx
, parent_name
.c_str(), 4<<20, opts
));
5504 // check order is returned in opts
5505 ASSERT_EQ(0, opts
.get(RBD_IMAGE_OPTION_ORDER
, &order
));
5506 ASSERT_NE((uint64_t)0, order
);
5508 // write some data to parent
5509 librbd::Image parent
;
5510 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), NULL
));
5514 bl
.append(buffer::create(len
));
5516 ASSERT_EQ(len
, parent
.write(0, len
, bl
));
5517 ASSERT_EQ(len
, parent
.write(len
, len
, bl
));
5519 // create a snapshot, reopen as the parent we're interested in
5520 ASSERT_EQ(0, parent
.snap_create("parent_snap"));
5521 ASSERT_EQ(0, parent
.close());
5522 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), "parent_snap"));
5525 std::string child_name
= get_temp_image_name();
5526 ASSERT_EQ(0, parent
.snap_protect("parent_snap"));
5527 ASSERT_EQ(0, rbd
.clone3(ioctx
, parent_name
.c_str(), "parent_snap", ioctx
,
5528 child_name
.c_str(), opts
));
5531 std::string copy1_name
= get_temp_image_name();
5532 ASSERT_EQ(0, parent
.copy3(ioctx
, copy1_name
.c_str(), opts
));
5533 std::string copy2_name
= get_temp_image_name();
5535 ASSERT_EQ(0, parent
.copy_with_progress3(ioctx
, copy2_name
.c_str(), opts
, pp
));
5537 ASSERT_EQ(0, parent
.close());
5540 TEST_F(TestLibRBD
, EventSocketPipe
)
5542 EventSocket event_sock
;
5543 int pipe_fd
[2]; // read and write fd
5546 ASSERT_EQ(0, pipe(pipe_fd
));
5548 ASSERT_FALSE(event_sock
.is_valid());
5550 ASSERT_EQ(-EINVAL
, event_sock
.init(pipe_fd
[1], EVENT_SOCKET_TYPE_NONE
));
5551 ASSERT_FALSE(event_sock
.is_valid());
5553 ASSERT_EQ(-EINVAL
, event_sock
.init(pipe_fd
[1], 44));
5554 ASSERT_FALSE(event_sock
.is_valid());
5556 #ifndef HAVE_EVENTFD
5557 ASSERT_EQ(-EINVAL
, event_sock
.init(pipe_fd
[1], EVENT_SOCKET_TYPE_EVENTFD
));
5558 ASSERT_FALSE(event_sock
.is_valid());
5561 ASSERT_EQ(0, event_sock
.init(pipe_fd
[1], EVENT_SOCKET_TYPE_PIPE
));
5562 ASSERT_TRUE(event_sock
.is_valid());
5563 ASSERT_EQ(0, event_sock
.notify());
5564 ASSERT_EQ(1, read(pipe_fd
[0], buf
, 32));
5565 ASSERT_EQ('i', buf
[0]);
5571 TEST_F(TestLibRBD
, EventSocketEventfd
)
5574 EventSocket event_sock
;
5576 struct pollfd poll_fd
;
5579 event_fd
= eventfd(0, EFD_NONBLOCK
);
5580 ASSERT_NE(-1, event_fd
);
5582 ASSERT_FALSE(event_sock
.is_valid());
5584 ASSERT_EQ(-EINVAL
, event_sock
.init(event_fd
, EVENT_SOCKET_TYPE_NONE
));
5585 ASSERT_FALSE(event_sock
.is_valid());
5587 ASSERT_EQ(-EINVAL
, event_sock
.init(event_fd
, 44));
5588 ASSERT_FALSE(event_sock
.is_valid());
5590 ASSERT_EQ(0, event_sock
.init(event_fd
, EVENT_SOCKET_TYPE_EVENTFD
));
5591 ASSERT_TRUE(event_sock
.is_valid());
5592 ASSERT_EQ(0, event_sock
.notify());
5594 poll_fd
.fd
= event_fd
;
5595 poll_fd
.events
= POLLIN
;
5596 ASSERT_EQ(1, poll(&poll_fd
, 1, -1));
5597 ASSERT_TRUE(poll_fd
.revents
& POLLIN
);
5599 ASSERT_EQ(static_cast<ssize_t
>(sizeof(uint64_t)), read(event_fd
, buf
, 32));
5600 ASSERT_EQ(1U, *reinterpret_cast<uint64_t *>(buf
));
5606 TEST_F(TestLibRBD
, ImagePollIO
)
5609 rados_ioctx_t ioctx
;
5610 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5614 std::string name
= get_temp_image_name();
5615 uint64_t size
= 2 << 20;
5616 int fd
= eventfd(0, EFD_NONBLOCK
);
5618 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
5619 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
5621 ASSERT_EQ(0, rbd_set_image_notification(image
, fd
, EVENT_SOCKET_TYPE_EVENTFD
));
5623 char test_data
[TEST_IO_SIZE
+ 1];
5624 char zero_data
[TEST_IO_SIZE
+ 1];
5627 for (i
= 0; i
< TEST_IO_SIZE
; ++i
)
5628 test_data
[i
] = (char) (rand() % (126 - 33) + 33);
5629 test_data
[TEST_IO_SIZE
] = '\0';
5630 memset(zero_data
, 0, sizeof(zero_data
));
5632 for (i
= 0; i
< 5; ++i
)
5633 ASSERT_PASSED(write_test_data
, image
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
5635 for (i
= 5; i
< 10; ++i
)
5636 ASSERT_PASSED(aio_write_test_data_and_poll
, image
, fd
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
5638 for (i
= 5; i
< 10; ++i
)
5639 ASSERT_PASSED(aio_read_test_data_and_poll
, image
, fd
, test_data
, TEST_IO_SIZE
* i
, TEST_IO_SIZE
, 0);
5641 ASSERT_EQ(0, rbd_close(image
));
5642 rados_ioctx_destroy(ioctx
);
5648 static bool operator==(const mirror_peer_t
&lhs
, const mirror_peer_t
&rhs
) {
5649 return (lhs
.uuid
== rhs
.uuid
&&
5650 lhs
.cluster_name
== rhs
.cluster_name
&&
5651 lhs
.client_name
== rhs
.client_name
);
5654 static std::ostream
& operator<<(std::ostream
&os
, const mirror_peer_t
&peer
) {
5655 os
<< "uuid=" << peer
.uuid
<< ", "
5656 << "cluster=" << peer
.cluster_name
<< ", "
5657 << "client=" << peer
.client_name
;
5661 } // namespace librbd
5663 TEST_F(TestLibRBD
, Mirror
) {
5664 librados::IoCtx ioctx
;
5665 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5669 std::vector
<librbd::mirror_peer_t
> expected_peers
;
5670 std::vector
<librbd::mirror_peer_t
> peers
;
5671 ASSERT_EQ(0, rbd
.mirror_peer_list(ioctx
, &peers
));
5672 ASSERT_EQ(expected_peers
, peers
);
5675 ASSERT_EQ(-EINVAL
, rbd
.mirror_peer_add(ioctx
, &uuid1
, "cluster1", "client"));
5677 rbd_mirror_mode_t mirror_mode
;
5678 ASSERT_EQ(0, rbd
.mirror_mode_get(ioctx
, &mirror_mode
));
5679 ASSERT_EQ(RBD_MIRROR_MODE_DISABLED
, mirror_mode
);
5681 ASSERT_EQ(0, rbd
.mirror_mode_set(ioctx
, RBD_MIRROR_MODE_IMAGE
));
5682 ASSERT_EQ(0, rbd
.mirror_mode_get(ioctx
, &mirror_mode
));
5684 // Add some images to the pool
5686 std::string parent_name
= get_temp_image_name();
5687 std::string child_name
= get_temp_image_name();
5688 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, parent_name
.c_str(), 2 << 20,
5692 ASSERT_EQ(0, get_features(&old_format
, &features
));
5693 if ((features
& RBD_FEATURE_LAYERING
) != 0) {
5694 librbd::Image parent
;
5695 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), NULL
));
5696 ASSERT_EQ(0, parent
.snap_create("parent_snap"));
5697 ASSERT_EQ(0, parent
.close());
5698 ASSERT_EQ(0, rbd
.open(ioctx
, parent
, parent_name
.c_str(), "parent_snap"));
5699 ASSERT_EQ(0, parent
.snap_protect("parent_snap"));
5700 ASSERT_EQ(0, parent
.close());
5701 ASSERT_EQ(0, rbd
.clone(ioctx
, parent_name
.c_str(), "parent_snap", ioctx
,
5702 child_name
.c_str(), features
, &order
));
5705 ASSERT_EQ(RBD_MIRROR_MODE_IMAGE
, mirror_mode
);
5707 ASSERT_EQ(0, rbd
.mirror_mode_set(ioctx
, RBD_MIRROR_MODE_POOL
));
5708 ASSERT_EQ(0, rbd
.mirror_mode_get(ioctx
, &mirror_mode
));
5709 ASSERT_EQ(RBD_MIRROR_MODE_POOL
, mirror_mode
);
5713 ASSERT_EQ(0, rbd
.mirror_peer_add(ioctx
, &uuid1
, "cluster1", "client"));
5714 ASSERT_EQ(0, rbd
.mirror_peer_add(ioctx
, &uuid2
, "cluster2", "admin"));
5715 ASSERT_EQ(-EEXIST
, rbd
.mirror_peer_add(ioctx
, &uuid3
, "cluster1", "foo"));
5716 ASSERT_EQ(0, rbd
.mirror_peer_add(ioctx
, &uuid3
, "cluster3", "admin"));
5718 ASSERT_EQ(0, rbd
.mirror_peer_list(ioctx
, &peers
));
5719 auto sort_peers
= [](const librbd::mirror_peer_t
&lhs
,
5720 const librbd::mirror_peer_t
&rhs
) {
5721 return lhs
.uuid
< rhs
.uuid
;
5724 {uuid1
, "cluster1", "client"},
5725 {uuid2
, "cluster2", "admin"},
5726 {uuid3
, "cluster3", "admin"}};
5727 std::sort(expected_peers
.begin(), expected_peers
.end(), sort_peers
);
5728 ASSERT_EQ(expected_peers
, peers
);
5730 ASSERT_EQ(0, rbd
.mirror_peer_remove(ioctx
, "uuid4"));
5731 ASSERT_EQ(0, rbd
.mirror_peer_remove(ioctx
, uuid2
));
5733 ASSERT_EQ(-ENOENT
, rbd
.mirror_peer_set_client(ioctx
, "uuid4", "new client"));
5734 ASSERT_EQ(0, rbd
.mirror_peer_set_client(ioctx
, uuid1
, "new client"));
5736 ASSERT_EQ(-ENOENT
, rbd
.mirror_peer_set_cluster(ioctx
, "uuid4",
5738 ASSERT_EQ(0, rbd
.mirror_peer_set_cluster(ioctx
, uuid3
, "new cluster"));
5740 ASSERT_EQ(0, rbd
.mirror_peer_list(ioctx
, &peers
));
5742 {uuid1
, "cluster1", "new client"},
5743 {uuid3
, "new cluster", "admin"}};
5744 std::sort(expected_peers
.begin(), expected_peers
.end(), sort_peers
);
5745 ASSERT_EQ(expected_peers
, peers
);
5747 ASSERT_EQ(-EBUSY
, rbd
.mirror_mode_set(ioctx
, RBD_MIRROR_MODE_DISABLED
));
5750 TEST_F(TestLibRBD
, FlushCacheWithCopyupOnExternalSnapshot
) {
5751 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
5753 librados::IoCtx ioctx
;
5754 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5757 librbd::Image image
;
5758 std::string name
= get_temp_image_name();
5760 uint64_t size
= 1 << 18;
5763 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
5764 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
5767 bl
.append(std::string(size
, '1'));
5768 ASSERT_EQ((int)size
, image
.write(0, size
, bl
));
5769 ASSERT_EQ(0, image
.snap_create("one"));
5770 ASSERT_EQ(0, image
.snap_protect("one"));
5772 std::string clone_name
= this->get_temp_image_name();
5773 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "one", ioctx
, clone_name
.c_str(),
5774 RBD_FEATURE_LAYERING
, &order
));
5775 ASSERT_EQ(0, rbd
.open(ioctx
, image
, clone_name
.c_str(), NULL
));
5777 librbd::Image image2
;
5778 ASSERT_EQ(0, rbd
.open(ioctx
, image2
, clone_name
.c_str(), NULL
));
5780 // prepare CoW writeback that will be flushed on next op
5782 bl
.append(std::string(1, '1'));
5783 ASSERT_EQ(0, image
.flush());
5784 ASSERT_EQ(1, image
.write(0, 1, bl
));
5785 ASSERT_EQ(0, image2
.snap_create("snap1"));
5787 librbd::RBD::AioCompletion
*read_comp
=
5788 new librbd::RBD::AioCompletion(NULL
, NULL
);
5790 image
.aio_read(0, 1024, read_bl
, read_comp
);
5791 ASSERT_EQ(0, read_comp
->wait_for_complete());
5792 read_comp
->release();
5795 TEST_F(TestLibRBD
, ExclusiveLock
)
5797 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
5799 static char buf
[10];
5801 rados_ioctx_t ioctx
;
5802 rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
);
5804 std::string name
= get_temp_image_name();
5805 uint64_t size
= 2 << 20;
5807 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
5810 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image1
, NULL
));
5813 ASSERT_EQ(0, rbd_lock_acquire(image1
, RBD_LOCK_MODE_EXCLUSIVE
));
5814 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5815 ASSERT_TRUE(lock_owner
);
5817 rbd_lock_mode_t lock_mode
;
5818 char *lock_owners
[1];
5819 size_t max_lock_owners
= 0;
5820 ASSERT_EQ(-ERANGE
, rbd_lock_get_owners(image1
, &lock_mode
, lock_owners
,
5822 ASSERT_EQ(1U, max_lock_owners
);
5824 max_lock_owners
= 2;
5825 ASSERT_EQ(0, rbd_lock_get_owners(image1
, &lock_mode
, lock_owners
,
5827 ASSERT_EQ(RBD_LOCK_MODE_EXCLUSIVE
, lock_mode
);
5828 ASSERT_STRNE("", lock_owners
[0]);
5829 ASSERT_EQ(1U, max_lock_owners
);
5832 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image2
, NULL
));
5834 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5835 ASSERT_FALSE(lock_owner
);
5837 ASSERT_EQ(-EOPNOTSUPP
, rbd_lock_break(image1
, RBD_LOCK_MODE_SHARED
, ""));
5838 ASSERT_EQ(-EBUSY
, rbd_lock_break(image1
, RBD_LOCK_MODE_EXCLUSIVE
,
5841 ASSERT_EQ(0, rbd_lock_release(image1
));
5842 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5843 ASSERT_FALSE(lock_owner
);
5845 ASSERT_EQ(-ENOENT
, rbd_lock_break(image1
, RBD_LOCK_MODE_EXCLUSIVE
,
5847 rbd_lock_get_owners_cleanup(lock_owners
, max_lock_owners
);
5849 ASSERT_EQ(-EROFS
, rbd_write(image1
, 0, sizeof(buf
), buf
));
5850 ASSERT_EQ((ssize_t
)sizeof(buf
), rbd_write(image2
, 0, sizeof(buf
), buf
));
5852 ASSERT_EQ(0, rbd_lock_acquire(image2
, RBD_LOCK_MODE_EXCLUSIVE
));
5853 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5854 ASSERT_TRUE(lock_owner
);
5856 ASSERT_EQ(0, rbd_lock_release(image2
));
5857 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5858 ASSERT_FALSE(lock_owner
);
5860 ASSERT_EQ(0, rbd_lock_acquire(image1
, RBD_LOCK_MODE_EXCLUSIVE
));
5861 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5862 ASSERT_TRUE(lock_owner
);
5864 ASSERT_EQ((ssize_t
)sizeof(buf
), rbd_write(image1
, 0, sizeof(buf
), buf
));
5865 ASSERT_EQ(-EROFS
, rbd_write(image2
, 0, sizeof(buf
), buf
));
5867 ASSERT_EQ(0, rbd_lock_release(image1
));
5868 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5869 ASSERT_FALSE(lock_owner
);
5873 const auto pingpong
= [&,this](int m_id
, rbd_image_t
&m_image
) {
5874 for (int i
= 0; i
< 10; i
++) {
5876 lock_guard
<mutex
> locker(lock
);
5877 if (owner_id
== m_id
) {
5878 std::cout
<< m_id
<< ": releasing exclusive lock" << std::endl
;
5879 EXPECT_EQ(0, rbd_lock_release(m_image
));
5881 EXPECT_EQ(0, rbd_is_exclusive_lock_owner(m_image
, &lock_owner
));
5882 EXPECT_FALSE(lock_owner
);
5884 std::cout
<< m_id
<< ": exclusive lock released" << std::endl
;
5889 std::cout
<< m_id
<< ": acquiring exclusive lock" << std::endl
;
5892 r
= rbd_lock_acquire(m_image
, RBD_LOCK_MODE_EXCLUSIVE
);
5896 } while (r
== -EROFS
);
5900 EXPECT_EQ(0, rbd_is_exclusive_lock_owner(m_image
, &lock_owner
));
5901 EXPECT_TRUE(lock_owner
);
5902 std::cout
<< m_id
<< ": exclusive lock acquired" << std::endl
;
5904 lock_guard
<mutex
> locker(lock
);
5907 usleep(rand() % 50000);
5910 lock_guard
<mutex
> locker(lock
);
5911 if (owner_id
== m_id
) {
5912 EXPECT_EQ(0, rbd_lock_release(m_image
));
5914 EXPECT_EQ(0, rbd_is_exclusive_lock_owner(m_image
, &lock_owner
));
5915 EXPECT_FALSE(lock_owner
);
5919 thread
ping(bind(pingpong
, 1, ref(image1
)));
5920 thread
pong(bind(pingpong
, 2, ref(image2
)));
5925 ASSERT_EQ(0, rbd_lock_acquire(image2
, RBD_LOCK_MODE_EXCLUSIVE
));
5926 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image2
, &lock_owner
));
5927 ASSERT_TRUE(lock_owner
);
5929 ASSERT_EQ(0, rbd_close(image2
));
5931 ASSERT_EQ(0, rbd_lock_acquire(image1
, RBD_LOCK_MODE_EXCLUSIVE
));
5932 ASSERT_EQ(0, rbd_is_exclusive_lock_owner(image1
, &lock_owner
));
5933 ASSERT_TRUE(lock_owner
);
5935 ASSERT_EQ(0, rbd_close(image1
));
5936 rados_ioctx_destroy(ioctx
);
5939 TEST_F(TestLibRBD
, BreakLock
)
5941 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
5943 static char buf
[10];
5945 rados_t blacklist_cluster
;
5946 ASSERT_EQ("", connect_cluster(&blacklist_cluster
));
5948 rados_ioctx_t ioctx
, blacklist_ioctx
;
5949 ASSERT_EQ(0, rados_ioctx_create(_cluster
, m_pool_name
.c_str(), &ioctx
));
5950 ASSERT_EQ(0, rados_ioctx_create(blacklist_cluster
, m_pool_name
.c_str(),
5953 std::string name
= get_temp_image_name();
5954 uint64_t size
= 2 << 20;
5956 ASSERT_EQ(0, create_image(ioctx
, name
.c_str(), size
, &order
));
5958 rbd_image_t image
, blacklist_image
;
5959 ASSERT_EQ(0, rbd_open(ioctx
, name
.c_str(), &image
, NULL
));
5960 ASSERT_EQ(0, rbd_open(blacklist_ioctx
, name
.c_str(), &blacklist_image
, NULL
));
5962 ASSERT_EQ(0, rbd_metadata_set(image
, "rbd_blacklist_on_break_lock", "true"));
5963 ASSERT_EQ(0, rbd_lock_acquire(blacklist_image
, RBD_LOCK_MODE_EXCLUSIVE
));
5965 rbd_lock_mode_t lock_mode
;
5966 char *lock_owners
[1];
5967 size_t max_lock_owners
= 1;
5968 ASSERT_EQ(0, rbd_lock_get_owners(image
, &lock_mode
, lock_owners
,
5970 ASSERT_EQ(RBD_LOCK_MODE_EXCLUSIVE
, lock_mode
);
5971 ASSERT_STRNE("", lock_owners
[0]);
5972 ASSERT_EQ(1U, max_lock_owners
);
5974 ASSERT_EQ(0, rbd_lock_break(image
, RBD_LOCK_MODE_EXCLUSIVE
, lock_owners
[0]));
5975 ASSERT_EQ(0, rbd_lock_acquire(image
, RBD_LOCK_MODE_EXCLUSIVE
));
5976 EXPECT_EQ(0, rados_wait_for_latest_osdmap(blacklist_cluster
));
5978 ASSERT_EQ((ssize_t
)sizeof(buf
), rbd_write(image
, 0, sizeof(buf
), buf
));
5979 ASSERT_EQ(-EBLACKLISTED
, rbd_write(blacklist_image
, 0, sizeof(buf
), buf
));
5981 ASSERT_EQ(0, rbd_close(image
));
5982 ASSERT_EQ(0, rbd_close(blacklist_image
));
5984 rbd_lock_get_owners_cleanup(lock_owners
, max_lock_owners
);
5986 rados_ioctx_destroy(ioctx
);
5987 rados_ioctx_destroy(blacklist_ioctx
);
5988 rados_shutdown(blacklist_cluster
);
5991 TEST_F(TestLibRBD
, DiscardAfterWrite
)
5993 REQUIRE(!is_skip_partial_discard_enabled());
5995 librados::IoCtx ioctx
;
5996 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
5999 std::string name
= get_temp_image_name();
6000 uint64_t size
= 1 << 20;
6002 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
6004 librbd::Image image
;
6005 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), NULL
));
6007 // enable writeback cache
6008 ASSERT_EQ(0, image
.flush());
6011 bl
.append(std::string(256, '1'));
6013 librbd::RBD::AioCompletion
*write_comp
=
6014 new librbd::RBD::AioCompletion(NULL
, NULL
);
6015 ASSERT_EQ(0, image
.aio_write(0, bl
.length(), bl
, write_comp
));
6016 ASSERT_EQ(0, write_comp
->wait_for_complete());
6017 write_comp
->release();
6019 librbd::RBD::AioCompletion
*discard_comp
=
6020 new librbd::RBD::AioCompletion(NULL
, NULL
);
6021 ASSERT_EQ(0, image
.aio_discard(0, 256, discard_comp
));
6022 ASSERT_EQ(0, discard_comp
->wait_for_complete());
6023 discard_comp
->release();
6025 librbd::RBD::AioCompletion
*read_comp
=
6026 new librbd::RBD::AioCompletion(NULL
, NULL
);
6028 image
.aio_read(0, bl
.length(), read_bl
, read_comp
);
6029 ASSERT_EQ(0, read_comp
->wait_for_complete());
6030 ASSERT_EQ(bl
.length(), read_comp
->get_return_value());
6031 ASSERT_TRUE(read_bl
.is_zero());
6032 read_comp
->release();
6035 TEST_F(TestLibRBD
, DefaultFeatures
) {
6036 std::string orig_default_features
;
6037 ASSERT_EQ(0, _rados
.conf_get("rbd_default_features", orig_default_features
));
6038 BOOST_SCOPE_EXIT_ALL(orig_default_features
) {
6039 ASSERT_EQ(0, _rados
.conf_set("rbd_default_features",
6040 orig_default_features
.c_str()));
6043 std::list
<std::pair
<std::string
, std::string
> > feature_names_to_bitmask
= {
6044 {"", orig_default_features
},
6046 {"layering, exclusive-lock", "5"},
6047 {"exclusive-lock,journaling", "68"},
6051 for (auto &pair
: feature_names_to_bitmask
) {
6052 ASSERT_EQ(0, _rados
.conf_set("rbd_default_features", pair
.first
.c_str()));
6053 std::string features
;
6054 ASSERT_EQ(0, _rados
.conf_get("rbd_default_features", features
));
6055 ASSERT_EQ(pair
.second
, features
);
6059 TEST_F(TestLibRBD
, TestTrashMoveAndPurge
) {
6060 librados::IoCtx ioctx
;
6061 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
6064 std::string name
= get_temp_image_name();
6066 uint64_t size
= 1 << 18;
6068 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
6070 librbd::Image image
;
6071 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), nullptr));
6073 ASSERT_EQ(0, image
.old_format(&old_format
));
6076 ASSERT_EQ(-EOPNOTSUPP
, rbd
.trash_move(ioctx
, name
.c_str(), 0));
6080 std::string image_id
;
6081 ASSERT_EQ(0, image
.get_id(&image_id
));
6084 ASSERT_EQ(0, rbd
.trash_move(ioctx
, name
.c_str(), 0));
6086 std::vector
<std::string
> images
;
6087 ASSERT_EQ(0, rbd
.list(ioctx
, images
));
6088 for (const auto& image
: images
) {
6089 ASSERT_TRUE(image
!= name
);
6092 librbd::trash_image_info_t info
;
6093 ASSERT_EQ(-ENOENT
, rbd
.trash_get(ioctx
, "dummy image id", &info
));
6094 ASSERT_EQ(0, rbd
.trash_get(ioctx
, image_id
.c_str(), &info
));
6095 ASSERT_EQ(image_id
, info
.id
);
6097 std::vector
<librbd::trash_image_info_t
> entries
;
6098 ASSERT_EQ(0, rbd
.trash_list(ioctx
, entries
));
6099 ASSERT_FALSE(entries
.empty());
6100 ASSERT_EQ(entries
.begin()->id
, image_id
);
6104 ASSERT_EQ(0, rbd
.trash_remove_with_progress(ioctx
, image_id
.c_str(),
6106 ASSERT_EQ(0, rbd
.trash_list(ioctx
, entries
));
6107 ASSERT_TRUE(entries
.empty());
6110 TEST_F(TestLibRBD
, TestTrashMoveAndPurgeNonExpiredDelay
) {
6111 librados::IoCtx ioctx
;
6112 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
6115 std::string name
= get_temp_image_name();
6117 uint64_t size
= 1 << 18;
6119 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
6121 librbd::Image image
;
6122 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), nullptr));
6124 ASSERT_EQ(0, image
.old_format(&old_format
));
6127 ASSERT_EQ(-EOPNOTSUPP
, rbd
.trash_move(ioctx
, name
.c_str(), 0));
6131 std::string image_id
;
6132 ASSERT_EQ(0, image
.get_id(&image_id
));
6135 ASSERT_EQ(0, rbd
.trash_move(ioctx
, name
.c_str(), 100));
6138 ASSERT_EQ(-EPERM
, rbd
.trash_remove_with_progress(ioctx
, image_id
.c_str(),
6142 ASSERT_EQ(0, rbd
.trash_remove_with_progress(ioctx
, image_id
.c_str(),
6146 TEST_F(TestLibRBD
, TestTrashMoveAndRestore
) {
6147 librados::IoCtx ioctx
;
6148 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
6151 std::string name
= get_temp_image_name();
6153 uint64_t size
= 1 << 18;
6155 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
6157 librbd::Image image
;
6158 ASSERT_EQ(0, rbd
.open(ioctx
, image
, name
.c_str(), nullptr));
6160 ASSERT_EQ(0, image
.old_format(&old_format
));
6163 ASSERT_EQ(-EOPNOTSUPP
, rbd
.trash_move(ioctx
, name
.c_str(), 0));
6167 std::string image_id
;
6168 ASSERT_EQ(0, image
.get_id(&image_id
));
6171 ASSERT_EQ(0, rbd
.trash_move(ioctx
, name
.c_str(), 10));
6173 std::vector
<std::string
> images
;
6174 ASSERT_EQ(0, rbd
.list(ioctx
, images
));
6175 for (const auto& image
: images
) {
6176 ASSERT_TRUE(image
!= name
);
6179 std::vector
<librbd::trash_image_info_t
> entries
;
6180 ASSERT_EQ(0, rbd
.trash_list(ioctx
, entries
));
6181 ASSERT_FALSE(entries
.empty());
6182 ASSERT_EQ(entries
.begin()->id
, image_id
);
6185 ASSERT_EQ(0, rbd
.trash_restore(ioctx
, image_id
.c_str(), ""));
6186 ASSERT_EQ(0, rbd
.list(ioctx
, images
));
6187 ASSERT_FALSE(images
.empty());
6189 for (const auto& image
: images
) {
6190 if (image
== name
) {
6198 TEST_F(TestLibRBD
, ZeroOverlapFlatten
) {
6199 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
6201 librados::IoCtx ioctx
;
6202 ASSERT_EQ(0, _rados
.ioctx_create(m_pool_name
.c_str(), ioctx
));
6205 librbd::Image parent_image
;
6206 std::string name
= get_temp_image_name();
6211 ASSERT_EQ(0, create_image_pp(rbd
, ioctx
, name
.c_str(), size
, &order
));
6212 ASSERT_EQ(0, rbd
.open(ioctx
, parent_image
, name
.c_str(), NULL
));
6215 ASSERT_EQ(0, parent_image
.features(&features
));
6217 ASSERT_EQ(0, parent_image
.snap_create("snap"));
6218 ASSERT_EQ(0, parent_image
.snap_protect("snap"));
6220 std::string clone_name
= this->get_temp_image_name();
6221 ASSERT_EQ(0, rbd
.clone(ioctx
, name
.c_str(), "snap", ioctx
, clone_name
.c_str(),
6224 librbd::Image clone_image
;
6225 ASSERT_EQ(0, rbd
.open(ioctx
, clone_image
, clone_name
.c_str(), NULL
));
6226 ASSERT_EQ(0, clone_image
.resize(0));
6227 ASSERT_EQ(0, clone_image
.flatten());
6230 // poorman's assert()
6232 void __ceph_assert_fail(const char *assertion
, const char *file
, int line
,