1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "common/config.h"
5 #include "common/debug.h"
7 #include "objclass/objclass.h"
8 #include "osd/PrimaryLogPG.h"
9 #include "osd/osd_types.h"
11 #include "osd/ClassHandler.h"
13 #include "auth/Crypto.h"
14 #include "common/armor.h"
16 static constexpr int dout_subsys
= ceph_subsys_objclass
;
18 static ClassHandler
*ch
;
20 void cls_initialize(ClassHandler
*h
)
31 void *cls_alloc(size_t size
)
36 void cls_free(void *p
)
41 int cls_register(const char *name
, cls_handle_t
*handle
)
43 ClassHandler::ClassData
*cls
= ch
->register_class(name
);
44 *handle
= (cls_handle_t
)cls
;
48 int cls_unregister(cls_handle_t handle
)
50 ClassHandler::ClassData
*cls
= (ClassHandler::ClassData
*)handle
;
51 ch
->unregister_class(cls
);
55 int cls_register_method(cls_handle_t hclass
, const char *method
,
57 cls_method_call_t class_call
, cls_method_handle_t
*handle
)
59 if (!(flags
& (CLS_METHOD_RD
| CLS_METHOD_WR
)))
61 ClassHandler::ClassData
*cls
= (ClassHandler::ClassData
*)hclass
;
62 cls_method_handle_t hmethod
=(cls_method_handle_t
)cls
->register_method(method
, flags
, class_call
);
65 return (hmethod
!= NULL
);
68 int cls_register_cxx_method(cls_handle_t hclass
, const char *method
,
70 cls_method_cxx_call_t class_call
, cls_method_handle_t
*handle
)
72 ClassHandler::ClassData
*cls
= (ClassHandler::ClassData
*)hclass
;
73 cls_method_handle_t hmethod
= (cls_method_handle_t
)cls
->register_cxx_method(method
, flags
, class_call
);
76 return (hmethod
!= NULL
);
79 int cls_unregister_method(cls_method_handle_t handle
)
81 ClassHandler::ClassMethod
*method
= (ClassHandler::ClassMethod
*)handle
;
86 int cls_register_cxx_filter(cls_handle_t hclass
,
87 const std::string
&filter_name
,
88 cls_cxx_filter_factory_t fn
,
89 cls_filter_handle_t
*handle
)
91 ClassHandler::ClassData
*cls
= (ClassHandler::ClassData
*)hclass
;
92 cls_filter_handle_t hfilter
= (cls_filter_handle_t
)cls
->register_cxx_filter(filter_name
, fn
);
96 return (hfilter
!= NULL
);
99 void cls_unregister_filter(cls_filter_handle_t handle
)
101 ClassHandler::ClassFilter
*filter
= (ClassHandler::ClassFilter
*)handle
;
102 filter
->unregister();
105 int cls_call(cls_method_context_t hctx
, const char *cls
, const char *method
,
106 char *indata
, int datalen
,
107 char **outdata
, int *outdatalen
)
109 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
111 vector
<OSDOp
> nops(1);
115 op
.op
.op
= CEPH_OSD_OP_CALL
;
116 op
.op
.cls
.class_len
= strlen(cls
);
117 op
.op
.cls
.method_len
= strlen(method
);
118 op
.op
.cls
.indata_len
= datalen
;
119 op
.indata
.append(cls
, op
.op
.cls
.class_len
);
120 op
.indata
.append(method
, op
.op
.cls
.method_len
);
121 op
.indata
.append(indata
, datalen
);
122 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
126 *outdata
= (char *)malloc(op
.outdata
.length());
129 memcpy(*outdata
, op
.outdata
.c_str(), op
.outdata
.length());
130 *outdatalen
= op
.outdata
.length();
135 int cls_getxattr(cls_method_context_t hctx
, const char *name
,
136 char **outdata
, int *outdatalen
)
138 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
139 bufferlist name_data
;
140 vector
<OSDOp
> nops(1);
144 op
.op
.op
= CEPH_OSD_OP_GETXATTR
;
145 op
.indata
.append(name
);
146 op
.op
.xattr
.name_len
= strlen(name
);
147 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
151 *outdata
= (char *)malloc(op
.outdata
.length());
154 memcpy(*outdata
, op
.outdata
.c_str(), op
.outdata
.length());
155 *outdatalen
= op
.outdata
.length();
160 int cls_setxattr(cls_method_context_t hctx
, const char *name
,
161 const char *value
, int val_len
)
163 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
164 bufferlist name_data
;
165 vector
<OSDOp
> nops(1);
169 op
.op
.op
= CEPH_OSD_OP_SETXATTR
;
170 op
.indata
.append(name
);
171 op
.indata
.append(value
);
172 op
.op
.xattr
.name_len
= strlen(name
);
173 op
.op
.xattr
.value_len
= val_len
;
174 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
179 int cls_read(cls_method_context_t hctx
, int ofs
, int len
,
180 char **outdata
, int *outdatalen
)
182 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
183 vector
<OSDOp
> ops(1);
184 ops
[0].op
.op
= CEPH_OSD_OP_SYNC_READ
;
185 ops
[0].op
.extent
.offset
= ofs
;
186 ops
[0].op
.extent
.length
= len
;
187 int r
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
191 *outdata
= (char *)malloc(ops
[0].outdata
.length());
194 memcpy(*outdata
, ops
[0].outdata
.c_str(), ops
[0].outdata
.length());
195 *outdatalen
= ops
[0].outdata
.length();
200 int cls_get_request_origin(cls_method_context_t hctx
, entity_inst_t
*origin
)
202 PrimaryLogPG::OpContext
**pctx
= static_cast<PrimaryLogPG::OpContext
**>(hctx
);
203 *origin
= (*pctx
)->op
->get_req()->get_orig_source_inst();
207 int cls_cxx_create(cls_method_context_t hctx
, bool exclusive
)
209 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
210 vector
<OSDOp
> ops(1);
211 ops
[0].op
.op
= CEPH_OSD_OP_CREATE
;
212 ops
[0].op
.flags
= (exclusive
? CEPH_OSD_OP_FLAG_EXCL
: 0);
213 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
216 int cls_cxx_remove(cls_method_context_t hctx
)
218 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
219 vector
<OSDOp
> ops(1);
220 ops
[0].op
.op
= CEPH_OSD_OP_DELETE
;
221 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
224 int cls_cxx_stat(cls_method_context_t hctx
, uint64_t *size
, time_t *mtime
)
226 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
227 vector
<OSDOp
> ops(1);
229 ops
[0].op
.op
= CEPH_OSD_OP_STAT
;
230 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
233 bufferlist::iterator iter
= ops
[0].outdata
.begin();
239 } catch (buffer::error
& err
) {
249 int cls_cxx_stat2(cls_method_context_t hctx
, uint64_t *size
, ceph::real_time
*mtime
)
251 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
252 vector
<OSDOp
> ops(1);
254 ops
[0].op
.op
= CEPH_OSD_OP_STAT
;
255 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
258 bufferlist::iterator iter
= ops
[0].outdata
.begin();
264 } catch (buffer::error
& err
) {
274 int cls_cxx_read(cls_method_context_t hctx
, int ofs
, int len
, bufferlist
*outbl
)
276 return cls_cxx_read2(hctx
, ofs
, len
, outbl
, 0);
279 int cls_cxx_read2(cls_method_context_t hctx
, int ofs
, int len
,
280 bufferlist
*outbl
, uint32_t op_flags
)
282 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
283 vector
<OSDOp
> ops(1);
285 ops
[0].op
.op
= CEPH_OSD_OP_SYNC_READ
;
286 ops
[0].op
.extent
.offset
= ofs
;
287 ops
[0].op
.extent
.length
= len
;
288 ops
[0].op
.flags
= op_flags
;
289 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
292 outbl
->claim(ops
[0].outdata
);
293 return outbl
->length();
296 int cls_cxx_write(cls_method_context_t hctx
, int ofs
, int len
, bufferlist
*inbl
)
298 return cls_cxx_write2(hctx
, ofs
, len
, inbl
, 0);
301 int cls_cxx_write2(cls_method_context_t hctx
, int ofs
, int len
,
302 bufferlist
*inbl
, uint32_t op_flags
)
304 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
305 vector
<OSDOp
> ops(1);
306 ops
[0].op
.op
= CEPH_OSD_OP_WRITE
;
307 ops
[0].op
.extent
.offset
= ofs
;
308 ops
[0].op
.extent
.length
= len
;
309 ops
[0].op
.flags
= op_flags
;
310 ops
[0].indata
= *inbl
;
311 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
314 int cls_cxx_write_full(cls_method_context_t hctx
, bufferlist
*inbl
)
316 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
317 vector
<OSDOp
> ops(1);
318 ops
[0].op
.op
= CEPH_OSD_OP_WRITEFULL
;
319 ops
[0].op
.extent
.offset
= 0;
320 ops
[0].op
.extent
.length
= inbl
->length();
321 ops
[0].indata
= *inbl
;
322 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
325 int cls_cxx_replace(cls_method_context_t hctx
, int ofs
, int len
, bufferlist
*inbl
)
327 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
328 vector
<OSDOp
> ops(2);
329 ops
[0].op
.op
= CEPH_OSD_OP_TRUNCATE
;
330 ops
[0].op
.extent
.offset
= 0;
331 ops
[0].op
.extent
.length
= 0;
332 ops
[1].op
.op
= CEPH_OSD_OP_WRITE
;
333 ops
[1].op
.extent
.offset
= ofs
;
334 ops
[1].op
.extent
.length
= len
;
335 ops
[1].indata
= *inbl
;
336 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
339 int cls_cxx_getxattr(cls_method_context_t hctx
, const char *name
,
342 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
343 bufferlist name_data
;
344 vector
<OSDOp
> nops(1);
348 op
.op
.op
= CEPH_OSD_OP_GETXATTR
;
349 op
.indata
.append(name
);
350 op
.op
.xattr
.name_len
= strlen(name
);
351 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
355 outbl
->claim(op
.outdata
);
356 return outbl
->length();
359 int cls_cxx_getxattrs(cls_method_context_t hctx
, map
<string
, bufferlist
> *attrset
)
361 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
362 vector
<OSDOp
> nops(1);
366 op
.op
.op
= CEPH_OSD_OP_GETXATTRS
;
367 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
371 bufferlist::iterator iter
= op
.outdata
.begin();
373 ::decode(*attrset
, iter
);
374 } catch (buffer::error
& err
) {
380 int cls_cxx_setxattr(cls_method_context_t hctx
, const char *name
,
383 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
384 bufferlist name_data
;
385 vector
<OSDOp
> nops(1);
389 op
.op
.op
= CEPH_OSD_OP_SETXATTR
;
390 op
.indata
.append(name
);
391 op
.indata
.append(*inbl
);
392 op
.op
.xattr
.name_len
= strlen(name
);
393 op
.op
.xattr
.value_len
= inbl
->length();
394 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
399 int cls_cxx_snap_revert(cls_method_context_t hctx
, snapid_t snapid
)
401 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
402 vector
<OSDOp
> ops(1);
403 ops
[0].op
.op
= CEPH_OSD_OP_ROLLBACK
;
404 ops
[0].op
.snap
.snapid
= snapid
;
405 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
408 int cls_cxx_map_get_all_vals(cls_method_context_t hctx
, map
<string
, bufferlist
>* vals
,
411 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
412 vector
<OSDOp
> ops(1);
417 string filter_prefix
;
418 uint64_t max
= (uint64_t)-1;
420 ::encode(start_after
, op
.indata
);
421 ::encode(max
, op
.indata
);
422 ::encode(filter_prefix
, op
.indata
);
424 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALS
;
426 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
430 bufferlist::iterator iter
= op
.outdata
.begin();
432 ::decode(*vals
, iter
);
433 ::decode(*more
, iter
);
434 } catch (buffer::error
& err
) {
440 int cls_cxx_map_get_keys(cls_method_context_t hctx
, const string
&start_obj
,
441 uint64_t max_to_get
, set
<string
> *keys
,
444 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
445 vector
<OSDOp
> ops(1);
449 ::encode(start_obj
, op
.indata
);
450 ::encode(max_to_get
, op
.indata
);
452 op
.op
.op
= CEPH_OSD_OP_OMAPGETKEYS
;
454 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
458 bufferlist::iterator iter
= op
.outdata
.begin();
460 ::decode(*keys
, iter
);
461 ::decode(*more
, iter
);
462 } catch (buffer::error
& err
) {
468 int cls_cxx_map_get_vals(cls_method_context_t hctx
, const string
&start_obj
,
469 const string
&filter_prefix
, uint64_t max_to_get
,
470 map
<string
, bufferlist
> *vals
, bool *more
)
472 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
473 vector
<OSDOp
> ops(1);
477 ::encode(start_obj
, op
.indata
);
478 ::encode(max_to_get
, op
.indata
);
479 ::encode(filter_prefix
, op
.indata
);
481 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALS
;
483 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
487 bufferlist::iterator iter
= op
.outdata
.begin();
489 ::decode(*vals
, iter
);
490 ::decode(*more
, iter
);
491 } catch (buffer::error
& err
) {
497 int cls_cxx_map_read_header(cls_method_context_t hctx
, bufferlist
*outbl
)
499 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
500 vector
<OSDOp
> ops(1);
503 op
.op
.op
= CEPH_OSD_OP_OMAPGETHEADER
;
504 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
508 outbl
->claim(op
.outdata
);
513 int cls_cxx_map_get_val(cls_method_context_t hctx
, const string
&key
,
516 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
517 vector
<OSDOp
> ops(1);
523 ::encode(k
, op
.indata
);
525 op
.op
.op
= CEPH_OSD_OP_OMAPGETVALSBYKEYS
;
526 ret
= (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
530 bufferlist::iterator iter
= op
.outdata
.begin();
532 map
<string
, bufferlist
> m
;
535 map
<string
, bufferlist
>::iterator iter
= m
.begin();
539 *outbl
= iter
->second
;
540 } catch (buffer::error
& e
) {
546 int cls_cxx_map_set_val(cls_method_context_t hctx
, const string
&key
,
549 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
550 vector
<OSDOp
> ops(1);
552 bufferlist
& update_bl
= op
.indata
;
553 map
<string
, bufferlist
> m
;
555 ::encode(m
, update_bl
);
557 op
.op
.op
= CEPH_OSD_OP_OMAPSETVALS
;
559 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
562 int cls_cxx_map_set_vals(cls_method_context_t hctx
,
563 const std::map
<string
, bufferlist
> *map
)
565 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
566 vector
<OSDOp
> ops(1);
568 bufferlist
& update_bl
= op
.indata
;
569 ::encode(*map
, update_bl
);
571 op
.op
.op
= CEPH_OSD_OP_OMAPSETVALS
;
573 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
576 int cls_cxx_map_clear(cls_method_context_t hctx
)
578 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
579 vector
<OSDOp
> ops(1);
582 op
.op
.op
= CEPH_OSD_OP_OMAPCLEAR
;
584 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
587 int cls_cxx_map_write_header(cls_method_context_t hctx
, bufferlist
*inbl
)
589 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
590 vector
<OSDOp
> ops(1);
592 op
.indata
.claim(*inbl
);
594 op
.op
.op
= CEPH_OSD_OP_OMAPSETHEADER
;
596 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
599 int cls_cxx_map_remove_key(cls_method_context_t hctx
, const string
&key
)
601 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
602 vector
<OSDOp
> ops(1);
604 bufferlist
& update_bl
= op
.indata
;
608 ::encode(to_rm
, update_bl
);
610 op
.op
.op
= CEPH_OSD_OP_OMAPRMKEYS
;
612 return (*pctx
)->pg
->do_osd_ops(*pctx
, ops
);
615 int cls_cxx_list_watchers(cls_method_context_t hctx
,
616 obj_list_watch_response_t
*watchers
)
618 PrimaryLogPG::OpContext
**pctx
= (PrimaryLogPG::OpContext
**)hctx
;
619 vector
<OSDOp
> nops(1);
623 op
.op
.op
= CEPH_OSD_OP_LIST_WATCHERS
;
624 r
= (*pctx
)->pg
->do_osd_ops(*pctx
, nops
);
628 bufferlist::iterator iter
= op
.outdata
.begin();
630 ::decode(*watchers
, iter
);
631 } catch (buffer::error
& err
) {
637 int cls_gen_random_bytes(char *buf
, int size
)
639 return get_random_bytes(buf
, size
);
642 int cls_gen_rand_base64(char *dest
, int size
) /* size should be the required string size + 1 */
645 char tmp_dest
[size
+ 4]; /* so that there's space for the extra '=' characters, and some */
648 ret
= cls_gen_random_bytes(buf
, sizeof(buf
));
650 lgeneric_derr(ch
->cct
) << "cannot get random bytes: " << ret
<< dendl
;
654 ret
= ceph_armor(tmp_dest
, &tmp_dest
[sizeof(tmp_dest
)],
655 (const char *)buf
, ((const char *)buf
) + ((size
- 1) * 3 + 4 - 1) / 4);
657 lgeneric_derr(ch
->cct
) << "ceph_armor failed" << dendl
;
660 tmp_dest
[ret
] = '\0';
661 memcpy(dest
, tmp_dest
, size
);
667 uint64_t cls_current_version(cls_method_context_t hctx
)
669 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
671 return ctx
->pg
->info
.last_user_version
;
675 int cls_current_subop_num(cls_method_context_t hctx
)
677 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
679 return ctx
->current_osd_subop_num
;
682 uint64_t cls_get_features(cls_method_context_t hctx
)
684 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
685 return ctx
->pg
->get_osdmap()->get_up_osd_features();
688 uint64_t cls_get_client_features(cls_method_context_t hctx
)
690 PrimaryLogPG::OpContext
*ctx
= *(PrimaryLogPG::OpContext
**)hctx
;
691 return ctx
->op
->get_req()->get_connection()->get_features();
694 void cls_cxx_subop_version(cls_method_context_t hctx
, string
*s
)
700 uint64_t ver
= cls_current_version(hctx
);
701 int subop_num
= cls_current_subop_num(hctx
);
702 snprintf(buf
, sizeof(buf
), "%lld.%d", (long long)ver
, subop_num
);
707 int cls_log(int level
, const char *format
, ...)
713 va_start(ap
, format
);
714 int n
= vsnprintf(buf
, size
, format
, ap
);
716 #define MAX_SIZE 8196
717 if ((n
> -1 && n
< size
) || size
> MAX_SIZE
) {
718 ldout(ch
->cct
, level
) << buf
<< dendl
;