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