rados_ioctx_destroy(ioctx);
}
+TEST_F(TestLibRBD, CreateThickRemoveFullTry)
+{
+ REQUIRE(!is_librados_test_stub(_rados));
+
+ rados_ioctx_t ioctx;
+ auto pool_name = create_pool(true);
+ ASSERT_EQ(0, rados_ioctx_create(_cluster, pool_name.c_str(), &ioctx));
+
+ int order = 0;
+ auto image_name = get_temp_image_name();
+ uint64_t quota = 10 << 20;
+ uint64_t size = 5 * quota;
+ ASSERT_EQ(0, create_image(ioctx, image_name.c_str(), size, &order));
+
+ // FIXME: this is a workaround for rbd_trash object being created
+ // on the first remove -- pre-create it to avoid bumping into quota
+ ASSERT_EQ(0, rbd_remove(ioctx, image_name.c_str()));
+ ASSERT_EQ(0, create_image(ioctx, image_name.c_str(), size, &order));
+
+ std::string cmdstr = "{\"prefix\": \"osd pool set-quota\", \"pool\": \"" +
+ pool_name + "\", \"field\": \"max_bytes\", \"val\": \"" +
+ std::to_string(quota) + "\"}";
+ char *cmd[1];
+ cmd[0] = (char *)cmdstr.c_str();
+ ASSERT_EQ(0, rados_mon_command(_cluster, (const char **)cmd, 1, "", 0,
+ nullptr, 0, nullptr, 0));
+
+ rados_set_pool_full_try(ioctx);
+
+ rbd_image_t image;
+ ASSERT_EQ(0, rbd_open(ioctx, image_name.c_str(), &image, nullptr));
+
+ uint64_t off;
+ size_t len = 1 << 20;
+ ssize_t ret;
+ for (off = 0; off < size; off += len) {
+ ret = rbd_write_zeroes(image, off, len,
+ RBD_WRITE_ZEROES_FLAG_THICK_PROVISION, 0);
+ if (ret < 0) {
+ break;
+ }
+ ASSERT_EQ(ret, len);
+ sleep(1);
+ }
+ ASSERT_TRUE(off >= quota && off < size);
+ ASSERT_EQ(ret, -EDQUOT);
+
+ ASSERT_EQ(0, rbd_close(image));
+
+ // make sure we have latest map that marked the pool full
+ ASSERT_EQ(0, rados_wait_for_latest_osdmap(_cluster));
+ ASSERT_EQ(0, rbd_remove(ioctx, image_name.c_str()));
+
+ rados_ioctx_destroy(ioctx);
+}
+
TEST_F(TestLibRBD, TestIO)
{
rados_ioctx_t ioctx;