]> git.proxmox.com Git - ceph.git/blame - ceph/src/cls/cas/cls_cas.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / cls / cas / cls_cas.cc
CommitLineData
f67539c2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
11fdf7f2
TL
2// vim: ts=8 sw=2 smarttab
3
4#include <errno.h>
5
6#include "objclass/objclass.h"
7#include "cls_cas_ops.h"
f67539c2 8#include "cls_cas_internal.h"
11fdf7f2
TL
9
10#include "include/compat.h"
11#include "osd/osd_types.h"
12
f67539c2
TL
13using ceph::bufferlist;
14using ceph::decode;
15
11fdf7f2
TL
16CLS_VER(1,0)
17CLS_NAME(cas)
18
11fdf7f2 19
f67539c2
TL
20//
21// helpers
22//
23
24static int chunk_read_refcount(
25 cls_method_context_t hctx,
26 chunk_refs_t *objr)
11fdf7f2
TL
27{
28 bufferlist bl;
f67539c2 29 objr->clear();
11fdf7f2
TL
30 int ret = cls_cxx_getxattr(hctx, CHUNK_REFCOUNT_ATTR, &bl);
31 if (ret == -ENODATA) {
32 return 0;
33 }
34 if (ret < 0)
35 return ret;
36
37 try {
38 auto iter = bl.cbegin();
39 decode(*objr, iter);
f67539c2 40 } catch (ceph::buffer::error& err) {
11fdf7f2
TL
41 CLS_LOG(0, "ERROR: chunk_read_refcount(): failed to decode refcount entry\n");
42 return -EIO;
43 }
44
45 return 0;
46}
47
f67539c2
TL
48static int chunk_set_refcount(
49 cls_method_context_t hctx,
50 const struct chunk_refs_t& objr)
11fdf7f2
TL
51{
52 bufferlist bl;
53
54 encode(objr, bl);
55
56 int ret = cls_cxx_setxattr(hctx, CHUNK_REFCOUNT_ATTR, &bl);
57 if (ret < 0)
58 return ret;
59
60 return 0;
61}
62
f67539c2
TL
63
64//
65// methods
66//
67
68static int chunk_create_or_get_ref(cls_method_context_t hctx,
69 bufferlist *in, bufferlist *out)
11fdf7f2
TL
70{
71 auto in_iter = in->cbegin();
72
f67539c2 73 cls_cas_chunk_create_or_get_ref_op op;
11fdf7f2
TL
74 try {
75 decode(op, in_iter);
f67539c2
TL
76 } catch (ceph::buffer::error& err) {
77 CLS_LOG(1, "ERROR: failed to decode entry\n");
11fdf7f2
TL
78 return -EINVAL;
79 }
80
f67539c2 81 chunk_refs_t objr;
11fdf7f2 82 int ret = chunk_read_refcount(hctx, &objr);
f67539c2
TL
83 if (ret == -ENOENT) {
84 // new chunk; init refs
85 CLS_LOG(10, "create oid=%s\n",
86 op.source.oid.name.c_str());
87 ret = cls_cxx_write_full(hctx, &op.data);
88 if (ret < 0) {
89 return ret;
90 }
91 objr.get(op.source);
92 ret = chunk_set_refcount(hctx, objr);
93 if (ret < 0) {
94 return ret;
95 }
96 } else if (ret < 0) {
11fdf7f2 97 return ret;
f67539c2
TL
98 } else {
99 // existing chunk; inc ref
100 if (op.flags & cls_cas_chunk_create_or_get_ref_op::FLAG_VERIFY) {
101 bufferlist old;
102 cls_cxx_read(hctx, 0, 0, &old);
103 if (!old.contents_equal(op.data)) {
104 return -ENOMSG;
105 }
106 }
107 CLS_LOG(10, "inc ref oid=%s\n",
108 op.source.oid.name.c_str());
11fdf7f2 109
f67539c2 110 objr.get(op.source);
11fdf7f2 111
f67539c2
TL
112 ret = chunk_set_refcount(hctx, objr);
113 if (ret < 0) {
114 return ret;
115 }
116 }
11fdf7f2
TL
117 return 0;
118}
119
f67539c2
TL
120static int chunk_get_ref(cls_method_context_t hctx,
121 bufferlist *in, bufferlist *out)
11fdf7f2
TL
122{
123 auto in_iter = in->cbegin();
124
f67539c2 125 cls_cas_chunk_get_ref_op op;
11fdf7f2
TL
126 try {
127 decode(op, in_iter);
f67539c2
TL
128 } catch (ceph::buffer::error& err) {
129 CLS_LOG(1, "ERROR: failed to decode entry\n");
11fdf7f2
TL
130 return -EINVAL;
131 }
132
f67539c2 133 chunk_refs_t objr;
11fdf7f2 134 int ret = chunk_read_refcount(hctx, &objr);
f67539c2
TL
135 if (ret < 0) {
136 CLS_LOG(1, "ERROR: failed to read attr\n");
11fdf7f2 137 return ret;
11fdf7f2
TL
138 }
139
f67539c2
TL
140 // existing chunk; inc ref
141 CLS_LOG(10, "oid=%s\n", op.source.oid.name.c_str());
142
143 objr.get(op.source);
11fdf7f2
TL
144
145 ret = chunk_set_refcount(hctx, objr);
f67539c2 146 if (ret < 0) {
11fdf7f2 147 return ret;
f67539c2 148 }
11fdf7f2
TL
149 return 0;
150}
151
f67539c2
TL
152static int chunk_put_ref(cls_method_context_t hctx,
153 bufferlist *in, bufferlist *out)
11fdf7f2
TL
154{
155 auto in_iter = in->cbegin();
156
f67539c2 157 cls_cas_chunk_put_ref_op op;
11fdf7f2
TL
158 try {
159 decode(op, in_iter);
f67539c2
TL
160 } catch (ceph::buffer::error& err) {
161 CLS_LOG(1, "ERROR: failed to decode entry\n");
11fdf7f2
TL
162 return -EINVAL;
163 }
164
f67539c2 165 chunk_refs_t objr;
11fdf7f2
TL
166 int ret = chunk_read_refcount(hctx, &objr);
167 if (ret < 0)
168 return ret;
169
f67539c2
TL
170 if (!objr.put(op.source)) {
171 CLS_LOG(10, "oid=%s (no ref)\n", op.source.oid.name.c_str());
172 return -ENOLINK;
11fdf7f2
TL
173 }
174
f67539c2
TL
175 if (objr.empty()) {
176 CLS_LOG(10, "oid=%s (last ref)\n", op.source.oid.name.c_str());
177 return cls_cxx_remove(hctx);
11fdf7f2
TL
178 }
179
f67539c2 180 CLS_LOG(10, "oid=%s (dec)\n", op.source.oid.name.c_str());
11fdf7f2
TL
181 ret = chunk_set_refcount(hctx, objr);
182 if (ret < 0)
183 return ret;
184
185 return 0;
186}
187
f67539c2
TL
188static int references_chunk(cls_method_context_t hctx,
189 bufferlist *in, bufferlist *out)
11fdf7f2
TL
190{
191 auto in_iter = in->cbegin();
f67539c2 192 std::string fp_oid;
11fdf7f2
TL
193 bufferlist indata, outdata;
194 try {
195 decode (fp_oid, in_iter);
196 }
f67539c2 197 catch (ceph::buffer::error& e) {
11fdf7f2
TL
198 return -EINVAL;
199 }
f67539c2 200 CLS_LOG(10, "fp_oid: %s \n", fp_oid.c_str());
11fdf7f2 201
f67539c2 202 int ret = cls_get_manifest_ref_count(hctx, fp_oid);
11fdf7f2 203 if (ret) {
f67539c2 204 return ret;
11fdf7f2 205 }
f67539c2 206 return -ENOLINK;
11fdf7f2
TL
207}
208
209CLS_INIT(cas)
210{
211 CLS_LOG(1, "Loaded cas class!");
212
213 cls_handle_t h_class;
f67539c2
TL
214 cls_method_handle_t h_chunk_create_or_get_ref;
215 cls_method_handle_t h_chunk_get_ref;
216 cls_method_handle_t h_chunk_put_ref;
217 cls_method_handle_t h_references_chunk;
11fdf7f2
TL
218
219 cls_register("cas", &h_class);
220
f67539c2
TL
221 cls_register_cxx_method(h_class, "chunk_create_or_get_ref",
222 CLS_METHOD_RD | CLS_METHOD_WR,
223 chunk_create_or_get_ref,
224 &h_chunk_create_or_get_ref);
225 cls_register_cxx_method(h_class, "chunk_get_ref",
226 CLS_METHOD_RD | CLS_METHOD_WR,
227 chunk_get_ref,
228 &h_chunk_get_ref);
229 cls_register_cxx_method(h_class, "chunk_put_ref",
230 CLS_METHOD_RD | CLS_METHOD_WR,
231 chunk_put_ref,
232 &h_chunk_put_ref);
233 cls_register_cxx_method(h_class, "references_chunk", CLS_METHOD_RD,
234 references_chunk,
235 &h_references_chunk);
11fdf7f2
TL
236
237 return;
238}
239