1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 #include "common/ceph_context.h"
6 #include "common/ceph_releases.h"
7 #include "common/config.h"
8 #include "common/debug.h"
10 #include "objclass/objclass.h"
11 #include "osd/PrimaryLogPG.h"
13 #include "osd/ClassHandler.h"
15 #include "auth/Crypto.h"
16 #include "common/armor.h"
18 #define dout_context ClassHandler::get_instance().cct
21 int cls_call(cls_method_context_t hctx
, const char *cls
, const char *method
,
22 char *indata
, int datalen
,
23 char **outdata
, int *outdatalen
)
25 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
27 vector
<OSDOp
> nops(1);
31 op
.op
.op
= CEPH_OSD_OP_CALL
;
32 op
.op
.cls
.class_len
= strlen(cls
);
33 op
.op
.cls
.method_len
= strlen(method
);
34 op
.op
.cls
.indata_len
= datalen
;
35 op
.indata
.append(cls
, op
.op
.cls
.class_len
);
36 op
.indata
.append(method
, op
.op
.cls
.method_len
);
37 op
.indata
.append(indata
, datalen
);
38 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
42 *outdata
= (char *)malloc(op
.outdata
.length());
45 memcpy(*outdata
, op
.outdata
.c_str(), op
.outdata
.length());
46 *outdatalen
= op
.outdata
.length();
51 int cls_getxattr(cls_method_context_t hctx
, const char *name
,
52 char **outdata
, int *outdatalen
)
54 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
55 vector
<OSDOp
> nops(1);
59 op
.op
.op
= CEPH_OSD_OP_GETXATTR
;
60 op
.op
.xattr
.name_len
= strlen(name
);
61 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
62 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
66 *outdata
= (char *)malloc(op
.outdata
.length());
69 memcpy(*outdata
, op
.outdata
.c_str(), op
.outdata
.length());
70 *outdatalen
= op
.outdata
.length();
75 int cls_setxattr(cls_method_context_t hctx
, const char *name
,
76 const char *value
, int val_len
)
78 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
79 vector
<OSDOp
> nops(1);
83 op
.op
.op
= CEPH_OSD_OP_SETXATTR
;
84 op
.op
.xattr
.name_len
= strlen(name
);
85 op
.op
.xattr
.value_len
= val_len
;
86 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
87 op
.indata
.append(value
, val_len
);
88 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
93 int cls_read(cls_method_context_t hctx
, int ofs
, int len
,
94 char **outdata
, int *outdatalen
)
96 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
98 ops
[0].op
.op
= CEPH_OSD_OP_SYNC_READ
;
99 ops
[0].op
.extent
.offset
= ofs
;
100 ops
[0].op
.extent
.length
= len
;
101 int r
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
105 *outdata
= (char *)malloc(ops
[0].outdata
.length());
108 memcpy(*outdata
, ops
[0].outdata
.c_str(), ops
[0].outdata
.length());
109 *outdatalen
= ops
[0].outdata
.length();
114 int cls_get_request_origin(cls_method_context_t hctx
, entity_inst_t
*origin
)
116 PrimaryLogPG::OpContext
**pctx
= static_cast<PrimaryLogPG::OpContext
**>(hctx
);
117 *origin
= (*pctx
)->op
->get_req()->get_orig_source_inst();
121 int cls_cxx_create(cls_method_context_t hctx
, bool exclusive
)
123 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
124 vector
<OSDOp
> ops(1);
125 ops
[0].op
.op
= CEPH_OSD_OP_CREATE
;
126 ops
[0].op
.flags
= (exclusive
? CEPH_OSD_OP_FLAG_EXCL
: 0);
127 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
130 int cls_cxx_remove(cls_method_context_t hctx
)
132 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
133 vector
<OSDOp
> ops(1);
134 ops
[0].op
.op
= CEPH_OSD_OP_DELETE
;
135 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
138 int cls_cxx_stat(cls_method_context_t hctx
, uint64_t *size
, time_t *mtime
)
140 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
141 vector
<OSDOp
> ops(1);
143 ops
[0].op
.op
= CEPH_OSD_OP_STAT
;
144 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
147 auto iter
= ops
[0].outdata
.cbegin();
153 } catch (buffer::error
& err
) {
163 int cls_cxx_stat2(cls_method_context_t hctx
, uint64_t *size
, ceph::real_time
*mtime
)
165 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
166 vector
<OSDOp
> ops(1);
168 ops
[0].op
.op
= CEPH_OSD_OP_STAT
;
169 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
172 auto iter
= ops
[0].outdata
.cbegin();
178 } catch (buffer::error
& err
) {
188 int cls_cxx_read2(cls_method_context_t hctx
, int ofs
, int len
,
189 bufferlist
*outbl
, uint32_t op_flags
)
191 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
192 vector
<OSDOp
> ops(1);
194 ops
[0].op
.op
= CEPH_OSD_OP_SYNC_READ
;
195 ops
[0].op
.extent
.offset
= ofs
;
196 ops
[0].op
.extent
.length
= len
;
197 ops
[0].op
.flags
= op_flags
;
198 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
201 outbl
->claim(ops
[0].outdata
);
202 return outbl
->length();
205 int cls_cxx_write2(cls_method_context_t hctx
, int ofs
, int len
,
206 bufferlist
*inbl
, uint32_t op_flags
)
208 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
209 vector
<OSDOp
> ops(1);
210 ops
[0].op
.op
= CEPH_OSD_OP_WRITE
;
211 ops
[0].op
.extent
.offset
= ofs
;
212 ops
[0].op
.extent
.length
= len
;
213 ops
[0].op
.flags
= op_flags
;
214 ops
[0].indata
= *inbl
;
215 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
218 int cls_cxx_write_full(cls_method_context_t hctx
, bufferlist
*inbl
)
220 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
221 vector
<OSDOp
> ops(1);
222 ops
[0].op
.op
= CEPH_OSD_OP_WRITEFULL
;
223 ops
[0].op
.extent
.offset
= 0;
224 ops
[0].op
.extent
.length
= inbl
->length();
225 ops
[0].indata
= *inbl
;
226 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
229 int cls_cxx_replace(cls_method_context_t hctx
, int ofs
, int len
, bufferlist
*inbl
)
231 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
232 vector
<OSDOp
> ops(2);
233 ops
[0].op
.op
= CEPH_OSD_OP_TRUNCATE
;
234 ops
[0].op
.extent
.offset
= 0;
235 ops
[0].op
.extent
.length
= 0;
236 ops
[1].op
.op
= CEPH_OSD_OP_WRITE
;
237 ops
[1].op
.extent
.offset
= ofs
;
238 ops
[1].op
.extent
.length
= len
;
239 ops
[1].indata
= *inbl
;
240 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
243 int cls_cxx_truncate(cls_method_context_t hctx
, int ofs
)
245 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
246 vector
<OSDOp
> ops(1);
247 ops
[0].op
.op
= CEPH_OSD_OP_TRUNCATE
;
248 ops
[0].op
.extent
.offset
= ofs
;
249 ops
[0].op
.extent
.length
= 0;
250 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
253 int cls_cxx_write_zero(cls_method_context_t hctx
, int ofs
, int len
)
255 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
256 vector
<OSDOp
> ops(1);
257 ops
[0].op
.op
= CEPH_OSD_OP_ZERO
;
258 ops
[0].op
.extent
.offset
= ofs
;
259 ops
[0].op
.extent
.length
= len
;
260 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
263 int cls_cxx_getxattr(cls_method_context_t hctx
, const char *name
,
266 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
267 vector
<OSDOp
> nops(1);
271 op
.op
.op
= CEPH_OSD_OP_GETXATTR
;
272 op
.op
.xattr
.name_len
= strlen(name
);
273 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
274 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
278 outbl
->claim(op
.outdata
);
279 return outbl
->length();
282 int cls_cxx_getxattrs(cls_method_context_t hctx
, map
<string
, bufferlist
> *attrset
)
284 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
285 vector
<OSDOp
> nops(1);
289 op
.op
.op
= CEPH_OSD_OP_GETXATTRS
;
290 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
294 auto iter
= op
.outdata
.cbegin();
296 decode(*attrset
, iter
);
297 } catch (buffer::error
& err
) {
303 int cls_cxx_setxattr(cls_method_context_t hctx
, const char *name
,
306 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
307 vector
<OSDOp
> nops(1);
311 op
.op
.op
= CEPH_OSD_OP_SETXATTR
;
312 op
.op
.xattr
.name_len
= strlen(name
);
313 op
.op
.xattr
.value_len
= inbl
->length();
314 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
315 op
.indata
.append(*inbl
);
316 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
321 int cls_cxx_snap_revert(cls_method_context_t hctx
, snapid_t snapid
)
323 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
324 vector
<OSDOp
> ops(1);
325 ops
[0].op
.op
= CEPH_OSD_OP_ROLLBACK
;
326 ops
[0].op
.snap
.snapid
= snapid
;
327 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
330 int cls_cxx_map_get_all_vals(cls_method_context_t hctx
, map
<string
, bufferlist
>* vals
,
333 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
334 vector
<OSDOp
> ops(1);
339 string filter_prefix
;
340 uint64_t max
= (uint64_t)-1;
342 encode(start_after
, op
.indata
);
343 encode(max
, op
.indata
);
344 encode(filter_prefix
, op
.indata
);
346 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALS
;
348 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
352 auto iter
= op
.outdata
.cbegin();
356 } catch (buffer::error
& err
) {
362 int cls_cxx_map_get_keys(cls_method_context_t hctx
, const string
&start_obj
,
363 uint64_t max_to_get
, set
<string
> *keys
,
366 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
367 vector
<OSDOp
> ops(1);
371 encode(start_obj
, op
.indata
);
372 encode(max_to_get
, op
.indata
);
374 op
.op
.op
= CEPH_OSD_OP_OMAPGETKEYS
;
376 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
380 auto iter
= op
.outdata
.cbegin();
384 } catch (buffer::error
& err
) {
390 int cls_cxx_map_get_vals(cls_method_context_t hctx
, const string
&start_obj
,
391 const string
&filter_prefix
, uint64_t max_to_get
,
392 map
<string
, bufferlist
> *vals
, bool *more
)
394 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
395 vector
<OSDOp
> ops(1);
399 encode(start_obj
, op
.indata
);
400 encode(max_to_get
, op
.indata
);
401 encode(filter_prefix
, op
.indata
);
403 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALS
;
405 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
409 auto iter
= op
.outdata
.cbegin();
413 } catch (buffer::error
& err
) {
419 int cls_cxx_map_read_header(cls_method_context_t hctx
, bufferlist
*outbl
)
421 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
422 vector
<OSDOp
> ops(1);
425 op
.op
.op
= CEPH_OSD_OP_OMAPGETHEADER
;
426 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
430 outbl
->claim(op
.outdata
);
435 int cls_cxx_map_get_val(cls_method_context_t hctx
, const string
&key
,
438 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
439 vector
<OSDOp
> ops(1);
445 encode(k
, op
.indata
);
447 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALSBYKEYS
;
448 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
452 auto iter
= op
.outdata
.cbegin();
454 map
<string
, bufferlist
> m
;
457 map
<string
, bufferlist
>::iterator iter
= m
.begin();
461 *outbl
= iter
->second
;
462 } catch (buffer::error
& e
) {
468 int cls_cxx_map_set_val(cls_method_context_t hctx
, const string
&key
,
471 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
472 vector
<OSDOp
> ops(1);
474 bufferlist
& update_bl
= op
.indata
;
475 map
<string
, bufferlist
> m
;
477 encode(m
, update_bl
);
479 op
.op
.op
= CEPH_OSD_OP_OMAPSETVALS
;
481 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
484 int cls_cxx_map_set_vals(cls_method_context_t hctx
,
485 const std::map
<string
, bufferlist
> *map
)
487 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
488 vector
<OSDOp
> ops(1);
490 bufferlist
& update_bl
= op
.indata
;
491 encode(*map
, update_bl
);
493 op
.op
.op
= CEPH_OSD_OP_OMAPSETVALS
;
495 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
498 int cls_cxx_map_clear(cls_method_context_t hctx
)
500 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
501 vector
<OSDOp
> ops(1);
504 op
.op
.op
= CEPH_OSD_OP_OMAPCLEAR
;
506 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
509 int cls_cxx_map_write_header(cls_method_context_t hctx
, bufferlist
*inbl
)
511 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
512 vector
<OSDOp
> ops(1);
514 op
.indata
.claim(*inbl
);
516 op
.op
.op
= CEPH_OSD_OP_OMAPSETHEADER
;
518 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
521 int cls_cxx_map_remove_range(cls_method_context_t hctx
,
522 const std::string
& key_begin
,
523 const std::string
& key_end
)
525 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
526 vector
<OSDOp
> ops(1);
528 bufferlist
& update_bl
= op
.indata
;
530 ::encode(key_begin
, update_bl
);
531 ::encode(key_end
, update_bl
);
533 op
.op
.op
= CEPH_OSD_OP_OMAPRMKEYRANGE
;
535 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
538 int cls_cxx_map_remove_key(cls_method_context_t hctx
, const string
&key
)
540 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
541 vector
<OSDOp
> ops(1);
543 bufferlist
& update_bl
= op
.indata
;
547 encode(to_rm
, update_bl
);
549 op
.op
.op
= CEPH_OSD_OP_OMAPRMKEYS
;
551 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
554 int cls_cxx_list_watchers(cls_method_context_t hctx
,
555 obj_list_watch_response_t
*watchers
)
557 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
558 vector
<OSDOp
> nops(1);
562 op
.op
.op
= CEPH_OSD_OP_LIST_WATCHERS
;
563 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
567 auto iter
= op
.outdata
.cbegin();
569 decode(*watchers
, iter
);
570 } catch (buffer::error
& err
) {
576 uint64_t cls_current_version(cls_method_context_t hctx
)
578 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
580 return ctx
->pg
->get_last_user_version();
584 int cls_current_subop_num(cls_method_context_t hctx
)
586 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
588 return ctx
->processed_subop_count
;
591 uint64_t cls_get_features(cls_method_context_t hctx
)
593 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
594 return ctx
->pg
->get_osdmap()->get_up_osd_features();
597 uint64_t cls_get_client_features(cls_method_context_t hctx
)
599 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
600 return ctx
->op
->get_req()->get_connection()->get_features();
603 ceph_release_t
cls_get_required_osd_release(cls_method_context_t hctx
)
605 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
606 return ctx
->pg
->get_osdmap()->require_osd_release
;
609 ceph_release_t
cls_get_min_compatible_client(cls_method_context_t hctx
)
611 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
612 return ctx
->pg
->get_osdmap()->get_require_min_compat_client();
615 int cls_get_snapset_seq(cls_method_context_t hctx
, uint64_t *snap_seq
) {
616 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
617 if (!ctx
->new_obs
.exists
|| (ctx
->new_obs
.oi
.is_whiteout() &&
618 ctx
->obc
->ssc
->snapset
.clones
.empty())) {
621 *snap_seq
= ctx
->obc
->ssc
->snapset
.seq
;
625 int cls_cxx_chunk_write_and_set(cls_method_context_t hctx
, int ofs
, int len
,
626 bufferlist
*write_inbl
, uint32_t op_flags
, bufferlist
*set_inbl
,
629 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
630 char cname
[] = "cas";
631 char method
[] = "chunk_set";
633 vector
<OSDOp
> ops(2);
634 ops
[0].op
.op
= CEPH_OSD_OP_WRITE
;
635 ops
[0].op
.extent
.offset
= ofs
;
636 ops
[0].op
.extent
.length
= len
;
637 ops
[0].op
.flags
= op_flags
;
638 ops
[0].indata
= *write_inbl
;
640 ops
[1].op
.op
= CEPH_OSD_OP_CALL
;
641 ops
[1].op
.cls
.class_len
= strlen(cname
);
642 ops
[1].op
.cls
.method_len
= strlen(method
);
643 ops
[1].op
.cls
.indata_len
= set_len
;
644 ops
[1].indata
.append(cname
, ops
[1].op
.cls
.class_len
);
645 ops
[1].indata
.append(method
, ops
[1].op
.cls
.method_len
);
646 ops
[1].indata
.append(*set_inbl
);
648 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
651 bool cls_has_chunk(cls_method_context_t hctx
, string fp_oid
)
653 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
654 if (!ctx
->obc
->obs
.oi
.has_manifest()) {
658 for (auto &p
: ctx
->obc
->obs
.oi
.manifest
.chunk_map
) {
659 if (p
.second
.oid
.oid
.name
== fp_oid
) {
667 uint64_t cls_get_osd_min_alloc_size(cls_method_context_t hctx
) {
668 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
670 return ctx
->pg
->get_min_alloc_size();