]> git.proxmox.com Git - ceph.git/blame - ceph/src/cls/refcount/cls_refcount.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / cls / refcount / cls_refcount.cc
CommitLineData
f67539c2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
7c673cae
FG
2// vim: ts=8 sw=2 smarttab
3
7c673cae
FG
4#include <errno.h>
5
7c673cae
FG
6#include "objclass/objclass.h"
7#include "cls/refcount/cls_refcount_ops.h"
7c673cae 8
7c673cae
FG
9#include "include/compat.h"
10
f67539c2
TL
11using std::string;
12
13using ceph::bufferlist;
14
7c673cae
FG
15CLS_VER(1,0)
16CLS_NAME(refcount)
17
7c673cae
FG
18#define REFCOUNT_ATTR "refcount"
19
7c673cae
FG
20static string wildcard_tag;
21
22static int read_refcount(cls_method_context_t hctx, bool implicit_ref, obj_refcount *objr)
23{
24 bufferlist bl;
25 objr->refs.clear();
26 int ret = cls_cxx_getxattr(hctx, REFCOUNT_ATTR, &bl);
27 if (ret == -ENODATA) {
28 if (implicit_ref) {
29 objr->refs[wildcard_tag] = true;
30 }
31 return 0;
32 }
33 if (ret < 0)
34 return ret;
35
36 try {
11fdf7f2
TL
37 auto iter = bl.cbegin();
38 decode(*objr, iter);
f67539c2 39 } catch (ceph::buffer::error& err) {
7c673cae
FG
40 CLS_LOG(0, "ERROR: read_refcount(): failed to decode refcount entry\n");
41 return -EIO;
42 }
43
44 return 0;
45}
46
c07f9fc5 47static int set_refcount(cls_method_context_t hctx, const struct obj_refcount& objr)
7c673cae
FG
48{
49 bufferlist bl;
7c673cae 50
11fdf7f2 51 encode(objr, bl);
7c673cae
FG
52
53 int ret = cls_cxx_setxattr(hctx, REFCOUNT_ATTR, &bl);
54 if (ret < 0)
55 return ret;
56
57 return 0;
58}
59
60static int cls_rc_refcount_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
61{
11fdf7f2 62 auto in_iter = in->cbegin();
7c673cae
FG
63
64 cls_refcount_get_op op;
65 try {
11fdf7f2 66 decode(op, in_iter);
f67539c2 67 } catch (ceph::buffer::error& err) {
7c673cae
FG
68 CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
69 return -EINVAL;
70 }
71
72 obj_refcount objr;
73 int ret = read_refcount(hctx, op.implicit_ref, &objr);
74 if (ret < 0)
75 return ret;
76
77 CLS_LOG(10, "cls_rc_refcount_get() tag=%s\n", op.tag.c_str());
78
79 objr.refs[op.tag] = true;
80
c07f9fc5 81 ret = set_refcount(hctx, objr);
7c673cae
FG
82 if (ret < 0)
83 return ret;
84
85 return 0;
86}
87
88static int cls_rc_refcount_put(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
89{
11fdf7f2 90 auto in_iter = in->cbegin();
7c673cae
FG
91
92 cls_refcount_put_op op;
93 try {
11fdf7f2 94 decode(op, in_iter);
f67539c2 95 } catch (ceph::buffer::error& err) {
7c673cae
FG
96 CLS_LOG(1, "ERROR: cls_rc_refcount_put(): failed to decode entry\n");
97 return -EINVAL;
98 }
99
100 obj_refcount objr;
101 int ret = read_refcount(hctx, op.implicit_ref, &objr);
102 if (ret < 0)
103 return ret;
104
105 if (objr.refs.empty()) {// shouldn't happen!
106 CLS_LOG(0, "ERROR: cls_rc_refcount_put() was called without any references!\n");
107 return -EINVAL;
108 }
109
110 CLS_LOG(10, "cls_rc_refcount_put() tag=%s\n", op.tag.c_str());
111
112 bool found = false;
f67539c2 113 auto iter = objr.refs.find(op.tag);
7c673cae
FG
114 if (iter != objr.refs.end()) {
115 found = true;
116 } else if (op.implicit_ref) {
117 iter = objr.refs.find(wildcard_tag);
118 if (iter != objr.refs.end()) {
119 found = true;
120 }
121 }
122
c07f9fc5
FG
123 if (!found ||
124 objr.retired_refs.find(op.tag) != objr.retired_refs.end())
7c673cae
FG
125 return 0;
126
c07f9fc5 127 objr.retired_refs.insert(op.tag);
7c673cae
FG
128 objr.refs.erase(iter);
129
130 if (objr.refs.empty()) {
131 return cls_cxx_remove(hctx);
132 }
133
c07f9fc5 134 ret = set_refcount(hctx, objr);
7c673cae
FG
135 if (ret < 0)
136 return ret;
137
138 return 0;
139}
140
141static int cls_rc_refcount_set(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
142{
11fdf7f2 143 auto in_iter = in->cbegin();
7c673cae
FG
144
145 cls_refcount_set_op op;
146 try {
11fdf7f2 147 decode(op, in_iter);
f67539c2 148 } catch (ceph::buffer::error& err) {
7c673cae
FG
149 CLS_LOG(1, "ERROR: cls_refcount_set(): failed to decode entry\n");
150 return -EINVAL;
151 }
152
153 if (!op.refs.size()) {
154 return cls_cxx_remove(hctx);
155 }
156
157 obj_refcount objr;
f67539c2 158 for (auto iter = op.refs.begin(); iter != op.refs.end(); ++iter) {
7c673cae
FG
159 objr.refs[*iter] = true;
160 }
161
c07f9fc5 162 int ret = set_refcount(hctx, objr);
7c673cae
FG
163 if (ret < 0)
164 return ret;
165
166 return 0;
167}
168
169static int cls_rc_refcount_read(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
170{
11fdf7f2 171 auto in_iter = in->cbegin();
7c673cae
FG
172
173 cls_refcount_read_op op;
174 try {
11fdf7f2 175 decode(op, in_iter);
f67539c2 176 } catch (ceph::buffer::error& err) {
7c673cae
FG
177 CLS_LOG(1, "ERROR: cls_rc_refcount_read(): failed to decode entry\n");
178 return -EINVAL;
179 }
180
181 obj_refcount objr;
182
183 cls_refcount_read_ret read_ret;
184 int ret = read_refcount(hctx, op.implicit_ref, &objr);
185 if (ret < 0)
186 return ret;
187
f67539c2 188 for (auto iter = objr.refs.begin(); iter != objr.refs.end(); ++iter) {
7c673cae
FG
189 read_ret.refs.push_back(iter->first);
190 }
191
11fdf7f2 192 encode(read_ret, *out);
7c673cae
FG
193
194 return 0;
195}
196
197CLS_INIT(refcount)
198{
199 CLS_LOG(1, "Loaded refcount class!");
200
201 cls_handle_t h_class;
202 cls_method_handle_t h_refcount_get;
203 cls_method_handle_t h_refcount_put;
204 cls_method_handle_t h_refcount_set;
205 cls_method_handle_t h_refcount_read;
206
207 cls_register("refcount", &h_class);
208
209 /* refcount */
210 cls_register_cxx_method(h_class, "get", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_refcount_get, &h_refcount_get);
211 cls_register_cxx_method(h_class, "put", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_refcount_put, &h_refcount_put);
212 cls_register_cxx_method(h_class, "set", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_refcount_set, &h_refcount_set);
213 cls_register_cxx_method(h_class, "read", CLS_METHOD_RD, cls_rc_refcount_read, &h_refcount_read);
214
215 return;
216}
217