From 121b6ca1716e05dcb76776ccc02a4238962ebae2 Mon Sep 17 00:00:00 2001 From: PCzhangPC Date: Mon, 21 Aug 2017 19:53:07 +0800 Subject: [PATCH] rbd:snap limit should't be set smaller than the num of existing snaps new snap limit must be bigger than the num of existing snaps Signed-off-by: PCzhangPC --- src/cls/rbd/cls_rbd.cc | 44 +++++++++++++++++++++++++++++++++- src/librbd/journal/Replay.cc | 2 ++ src/test/librbd/test_librbd.cc | 2 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 0c2d7aee595ec..3dedd86715fea 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -2799,6 +2799,7 @@ int snapshot_set_limit(cls_method_context_t hctx, bufferlist *in, int rc; uint64_t new_limit; bufferlist bl; + size_t snap_count = 0; try { bufferlist::iterator iter = in->begin(); @@ -2810,8 +2811,49 @@ int snapshot_set_limit(cls_method_context_t hctx, bufferlist *in, if (new_limit == UINT64_MAX) { CLS_LOG(20, "remove snapshot limit\n"); rc = cls_cxx_map_remove_key(hctx, "snap_limit"); + return rc; + } + + //try to read header as v1 format + rc = snap_read_header(hctx, bl); + + // error when reading header + if (rc < 0 && rc != -EINVAL) { + return rc; + } else if (rc >= 0) { + // success, the image is v1 format + struct rbd_obj_header_ondisk *header; + header = (struct rbd_obj_header_ondisk *)bl.c_str(); + snap_count = header->snap_count; + } else { + // else, the image is v2 format + int max_read = RBD_MAX_KEYS_READ; + string last_read = RBD_SNAP_KEY_PREFIX; + bool more; + + do { + set keys; + rc = cls_cxx_map_get_keys(hctx, last_read, max_read, &keys, &more); + if (rc < 0) { + CLS_ERR("error retrieving snapshots: %s", cpp_strerror(rc).c_str()); + return rc; + } + for (auto& key : keys) { + if (key.find(RBD_SNAP_KEY_PREFIX) != 0) + break; + snap_count++; + } + if (!keys.empty()) + last_read = *(keys.rbegin()); + } while (more); + } + + if (new_limit < snap_count) { + rc = -ERANGE; + CLS_LOG(10, "snapshot limit is less than the number of snapshots.\n"); } else { CLS_LOG(20, "set snapshot limit to %" PRIu64 "\n", new_limit); + bl.clear(); ::encode(new_limit, bl); rc = cls_cxx_map_set_val(hctx, "snap_limit", &bl); } @@ -5305,7 +5347,7 @@ CLS_INIT(rbd) CLS_METHOD_RD, snapshot_get_limit, &h_snapshot_get_limit); cls_register_cxx_method(h_class, "snapshot_set_limit", - CLS_METHOD_WR, + CLS_METHOD_RD | CLS_METHOD_WR, snapshot_set_limit, &h_snapshot_set_limit); /* methods for the rbd_children object */ diff --git a/src/librbd/journal/Replay.cc b/src/librbd/journal/Replay.cc index 92accbc1382aa..a585208849297 100644 --- a/src/librbd/journal/Replay.cc +++ b/src/librbd/journal/Replay.cc @@ -772,6 +772,8 @@ void Replay::handle_event(const journal::SnapLimitEvent &event, event, on_op_complete)); + op_event->ignore_error_codes = {-ERANGE}; + on_ready->complete(0); } diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 92a9b5c2cc112..e8acd6d9ad140 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -3879,6 +3879,7 @@ TEST_F(TestLibRBD, SnapshotLimit) ASSERT_EQ(2U, limit); ASSERT_EQ(0, rbd_snap_create(image, "snap1")); + ASSERT_EQ(-ERANGE, rbd_snap_set_limit(image, 0)); ASSERT_EQ(0, rbd_snap_create(image, "snap2")); ASSERT_EQ(-EDQUOT, rbd_snap_create(image, "snap3")); ASSERT_EQ(0, rbd_snap_set_limit(image, UINT64_MAX)); @@ -3912,6 +3913,7 @@ TEST_F(TestLibRBD, SnapshotLimitPP) ASSERT_EQ(2U, limit); ASSERT_EQ(0, image.snap_create("snap1")); + ASSERT_EQ(-ERANGE, image.snap_set_limit(0)); ASSERT_EQ(0, image.snap_create("snap2")); ASSERT_EQ(-EDQUOT, image.snap_create("snap3")); ASSERT_EQ(0, image.snap_set_limit(UINT64_MAX)); -- 2.39.5