]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cls/user: implement reset user stats
authorAbhishek Lekshmanan <abhishek@suse.com>
Mon, 12 Mar 2018 19:17:36 +0000 (20:17 +0100)
committerAbhishek Lekshmanan <abhishek@suse.com>
Thu, 12 Apr 2018 18:04:06 +0000 (20:04 +0200)
This is an implementation of reset user stats, that recalculates the user stats
purely based on the values of bucket entries in user.buckets object. This is
helpful in cases when user stats has been improperly set in case of manual
resharding etc.

Luminous only additions:
use global scope for encode in cls_user_ops

Fixes: http://tracker.ceph.com/issues/23335
Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com>
(cherry picked from commit 63f9127dd685890d938a612739320c942a96f910)

src/cls/user/cls_user.cc
src/cls/user/cls_user_client.cc
src/cls/user/cls_user_client.h
src/cls/user/cls_user_ops.h

index 840470e9f4d9b665a6b0d647046759a39f2099bb..9a9c5bd9f7ebb4324b06a3271ac937e970704c98 100644 (file)
@@ -359,6 +359,52 @@ static int cls_user_get_header(cls_method_context_t hctx, bufferlist *in, buffer
   return 0;
 }
 
+/// A method to reset the user.buckets header stats in accordance to the values
+/// seen in the user.buckets omap keys. This will not be equivalent to --sync-stats
+/// which requires comparing the values with actual bucket meta stats supplied
+/// by RGW
+static int cls_user_reset_stats(cls_method_context_t hctx, bufferlist *in, bufferlist *out /*ignore*/)
+{
+  cls_user_reset_stats_op op;
+
+  try {
+    auto bliter = in->begin();
+    ::decode(op, bliter);
+  } catch (buffer::error& err) {
+    CLS_LOG(0, "ERROR: cls_user_reset_op(): failed to decode op");
+    return -EINVAL;
+  }
+  cls_user_header header;
+  bool truncated = false;
+  string from_index, prefix;
+  do {
+    map<string, bufferlist> keys;
+    int rc = cls_cxx_map_get_vals(hctx, from_index, prefix, MAX_ENTRIES, &keys, &truncated);
+
+    if (rc < 0)
+      return rc;
+
+    for (const auto&kv : keys){
+      cls_user_bucket_entry e;
+      try {
+       auto bl = kv.second;
+       auto bliter = bl.begin();
+       decode(e, bliter);
+      } catch (buffer::error& err) {
+       CLS_LOG(0, "ERROR: failed to decode bucket entry for %s", kv.first.c_str());
+       return -EIO;
+      }
+      add_header_stats(&header.stats, e);
+    }
+  } while (truncated);
+
+  bufferlist bl;
+  header.last_stats_update = op.time;
+  ::encode(header, bl);
+
+  return cls_cxx_map_write_header(hctx, &bl);
+}
+
 CLS_INIT(user)
 {
   CLS_LOG(1, "Loaded user class!");
@@ -369,6 +415,7 @@ CLS_INIT(user)
   cls_method_handle_t h_user_remove_bucket;
   cls_method_handle_t h_user_list_buckets;
   cls_method_handle_t h_user_get_header;
+  cls_method_handle_t h_user_reset_stats;
 
   cls_register("user", &h_class);
 
@@ -380,7 +427,7 @@ CLS_INIT(user)
   cls_register_cxx_method(h_class, "remove_bucket", CLS_METHOD_RD | CLS_METHOD_WR, cls_user_remove_bucket, &h_user_remove_bucket);
   cls_register_cxx_method(h_class, "list_buckets", CLS_METHOD_RD, cls_user_list_buckets, &h_user_list_buckets);
   cls_register_cxx_method(h_class, "get_header", CLS_METHOD_RD, cls_user_get_header, &h_user_get_header);
-
+  cls_register_cxx_method(h_class, "reset_user_stats", CLS_METHOD_RD | CLS_METHOD_WR, cls_user_reset_stats, &h_user_reset_stats);
   return;
 }
 
index c77075dcb24a72c1ceefb5adf936ac6aacf2b6b4..5e0d65a8dbd3e064aed0b6a792f249736ee972a5 100644 (file)
@@ -132,6 +132,15 @@ void cls_user_get_header(librados::ObjectReadOperation& op,
   op.exec("user", "get_header", inbl, new ClsUserGetHeaderCtx(header, NULL, pret));
 }
 
+void cls_user_reset_stats(librados::ObjectWriteOperation &op)
+{
+  bufferlist inbl;
+  cls_user_reset_stats_op call;
+  call.time = real_clock::now();
+  ::encode(call, inbl);
+  op.exec("user", "reset_user_stats", inbl);
+}
+
 int cls_user_get_header_async(IoCtx& io_ctx, string& oid, RGWGetUserHeader_CB *ctx)
 {
   bufferlist in, out;
index 5e5d3063d011b00226b954dcc9c1f1dd170549fe..b398961e061e629e47aa09ab948f2fe6687e474b 100644 (file)
@@ -36,5 +36,6 @@ void cls_user_bucket_list(librados::ObjectReadOperation& op,
                        int *pret);
 void cls_user_get_header(librados::ObjectReadOperation& op, cls_user_header *header, int *pret);
 int cls_user_get_header_async(librados::IoCtx& io_ctx, string& oid, RGWGetUserHeader_CB *ctx);
+void cls_user_reset_stats(librados::ObjectWriteOperation& op);
 
 #endif
index 2219a49596200e9e23c3b76a98f6056d133ceaff..a79e03cc6cf7f28762dc7fb9f9658f85d32e0dab 100644 (file)
@@ -135,6 +135,27 @@ struct cls_user_get_header_op {
 };
 WRITE_CLASS_ENCODER(cls_user_get_header_op)
 
+struct cls_user_reset_stats_op {
+  real_time time;
+  cls_user_reset_stats_op() {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    ::encode(time, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    DECODE_START(1, bl);
+    ::decode(time, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void dump(Formatter *f) const;
+  static void generate_test_instances(list<cls_user_reset_stats_op*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_user_reset_stats_op);
+
 struct cls_user_get_header_ret {
   cls_user_header header;