summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/librbd/image/RefreshRequest.cc4
-rw-r--r--src/librbd/image/RefreshRequest.h4
-rw-r--r--src/test/librbd/image/test_mock_RefreshRequest.cc33
3 files changed, 38 insertions, 3 deletions
diff --git a/src/librbd/image/RefreshRequest.cc b/src/librbd/image/RefreshRequest.cc
index 9021eec8cb4..19a57b9a511 100644
--- a/src/librbd/image/RefreshRequest.cc
+++ b/src/librbd/image/RefreshRequest.cc
@@ -805,8 +805,8 @@ Context *RefreshRequest<I>::handle_v2_get_snapshots(int *result) {
}
}
- if (*result == -ENOENT) {
- ldout(cct, 10) << "out-of-sync snapshot state detected" << dendl;
+ if (*result == -ENOENT && m_enoent_retries++ < MAX_ENOENT_RETRIES) {
+ ldout(cct, 10) << "out-of-sync snapshot state detected, retrying" << dendl;
send_v2_get_mutable_metadata();
return nullptr;
} else if (m_legacy_snapshot == LEGACY_SNAPSHOT_DISABLED &&
diff --git a/src/librbd/image/RefreshRequest.h b/src/librbd/image/RefreshRequest.h
index b7b877dd3c2..ab7b5089295 100644
--- a/src/librbd/image/RefreshRequest.h
+++ b/src/librbd/image/RefreshRequest.h
@@ -27,6 +27,8 @@ template<typename> class RefreshParentRequest;
template<typename ImageCtxT = ImageCtx>
class RefreshRequest {
public:
+ static constexpr int MAX_ENOENT_RETRIES = 10;
+
static RefreshRequest *create(ImageCtxT &image_ctx, bool acquiring_lock,
bool skip_open_parent, Context *on_finish) {
return new RefreshRequest(image_ctx, acquiring_lock, skip_open_parent,
@@ -144,6 +146,8 @@ private:
bool m_legacy_parent = false;
LegacySnapshot m_legacy_snapshot = LEGACY_SNAPSHOT_DISABLED;
+ int m_enoent_retries = 0;
+
uint8_t m_order = 0;
uint64_t m_size = 0;
uint64_t m_features = 0;
diff --git a/src/test/librbd/image/test_mock_RefreshRequest.cc b/src/test/librbd/image/test_mock_RefreshRequest.cc
index 96b8fe30673..261604c4337 100644
--- a/src/test/librbd/image/test_mock_RefreshRequest.cc
+++ b/src/test/librbd/image/test_mock_RefreshRequest.cc
@@ -722,7 +722,6 @@ TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotNoTimestampV2) {
ASSERT_EQ(0, ctx.wait());
}
-
TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
REQUIRE_FORMAT_V2();
@@ -765,6 +764,38 @@ TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
ASSERT_EQ(0, ctx.wait());
}
+TEST_F(TestMockImageRefreshRequest, SnapshotV2EnoentRetriesLimit) {
+ REQUIRE_FORMAT_V2();
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+ ASSERT_EQ(0, snap_create(*ictx, "snap"));
+
+ MockRefreshImageCtx mock_image_ctx(*ictx);
+ MockGetMetadataRequest mock_get_metadata_request;
+ expect_op_work_queue(mock_image_ctx);
+ expect_test_features(mock_image_ctx);
+
+ InSequence seq;
+ for (int i = 0; i < RefreshRequest<>::MAX_ENOENT_RETRIES + 1; ++i) {
+ expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
+ expect_get_parent(mock_image_ctx, 0);
+ expect_get_metadata(mock_image_ctx, mock_get_metadata_request,
+ mock_image_ctx.header_oid, {}, 0);
+ expect_get_metadata(mock_image_ctx, mock_get_metadata_request, RBD_INFO, {},
+ 0);
+ expect_apply_metadata(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
+ expect_get_snapshots(mock_image_ctx, false, -ENOENT);
+ }
+
+ C_SaferCond ctx;
+ auto req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
+ req->send();
+
+ ASSERT_EQ(-ENOENT, ctx.wait());
+}
+
TEST_F(TestMockImageRefreshRequest, SuccessChild) {
REQUIRE_FEATURE(RBD_FEATURE_LAYERING);