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
25 using ceph::bufferlist
;
28 using ceph::real_time
;
31 int cls_call(cls_method_context_t hctx
, const char *cls
, const char *method
,
32 char *indata
, int datalen
, char **outdata
, int *outdatalen
)
34 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
36 vector
<OSDOp
> nops(1);
40 op
.op
.op
= CEPH_OSD_OP_CALL
;
41 op
.op
.cls
.class_len
= strlen(cls
);
42 op
.op
.cls
.method_len
= strlen(method
);
43 op
.op
.cls
.indata_len
= datalen
;
44 op
.indata
.append(cls
, op
.op
.cls
.class_len
);
45 op
.indata
.append(method
, op
.op
.cls
.method_len
);
46 op
.indata
.append(indata
, datalen
);
47 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
51 *outdata
= (char *)malloc(op
.outdata
.length());
54 memcpy(*outdata
, op
.outdata
.c_str(), op
.outdata
.length());
55 *outdatalen
= op
.outdata
.length();
60 int cls_getxattr(cls_method_context_t hctx
, const char *name
,
61 char **outdata
, int *outdatalen
)
63 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
64 vector
<OSDOp
> nops(1);
68 op
.op
.op
= CEPH_OSD_OP_GETXATTR
;
69 op
.op
.xattr
.name_len
= strlen(name
);
70 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
71 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
75 *outdata
= (char *)malloc(op
.outdata
.length());
78 memcpy(*outdata
, op
.outdata
.c_str(), op
.outdata
.length());
79 *outdatalen
= op
.outdata
.length();
84 int cls_setxattr(cls_method_context_t hctx
, const char *name
,
85 const char *value
, int val_len
)
87 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
88 vector
<OSDOp
> nops(1);
92 op
.op
.op
= CEPH_OSD_OP_SETXATTR
;
93 op
.op
.xattr
.name_len
= strlen(name
);
94 op
.op
.xattr
.value_len
= val_len
;
95 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
96 op
.indata
.append(value
, val_len
);
97 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
102 int cls_read(cls_method_context_t hctx
, int ofs
, int len
,
103 char **outdata
, int *outdatalen
)
105 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
106 vector
<OSDOp
> ops(1);
107 ops
[0].op
.op
= CEPH_OSD_OP_SYNC_READ
;
108 ops
[0].op
.extent
.offset
= ofs
;
109 ops
[0].op
.extent
.length
= len
;
110 int r
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
114 *outdata
= (char *)malloc(ops
[0].outdata
.length());
117 memcpy(*outdata
, ops
[0].outdata
.c_str(), ops
[0].outdata
.length());
118 *outdatalen
= ops
[0].outdata
.length();
123 int cls_get_request_origin(cls_method_context_t hctx
, entity_inst_t
*origin
)
125 PrimaryLogPG::OpContext
**pctx
= static_cast<PrimaryLogPG::OpContext
**>(hctx
);
126 *origin
= (*pctx
)->op
->get_req()->get_orig_source_inst();
130 int cls_cxx_create(cls_method_context_t hctx
, bool exclusive
)
132 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
133 vector
<OSDOp
> ops(1);
134 ops
[0].op
.op
= CEPH_OSD_OP_CREATE
;
135 ops
[0].op
.flags
= (exclusive
? CEPH_OSD_OP_FLAG_EXCL
: 0);
136 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
139 int cls_cxx_remove(cls_method_context_t hctx
)
141 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
142 vector
<OSDOp
> ops(1);
143 ops
[0].op
.op
= CEPH_OSD_OP_DELETE
;
144 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
147 int cls_cxx_stat(cls_method_context_t hctx
, uint64_t *size
, time_t *mtime
)
149 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
150 vector
<OSDOp
> ops(1);
152 ops
[0].op
.op
= CEPH_OSD_OP_STAT
;
153 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
156 auto iter
= ops
[0].outdata
.cbegin();
162 } catch (ceph::buffer::error
& err
) {
172 int cls_cxx_stat2(cls_method_context_t hctx
, uint64_t *size
, ceph::real_time
*mtime
)
174 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
175 vector
<OSDOp
> ops(1);
177 ops
[0].op
.op
= CEPH_OSD_OP_STAT
;
178 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
181 auto iter
= ops
[0].outdata
.cbegin();
187 } catch (ceph::buffer::error
& err
) {
197 int cls_cxx_read2(cls_method_context_t hctx
, int ofs
, int len
,
198 bufferlist
*outbl
, uint32_t op_flags
)
200 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
201 vector
<OSDOp
> ops(1);
203 ops
[0].op
.op
= CEPH_OSD_OP_SYNC_READ
;
204 ops
[0].op
.extent
.offset
= ofs
;
205 ops
[0].op
.extent
.length
= len
;
206 ops
[0].op
.flags
= op_flags
;
207 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
210 *outbl
= std::move(ops
[0].outdata
);
211 return outbl
->length();
214 int cls_cxx_write2(cls_method_context_t hctx
, int ofs
, int len
,
215 bufferlist
*inbl
, uint32_t op_flags
)
217 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
218 vector
<OSDOp
> ops(1);
219 ops
[0].op
.op
= CEPH_OSD_OP_WRITE
;
220 ops
[0].op
.extent
.offset
= ofs
;
221 ops
[0].op
.extent
.length
= len
;
222 ops
[0].op
.flags
= op_flags
;
223 ops
[0].indata
= *inbl
;
224 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
227 int cls_cxx_write_full(cls_method_context_t hctx
, bufferlist
*inbl
)
229 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
230 vector
<OSDOp
> ops(1);
231 ops
[0].op
.op
= CEPH_OSD_OP_WRITEFULL
;
232 ops
[0].op
.extent
.offset
= 0;
233 ops
[0].op
.extent
.length
= inbl
->length();
234 ops
[0].indata
= *inbl
;
235 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
238 int cls_cxx_replace(cls_method_context_t hctx
, int ofs
, int len
, bufferlist
*inbl
)
240 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
241 vector
<OSDOp
> ops(2);
242 ops
[0].op
.op
= CEPH_OSD_OP_TRUNCATE
;
243 ops
[0].op
.extent
.offset
= 0;
244 ops
[0].op
.extent
.length
= 0;
245 ops
[1].op
.op
= CEPH_OSD_OP_WRITE
;
246 ops
[1].op
.extent
.offset
= ofs
;
247 ops
[1].op
.extent
.length
= len
;
248 ops
[1].indata
= *inbl
;
249 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
252 int cls_cxx_truncate(cls_method_context_t hctx
, int ofs
)
254 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
255 vector
<OSDOp
> ops(1);
256 ops
[0].op
.op
= CEPH_OSD_OP_TRUNCATE
;
257 ops
[0].op
.extent
.offset
= ofs
;
258 ops
[0].op
.extent
.length
= 0;
259 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
262 int cls_cxx_write_zero(cls_method_context_t hctx
, int ofs
, int len
)
264 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
265 vector
<OSDOp
> ops(1);
266 ops
[0].op
.op
= CEPH_OSD_OP_ZERO
;
267 ops
[0].op
.extent
.offset
= ofs
;
268 ops
[0].op
.extent
.length
= len
;
269 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
272 int cls_cxx_getxattr(cls_method_context_t hctx
, const char *name
,
275 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
276 vector
<OSDOp
> nops(1);
280 op
.op
.op
= CEPH_OSD_OP_GETXATTR
;
281 op
.op
.xattr
.name_len
= strlen(name
);
282 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
283 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
287 *outbl
= std::move(op
.outdata
);
288 return outbl
->length();
291 int cls_cxx_getxattrs(cls_method_context_t hctx
, map
<string
, bufferlist
> *attrset
)
293 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
294 vector
<OSDOp
> nops(1);
298 op
.op
.op
= CEPH_OSD_OP_GETXATTRS
;
299 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
303 auto iter
= op
.outdata
.cbegin();
305 decode(*attrset
, iter
);
306 } catch (ceph::buffer::error
& err
) {
312 int cls_cxx_setxattr(cls_method_context_t hctx
, const char *name
,
315 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
316 vector
<OSDOp
> nops(1);
320 op
.op
.op
= CEPH_OSD_OP_SETXATTR
;
321 op
.op
.xattr
.name_len
= strlen(name
);
322 op
.op
.xattr
.value_len
= inbl
->length();
323 op
.indata
.append(name
, op
.op
.xattr
.name_len
);
324 op
.indata
.append(*inbl
);
325 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
330 int cls_cxx_snap_revert(cls_method_context_t hctx
, snapid_t snapid
)
332 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
333 vector
<OSDOp
> ops(1);
334 ops
[0].op
.op
= CEPH_OSD_OP_ROLLBACK
;
335 ops
[0].op
.snap
.snapid
= snapid
;
336 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
339 int cls_cxx_map_get_all_vals(cls_method_context_t hctx
, map
<string
, bufferlist
>* vals
,
342 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
343 vector
<OSDOp
> ops(1);
348 string filter_prefix
;
349 uint64_t max
= (uint64_t)-1;
351 encode(start_after
, op
.indata
);
352 encode(max
, op
.indata
);
353 encode(filter_prefix
, op
.indata
);
355 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALS
;
357 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
361 auto iter
= op
.outdata
.cbegin();
365 } catch (ceph::buffer::error
& err
) {
371 int cls_cxx_map_get_keys(cls_method_context_t hctx
, const string
&start_obj
,
372 uint64_t max_to_get
, set
<string
> *keys
,
375 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
376 vector
<OSDOp
> ops(1);
380 encode(start_obj
, op
.indata
);
381 encode(max_to_get
, op
.indata
);
383 op
.op
.op
= CEPH_OSD_OP_OMAPGETKEYS
;
385 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
389 auto iter
= op
.outdata
.cbegin();
393 } catch (ceph::buffer::error
& err
) {
399 int cls_cxx_map_get_vals(cls_method_context_t hctx
, const string
&start_obj
,
400 const string
&filter_prefix
, uint64_t max_to_get
,
401 map
<string
, bufferlist
> *vals
, bool *more
)
403 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
404 vector
<OSDOp
> ops(1);
408 encode(start_obj
, op
.indata
);
409 encode(max_to_get
, op
.indata
);
410 encode(filter_prefix
, op
.indata
);
412 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALS
;
414 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
418 auto iter
= op
.outdata
.cbegin();
422 } catch (ceph::buffer::error
& err
) {
428 int cls_cxx_map_read_header(cls_method_context_t hctx
, bufferlist
*outbl
)
430 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
431 vector
<OSDOp
> ops(1);
434 op
.op
.op
= CEPH_OSD_OP_OMAPGETHEADER
;
435 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
439 *outbl
= std::move(op
.outdata
);
444 int cls_cxx_map_get_val(cls_method_context_t hctx
, const string
&key
,
447 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
448 vector
<OSDOp
> ops(1);
454 encode(k
, op
.indata
);
456 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALSBYKEYS
;
457 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
461 auto iter
= op
.outdata
.cbegin();
463 map
<string
, bufferlist
> m
;
466 map
<string
, bufferlist
>::iterator iter
= m
.begin();
470 *outbl
= iter
->second
;
471 } catch (ceph::buffer::error
& e
) {
477 int cls_cxx_map_get_vals_by_keys(cls_method_context_t hctx
,
478 const std::set
<std::string
> &keys
,
479 std::map
<std::string
, bufferlist
> *map
)
481 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
482 vector
<OSDOp
> ops(1);
486 encode(keys
, op
.indata
);
488 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALSBYKEYS
;
489 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
493 auto iter
= op
.outdata
.cbegin();
496 } catch (buffer::error
& e
) {
502 int cls_cxx_map_set_val(cls_method_context_t hctx
, const string
&key
,
505 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
506 vector
<OSDOp
> ops(1);
508 bufferlist
& update_bl
= op
.indata
;
509 map
<string
, bufferlist
> m
;
511 encode(m
, update_bl
);
513 op
.op
.op
= CEPH_OSD_OP_OMAPSETVALS
;
515 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
518 int cls_cxx_map_set_vals(cls_method_context_t hctx
,
519 const std::map
<string
, bufferlist
> *map
)
521 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
522 vector
<OSDOp
> ops(1);
524 bufferlist
& update_bl
= op
.indata
;
525 encode(*map
, update_bl
);
527 op
.op
.op
= CEPH_OSD_OP_OMAPSETVALS
;
529 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
532 int cls_cxx_map_clear(cls_method_context_t hctx
)
534 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
535 vector
<OSDOp
> ops(1);
538 op
.op
.op
= CEPH_OSD_OP_OMAPCLEAR
;
540 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
543 int cls_cxx_map_write_header(cls_method_context_t hctx
, bufferlist
*inbl
)
545 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
546 vector
<OSDOp
> ops(1);
548 op
.indata
= std::move(*inbl
);
550 op
.op
.op
= CEPH_OSD_OP_OMAPSETHEADER
;
552 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
555 int cls_cxx_map_remove_range(cls_method_context_t hctx
,
556 const std::string
& key_begin
,
557 const std::string
& key_end
)
559 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
560 vector
<OSDOp
> ops(1);
562 bufferlist
& update_bl
= op
.indata
;
564 ::encode(key_begin
, update_bl
);
565 ::encode(key_end
, update_bl
);
567 op
.op
.op
= CEPH_OSD_OP_OMAPRMKEYRANGE
;
569 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
572 int cls_cxx_map_remove_key(cls_method_context_t hctx
, const string
&key
)
574 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
575 vector
<OSDOp
> ops(1);
577 bufferlist
& update_bl
= op
.indata
;
581 encode(to_rm
, update_bl
);
583 op
.op
.op
= CEPH_OSD_OP_OMAPRMKEYS
;
585 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
588 int cls_cxx_list_watchers(cls_method_context_t hctx
,
589 obj_list_watch_response_t
*watchers
)
591 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
592 vector
<OSDOp
> nops(1);
596 op
.op
.op
= CEPH_OSD_OP_LIST_WATCHERS
;
597 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
601 auto iter
= op
.outdata
.cbegin();
603 decode(*watchers
, iter
);
604 } catch (ceph::buffer::error
& err
) {
610 uint64_t cls_current_version(cls_method_context_t hctx
)
612 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
614 return ctx
->pg
->get_last_user_version();
618 int cls_current_subop_num(cls_method_context_t hctx
)
620 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
622 return ctx
->processed_subop_count
;
625 uint64_t cls_get_features(cls_method_context_t hctx
)
627 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
628 return ctx
->pg
->get_osdmap()->get_up_osd_features();
631 uint64_t cls_get_client_features(cls_method_context_t hctx
)
633 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
634 return ctx
->op
->get_req()->get_connection()->get_features();
637 ceph_release_t
cls_get_required_osd_release(cls_method_context_t hctx
)
639 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
640 return ctx
->pg
->get_osdmap()->require_osd_release
;
643 ceph_release_t
cls_get_min_compatible_client(cls_method_context_t hctx
)
645 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
646 return ctx
->pg
->get_osdmap()->get_require_min_compat_client();
649 int cls_get_snapset_seq(cls_method_context_t hctx
, uint64_t *snap_seq
) {
650 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
651 if (!ctx
->new_obs
.exists
|| (ctx
->new_obs
.oi
.is_whiteout() &&
652 ctx
->obc
->ssc
->snapset
.clones
.empty())) {
655 *snap_seq
= ctx
->obc
->ssc
->snapset
.seq
;
659 int cls_cxx_chunk_write_and_set(cls_method_context_t hctx
, int ofs
, int len
,
660 bufferlist
*write_inbl
, uint32_t op_flags
,
661 bufferlist
*set_inbl
, int set_len
)
663 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
664 char cname
[] = "cas";
665 char method
[] = "chunk_set";
667 vector
<OSDOp
> ops(2);
668 ops
[0].op
.op
= CEPH_OSD_OP_WRITE
;
669 ops
[0].op
.extent
.offset
= ofs
;
670 ops
[0].op
.extent
.length
= len
;
671 ops
[0].op
.flags
= op_flags
;
672 ops
[0].indata
= *write_inbl
;
674 ops
[1].op
.op
= CEPH_OSD_OP_CALL
;
675 ops
[1].op
.cls
.class_len
= strlen(cname
);
676 ops
[1].op
.cls
.method_len
= strlen(method
);
677 ops
[1].op
.cls
.indata_len
= set_len
;
678 ops
[1].indata
.append(cname
, ops
[1].op
.cls
.class_len
);
679 ops
[1].indata
.append(method
, ops
[1].op
.cls
.method_len
);
680 ops
[1].indata
.append(*set_inbl
);
682 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
685 int cls_get_manifest_ref_count(cls_method_context_t hctx
, string fp_oid
)
687 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
688 return ctx
->pg
->get_manifest_ref_count(ctx
->obc
, fp_oid
);
691 uint64_t cls_get_osd_min_alloc_size(cls_method_context_t hctx
) {
692 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
694 return ctx
->pg
->get_min_alloc_size();
697 uint64_t cls_get_pool_stripe_width(cls_method_context_t hctx
)
699 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
701 return ctx
->pg
->get_pool().stripe_width
;