From: Ilya Dryomov Date: Fri, 17 Sep 2021 13:00:59 +0000 (+0200) Subject: librbd: propagate CEPH_OSD_FLAG_FULL_TRY from IoCtx to IOContext X-Git-Tag: v17.1.0~811^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4ee20f859bbac94152bc13a81bbb24f126f77bf3;p=ceph.git librbd: propagate CEPH_OSD_FLAG_FULL_TRY from IoCtx to IOContext We use neorados on the I/O path so data_io_context needs to have the same setting as data_ctx. Fixes: https://tracker.ceph.com/issues/52648 Signed-off-by: Ilya Dryomov --- diff --git a/src/include/rados/librados.hpp b/src/include/rados/librados.hpp index dc3ecefa7e5..76fe6dfd0cd 100644 --- a/src/include/rados/librados.hpp +++ b/src/include/rados/librados.hpp @@ -1339,6 +1339,7 @@ inline namespace v14_2_0 { void unset_osdmap_full_try() __attribute__ ((deprecated)); + bool get_pool_full_try(); void set_pool_full_try(); void unset_pool_full_try(); diff --git a/src/librados/librados_cxx.cc b/src/librados/librados_cxx.cc index 85f3b92137f..75e3e797a9a 100644 --- a/src/librados/librados_cxx.cc +++ b/src/librados/librados_cxx.cc @@ -2318,6 +2318,11 @@ void librados::IoCtx::unset_osdmap_full_try() io_ctx_impl->extra_op_flags &= ~CEPH_OSD_FLAG_FULL_TRY; } +bool librados::IoCtx::get_pool_full_try() +{ + return (io_ctx_impl->extra_op_flags & CEPH_OSD_FLAG_FULL_TRY) != 0; +} + void librados::IoCtx::set_pool_full_try() { io_ctx_impl->extra_op_flags |= CEPH_OSD_FLAG_FULL_TRY; diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index 0e3d40e7008..8a8e87a3362 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -939,6 +939,9 @@ librados::IoCtx duplicate_io_ctx(librados::IoCtx& io_ctx) { ctx->write_snap_context( {{snapc.seq, {snapc.snaps.begin(), snapc.snaps.end()}}}); } + if (data_ctx.get_pool_full_try()) { + ctx->full_try(true); + } // atomically reset the data IOContext to new version atomic_store(&data_io_context, ctx); diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index e1a6800b037..53bee26f701 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -2118,6 +2118,62 @@ TEST_F(TestLibRBD, ConcurrentCreatesUnvalidatedPool) 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;