]> git.proxmox.com Git - ceph.git/blob - ceph/src/cls/cas/cls_cas.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / cls / cas / cls_cas.cc
1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <errno.h>
5
6 #include "objclass/objclass.h"
7 #include "cls_cas_ops.h"
8
9 #include "include/compat.h"
10 #include "osd/osd_types.h"
11
12 CLS_VER(1,0)
13 CLS_NAME(cas)
14
15 struct chunk_obj_refcount;
16
17 static int chunk_read_refcount(cls_method_context_t hctx, chunk_obj_refcount *objr)
18 {
19 bufferlist bl;
20 objr->refs.clear();
21 int ret = cls_cxx_getxattr(hctx, CHUNK_REFCOUNT_ATTR, &bl);
22 if (ret == -ENODATA) {
23 return 0;
24 }
25 if (ret < 0)
26 return ret;
27
28 try {
29 auto iter = bl.cbegin();
30 decode(*objr, iter);
31 } catch (buffer::error& err) {
32 CLS_LOG(0, "ERROR: chunk_read_refcount(): failed to decode refcount entry\n");
33 return -EIO;
34 }
35
36 return 0;
37 }
38
39 static int chunk_set_refcount(cls_method_context_t hctx, const struct chunk_obj_refcount& objr)
40 {
41 bufferlist bl;
42
43 encode(objr, bl);
44
45 int ret = cls_cxx_setxattr(hctx, CHUNK_REFCOUNT_ATTR, &bl);
46 if (ret < 0)
47 return ret;
48
49 return 0;
50 }
51
52 static int cls_rc_chunk_refcount_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
53 {
54 auto in_iter = in->cbegin();
55
56 cls_chunk_refcount_get_op op;
57 try {
58 decode(op, in_iter);
59 } catch (buffer::error& err) {
60 CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
61 return -EINVAL;
62 }
63
64 chunk_obj_refcount objr;
65 int ret = chunk_read_refcount(hctx, &objr);
66 if (ret < 0)
67 return ret;
68
69 CLS_LOG(10, "cls_rc_chunk_refcount_get() oid=%s\n", op.source.oid.name.c_str());
70
71 objr.refs.insert(op.source);
72
73 ret = chunk_set_refcount(hctx, objr);
74 if (ret < 0)
75 return ret;
76
77 return 0;
78 }
79
80 static int cls_rc_chunk_refcount_put(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
81 {
82 auto in_iter = in->cbegin();
83
84 cls_chunk_refcount_put_op op;
85 try {
86 decode(op, in_iter);
87 } catch (buffer::error& err) {
88 CLS_LOG(1, "ERROR: cls_rc_chunk_refcount_put(): failed to decode entry\n");
89 return -EINVAL;
90 }
91
92 chunk_obj_refcount objr;
93 int ret = chunk_read_refcount(hctx, &objr);
94 if (ret < 0)
95 return ret;
96
97 if (objr.refs.empty()) {// shouldn't happen!
98 CLS_LOG(0, "ERROR: cls_rc_chunk_refcount_put() was called without any references!\n");
99 return -EINVAL;
100 }
101
102 CLS_LOG(10, "cls_rc_chunk_refcount_put() oid=%s\n", op.source.oid.name.c_str());
103
104 bool found = false;
105 for (auto &p : objr.refs) {
106 if (p == op.source) {
107 found = true;
108 break;
109 }
110 }
111
112 if (!found) {
113 return 0;
114 }
115
116 auto p = objr.refs.find(op.source);
117 objr.refs.erase(p);
118
119 if (objr.refs.empty()) {
120 return cls_cxx_remove(hctx);
121 }
122
123 ret = chunk_set_refcount(hctx, objr);
124 if (ret < 0)
125 return ret;
126
127 return 0;
128 }
129
130 static int cls_rc_chunk_refcount_set(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
131 {
132 auto in_iter = in->cbegin();
133
134 cls_chunk_refcount_set_op op;
135 try {
136 decode(op, in_iter);
137 } catch (buffer::error& err) {
138 CLS_LOG(1, "ERROR: cls_chunk_refcount_set(): failed to decode entry\n");
139 return -EINVAL;
140 }
141
142 if (!op.refs.size()) {
143 return cls_cxx_remove(hctx);
144 }
145
146 chunk_obj_refcount objr;
147 objr.refs = op.refs;
148
149 int ret = chunk_set_refcount(hctx, objr);
150 if (ret < 0)
151 return ret;
152
153 return 0;
154 }
155
156 static int cls_rc_chunk_refcount_read(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
157 {
158 chunk_obj_refcount objr;
159
160 cls_chunk_refcount_read_ret read_ret;
161 int ret = chunk_read_refcount(hctx, &objr);
162 if (ret < 0)
163 return ret;
164
165 for (auto &p : objr.refs) {
166 read_ret.refs.insert(p);
167 }
168
169 encode(read_ret, *out);
170
171 return 0;
172 }
173
174 static int cls_rc_write_or_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
175 {
176 auto in_iter = in->cbegin();
177 hobject_t src_obj;
178 bufferlist indata, outdata;
179 ceph_osd_op op;
180 try {
181 decode (op, in_iter);
182 decode(src_obj, in_iter);
183 in_iter.copy(op.extent.length, indata);
184 }
185 catch (buffer::error& e) {
186 return -EINVAL;
187 }
188
189 CLS_LOG(10, " offset: %llu length: %llu \n",
190 static_cast<long long unsigned>(op.extent.offset),
191 static_cast<long long unsigned>(op.extent.length));
192 chunk_obj_refcount objr;
193 int ret = chunk_read_refcount(hctx, &objr);
194 if (ret == -ENOENT) {
195 objr.refs.insert(src_obj);
196 bufferlist set_bl;
197 encode(objr, set_bl);
198 ret = cls_cxx_chunk_write_and_set(hctx, op.extent.offset, op.extent.length, &indata, op.flags,
199 &set_bl, set_bl.length());
200 if (ret < 0)
201 return ret;
202
203 return 0;
204 }
205
206 objr.refs.insert(src_obj);
207 ret = chunk_set_refcount(hctx, objr);
208 if (ret < 0)
209 return ret;
210
211 return 0;
212 }
213
214
215 static int cls_rc_has_chunk(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
216 {
217 auto in_iter = in->cbegin();
218 string fp_oid;
219 bufferlist indata, outdata;
220 try {
221 decode (fp_oid, in_iter);
222 }
223 catch (buffer::error& e) {
224 return -EINVAL;
225 }
226 CLS_LOG(10, " fp_oid: %s \n", fp_oid.c_str());
227
228 bool ret = cls_has_chunk(hctx, fp_oid);
229 if (ret) {
230 return 0;
231 }
232 return -ENOENT;
233 }
234
235 CLS_INIT(cas)
236 {
237 CLS_LOG(1, "Loaded cas class!");
238
239 cls_handle_t h_class;
240 cls_method_handle_t h_cas_write_or_get;
241 cls_method_handle_t h_chunk_refcount_get;
242 cls_method_handle_t h_chunk_refcount_put;
243 cls_method_handle_t h_chunk_refcount_set;
244 cls_method_handle_t h_chunk_refcount_read;
245 cls_method_handle_t h_chunk_has_chunk;
246
247 cls_register("cas", &h_class);
248
249 /* chunk refcount */
250 cls_register_cxx_method(h_class, "chunk_get", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_chunk_refcount_get,
251 &h_chunk_refcount_get);
252 cls_register_cxx_method(h_class, "chunk_put", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_chunk_refcount_put,
253 &h_chunk_refcount_put);
254 cls_register_cxx_method(h_class, "chunk_set", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_chunk_refcount_set,
255 &h_chunk_refcount_set);
256 cls_register_cxx_method(h_class, "chunk_read", CLS_METHOD_RD, cls_rc_chunk_refcount_read,
257 &h_chunk_refcount_read);
258 cls_register_cxx_method(h_class, "cas_write_or_get", CLS_METHOD_RD | CLS_METHOD_WR, cls_rc_write_or_get,
259 &h_cas_write_or_get);
260 cls_register_cxx_method(h_class, "has_chunk", CLS_METHOD_RD, cls_rc_has_chunk,
261 &h_chunk_has_chunk);
262
263 return;
264 }
265