From 70828e1f6714fc7ac0b0eaa63af25ad0aaa47ee0 Mon Sep 17 00:00:00 2001 From: myoungwon oh Date: Mon, 19 Feb 2018 16:59:55 +0900 Subject: [PATCH] cls/refcount: add chunk_refcount refcount() for chunked object is added (based on source id, pool id and offset) Signed-off-by: Myoungwon Oh --- src/cls/refcount/cls_refcount.cc | 191 ++++++++++++++++++++++++++++ src/cls/refcount/cls_refcount_ops.h | 86 +++++++++++++ 2 files changed, 277 insertions(+) diff --git a/src/cls/refcount/cls_refcount.cc b/src/cls/refcount/cls_refcount.cc index 11a600d50db..335c712db95 100644 --- a/src/cls/refcount/cls_refcount.cc +++ b/src/cls/refcount/cls_refcount.cc @@ -13,6 +13,26 @@ CLS_NAME(refcount) #define REFCOUNT_ATTR "refcount" +#define CHUNK_REFCOUNT_ATTR "chunk_refcount" + +struct chunk_obj_refcount { + set 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 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; } diff --git a/src/cls/refcount/cls_refcount_ops.h b/src/cls/refcount/cls_refcount_ops.h index ee560c52f23..93a213aa4aa 100644 --- a/src/cls/refcount/cls_refcount_ops.h +++ b/src/cls/refcount/cls_refcount_ops.h @@ -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& 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& ls); +}; +WRITE_CLASS_ENCODER(cls_chunk_refcount_put_op) + +struct cls_chunk_refcount_set_op { + set 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& ls); +}; +WRITE_CLASS_ENCODER(cls_chunk_refcount_set_op) + +struct cls_chunk_refcount_read_ret { + set 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& ls); +}; +WRITE_CLASS_ENCODER(cls_chunk_refcount_read_ret) #endif -- 2.39.5