]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cls/refcount: add chunk_refcount
authormyoungwon oh <omwmw@sk.com>
Mon, 19 Feb 2018 07:59:55 +0000 (16:59 +0900)
committermyoungwon oh <omwmw@sk.com>
Fri, 13 Apr 2018 17:33:40 +0000 (02:33 +0900)
refcount() for chunked object is added (based on source id,
pool id and offset)

Signed-off-by: Myoungwon Oh <omwmw@sk.com>
src/cls/refcount/cls_refcount.cc
src/cls/refcount/cls_refcount_ops.h

index 11a600d50db3fd2d1feafcf6ba1ca7e12e26aa80..335c712db95c3efa8993fb978e771b513eb5221b 100644 (file)
@@ -13,6 +13,26 @@ CLS_NAME(refcount)
 
 
 #define REFCOUNT_ATTR "refcount"
+#define CHUNK_REFCOUNT_ATTR "chunk_refcount"
+
+struct chunk_obj_refcount {
+  set<hobject_t> refs;
+
+  chunk_obj_refcount() {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(refs, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    DECODE_START(1, bl);
+    decode(refs, bl);
+    DECODE_FINISH(bl);
+  }
+};
+WRITE_CLASS_ENCODER(chunk_obj_refcount)
 
 struct obj_refcount {
   map<string, bool> refs;
@@ -217,6 +237,163 @@ static int cls_rc_refcount_read(cls_method_context_t hctx, bufferlist *in, buffe
   return 0;
 }
 
+static int chunk_read_refcount(cls_method_context_t hctx, chunk_obj_refcount *objr)
+{
+  bufferlist bl;
+  objr->refs.clear();
+  int ret = cls_cxx_getxattr(hctx, CHUNK_REFCOUNT_ATTR, &bl);
+  if (ret == -ENODATA) {
+    return 0;
+  }
+  if (ret < 0)
+    return ret;
+
+  try {
+    bufferlist::iterator iter = bl.begin();
+    decode(*objr, iter);
+  } catch (buffer::error& err) {
+    CLS_LOG(0, "ERROR: chunk_read_refcount(): failed to decode refcount entry\n");
+    return -EIO;
+  }
+
+  return 0;
+}
+
+static int chunk_set_refcount(cls_method_context_t hctx, const struct chunk_obj_refcount& objr)
+{
+  bufferlist bl;
+
+  encode(objr, bl);
+
+  int ret = cls_cxx_setxattr(hctx, CHUNK_REFCOUNT_ATTR, &bl);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+static int cls_rc_chunk_refcount_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  bufferlist::iterator in_iter = in->begin();
+
+  cls_chunk_refcount_get_op op;
+  try {
+    decode(op, in_iter);
+  } catch (buffer::error& err) {
+    CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
+    return -EINVAL;
+  }
+
+  chunk_obj_refcount objr;
+  int ret = chunk_read_refcount(hctx, &objr);
+  if (ret < 0)
+    return ret;
+
+  CLS_LOG(10, "cls_rc_chunk_refcount_get() oid=%s\n", op.source.oid.name.c_str());
+
+  objr.refs.insert(op.source);
+
+  ret = chunk_set_refcount(hctx, objr);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+static int cls_rc_chunk_refcount_put(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  bufferlist::iterator in_iter = in->begin();
+
+  cls_chunk_refcount_put_op op;
+  try {
+    decode(op, in_iter);
+  } catch (buffer::error& err) {
+    CLS_LOG(1, "ERROR: cls_rc_chunk_refcount_put(): failed to decode entry\n");
+    return -EINVAL;
+  }
+
+  chunk_obj_refcount objr;
+  int ret = chunk_read_refcount(hctx, &objr);
+  if (ret < 0)
+    return ret;
+
+  if (objr.refs.empty()) {// shouldn't happen!
+    CLS_LOG(0, "ERROR: cls_rc_chunk_refcount_put() was called without any references!\n");
+    return -EINVAL;
+  }
+
+  CLS_LOG(10, "cls_rc_chunk_refcount_put() oid=%s\n", op.source.oid.name.c_str());
+
+  bool found = false;
+  for (auto &p : objr.refs) {
+    if (p == op.source) {
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    return 0;
+  }
+
+  auto p = objr.refs.find(op.source);
+  objr.refs.erase(p);
+
+  if (objr.refs.empty()) {
+    return cls_cxx_remove(hctx);
+  }
+
+  ret = chunk_set_refcount(hctx, objr);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+static int cls_rc_chunk_refcount_set(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  bufferlist::iterator in_iter = in->begin();
+
+  cls_chunk_refcount_set_op op;
+  try {
+    decode(op, in_iter);
+  } catch (buffer::error& err) {
+    CLS_LOG(1, "ERROR: cls_chunk_refcount_set(): failed to decode entry\n");
+    return -EINVAL;
+  }
+
+  if (!op.refs.size()) {
+    return cls_cxx_remove(hctx);
+  }
+
+  chunk_obj_refcount objr;
+  objr.refs = op.refs;
+
+  int ret = chunk_set_refcount(hctx, objr);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+static int cls_rc_chunk_refcount_read(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  chunk_obj_refcount objr;
+
+  cls_chunk_refcount_read_ret read_ret;
+  int ret = chunk_read_refcount(hctx, &objr);
+  if (ret < 0)
+    return ret;
+
+  for (auto &p : objr.refs) {
+    read_ret.refs.insert(p);
+  }
+
+  encode(read_ret, *out);
+
+  return 0;
+}
+
 CLS_INIT(refcount)
 {
   CLS_LOG(1, "Loaded refcount class!");
@@ -227,6 +404,11 @@ CLS_INIT(refcount)
   cls_method_handle_t h_refcount_set;
   cls_method_handle_t h_refcount_read;
 
+  cls_method_handle_t h_chunk_refcount_get;
+  cls_method_handle_t h_chunk_refcount_put;
+  cls_method_handle_t h_chunk_refcount_set;
+  cls_method_handle_t h_chunk_refcount_read;
+
   cls_register("refcount", &h_class);
 
   /* refcount */
@@ -234,6 +416,15 @@ CLS_INIT(refcount)
   cls_register_cxx_method(h_class, "put", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_refcount_put, &h_refcount_put);
   cls_register_cxx_method(h_class, "set", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_refcount_set, &h_refcount_set);
   cls_register_cxx_method(h_class, "read", CLS_METHOD_RD, cls_rc_refcount_read, &h_refcount_read);
+  /* chunk refcount */
+  cls_register_cxx_method(h_class, "chunk_get", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_chunk_refcount_get, 
+                         &h_chunk_refcount_get);
+  cls_register_cxx_method(h_class, "chunk_put", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_chunk_refcount_put, 
+                         &h_chunk_refcount_put);
+  cls_register_cxx_method(h_class, "chunk_set", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_chunk_refcount_set, 
+                         &h_chunk_refcount_set);
+  cls_register_cxx_method(h_class, "chunk_read", CLS_METHOD_RD, cls_rc_chunk_refcount_read, 
+                         &h_chunk_refcount_read);
 
   return;
 }
index ee560c52f2309aacf1a31e2f692591a2d667f9dd..93a213aa4aa39faf248fe1aecb052c276ea9ca80 100644 (file)
@@ -5,6 +5,7 @@
 #define CEPH_CLS_REFCOUNT_OPS_H
 
 #include "include/types.h"
+#include "common/hobject.h"
 
 struct cls_refcount_get_op {
   string tag;
@@ -123,5 +124,90 @@ struct cls_refcount_read_ret {
 };
 WRITE_CLASS_ENCODER(cls_refcount_read_ret)
 
+struct cls_chunk_refcount_get_op {
+  hobject_t source;
 
+  cls_chunk_refcount_get_op() {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(source, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    DECODE_START(1, bl);
+    decode(source, bl);
+    DECODE_FINISH(bl);
+  }
+  void dump(ceph::Formatter *f) const;
+  static void generate_test_instances(list<cls_chunk_refcount_get_op*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_chunk_refcount_get_op)
+
+struct cls_chunk_refcount_put_op {
+  hobject_t source;
+
+  cls_chunk_refcount_put_op() {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(source, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    DECODE_START(1, bl);
+    decode(source, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void dump(ceph::Formatter *f) const;
+  static void generate_test_instances(list<cls_chunk_refcount_put_op*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_chunk_refcount_put_op)
+
+struct cls_chunk_refcount_set_op {
+  set<hobject_t> refs;
+
+  cls_chunk_refcount_set_op() {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(refs, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    DECODE_START(1, bl);
+    decode(refs, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void dump(ceph::Formatter *f) const;
+  static void generate_test_instances(list<cls_chunk_refcount_set_op*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_chunk_refcount_set_op)
+
+struct cls_chunk_refcount_read_ret {
+  set<hobject_t> refs;
+
+  cls_chunk_refcount_read_ret() {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(refs, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    DECODE_START(1, bl);
+    decode(refs, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void dump(ceph::Formatter *f) const;
+  static void generate_test_instances(list<cls_chunk_refcount_read_ret*>& ls);
+};
+WRITE_CLASS_ENCODER(cls_chunk_refcount_read_ret)
 #endif