]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd:snap limit should't be set smaller than the num of existing snaps 16597/head
authorPCzhangPC <pengcheng.zhang@easystack.cn>
Mon, 21 Aug 2017 11:53:07 +0000 (19:53 +0800)
committerPCzhangPC <pengcheng.zhang@easystack.cn>
Mon, 21 Aug 2017 11:53:07 +0000 (19:53 +0800)
new snap limit must be bigger than the num of existing snaps

Signed-off-by: PCzhangPC <pengcheng.zhang@easystack.cn>
src/cls/rbd/cls_rbd.cc
src/librbd/journal/Replay.cc
src/test/librbd/test_librbd.cc

index 0c2d7aee595ec4ac52acc82cab009019225fe8dc..3dedd86715fea3a952a324637e86bd31860abb11 100644 (file)
@@ -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<string> 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 */
index 92accbc1382aaf91cc25982ab0253f5a64412a63..a5852088492978e4c62e2b0196c090640b69249c 100644 (file)
@@ -772,6 +772,8 @@ void Replay<I>::handle_event(const journal::SnapLimitEvent &event,
                                                           event,
                                                           on_op_complete));
 
+  op_event->ignore_error_codes = {-ERANGE};
+
   on_ready->complete(0);
 }
 
index 92a9b5c2cc112d3616771b2404bd74db694f71d0..e8acd6d9ad1407368317f076f29febfd87b0baa1 100644 (file)
@@ -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));