]>
Commit | Line | Data |
---|---|---|
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 |
11 | using std::string; |
12 | ||
13 | using ceph::bufferlist; | |
14 | ||
7c673cae FG |
15 | CLS_VER(1,0) |
16 | CLS_NAME(refcount) | |
17 | ||
7c673cae FG |
18 | #define REFCOUNT_ATTR "refcount" |
19 | ||
7c673cae FG |
20 | static string wildcard_tag; |
21 | ||
22 | static 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 | 47 | static 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 | ||
60 | static 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 | ||
88 | static 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 | ||
141 | static 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 | ||
169 | static 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 | ||
197 | CLS_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 |