1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14 #include "include/int_types.h"
15
16 #include <errno.h>
17
18 #include "common/deleter.h"
19 #include "common/dout.h"
20 #include "common/errno.h"
21 #include "common/TracepointProvider.h"
22 #include "include/Context.h"
23
24 #include "cls/rbd/cls_rbd_client.h"
25 #include "cls/rbd/cls_rbd_types.h"
26 #include "librbd/ImageCtx.h"
27 #include "librbd/ImageState.h"
28 #include "librbd/internal.h"
29 #include "librbd/Operations.h"
30 #include "librbd/api/Config.h"
31 #include "librbd/api/DiffIterate.h"
32 #include "librbd/api/Group.h"
33 #include "librbd/api/Image.h"
34 #include "librbd/api/Migration.h"
35 #include "librbd/api/Mirror.h"
36 #include "librbd/api/Namespace.h"
37 #include "librbd/api/Pool.h"
38 #include "librbd/api/PoolMetadata.h"
39 #include "librbd/api/Snapshot.h"
40 #include "librbd/api/Trash.h"
41 #include "librbd/io/AioCompletion.h"
42 #include "librbd/io/ImageRequestWQ.h"
43 #include "librbd/io/ReadResult.h"
44 #include <algorithm>
45 #include <string>
46 #include <vector>
47
48 #ifdef WITH_LTTNG
49 #define TRACEPOINT_DEFINE
50 #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
51 #include "tracing/librbd.h"
52 #undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
53 #undef TRACEPOINT_DEFINE
54 #else
55 #define tracepoint(...)
56 #endif
57
58 #define dout_subsys ceph_subsys_rbd
59 #undef dout_prefix
60 #define dout_prefix *_dout << "librbd: "
61
62 using std::string;
63 using std::vector;
64
65 using ceph::bufferlist;
66 using librados::snap_t;
67 using librados::IoCtx;
68
69 namespace {
70
71 TracepointProvider::Traits tracepoint_traits("librbd_tp.so", "rbd_tracing");
72
73 struct UserBufferDeleter : public deleter::impl {
74 CephContext* cct;
75 librbd::io::AioCompletion* aio_completion;
76
77 UserBufferDeleter(CephContext* cct, librbd::io::AioCompletion* aio_completion)
78 : deleter::impl(deleter()), cct(cct), aio_completion(aio_completion) {
79 aio_completion->block(cct);
80 }
81
82 ~UserBufferDeleter() override {
83 aio_completion->unblock(cct);
84 }
85 };
86
87 static auto create_write_raw(librbd::ImageCtx *ictx, const char *buf,
88 size_t len,
89 librbd::io::AioCompletion* aio_completion) {
90 if (ictx->disable_zero_copy || aio_completion == nullptr) {
91 // must copy the buffer if writeback/writearound cache is in-use (or using
92 // non-AIO)
93 return buffer::copy(buf, len);
94 }
95
96 // avoid copying memory for AIO operations, but possibly delay completions
97 // until the last reference to the user's memory has been released
98 return ceph::unique_leakable_ptr<ceph::buffer::raw>(
99 buffer::claim_buffer(
100 len, const_cast<char*>(buf),
101 deleter(new UserBufferDeleter(ictx->cct, aio_completion))));
102 }
103
104 CephContext* get_cct(IoCtx &io_ctx) {
105 return reinterpret_cast<CephContext*>(io_ctx.cct());
106 }
107
108 librbd::io::AioCompletion* get_aio_completion(librbd::RBD::AioCompletion *comp) {
109 return reinterpret_cast<librbd::io::AioCompletion *>(comp->pc);
110 }
111
112 struct C_AioCompletion : public Context {
113 CephContext *cct;
114 librbd::io::aio_type_t aio_type;
115 librbd::io::AioCompletion* aio_comp;
116
117 C_AioCompletion(librbd::ImageCtx *ictx, librbd::io::aio_type_t aio_type,
118 librbd::io::AioCompletion* aio_comp)
119 : cct(ictx->cct), aio_type(aio_type), aio_comp(aio_comp) {
120 aio_comp->init_time(ictx, aio_type);
121 aio_comp->get();
122 }
123 virtual ~C_AioCompletion() {
124 aio_comp->put();
125 }
126
127 void finish(int r) override {
128 ldout(cct, 20) << "C_AioComplete::finish: r=" << r << dendl;
129 if (r < 0) {
130 aio_comp->fail(r);
131 } else {
132 aio_comp->complete();
133 }
134 }
135 };
136
137 struct C_OpenComplete : public C_AioCompletion {
138 librbd::ImageCtx *ictx;
139 void **ictxp;
140 C_OpenComplete(librbd::ImageCtx *ictx, librbd::io::AioCompletion* comp,
141 void **ictxp)
142 : C_AioCompletion(ictx, librbd::io::AIO_TYPE_OPEN, comp),
143 ictx(ictx), ictxp(ictxp) {
144 }
145 void finish(int r) override {
146 ldout(ictx->cct, 20) << "C_OpenComplete::finish: r=" << r << dendl;
147 if (r < 0) {
148 *ictxp = nullptr;
149 } else {
150 *ictxp = ictx;
151 }
152
153 C_AioCompletion::finish(r);
154 }
155 };
156
157 struct C_OpenAfterCloseComplete : public Context {
158 librbd::ImageCtx *ictx;
159 librbd::io::AioCompletion* comp;
160 void **ictxp;
161 C_OpenAfterCloseComplete(librbd::ImageCtx *ictx,
162 librbd::io::AioCompletion* comp,
163 void **ictxp)
164 : ictx(ictx), comp(comp), ictxp(ictxp) {
165 }
166 void finish(int r) override {
167 ldout(ictx->cct, 20) << "C_OpenAfterCloseComplete::finish: r=" << r
168 << dendl;
169 delete reinterpret_cast<librbd::ImageCtx*>(*ictxp);
170 *ictxp = nullptr;
171
172 ictx->state->open(0, new C_OpenComplete(ictx, comp, ictxp));
173 }
174 };
175
176 struct C_UpdateWatchCB : public librbd::UpdateWatchCtx {
177 rbd_update_callback_t watch_cb;
178 void *arg;
179 uint64_t handle = 0;
180
181 C_UpdateWatchCB(rbd_update_callback_t watch_cb, void *arg) :
182 watch_cb(watch_cb), arg(arg) {
183 }
184 void handle_notify() override {
185 watch_cb(arg);
186 }
187 };
188
189 void group_image_status_cpp_to_c(const librbd::group_image_info_t &cpp_info,
190 rbd_group_image_info_t *c_info) {
191 c_info->name = strdup(cpp_info.name.c_str());
192 c_info->pool = cpp_info.pool;
193 c_info->state = cpp_info.state;
194 }
195
196 void group_info_cpp_to_c(const librbd::group_info_t &cpp_info,
197 rbd_group_info_t *c_info) {
198 c_info->name = strdup(cpp_info.name.c_str());
199 c_info->pool = cpp_info.pool;
200 }
201
202 void group_snap_info_cpp_to_c(const librbd::group_snap_info_t &cpp_info,
203 rbd_group_snap_info_t *c_info) {
204 c_info->name = strdup(cpp_info.name.c_str());
205 c_info->state = cpp_info.state;
206 }
207
208 void mirror_image_info_cpp_to_c(const librbd::mirror_image_info_t &cpp_info,
209 rbd_mirror_image_info_t *c_info) {
210 c_info->global_id = strdup(cpp_info.global_id.c_str());
211 c_info->state = cpp_info.state;
212 c_info->primary = cpp_info.primary;
213 }
214
215 void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_status,
216 rbd_mirror_image_status_t *c_status) {
217 c_status->name = strdup(cpp_status.name.c_str());
218 mirror_image_info_cpp_to_c(cpp_status.info, &c_status->info);
219 c_status->state = cpp_status.state;
220 c_status->description = strdup(cpp_status.description.c_str());
221 c_status->last_update = cpp_status.last_update;
222 c_status->up = cpp_status.up;
223 }
224
225 void trash_image_info_cpp_to_c(const librbd::trash_image_info_t &cpp_info,
226 rbd_trash_image_info_t *c_info) {
227 c_info->id = strdup(cpp_info.id.c_str());
228 c_info->name = strdup(cpp_info.name.c_str());
229 c_info->source = cpp_info.source;
230 c_info->deletion_time = cpp_info.deletion_time;
231 c_info->deferment_end_time = cpp_info.deferment_end_time;
232 }
233
234 void config_option_cpp_to_c(const librbd::config_option_t &cpp_option,
235 rbd_config_option_t *c_option) {
236 c_option->name = strdup(cpp_option.name.c_str());
237 c_option->value = strdup(cpp_option.value.c_str());
238 c_option->source = cpp_option.source;
239 }
240
241 void config_option_cleanup(rbd_config_option_t &option) {
242 free(option.name);
243 free(option.value);
244 }
245
246 struct C_MirrorImageGetInfo : public Context {
247 rbd_mirror_image_info_t *mirror_image_info;
248 Context *on_finish;
249
250 librbd::mirror_image_info_t cpp_mirror_image_info;
251
252 C_MirrorImageGetInfo(rbd_mirror_image_info_t *mirror_image_info,
253 Context *on_finish)
254 : mirror_image_info(mirror_image_info), on_finish(on_finish) {
255 }
256
257 void finish(int r) override {
258 if (r < 0) {
259 on_finish->complete(r);
260 return;
261 }
262
263 mirror_image_info_cpp_to_c(cpp_mirror_image_info, mirror_image_info);
264 on_finish->complete(0);
265 }
266 };
267
268 struct C_MirrorImageGetStatus : public Context {
269 rbd_mirror_image_status_t *mirror_image_status;
270 Context *on_finish;
271
272 librbd::mirror_image_status_t cpp_mirror_image_status;
273
274 C_MirrorImageGetStatus(rbd_mirror_image_status_t *mirror_image_status,
275 Context *on_finish)
276 : mirror_image_status(mirror_image_status), on_finish(on_finish) {
277 }
278
279 void finish(int r) override {
280 if (r < 0) {
281 on_finish->complete(r);
282 return;
283 }
284
285 mirror_image_status_cpp_to_c(cpp_mirror_image_status, mirror_image_status);
286 on_finish->complete(0);
287 }
288 };
289
290 } // anonymous namespace
291
292 namespace librbd {
293 ProgressContext::~ProgressContext()
294 {
295 }
296
297 class CProgressContext : public ProgressContext
298 {
299 public:
300 CProgressContext(librbd_progress_fn_t fn, void *data)
301 : m_fn(fn), m_data(data)
302 {
303 }
304 int update_progress(uint64_t offset, uint64_t src_size) override
305 {
306 return m_fn(offset, src_size, m_data);
307 }
308 private:
309 librbd_progress_fn_t m_fn;
310 void *m_data;
311 };
312
313 /*
314 * Pool stats
315 */
316 PoolStats::PoolStats() {
317 rbd_pool_stats_create(&pool_stats);
318 }
319
320 PoolStats::~PoolStats() {
321 rbd_pool_stats_destroy(pool_stats);
322 }
323
324 int PoolStats::add(rbd_pool_stat_option_t option, uint64_t* opt_val) {
325 return rbd_pool_stats_option_add_uint64(pool_stats, option, opt_val);
326 }
327
328 /*
329 * RBD
330 */
331 RBD::RBD()
332 {
333 }
334
335 RBD::~RBD()
336 {
337 }
338
339 void RBD::version(int *major, int *minor, int *extra)
340 {
341 rbd_version(major, minor, extra);
342 }
343
344 int RBD::open(IoCtx& io_ctx, Image& image, const char *name)
345 {
346 return open(io_ctx, image, name, NULL);
347 }
348
349 int RBD::open_by_id(IoCtx& io_ctx, Image& image, const char *id)
350 {
351 return open_by_id(io_ctx, image, id, nullptr);
352 }
353
354 int RBD::open(IoCtx& io_ctx, Image& image, const char *name,
355 const char *snap_name)
356 {
357 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
358 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
359 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
360
361 if (image.ctx != NULL) {
362 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
363 image.ctx = NULL;
364 }
365
366 int r = ictx->state->open(0);
367 if (r < 0) {
368 tracepoint(librbd, open_image_exit, r);
369 return r;
370 }
371
372 image.ctx = (image_ctx_t) ictx;
373 tracepoint(librbd, open_image_exit, 0);
374 return 0;
375 }
376
377 int RBD::open_by_id(IoCtx& io_ctx, Image& image, const char *id,
378 const char *snap_name)
379 {
380 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, false);
381 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
382 tracepoint(librbd, open_image_by_id_enter, ictx, ictx->id.c_str(),
383 ictx->snap_name.c_str(), ictx->read_only);
384
385 if (image.ctx != nullptr) {
386 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
387 image.ctx = nullptr;
388 }
389
390 int r = ictx->state->open(0);
391 if (r < 0) {
392 tracepoint(librbd, open_image_by_id_exit, r);
393 return r;
394 }
395
396 image.ctx = (image_ctx_t) ictx;
397 tracepoint(librbd, open_image_by_id_exit, 0);
398 return 0;
399 }
400
401 int RBD::aio_open(IoCtx& io_ctx, Image& image, const char *name,
402 const char *snap_name, RBD::AioCompletion *c)
403 {
404 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
405 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
406 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
407
408 if (image.ctx != NULL) {
409 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
410 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
411 } else {
412 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(c),
413 &image.ctx));
414 }
415 tracepoint(librbd, aio_open_image_exit, 0);
416 return 0;
417 }
418
419 int RBD::aio_open_by_id(IoCtx& io_ctx, Image& image, const char *id,
420 const char *snap_name, RBD::AioCompletion *c)
421 {
422 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, false);
423 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
424 tracepoint(librbd, aio_open_image_by_id_enter, ictx, ictx->id.c_str(),
425 ictx->snap_name.c_str(), ictx->read_only, c->pc);
426
427 if (image.ctx != nullptr) {
428 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
429 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
430 } else {
431 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(c),
432 &image.ctx));
433 }
434 tracepoint(librbd, aio_open_image_by_id_exit, 0);
435 return 0;
436 }
437
438 int RBD::open_read_only(IoCtx& io_ctx, Image& image, const char *name,
439 const char *snap_name)
440 {
441 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, true);
442 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
443 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
444
445 if (image.ctx != NULL) {
446 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
447 image.ctx = NULL;
448 }
449
450 int r = ictx->state->open(0);
451 if (r < 0) {
452 tracepoint(librbd, open_image_exit, r);
453 return r;
454 }
455
456 image.ctx = (image_ctx_t) ictx;
457 tracepoint(librbd, open_image_exit, 0);
458 return 0;
459 }
460
461 int RBD::open_by_id_read_only(IoCtx& io_ctx, Image& image, const char *id,
462 const char *snap_name)
463 {
464 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, true);
465 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
466 tracepoint(librbd, open_image_by_id_enter, ictx, ictx->id.c_str(),
467 ictx->snap_name.c_str(), ictx->read_only);
468
469 if (image.ctx != nullptr) {
470 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
471 image.ctx = nullptr;
472 }
473
474 int r = ictx->state->open(0);
475 if (r < 0) {
476 tracepoint(librbd, open_image_by_id_exit, r);
477 return r;
478 }
479
480 image.ctx = (image_ctx_t) ictx;
481 tracepoint(librbd, open_image_by_id_exit, 0);
482 return 0;
483 }
484
485 int RBD::aio_open_read_only(IoCtx& io_ctx, Image& image, const char *name,
486 const char *snap_name, RBD::AioCompletion *c)
487 {
488 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, true);
489 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
490 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
491
492 if (image.ctx != NULL) {
493 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
494 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
495 } else {
496 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(c),
497 &image.ctx));
498 }
499 tracepoint(librbd, aio_open_image_exit, 0);
500 return 0;
501 }
502
503 int RBD::aio_open_by_id_read_only(IoCtx& io_ctx, Image& image, const char *id,
504 const char *snap_name, RBD::AioCompletion *c)
505 {
506 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, true);
507 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
508 tracepoint(librbd, aio_open_image_by_id_enter, ictx, ictx->id.c_str(),
509 ictx->snap_name.c_str(), ictx->read_only, c->pc);
510
511 if (image.ctx != nullptr) {
512 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
513 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
514 } else {
515 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(c),
516 &image.ctx));
517 }
518 tracepoint(librbd, aio_open_image_by_id_exit, 0);
519 return 0;
520 }
521
522 int RBD::create(IoCtx& io_ctx, const char *name, uint64_t size, int *order)
523 {
524 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
525 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
526 int r = librbd::create(io_ctx, name, size, order);
527 tracepoint(librbd, create_exit, r, *order);
528 return r;
529 }
530
531 int RBD::create2(IoCtx& io_ctx, const char *name, uint64_t size,
532 uint64_t features, int *order)
533 {
534 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
535 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
536 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
537 tracepoint(librbd, create2_exit, r, *order);
538 return r;
539 }
540
541 int RBD::create3(IoCtx& io_ctx, const char *name, uint64_t size,
542 uint64_t features, int *order, uint64_t stripe_unit,
543 uint64_t stripe_count)
544 {
545 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
546 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
547 int r = librbd::create(io_ctx, name, size, false, features, order,
548 stripe_unit, stripe_count);
549 tracepoint(librbd, create3_exit, r, *order);
550 return r;
551 }
552
553 int RBD::create4(IoCtx& io_ctx, const char *name, uint64_t size,
554 ImageOptions& opts)
555 {
556 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
557 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts.opts);
558 int r = librbd::create(io_ctx, name, "", size, opts, "", "", false);
559 tracepoint(librbd, create4_exit, r);
560 return r;
561 }
562
563 int RBD::clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
564 IoCtx& c_ioctx, const char *c_name, uint64_t features,
565 int *c_order)
566 {
567 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
568 tracepoint(librbd, clone_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, features);
569 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
570 features, c_order, 0, 0);
571 tracepoint(librbd, clone_exit, r, *c_order);
572 return r;
573 }
574
575 int RBD::clone2(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
576 IoCtx& c_ioctx, const char *c_name, uint64_t features,
577 int *c_order, uint64_t stripe_unit, int stripe_count)
578 {
579 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
580 tracepoint(librbd, clone2_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, features, stripe_unit, stripe_count);
581 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
582 features, c_order, stripe_unit, stripe_count);
583 tracepoint(librbd, clone2_exit, r, *c_order);
584 return r;
585 }
586
587 int RBD::clone3(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
588 IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts)
589 {
590 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
591 tracepoint(librbd, clone3_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, c_opts.opts);
592 int r = librbd::clone(p_ioctx, nullptr, p_name, p_snap_name, c_ioctx,
593 nullptr, c_name, c_opts, "", "");
594 tracepoint(librbd, clone3_exit, r);
595 return r;
596 }
597
598 int RBD::remove(IoCtx& io_ctx, const char *name)
599 {
600 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
601 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
602 librbd::NoOpProgressContext prog_ctx;
603 int r = librbd::api::Image<>::remove(io_ctx, name, prog_ctx);
604 tracepoint(librbd, remove_exit, r);
605 return r;
606 }
607
608 int RBD::remove_with_progress(IoCtx& io_ctx, const char *name,
609 ProgressContext& pctx)
610 {
611 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
612 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
613 int r = librbd::api::Image<>::remove(io_ctx, name, pctx);
614 tracepoint(librbd, remove_exit, r);
615 return r;
616 }
617
618 int RBD::trash_move(IoCtx &io_ctx, const char *name, uint64_t delay) {
619 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
620 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
621 io_ctx.get_id(), name);
622 int r = librbd::api::Trash<>::move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER,
623 name, delay);
624 tracepoint(librbd, trash_move_exit, r);
625 return r;
626 }
627
628 int RBD::trash_get(IoCtx &io_ctx, const char *id, trash_image_info_t *info) {
629 return librbd::api::Trash<>::get(io_ctx, id, info);
630 }
631
632 int RBD::trash_list(IoCtx &io_ctx, vector<trash_image_info_t> &entries) {
633 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
634 tracepoint(librbd, trash_list_enter,
635 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
636 int r = librbd::api::Trash<>::list(io_ctx, entries, true);
637 #ifdef WITH_LTTNG
638 if (r >= 0) {
639 for (const auto& entry : entries) {
640 tracepoint(librbd, trash_list_entry, entry.id.c_str());
641 }
642 }
643 #endif
644 tracepoint(librbd, trash_list_exit, r, r);
645 return r;
646 }
647
648 int RBD::trash_remove(IoCtx &io_ctx, const char *image_id, bool force) {
649 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
650 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
651 io_ctx.get_id(), image_id, force);
652 librbd::NoOpProgressContext prog_ctx;
653 int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx);
654 tracepoint(librbd, trash_remove_exit, r);
655 return r;
656 }
657
658 int RBD::trash_remove_with_progress(IoCtx &io_ctx, const char *image_id,
659 bool force, ProgressContext &pctx) {
660 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
661 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
662 io_ctx.get_id(), image_id, force);
663 int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, pctx);
664 tracepoint(librbd, trash_remove_exit, r);
665 return r;
666 }
667
668 int RBD::trash_restore(IoCtx &io_ctx, const char *id, const char *name) {
669 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
670 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
671 io_ctx.get_id(), id, name);
672 int r = librbd::api::Trash<>::restore(
673 io_ctx, librbd::api::Trash<>::RESTORE_SOURCE_WHITELIST, id, name);
674 tracepoint(librbd, trash_undelete_exit, r);
675 return r;
676 }
677
678 int RBD::trash_purge(IoCtx &io_ctx, time_t expire_ts, float threshold) {
679 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
680 tracepoint(librbd, trash_purge_enter, io_ctx.get_pool_name().c_str(),
681 io_ctx.get_id(), expire_ts, threshold);
682 NoOpProgressContext nop_pctx;
683 int r = librbd::api::Trash<>::purge(io_ctx, expire_ts, threshold, nop_pctx);
684 tracepoint(librbd, trash_purge_exit, r);
685 return r;
686 }
687
688 int RBD::trash_purge_with_progress(IoCtx &io_ctx, time_t expire_ts,
689 float threshold, ProgressContext &pctx) {
690 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
691 tracepoint(librbd, trash_purge_enter, io_ctx.get_pool_name().c_str(),
692 io_ctx.get_id(), expire_ts, threshold);
693 int r = librbd::api::Trash<>::purge(io_ctx, expire_ts, threshold, pctx);
694 tracepoint(librbd, trash_purge_exit, r);
695 return r;
696 }
697
698 int RBD::namespace_create(IoCtx& io_ctx, const char *namespace_name) {
699 return librbd::api::Namespace<>::create(io_ctx, namespace_name);
700 }
701
702 int RBD::namespace_remove(IoCtx& io_ctx, const char *namespace_name) {
703 return librbd::api::Namespace<>::remove(io_ctx, namespace_name);
704 }
705
706 int RBD::namespace_list(IoCtx& io_ctx,
707 std::vector<std::string>* namespace_names) {
708 return librbd::api::Namespace<>::list(io_ctx, namespace_names);
709 }
710
711 int RBD::namespace_exists(IoCtx& io_ctx, const char *namespace_name,
712 bool *exists) {
713 return librbd::api::Namespace<>::exists(io_ctx, namespace_name, exists);
714 }
715
716 int RBD::pool_init(IoCtx& io_ctx, bool force) {
717 return librbd::api::Pool<>::init(io_ctx, force);
718 }
719
720 int RBD::pool_stats_get(IoCtx& io_ctx, PoolStats* stats) {
721 auto pool_stat_options =
722 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats->pool_stats);
723 return librbd::api::Pool<>::get_stats(io_ctx, pool_stat_options);
724 }
725
726 int RBD::list(IoCtx& io_ctx, vector<string>& names)
727 {
728 std::vector<image_spec_t> image_specs;
729 int r = list2(io_ctx, &image_specs);
730 if (r < 0) {
731 return r;
732 }
733
734 names.clear();
735 for (auto& it : image_specs) {
736 names.push_back(it.name);
737 }
738 return 0;
739 }
740
741 int RBD::list2(IoCtx& io_ctx, std::vector<image_spec_t> *images)
742 {
743 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
744 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(),
745 io_ctx.get_id());
746
747 int r = librbd::api::Image<>::list_images(io_ctx, images);
748 #ifdef WITH_LTTNG
749 if (r >= 0) {
750 for (auto& it : *images) {
751 tracepoint(librbd, list_entry, it.name.c_str());
752 }
753 }
754 #endif
755 tracepoint(librbd, list_exit, r, r);
756 return r;
757 }
758
759 int RBD::rename(IoCtx& src_io_ctx, const char *srcname, const char *destname)
760 {
761 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
762 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
763 int r = librbd::rename(src_io_ctx, srcname, destname);
764 tracepoint(librbd, rename_exit, r);
765 return r;
766 }
767
768 int RBD::migration_prepare(IoCtx& io_ctx, const char *image_name,
769 IoCtx& dest_io_ctx, const char *dest_image_name,
770 ImageOptions& opts)
771 {
772 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
773 tracepoint(librbd, migration_prepare_enter, io_ctx.get_pool_name().c_str(),
774 io_ctx.get_id(), image_name, dest_io_ctx.get_pool_name().c_str(),
775 dest_io_ctx.get_id(), dest_image_name, opts.opts);
776 int r = librbd::api::Migration<>::prepare(io_ctx, image_name, dest_io_ctx,
777 dest_image_name, opts);
778 tracepoint(librbd, migration_prepare_exit, r);
779 return r;
780 }
781
782 int RBD::migration_execute(IoCtx& io_ctx, const char *image_name)
783 {
784 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
785 tracepoint(librbd, migration_execute_enter, io_ctx.get_pool_name().c_str(),
786 io_ctx.get_id(), image_name);
787 librbd::NoOpProgressContext prog_ctx;
788 int r = librbd::api::Migration<>::execute(io_ctx, image_name, prog_ctx);
789 tracepoint(librbd, migration_execute_exit, r);
790 return r;
791 }
792
793 int RBD::migration_execute_with_progress(IoCtx& io_ctx,
794 const char *image_name,
795 librbd::ProgressContext &prog_ctx)
796 {
797 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
798 tracepoint(librbd, migration_execute_enter, io_ctx.get_pool_name().c_str(),
799 io_ctx.get_id(), image_name);
800 int r = librbd::api::Migration<>::execute(io_ctx, image_name, prog_ctx);
801 tracepoint(librbd, migration_execute_exit, r);
802 return r;
803 }
804
805 int RBD::migration_abort(IoCtx& io_ctx, const char *image_name)
806 {
807 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
808 tracepoint(librbd, migration_abort_enter, io_ctx.get_pool_name().c_str(),
809 io_ctx.get_id(), image_name);
810 librbd::NoOpProgressContext prog_ctx;
811 int r = librbd::api::Migration<>::abort(io_ctx, image_name, prog_ctx);
812 tracepoint(librbd, migration_abort_exit, r);
813 return r;
814 }
815
816 int RBD::migration_abort_with_progress(IoCtx& io_ctx, const char *image_name,
817 librbd::ProgressContext &prog_ctx)
818 {
819 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
820 tracepoint(librbd, migration_abort_enter, io_ctx.get_pool_name().c_str(),
821 io_ctx.get_id(), image_name);
822 int r = librbd::api::Migration<>::abort(io_ctx, image_name, prog_ctx);
823 tracepoint(librbd, migration_abort_exit, r);
824 return r;
825 }
826
827 int RBD::migration_commit(IoCtx& io_ctx, const char *image_name)
828 {
829 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
830 tracepoint(librbd, migration_commit_enter, io_ctx.get_pool_name().c_str(),
831 io_ctx.get_id(), image_name);
832 librbd::NoOpProgressContext prog_ctx;
833 int r = librbd::api::Migration<>::commit(io_ctx, image_name, prog_ctx);
834 tracepoint(librbd, migration_commit_exit, r);
835 return r;
836 }
837
838 int RBD::migration_commit_with_progress(IoCtx& io_ctx, const char *image_name,
839 librbd::ProgressContext &prog_ctx)
840 {
841 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
842 tracepoint(librbd, migration_commit_enter, io_ctx.get_pool_name().c_str(),
843 io_ctx.get_id(), image_name);
844 int r = librbd::api::Migration<>::commit(io_ctx, image_name, prog_ctx);
845 tracepoint(librbd, migration_commit_exit, r);
846 return r;
847 }
848
849 int RBD::migration_status(IoCtx& io_ctx, const char *image_name,
850 image_migration_status_t *status,
851 size_t status_size)
852 {
853 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
854 tracepoint(librbd, migration_status_enter, io_ctx.get_pool_name().c_str(),
855 io_ctx.get_id(), image_name);
856
857 if (status_size != sizeof(image_migration_status_t)) {
858 tracepoint(librbd, migration_status_exit, -ERANGE);
859 return -ERANGE;
860 }
861
862 int r = librbd::api::Migration<>::status(io_ctx, image_name, status);
863 tracepoint(librbd, migration_status_exit, r);
864 return r;
865 }
866
867 int RBD::mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) {
868 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
869 }
870
871 int RBD::mirror_site_name_get(librados::Rados& rados,
872 std::string* site_name) {
873 return librbd::api::Mirror<>::site_name_get(rados, site_name);
874 }
875
876 int RBD::mirror_site_name_set(librados::Rados& rados,
877 const std::string& site_name) {
878 return librbd::api::Mirror<>::site_name_set(rados, site_name);
879 }
880
881 int RBD::mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) {
882 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
883 }
884
885 int RBD::mirror_peer_bootstrap_create(IoCtx& io_ctx, std::string* token) {
886 return librbd::api::Mirror<>::peer_bootstrap_create(io_ctx, token);
887 }
888
889 int RBD::mirror_peer_bootstrap_import(IoCtx& io_ctx,
890 rbd_mirror_peer_direction_t direction,
891 const std::string& token) {
892 return librbd::api::Mirror<>::peer_bootstrap_import(io_ctx, direction,
893 token);
894 }
895
896 int RBD::mirror_peer_add(IoCtx& io_ctx, std::string *uuid,
897 const std::string &cluster_name,
898 const std::string &client_name) {
899 return librbd::api::Mirror<>::peer_add(io_ctx, uuid, cluster_name,
900 client_name);
901 }
902
903 int RBD::mirror_peer_remove(IoCtx& io_ctx, const std::string &uuid) {
904 return librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
905 }
906
907 int RBD::mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers) {
908 return librbd::api::Mirror<>::peer_list(io_ctx, peers);
909 }
910
911 int RBD::mirror_peer_set_client(IoCtx& io_ctx, const std::string &uuid,
912 const std::string &client_name) {
913 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
914 }
915
916 int RBD::mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
917 const std::string &cluster_name) {
918 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
919 }
920
921 int RBD::mirror_peer_get_attributes(
922 IoCtx& io_ctx, const std::string &uuid,
923 std::map<std::string, std::string> *key_vals) {
924 return librbd::api::Mirror<>::peer_get_attributes(io_ctx, uuid, key_vals);
925 }
926
927 int RBD::mirror_peer_set_attributes(
928 IoCtx& io_ctx, const std::string &uuid,
929 const std::map<std::string, std::string>& key_vals) {
930 return librbd::api::Mirror<>::peer_set_attributes(io_ctx, uuid, key_vals);
931 }
932
933 int RBD::mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
934 size_t max, std::map<std::string, mirror_image_status_t> *images) {
935 return librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
936 images);
937 }
938
939 int RBD::mirror_image_status_summary(IoCtx& io_ctx,
940 std::map<mirror_image_status_state_t, int> *states) {
941 return librbd::api::Mirror<>::image_status_summary(io_ctx, states);
942 }
943
944 int RBD::mirror_image_instance_id_list(IoCtx& io_ctx,
945 const std::string &start_id, size_t max,
946 std::map<std::string, std::string> *instance_ids) {
947 return librbd::api::Mirror<>::image_instance_id_list(io_ctx, start_id, max,
948 instance_ids);
949 }
950
951 int RBD::group_create(IoCtx& io_ctx, const char *group_name)
952 {
953 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
954 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
955 io_ctx.get_id(), group_name);
956 int r = librbd::api::Group<>::create(io_ctx, group_name);
957 tracepoint(librbd, group_create_exit, r);
958 return r;
959 }
960
961 int RBD::group_remove(IoCtx& io_ctx, const char *group_name)
962 {
963 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
964 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
965 io_ctx.get_id(), group_name);
966 int r = librbd::api::Group<>::remove(io_ctx, group_name);
967 tracepoint(librbd, group_remove_exit, r);
968 return r;
969 }
970
971 int RBD::group_list(IoCtx& io_ctx, vector<string> *names)
972 {
973 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
974 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
975 io_ctx.get_id());
976
977 int r = librbd::api::Group<>::list(io_ctx, names);
978 if (r >= 0) {
979 for (auto itr : *names) {
980 tracepoint(librbd, group_list_entry, itr.c_str());
981 }
982 }
983 tracepoint(librbd, group_list_exit, r);
984 return r;
985 }
986
987 int RBD::group_rename(IoCtx& io_ctx, const char *src_name,
988 const char *dest_name)
989 {
990 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
991 tracepoint(librbd, group_rename_enter, io_ctx.get_pool_name().c_str(),
992 io_ctx.get_id(), src_name, dest_name);
993 int r = librbd::api::Group<>::rename(io_ctx, src_name, dest_name);
994 tracepoint(librbd, group_rename_exit, r);
995 return r;
996 }
997
998 int RBD::group_image_add(IoCtx& group_ioctx, const char *group_name,
999 IoCtx& image_ioctx, const char *image_name)
1000 {
1001 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1002 tracepoint(librbd, group_image_add_enter,
1003 group_ioctx.get_pool_name().c_str(),
1004 group_ioctx.get_id(), group_name,
1005 image_ioctx.get_pool_name().c_str(),
1006 image_ioctx.get_id(), image_name);
1007 int r = librbd::api::Group<>::image_add(group_ioctx, group_name,
1008 image_ioctx, image_name);
1009 tracepoint(librbd, group_image_add_exit, r);
1010 return r;
1011 }
1012
1013 int RBD::group_image_remove(IoCtx& group_ioctx, const char *group_name,
1014 IoCtx& image_ioctx, const char *image_name)
1015 {
1016 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1017 tracepoint(librbd, group_image_remove_enter,
1018 group_ioctx.get_pool_name().c_str(),
1019 group_ioctx.get_id(), group_name,
1020 image_ioctx.get_pool_name().c_str(),
1021 image_ioctx.get_id(), image_name);
1022 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
1023 image_ioctx, image_name);
1024 tracepoint(librbd, group_image_remove_exit, r);
1025 return r;
1026 }
1027
1028 int RBD::group_image_remove_by_id(IoCtx& group_ioctx, const char *group_name,
1029 IoCtx& image_ioctx, const char *image_id)
1030 {
1031 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1032 tracepoint(librbd, group_image_remove_by_id_enter,
1033 group_ioctx.get_pool_name().c_str(),
1034 group_ioctx.get_id(), group_name,
1035 image_ioctx.get_pool_name().c_str(),
1036 image_ioctx.get_id(), image_id);
1037 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
1038 image_ioctx, image_id);
1039 tracepoint(librbd, group_image_remove_by_id_exit, r);
1040 return r;
1041 }
1042
1043 int RBD::group_image_list(IoCtx& group_ioctx, const char *group_name,
1044 std::vector<group_image_info_t> *images,
1045 size_t group_image_info_size)
1046 {
1047 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1048 tracepoint(librbd, group_image_list_enter,
1049 group_ioctx.get_pool_name().c_str(),
1050 group_ioctx.get_id(), group_name);
1051
1052 if (group_image_info_size != sizeof(group_image_info_t)) {
1053 tracepoint(librbd, group_image_list_exit, -ERANGE);
1054 return -ERANGE;
1055 }
1056
1057 int r = librbd::api::Group<>::image_list(group_ioctx, group_name, images);
1058 tracepoint(librbd, group_image_list_exit, r);
1059 return r;
1060 }
1061
1062 int RBD::group_snap_create(IoCtx& group_ioctx, const char *group_name,
1063 const char *snap_name) {
1064 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1065 tracepoint(librbd, group_snap_create_enter,
1066 group_ioctx.get_pool_name().c_str(),
1067 group_ioctx.get_id(), group_name, snap_name);
1068 int r = librbd::api::Group<>::snap_create(group_ioctx, group_name,
1069 snap_name);
1070 tracepoint(librbd, group_snap_create_exit, r);
1071 return r;
1072 }
1073
1074 int RBD::group_snap_remove(IoCtx& group_ioctx, const char *group_name,
1075 const char *snap_name) {
1076 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1077 tracepoint(librbd, group_snap_remove_enter,
1078 group_ioctx.get_pool_name().c_str(),
1079 group_ioctx.get_id(), group_name, snap_name);
1080 int r = librbd::api::Group<>::snap_remove(group_ioctx, group_name,
1081 snap_name);
1082 tracepoint(librbd, group_snap_remove_exit, r);
1083 return r;
1084 }
1085
1086 int RBD::group_snap_list(IoCtx& group_ioctx, const char *group_name,
1087 std::vector<group_snap_info_t> *snaps,
1088 size_t group_snap_info_size)
1089 {
1090 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1091 tracepoint(librbd, group_snap_list_enter,
1092 group_ioctx.get_pool_name().c_str(),
1093 group_ioctx.get_id(), group_name);
1094
1095 if (group_snap_info_size != sizeof(group_snap_info_t)) {
1096 tracepoint(librbd, group_snap_list_exit, -ERANGE);
1097 return -ERANGE;
1098 }
1099
1100 int r = librbd::api::Group<>::snap_list(group_ioctx, group_name, snaps);
1101 tracepoint(librbd, group_snap_list_exit, r);
1102 return r;
1103 }
1104
1105 int RBD::group_snap_rename(IoCtx& group_ioctx, const char *group_name,
1106 const char *old_snap_name,
1107 const char *new_snap_name)
1108 {
1109 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1110 tracepoint(librbd, group_snap_rename_enter,
1111 group_ioctx.get_pool_name().c_str(), group_ioctx.get_id(),
1112 group_name, old_snap_name, new_snap_name);
1113 int r = librbd::api::Group<>::snap_rename(group_ioctx, group_name,
1114 old_snap_name, new_snap_name);
1115 tracepoint(librbd, group_snap_list_exit, r);
1116 return r;
1117 }
1118
1119 int RBD::group_snap_rollback(IoCtx& group_ioctx, const char *group_name,
1120 const char *snap_name) {
1121 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1122 tracepoint(librbd, group_snap_rollback_enter,
1123 group_ioctx.get_pool_name().c_str(),
1124 group_ioctx.get_id(), group_name, snap_name);
1125 librbd::NoOpProgressContext prog_ctx;
1126 int r = librbd::api::Group<>::snap_rollback(group_ioctx, group_name,
1127 snap_name, prog_ctx);
1128 tracepoint(librbd, group_snap_rollback_exit, r);
1129 return r;
1130 }
1131
1132 int RBD::group_snap_rollback_with_progress(IoCtx& group_ioctx,
1133 const char *group_name,
1134 const char *snap_name,
1135 ProgressContext& prog_ctx) {
1136 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
1137 tracepoint(librbd, group_snap_rollback_enter,
1138 group_ioctx.get_pool_name().c_str(),
1139 group_ioctx.get_id(), group_name, snap_name);
1140 int r = librbd::api::Group<>::snap_rollback(group_ioctx, group_name,
1141 snap_name, prog_ctx);
1142 tracepoint(librbd, group_snap_rollback_exit, r);
1143 return r;
1144 }
1145
1146 int RBD::pool_metadata_get(IoCtx& ioctx, const std::string &key,
1147 std::string *value)
1148 {
1149 int r = librbd::api::PoolMetadata<>::get(ioctx, key, value);
1150 return r;
1151 }
1152
1153 int RBD::pool_metadata_set(IoCtx& ioctx, const std::string &key,
1154 const std::string &value)
1155 {
1156 int r = librbd::api::PoolMetadata<>::set(ioctx, key, value);
1157 return r;
1158 }
1159
1160 int RBD::pool_metadata_remove(IoCtx& ioctx, const std::string &key)
1161 {
1162 int r = librbd::api::PoolMetadata<>::remove(ioctx, key);
1163 return r;
1164 }
1165
1166 int RBD::pool_metadata_list(IoCtx& ioctx, const std::string &start,
1167 uint64_t max, map<string, bufferlist> *pairs)
1168 {
1169 int r = librbd::api::PoolMetadata<>::list(ioctx, start, max, pairs);
1170 return r;
1171 }
1172
1173 int RBD::config_list(IoCtx& io_ctx, std::vector<config_option_t> *options) {
1174 return librbd::api::Config<>::list(io_ctx, options);
1175 }
1176
1177 RBD::AioCompletion::AioCompletion(void *cb_arg, callback_t complete_cb)
1178 {
1179 auto aio_comp = librbd::io::AioCompletion::create(
1180 cb_arg, complete_cb, this);
1181 aio_comp->external_callback = true;
1182 pc = reinterpret_cast<void*>(aio_comp);
1183 }
1184
1185 bool RBD::AioCompletion::is_complete()
1186 {
1187 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
1188 return c->is_complete();
1189 }
1190
1191 int RBD::AioCompletion::wait_for_complete()
1192 {
1193 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
1194 return c->wait_for_complete();
1195 }
1196
1197 ssize_t RBD::AioCompletion::get_return_value()
1198 {
1199 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
1200 return c->get_return_value();
1201 }
1202
1203 void *RBD::AioCompletion::get_arg()
1204 {
1205 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
1206 return c->get_arg();
1207 }
1208
1209 void RBD::AioCompletion::release()
1210 {
1211 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
1212 c->release();
1213 delete this;
1214 }
1215
1216 /*
1217 ImageOptions
1218 */
1219
1220 ImageOptions::ImageOptions()
1221 {
1222 librbd::image_options_create(&opts);
1223 }
1224
1225 ImageOptions::ImageOptions(rbd_image_options_t opts_)
1226 {
1227 librbd::image_options_create_ref(&opts, opts_);
1228 }
1229
1230 ImageOptions::ImageOptions(const ImageOptions &imgopts)
1231 {
1232 librbd::image_options_copy(&opts, imgopts);
1233 }
1234
1235 ImageOptions::~ImageOptions()
1236 {
1237 librbd::image_options_destroy(opts);
1238 }
1239
1240 int ImageOptions::set(int optname, const std::string& optval)
1241 {
1242 return librbd::image_options_set(opts, optname, optval);
1243 }
1244
1245 int ImageOptions::set(int optname, uint64_t optval)
1246 {
1247 return librbd::image_options_set(opts, optname, optval);
1248 }
1249
1250 int ImageOptions::get(int optname, std::string* optval) const
1251 {
1252 return librbd::image_options_get(opts, optname, optval);
1253 }
1254
1255 int ImageOptions::get(int optname, uint64_t* optval) const
1256 {
1257 return librbd::image_options_get(opts, optname, optval);
1258 }
1259
1260 int ImageOptions::is_set(int optname, bool* is_set)
1261 {
1262 return librbd::image_options_is_set(opts, optname, is_set);
1263 }
1264
1265 int ImageOptions::unset(int optname)
1266 {
1267 return librbd::image_options_unset(opts, optname);
1268 }
1269
1270 void ImageOptions::clear()
1271 {
1272 librbd::image_options_clear(opts);
1273 }
1274
1275 bool ImageOptions::empty() const
1276 {
1277 return librbd::image_options_is_empty(opts);
1278 }
1279
1280 /*
1281 Image
1282 */
1283
1284 Image::Image() : ctx(NULL)
1285 {
1286 }
1287
1288 Image::~Image()
1289 {
1290 close();
1291 }
1292
1293 int Image::close()
1294 {
1295 int r = 0;
1296 if (ctx) {
1297 ImageCtx *ictx = (ImageCtx *)ctx;
1298 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1299
1300 r = ictx->state->close();
1301 ctx = NULL;
1302
1303 tracepoint(librbd, close_image_exit, r);
1304 }
1305 return r;
1306 }
1307
1308 int Image::aio_close(RBD::AioCompletion *c)
1309 {
1310 if (!ctx) {
1311 return -EINVAL;
1312 }
1313
1314 ImageCtx *ictx = (ImageCtx *)ctx;
1315 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), c->pc);
1316
1317 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
1318 get_aio_completion(c)));
1319 ctx = NULL;
1320
1321 tracepoint(librbd, aio_close_image_exit, 0);
1322 return 0;
1323 }
1324
1325 int Image::resize(uint64_t size)
1326 {
1327 ImageCtx *ictx = (ImageCtx *)ctx;
1328 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
1329 librbd::NoOpProgressContext prog_ctx;
1330 int r = ictx->operations->resize(size, true, prog_ctx);
1331 tracepoint(librbd, resize_exit, r);
1332 return r;
1333 }
1334
1335 int Image::resize2(uint64_t size, bool allow_shrink, librbd::ProgressContext& pctx)
1336 {
1337 ImageCtx *ictx = (ImageCtx *)ctx;
1338 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
1339 int r = ictx->operations->resize(size, allow_shrink, pctx);
1340 tracepoint(librbd, resize_exit, r);
1341 return r;
1342 }
1343
1344 int Image::resize_with_progress(uint64_t size, librbd::ProgressContext& pctx)
1345 {
1346 ImageCtx *ictx = (ImageCtx *)ctx;
1347 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
1348 int r = ictx->operations->resize(size, true, pctx);
1349 tracepoint(librbd, resize_exit, r);
1350 return r;
1351 }
1352
1353 int Image::stat(image_info_t& info, size_t infosize)
1354 {
1355 ImageCtx *ictx = (ImageCtx *)ctx;
1356 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1357 int r = librbd::info(ictx, info, infosize);
1358 tracepoint(librbd, stat_exit, r, &info);
1359 return r;
1360 }
1361
1362 int Image::old_format(uint8_t *old)
1363 {
1364 ImageCtx *ictx = (ImageCtx *)ctx;
1365 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1366 int r = librbd::get_old_format(ictx, old);
1367 tracepoint(librbd, get_old_format_exit, r, *old);
1368 return r;
1369 }
1370
1371 int Image::size(uint64_t *size)
1372 {
1373 ImageCtx *ictx = (ImageCtx *)ctx;
1374 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1375 int r = librbd::get_size(ictx, size);
1376 tracepoint(librbd, get_size_exit, r, *size);
1377 return r;
1378 }
1379
1380 int Image::get_group(group_info_t *group_info, size_t group_info_size)
1381 {
1382 ImageCtx *ictx = (ImageCtx *)ctx;
1383 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
1384
1385 if (group_info_size != sizeof(group_info_t)) {
1386 tracepoint(librbd, image_get_group_exit, -ERANGE);
1387 return -ERANGE;
1388 }
1389
1390 int r = librbd::api::Group<>::image_get_group(ictx, group_info);
1391 tracepoint(librbd, image_get_group_exit, r);
1392 return r;
1393 }
1394
1395 int Image::features(uint64_t *features)
1396 {
1397 ImageCtx *ictx = (ImageCtx *)ctx;
1398 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1399 int r = librbd::get_features(ictx, features);
1400 tracepoint(librbd, get_features_exit, r, *features);
1401 return r;
1402 }
1403
1404 int Image::update_features(uint64_t features, bool enabled)
1405 {
1406 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1407 tracepoint(librbd, update_features_enter, ictx, features, enabled);
1408 int r = ictx->operations->update_features(features, enabled);
1409 tracepoint(librbd, update_features_exit, r);
1410 return r;
1411 }
1412
1413 int Image::get_op_features(uint64_t *op_features)
1414 {
1415 ImageCtx *ictx = (ImageCtx *)ctx;
1416 return librbd::api::Image<>::get_op_features(ictx, op_features);
1417 }
1418
1419 uint64_t Image::get_stripe_unit() const
1420 {
1421 ImageCtx *ictx = (ImageCtx *)ctx;
1422 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1423 uint64_t stripe_unit = ictx->get_stripe_unit();
1424 tracepoint(librbd, get_stripe_unit_exit, 0, stripe_unit);
1425 return stripe_unit;
1426 }
1427
1428 uint64_t Image::get_stripe_count() const
1429 {
1430 ImageCtx *ictx = (ImageCtx *)ctx;
1431 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1432 uint64_t stripe_count = ictx->get_stripe_count();
1433 tracepoint(librbd, get_stripe_count_exit, 0, stripe_count);
1434 return stripe_count;
1435 }
1436
1437 int Image::get_create_timestamp(struct timespec *timestamp)
1438 {
1439 ImageCtx *ictx = (ImageCtx *)ctx;
1440 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
1441 ictx->read_only);
1442 utime_t time = ictx->get_create_timestamp();
1443 time.to_timespec(timestamp);
1444 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
1445 return 0;
1446 }
1447
1448 int Image::get_access_timestamp(struct timespec *timestamp)
1449 {
1450 ImageCtx *ictx = (ImageCtx *)ctx;
1451 tracepoint(librbd, get_access_timestamp_enter, ictx, ictx->name.c_str(),
1452 ictx->read_only);
1453 {
1454 std::shared_lock timestamp_locker{ictx->timestamp_lock};
1455 utime_t time = ictx->get_access_timestamp();
1456 time.to_timespec(timestamp);
1457 }
1458 tracepoint(librbd, get_access_timestamp_exit, 0, timestamp);
1459 return 0;
1460 }
1461
1462 int Image::get_modify_timestamp(struct timespec *timestamp)
1463 {
1464 ImageCtx *ictx = (ImageCtx *)ctx;
1465 tracepoint(librbd, get_modify_timestamp_enter, ictx, ictx->name.c_str(),
1466 ictx->read_only);
1467 {
1468 std::shared_lock timestamp_locker{ictx->timestamp_lock};
1469 utime_t time = ictx->get_modify_timestamp();
1470 time.to_timespec(timestamp);
1471 }
1472 tracepoint(librbd, get_modify_timestamp_exit, 0, timestamp);
1473 return 0;
1474 }
1475
1476 int Image::overlap(uint64_t *overlap)
1477 {
1478 ImageCtx *ictx = (ImageCtx *)ctx;
1479 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1480 int r = librbd::get_overlap(ictx, overlap);
1481 tracepoint(librbd, get_overlap_exit, r, *overlap);
1482 return r;
1483 }
1484
1485 int Image::get_name(std::string *name)
1486 {
1487 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1488 *name = ictx->name;
1489 return 0;
1490 }
1491
1492 int Image::get_id(std::string *id)
1493 {
1494 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1495 if (ictx->old_format) {
1496 return -EINVAL;
1497 }
1498 *id = ictx->id;
1499 return 0;
1500 }
1501
1502 std::string Image::get_block_name_prefix()
1503 {
1504 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1505 return ictx->object_prefix;
1506 }
1507
1508 int64_t Image::get_data_pool_id()
1509 {
1510 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1511 return librbd::api::Image<>::get_data_pool_id(ictx);
1512 }
1513
1514 int Image::parent_info(string *parent_pool_name, string *parent_name,
1515 string *parent_snap_name)
1516 {
1517 librbd::linked_image_spec_t parent_image;
1518 librbd::snap_spec_t parent_snap;
1519 int r = get_parent(&parent_image, &parent_snap);
1520 if (r >= 0) {
1521 if (parent_pool_name != nullptr) {
1522 *parent_pool_name = parent_image.pool_name;
1523 }
1524 if (parent_name != nullptr) {
1525 *parent_name = parent_image.image_name;
1526 }
1527 if (parent_snap_name != nullptr) {
1528 *parent_snap_name = parent_snap.name;
1529 }
1530 }
1531 return r;
1532 }
1533
1534 int Image::parent_info2(string *parent_pool_name, string *parent_name,
1535 string *parent_id, string *parent_snap_name)
1536 {
1537 librbd::linked_image_spec_t parent_image;
1538 librbd::snap_spec_t parent_snap;
1539 int r = get_parent(&parent_image, &parent_snap);
1540 if (r >= 0) {
1541 if (parent_pool_name != nullptr) {
1542 *parent_pool_name = parent_image.pool_name;
1543 }
1544 if (parent_name != nullptr) {
1545 *parent_name = parent_image.image_name;
1546 }
1547 if (parent_id != nullptr) {
1548 *parent_id = parent_image.image_id;
1549 }
1550 if (parent_snap_name != nullptr) {
1551 *parent_snap_name = parent_snap.name;
1552 }
1553 }
1554 return r;
1555 }
1556
1557 int Image::get_parent(linked_image_spec_t *parent_image,
1558 snap_spec_t *parent_snap)
1559 {
1560 auto ictx = reinterpret_cast<ImageCtx*>(ctx);
1561 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
1562 ictx->snap_name.c_str(), ictx->read_only);
1563
1564 int r = librbd::api::Image<>::get_parent(ictx, parent_image, parent_snap);
1565
1566 tracepoint(librbd, get_parent_info_exit, r,
1567 parent_image->pool_name.c_str(),
1568 parent_image->image_name.c_str(),
1569 parent_image->image_id.c_str(),
1570 parent_snap->name.c_str());
1571 return r;
1572 }
1573
1574 int Image::get_flags(uint64_t *flags)
1575 {
1576 ImageCtx *ictx = (ImageCtx *)ctx;
1577 tracepoint(librbd, get_flags_enter, ictx);
1578 int r = librbd::get_flags(ictx, flags);
1579 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
1580 return r;
1581 }
1582
1583 int Image::set_image_notification(int fd, int type)
1584 {
1585 ImageCtx *ictx = (ImageCtx *)ctx;
1586 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
1587 int r = librbd::set_image_notification(ictx, fd, type);
1588 tracepoint(librbd, set_image_notification_exit, ictx, r);
1589 return r;
1590 }
1591
1592 int Image::is_exclusive_lock_owner(bool *is_owner)
1593 {
1594 ImageCtx *ictx = (ImageCtx *)ctx;
1595 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
1596 int r = librbd::is_exclusive_lock_owner(ictx, is_owner);
1597 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
1598 return r;
1599 }
1600
1601 int Image::lock_acquire(rbd_lock_mode_t lock_mode)
1602 {
1603 ImageCtx *ictx = (ImageCtx *)ctx;
1604 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
1605 int r = librbd::lock_acquire(ictx, lock_mode);
1606 tracepoint(librbd, lock_acquire_exit, ictx, r);
1607 return r;
1608 }
1609
1610 int Image::lock_release()
1611 {
1612 ImageCtx *ictx = (ImageCtx *)ctx;
1613 tracepoint(librbd, lock_release_enter, ictx);
1614 int r = librbd::lock_release(ictx);
1615 tracepoint(librbd, lock_release_exit, ictx, r);
1616 return r;
1617 }
1618
1619 int Image::lock_get_owners(rbd_lock_mode_t *lock_mode,
1620 std::list<std::string> *lock_owners)
1621 {
1622 ImageCtx *ictx = (ImageCtx *)ctx;
1623 tracepoint(librbd, lock_get_owners_enter, ictx);
1624 int r = librbd::lock_get_owners(ictx, lock_mode, lock_owners);
1625 tracepoint(librbd, lock_get_owners_exit, ictx, r);
1626 return r;
1627 }
1628
1629 int Image::lock_break(rbd_lock_mode_t lock_mode,
1630 const std::string &lock_owner)
1631 {
1632 ImageCtx *ictx = (ImageCtx *)ctx;
1633 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner.c_str());
1634 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
1635 tracepoint(librbd, lock_break_exit, ictx, r);
1636 return r;
1637 }
1638
1639 int Image::rebuild_object_map(ProgressContext &prog_ctx)
1640 {
1641 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1642 return ictx->operations->rebuild_object_map(prog_ctx);
1643 }
1644
1645 int Image::check_object_map(ProgressContext &prog_ctx)
1646 {
1647 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1648 return ictx->operations->check_object_map(prog_ctx);
1649 }
1650
1651 int Image::copy(IoCtx& dest_io_ctx, const char *destname)
1652 {
1653 ImageCtx *ictx = (ImageCtx *)ctx;
1654 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
1655 ImageOptions opts;
1656 librbd::NoOpProgressContext prog_ctx;
1657 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1658 tracepoint(librbd, copy_exit, r);
1659 return r;
1660 }
1661
1662 int Image::copy2(Image& dest)
1663 {
1664 ImageCtx *srcctx = (ImageCtx *)ctx;
1665 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1666 tracepoint(librbd, copy2_enter, srcctx, srcctx->name.c_str(), srcctx->snap_name.c_str(), srcctx->read_only, destctx, destctx->name.c_str(), destctx->snap_name.c_str(), destctx->read_only);
1667 librbd::NoOpProgressContext prog_ctx;
1668 int r = librbd::copy(srcctx, destctx, prog_ctx, 0);
1669 tracepoint(librbd, copy2_exit, r);
1670 return r;
1671 }
1672
1673 int Image::copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts)
1674 {
1675 ImageCtx *ictx = (ImageCtx *)ctx;
1676 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
1677 librbd::NoOpProgressContext prog_ctx;
1678 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1679 tracepoint(librbd, copy3_exit, r);
1680 return r;
1681 }
1682
1683 int Image::copy4(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts, size_t sparse_size)
1684 {
1685 ImageCtx *ictx = (ImageCtx *)ctx;
1686 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts, sparse_size);
1687 librbd::NoOpProgressContext prog_ctx;
1688 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, sparse_size);
1689 tracepoint(librbd, copy4_exit, r);
1690 return r;
1691 }
1692
1693 int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
1694 librbd::ProgressContext &pctx)
1695 {
1696 ImageCtx *ictx = (ImageCtx *)ctx;
1697 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
1698 ImageOptions opts;
1699 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1700 tracepoint(librbd, copy_exit, r);
1701 return r;
1702 }
1703
1704 int Image::copy_with_progress2(Image& dest, librbd::ProgressContext &pctx)
1705 {
1706 ImageCtx *srcctx = (ImageCtx *)ctx;
1707 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1708 tracepoint(librbd, copy2_enter, srcctx, srcctx->name.c_str(), srcctx->snap_name.c_str(), srcctx->read_only, destctx, destctx->name.c_str(), destctx->snap_name.c_str(), destctx->read_only);
1709 int r = librbd::copy(srcctx, destctx, pctx, 0);
1710 tracepoint(librbd, copy2_exit, r);
1711 return r;
1712 }
1713
1714 int Image::copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
1715 ImageOptions& opts,
1716 librbd::ProgressContext &pctx)
1717 {
1718 ImageCtx *ictx = (ImageCtx *)ctx;
1719 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
1720 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1721 tracepoint(librbd, copy3_exit, r);
1722 return r;
1723 }
1724
1725 int Image::copy_with_progress4(IoCtx& dest_io_ctx, const char *destname,
1726 ImageOptions& opts,
1727 librbd::ProgressContext &pctx,
1728 size_t sparse_size)
1729 {
1730 ImageCtx *ictx = (ImageCtx *)ctx;
1731 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts, sparse_size);
1732 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, sparse_size);
1733 tracepoint(librbd, copy4_exit, r);
1734 return r;
1735 }
1736
1737 int Image::deep_copy(IoCtx& dest_io_ctx, const char *destname,
1738 ImageOptions& opts)
1739 {
1740 ImageCtx *ictx = (ImageCtx *)ctx;
1741 tracepoint(librbd, deep_copy_enter, ictx, ictx->name.c_str(),
1742 ictx->snap_name.c_str(), ictx->read_only,
1743 dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(),
1744 destname, opts.opts);
1745 librbd::NoOpProgressContext prog_ctx;
1746 int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
1747 prog_ctx);
1748 tracepoint(librbd, deep_copy_exit, r);
1749 return r;
1750 }
1751
1752 int Image::deep_copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
1753 ImageOptions& opts,
1754 librbd::ProgressContext &prog_ctx)
1755 {
1756 ImageCtx *ictx = (ImageCtx *)ctx;
1757 tracepoint(librbd, deep_copy_enter, ictx, ictx->name.c_str(),
1758 ictx->snap_name.c_str(), ictx->read_only,
1759 dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(),
1760 destname, opts.opts);
1761 int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
1762 prog_ctx);
1763 tracepoint(librbd, deep_copy_exit, r);
1764 return r;
1765 }
1766
1767 int Image::flatten()
1768 {
1769 ImageCtx *ictx = (ImageCtx *)ctx;
1770 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1771 librbd::NoOpProgressContext prog_ctx;
1772 int r = ictx->operations->flatten(prog_ctx);
1773 tracepoint(librbd, flatten_exit, r);
1774 return r;
1775 }
1776
1777 int Image::flatten_with_progress(librbd::ProgressContext& prog_ctx)
1778 {
1779 ImageCtx *ictx = (ImageCtx *)ctx;
1780 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1781 int r = ictx->operations->flatten(prog_ctx);
1782 tracepoint(librbd, flatten_exit, r);
1783 return r;
1784 }
1785
1786 int Image::sparsify(size_t sparse_size)
1787 {
1788 ImageCtx *ictx = (ImageCtx *)ctx;
1789 tracepoint(librbd, sparsify_enter, ictx, ictx->name.c_str(), sparse_size,
1790 ictx->id.c_str());
1791 librbd::NoOpProgressContext prog_ctx;
1792 int r = ictx->operations->sparsify(sparse_size, prog_ctx);
1793 tracepoint(librbd, sparsify_exit, r);
1794 return r;
1795 }
1796
1797 int Image::sparsify_with_progress(size_t sparse_size,
1798 librbd::ProgressContext& prog_ctx)
1799 {
1800 ImageCtx *ictx = (ImageCtx *)ctx;
1801 tracepoint(librbd, sparsify_enter, ictx, ictx->name.c_str(), sparse_size,
1802 ictx->id.c_str());
1803 int r = ictx->operations->sparsify(sparse_size, prog_ctx);
1804 tracepoint(librbd, sparsify_exit, r);
1805 return r;
1806 }
1807
1808 int Image::list_children(set<pair<string, string> > *children)
1809 {
1810 std::vector<linked_image_spec_t> images;
1811 int r = list_children3(&images);
1812 if (r < 0) {
1813 return r;
1814 }
1815
1816 for (auto& image : images) {
1817 if (!image.trash) {
1818 children->insert({image.pool_name, image.image_name});
1819 }
1820 }
1821 return 0;
1822 }
1823
1824 int Image::list_children2(vector<librbd::child_info_t> *children)
1825 {
1826 std::vector<linked_image_spec_t> images;
1827 int r = list_children3(&images);
1828 if (r < 0) {
1829 return r;
1830 }
1831
1832 for (auto& image : images) {
1833 children->push_back({
1834 .pool_name = image.pool_name,
1835 .image_name = image.image_name,
1836 .image_id = image.image_id,
1837 .trash = image.trash});
1838 }
1839
1840 return 0;
1841 }
1842
1843 int Image::list_children3(std::vector<linked_image_spec_t> *images)
1844 {
1845 auto ictx = reinterpret_cast<ImageCtx*>(ctx);
1846 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
1847 ictx->snap_name.c_str(), ictx->read_only);
1848
1849 int r = librbd::api::Image<>::list_children(ictx, images);
1850 #ifdef WITH_LTTNG
1851 if (r >= 0) {
1852 for (auto& it : *images) {
1853 tracepoint(librbd, list_children_entry, it.pool_name.c_str(),
1854 it.image_name.c_str());
1855 }
1856 }
1857 #endif
1858 tracepoint(librbd, list_children_exit, r);
1859 return r;
1860 }
1861
1862 int Image::list_descendants(std::vector<linked_image_spec_t> *images)
1863 {
1864 auto ictx = reinterpret_cast<ImageCtx*>(ctx);
1865
1866 images->clear();
1867 int r = librbd::api::Image<>::list_descendants(ictx, {}, images);
1868 return r;
1869 }
1870
1871 int Image::list_lockers(std::list<librbd::locker_t> *lockers,
1872 bool *exclusive, string *tag)
1873 {
1874 ImageCtx *ictx = (ImageCtx *)ctx;
1875 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1876 int r = librbd::list_lockers(ictx, lockers, exclusive, tag);
1877 if (r >= 0) {
1878 for (std::list<librbd::locker_t>::const_iterator it = lockers->begin();
1879 it != lockers->end(); ++it) {
1880 tracepoint(librbd, list_lockers_entry, it->client.c_str(), it->cookie.c_str(), it->address.c_str());
1881 }
1882 }
1883 tracepoint(librbd, list_lockers_exit, r);
1884 return r;
1885 }
1886
1887 int Image::lock_exclusive(const string& cookie)
1888 {
1889 ImageCtx *ictx = (ImageCtx *)ctx;
1890 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1891 int r = librbd::lock(ictx, true, cookie, "");
1892 tracepoint(librbd, lock_exclusive_exit, r);
1893 return r;
1894 }
1895
1896 int Image::lock_shared(const string& cookie, const std::string& tag)
1897 {
1898 ImageCtx *ictx = (ImageCtx *)ctx;
1899 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str(), tag.c_str());
1900 int r = librbd::lock(ictx, false, cookie, tag);
1901 tracepoint(librbd, lock_shared_exit, r);
1902 return r;
1903 }
1904
1905 int Image::unlock(const string& cookie)
1906 {
1907 ImageCtx *ictx = (ImageCtx *)ctx;
1908 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1909 int r = librbd::unlock(ictx, cookie);
1910 tracepoint(librbd, unlock_exit, r);
1911 return r;
1912 }
1913
1914 int Image::break_lock(const string& client, const string& cookie)
1915 {
1916 ImageCtx *ictx = (ImageCtx *)ctx;
1917 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client.c_str(), cookie.c_str());
1918 int r = librbd::break_lock(ictx, client, cookie);
1919 tracepoint(librbd, break_lock_exit, r);
1920 return r;
1921 }
1922
1923 int Image::snap_create(const char *snap_name)
1924 {
1925 ImageCtx *ictx = (ImageCtx *)ctx;
1926 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1927 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
1928 snap_name);
1929 tracepoint(librbd, snap_create_exit, r);
1930 return r;
1931 }
1932
1933 int Image::snap_remove(const char *snap_name)
1934 {
1935 ImageCtx *ictx = (ImageCtx *)ctx;
1936 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1937 librbd::NoOpProgressContext prog_ctx;
1938 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
1939 tracepoint(librbd, snap_remove_exit, r);
1940 return r;
1941 }
1942
1943 int Image::snap_remove2(const char *snap_name, uint32_t flags, ProgressContext& pctx)
1944 {
1945 ImageCtx *ictx = (ImageCtx *)ctx;
1946 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
1947 int r = librbd::snap_remove(ictx, snap_name, flags, pctx);
1948 tracepoint(librbd, snap_remove_exit, r);
1949 return r;
1950 }
1951
1952 int Image::snap_remove_by_id(uint64_t snap_id)
1953 {
1954 ImageCtx *ictx = (ImageCtx *)ctx;
1955 return librbd::api::Snapshot<>::remove(ictx, snap_id);
1956 }
1957
1958 int Image::snap_rollback(const char *snap_name)
1959 {
1960 ImageCtx *ictx = (ImageCtx *)ctx;
1961 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1962 librbd::NoOpProgressContext prog_ctx;
1963 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1964 tracepoint(librbd, snap_rollback_exit, r);
1965 return r;
1966 }
1967
1968 int Image::snap_rename(const char *srcname, const char *dstname)
1969 {
1970 ImageCtx *ictx = (ImageCtx *)ctx;
1971 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
1972 int r = ictx->operations->snap_rename(srcname, dstname);
1973 tracepoint(librbd, snap_rename_exit, r);
1974 return r;
1975 }
1976
1977 int Image::snap_rollback_with_progress(const char *snap_name,
1978 ProgressContext& prog_ctx)
1979 {
1980 ImageCtx *ictx = (ImageCtx *)ctx;
1981 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1982 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1983 tracepoint(librbd, snap_rollback_exit, r);
1984 return r;
1985 }
1986
1987 int Image::snap_protect(const char *snap_name)
1988 {
1989 ImageCtx *ictx = (ImageCtx *)ctx;
1990 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1991 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
1992 tracepoint(librbd, snap_protect_exit, r);
1993 return r;
1994 }
1995
1996 int Image::snap_unprotect(const char *snap_name)
1997 {
1998 ImageCtx *ictx = (ImageCtx *)ctx;
1999 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
2000 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
2001 tracepoint(librbd, snap_unprotect_exit, r);
2002 return r;
2003 }
2004
2005 int Image::snap_is_protected(const char *snap_name, bool *is_protected)
2006 {
2007 ImageCtx *ictx = (ImageCtx *)ctx;
2008 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
2009 int r = librbd::snap_is_protected(ictx, snap_name, is_protected);
2010 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
2011 return r;
2012 }
2013
2014 int Image::snap_list(vector<librbd::snap_info_t>& snaps)
2015 {
2016 ImageCtx *ictx = (ImageCtx *)ctx;
2017 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, &snaps);
2018 int r = librbd::snap_list(ictx, snaps);
2019 if (r >= 0) {
2020 for (int i = 0, n = snaps.size(); i < n; i++) {
2021 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name.c_str());
2022 }
2023 }
2024 tracepoint(librbd, snap_list_exit, r, snaps.size());
2025 if (r >= 0) {
2026 // A little ugly, but the C++ API doesn't need a Image::snap_list_end,
2027 // and we want the tracepoints to mirror the C API
2028 tracepoint(librbd, snap_list_end_enter, &snaps);
2029 tracepoint(librbd, snap_list_end_exit);
2030 }
2031 return r;
2032 }
2033
2034 bool Image::snap_exists(const char *snap_name)
2035 {
2036 ImageCtx *ictx = (ImageCtx *)ctx;
2037 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
2038 ictx->snap_name.c_str(), ictx->read_only, snap_name);
2039 bool exists;
2040 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, &exists);
2041 tracepoint(librbd, snap_exists_exit, r, exists);
2042 if (r < 0) {
2043 // lie to caller since we don't know the real answer yet.
2044 return false;
2045 }
2046 return exists;
2047 }
2048
2049 // A safer verion of snap_exists.
2050 int Image::snap_exists2(const char *snap_name, bool *exists)
2051 {
2052 ImageCtx *ictx = (ImageCtx *)ctx;
2053 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
2054 ictx->snap_name.c_str(), ictx->read_only, snap_name);
2055 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, exists);
2056 tracepoint(librbd, snap_exists_exit, r, *exists);
2057 return r;
2058 }
2059
2060 int Image::snap_get_timestamp(uint64_t snap_id, struct timespec *timestamp)
2061 {
2062 ImageCtx *ictx = (ImageCtx *)ctx;
2063 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
2064 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
2065 tracepoint(librbd, snap_get_timestamp_exit, r);
2066 return r;
2067 }
2068
2069 int Image::snap_get_limit(uint64_t *limit)
2070 {
2071 ImageCtx *ictx = (ImageCtx *)ctx;
2072 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
2073 int r = librbd::snap_get_limit(ictx, limit);
2074 tracepoint(librbd, snap_get_limit_exit, r, *limit);
2075 return r;
2076 }
2077
2078 int Image::snap_get_namespace_type(uint64_t snap_id,
2079 snap_namespace_type_t *namespace_type) {
2080 ImageCtx *ictx = (ImageCtx *)ctx;
2081 tracepoint(librbd, snap_get_namespace_type_enter, ictx, ictx->name.c_str());
2082 int r = librbd::api::Snapshot<>::get_namespace_type(ictx, snap_id, namespace_type);
2083 tracepoint(librbd, snap_get_namespace_type_exit, r);
2084 return r;
2085 }
2086
2087 int Image::snap_get_group_namespace(uint64_t snap_id,
2088 snap_group_namespace_t *group_snap,
2089 size_t group_snap_size) {
2090 ImageCtx *ictx = (ImageCtx *)ctx;
2091 tracepoint(librbd, snap_get_group_namespace_enter, ictx,
2092 ictx->name.c_str());
2093
2094 if (group_snap_size != sizeof(snap_group_namespace_t)) {
2095 tracepoint(librbd, snap_get_group_namespace_exit, -ERANGE);
2096 return -ERANGE;
2097 }
2098
2099 int r = librbd::api::Snapshot<>::get_group_namespace(ictx, snap_id,
2100 group_snap);
2101 tracepoint(librbd, snap_get_group_namespace_exit, r);
2102 return r;
2103 }
2104
2105 int Image::snap_get_trash_namespace(uint64_t snap_id,
2106 std::string* original_name) {
2107 ImageCtx *ictx = (ImageCtx *)ctx;
2108 return librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
2109 original_name);
2110 }
2111
2112 int Image::snap_set_limit(uint64_t limit)
2113 {
2114 ImageCtx *ictx = (ImageCtx *)ctx;
2115
2116 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
2117 int r = ictx->operations->snap_set_limit(limit);
2118 tracepoint(librbd, snap_set_limit_exit, r);
2119 return r;
2120 }
2121
2122 int Image::snap_set(const char *snap_name)
2123 {
2124 ImageCtx *ictx = (ImageCtx *)ctx;
2125 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
2126 int r = librbd::api::Image<>::snap_set(
2127 ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
2128 tracepoint(librbd, snap_set_exit, r);
2129 return r;
2130 }
2131
2132 int Image::snap_set_by_id(uint64_t snap_id)
2133 {
2134 ImageCtx *ictx = (ImageCtx *)ctx;
2135 return librbd::api::Image<>::snap_set(ictx, snap_id);
2136 }
2137
2138 ssize_t Image::read(uint64_t ofs, size_t len, bufferlist& bl)
2139 {
2140 ImageCtx *ictx = (ImageCtx *)ctx;
2141 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
2142 bufferptr ptr(len);
2143 bl.push_back(std::move(ptr));
2144
2145 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, 0);
2146 tracepoint(librbd, read_exit, r);
2147 return r;
2148 }
2149
2150 ssize_t Image::read2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
2151 {
2152 ImageCtx *ictx = (ImageCtx *)ctx;
2153 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
2154 ictx->read_only, ofs, len, op_flags);
2155 bufferptr ptr(len);
2156 bl.push_back(std::move(ptr));
2157
2158 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, op_flags);
2159 tracepoint(librbd, read_exit, r);
2160 return r;
2161 }
2162
2163 int64_t Image::read_iterate(uint64_t ofs, size_t len,
2164 int (*cb)(uint64_t, size_t, const char *, void *),
2165 void *arg)
2166 {
2167 ImageCtx *ictx = (ImageCtx *)ctx;
2168 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
2169
2170 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
2171 tracepoint(librbd, read_iterate_exit, r);
2172 return r;
2173 }
2174
2175 int Image::read_iterate2(uint64_t ofs, uint64_t len,
2176 int (*cb)(uint64_t, size_t, const char *, void *),
2177 void *arg)
2178 {
2179 ImageCtx *ictx = (ImageCtx *)ctx;
2180 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
2181
2182 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
2183 if (r > 0)
2184 r = 0;
2185 tracepoint(librbd, read_iterate2_exit, r);
2186 return (int)r;
2187 }
2188
2189 int Image::diff_iterate(const char *fromsnapname,
2190 uint64_t ofs, uint64_t len,
2191 int (*cb)(uint64_t, size_t, int, void *),
2192 void *arg)
2193 {
2194 ImageCtx *ictx = (ImageCtx *)ctx;
2195 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
2196 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
2197 true, false);
2198 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
2199 cls::rbd::UserSnapshotNamespace(),
2200 fromsnapname, ofs,
2201 len, true, false, cb, arg);
2202 tracepoint(librbd, diff_iterate_exit, r);
2203 return r;
2204 }
2205
2206 int Image::diff_iterate2(const char *fromsnapname, uint64_t ofs, uint64_t len,
2207 bool include_parent, bool whole_object,
2208 int (*cb)(uint64_t, size_t, int, void *), void *arg)
2209 {
2210 ImageCtx *ictx = (ImageCtx *)ctx;
2211 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
2212 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
2213 include_parent, whole_object);
2214 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
2215 cls::rbd::UserSnapshotNamespace(),
2216 fromsnapname, ofs,
2217 len, include_parent,
2218 whole_object, cb, arg);
2219 tracepoint(librbd, diff_iterate_exit, r);
2220 return r;
2221 }
2222
2223 ssize_t Image::write(uint64_t ofs, size_t len, bufferlist& bl)
2224 {
2225 ImageCtx *ictx = (ImageCtx *)ctx;
2226 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, bl.length() < len ? NULL : bl.c_str());
2227 if (bl.length() < len) {
2228 tracepoint(librbd, write_exit, -EINVAL);
2229 return -EINVAL;
2230 }
2231
2232 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, 0);
2233 tracepoint(librbd, write_exit, r);
2234 return r;
2235 }
2236
2237 ssize_t Image::write2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
2238 {
2239 ImageCtx *ictx = (ImageCtx *)ctx;
2240 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only,
2241 ofs, len, bl.length() < len ? NULL : bl.c_str(), op_flags);
2242 if (bl.length() < len) {
2243 tracepoint(librbd, write_exit, -EINVAL);
2244 return -EINVAL;
2245 }
2246
2247 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, op_flags);
2248 tracepoint(librbd, write_exit, r);
2249 return r;
2250 }
2251
2252 int Image::discard(uint64_t ofs, uint64_t len)
2253 {
2254 ImageCtx *ictx = (ImageCtx *)ctx;
2255 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
2256 if (len > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
2257 tracepoint(librbd, discard_exit, -EINVAL);
2258 return -EINVAL;
2259 }
2260 int r = ictx->io_work_queue->discard(
2261 ofs, len, ictx->discard_granularity_bytes);
2262 tracepoint(librbd, discard_exit, r);
2263 return r;
2264 }
2265
2266 ssize_t Image::writesame(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
2267 {
2268 ImageCtx *ictx = (ImageCtx *)ctx;
2269 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
2270 ictx->read_only, ofs, len, bl.length() <= 0 ? NULL : bl.c_str(), bl.length(),
2271 op_flags);
2272 if (bl.length() <= 0 || len % bl.length() ||
2273 len > static_cast<size_t>(std::numeric_limits<int>::max())) {
2274 tracepoint(librbd, writesame_exit, -EINVAL);
2275 return -EINVAL;
2276 }
2277
2278 bool discard_zero = ictx->config.get_val<bool>("rbd_discard_on_zeroed_write_same");
2279 if (discard_zero && mem_is_zero(bl.c_str(), bl.length())) {
2280 int r = ictx->io_work_queue->discard(ofs, len, 0);
2281 tracepoint(librbd, writesame_exit, r);
2282 return r;
2283 }
2284
2285 int r = ictx->io_work_queue->writesame(ofs, len, bufferlist{bl}, op_flags);
2286 tracepoint(librbd, writesame_exit, r);
2287 return r;
2288 }
2289
2290 ssize_t Image::compare_and_write(uint64_t ofs, size_t len,
2291 ceph::bufferlist &cmp_bl, ceph::bufferlist& bl,
2292 uint64_t *mismatch_off, int op_flags)
2293 {
2294 ImageCtx *ictx = (ImageCtx *)ctx;
2295 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
2296 ictx->snap_name.c_str(),
2297 ictx->read_only, ofs, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
2298 bl.length() < len ? NULL : bl.c_str(), op_flags);
2299
2300 if (bl.length() < len) {
2301 tracepoint(librbd, write_exit, -EINVAL);
2302 return -EINVAL;
2303 }
2304
2305 int r = ictx->io_work_queue->compare_and_write(ofs, len, bufferlist{cmp_bl},
2306 bufferlist{bl}, mismatch_off,
2307 op_flags);
2308
2309 tracepoint(librbd, compare_and_write_exit, r);
2310
2311 return r;
2312 }
2313
2314 int Image::aio_write(uint64_t off, size_t len, bufferlist& bl,
2315 RBD::AioCompletion *c)
2316 {
2317 ImageCtx *ictx = (ImageCtx *)ctx;
2318 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc);
2319 if (bl.length() < len) {
2320 tracepoint(librbd, aio_write_exit, -EINVAL);
2321 return -EINVAL;
2322 }
2323 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
2324 bufferlist{bl}, 0);
2325
2326 tracepoint(librbd, aio_write_exit, 0);
2327 return 0;
2328 }
2329
2330 int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
2331 RBD::AioCompletion *c, int op_flags)
2332 {
2333 ImageCtx *ictx = (ImageCtx *)ctx;
2334 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
2335 ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
2336 if (bl.length() < len) {
2337 tracepoint(librbd, aio_write_exit, -EINVAL);
2338 return -EINVAL;
2339 }
2340 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
2341 bufferlist{bl}, op_flags);
2342
2343 tracepoint(librbd, aio_write_exit, 0);
2344 return 0;
2345 }
2346
2347 int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
2348 {
2349 ImageCtx *ictx = (ImageCtx *)ctx;
2350 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
2351 ictx->io_work_queue->aio_discard(
2352 get_aio_completion(c), off, len, ictx->discard_granularity_bytes);
2353 tracepoint(librbd, aio_discard_exit, 0);
2354 return 0;
2355 }
2356
2357 int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
2358 RBD::AioCompletion *c)
2359 {
2360 ImageCtx *ictx = (ImageCtx *)ctx;
2361 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, bl.c_str(), c->pc);
2362 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
2363 << (void *)(bl.c_str() + len - 1) << dendl;
2364
2365 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
2366 io::ReadResult{&bl}, 0);
2367 tracepoint(librbd, aio_read_exit, 0);
2368 return 0;
2369 }
2370
2371 int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
2372 RBD::AioCompletion *c, int op_flags)
2373 {
2374 ImageCtx *ictx = (ImageCtx *)ctx;
2375 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
2376 ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
2377 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
2378 << (void *)(bl.c_str() + len - 1) << dendl;
2379
2380 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
2381 io::ReadResult{&bl}, op_flags);
2382 tracepoint(librbd, aio_read_exit, 0);
2383 return 0;
2384 }
2385
2386 int Image::flush()
2387 {
2388 ImageCtx *ictx = (ImageCtx *)ctx;
2389 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2390 int r = ictx->io_work_queue->flush();
2391 tracepoint(librbd, flush_exit, r);
2392 return r;
2393 }
2394
2395 int Image::aio_flush(RBD::AioCompletion *c)
2396 {
2397 ImageCtx *ictx = (ImageCtx *)ctx;
2398 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
2399 ictx->io_work_queue->aio_flush(get_aio_completion(c));
2400 tracepoint(librbd, aio_flush_exit, 0);
2401 return 0;
2402 }
2403
2404 int Image::aio_writesame(uint64_t off, size_t len, bufferlist& bl,
2405 RBD::AioCompletion *c, int op_flags)
2406 {
2407 ImageCtx *ictx = (ImageCtx *)ctx;
2408 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
2409 ictx->read_only, off, len, bl.length() <= len ? NULL : bl.c_str(), bl.length(),
2410 c->pc, op_flags);
2411 if (bl.length() <= 0 || len % bl.length()) {
2412 tracepoint(librbd, aio_writesame_exit, -EINVAL);
2413 return -EINVAL;
2414 }
2415
2416 bool discard_zero = ictx->config.get_val<bool>("rbd_discard_on_zeroed_write_same");
2417 if (discard_zero && mem_is_zero(bl.c_str(), bl.length())) {
2418 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, 0);
2419 tracepoint(librbd, aio_writesame_exit, 0);
2420 return 0;
2421 }
2422
2423 ictx->io_work_queue->aio_writesame(get_aio_completion(c), off, len,
2424 bufferlist{bl}, op_flags);
2425 tracepoint(librbd, aio_writesame_exit, 0);
2426 return 0;
2427 }
2428
2429 int Image::aio_compare_and_write(uint64_t off, size_t len,
2430 ceph::bufferlist& cmp_bl, ceph::bufferlist& bl,
2431 RBD::AioCompletion *c, uint64_t *mismatch_off,
2432 int op_flags)
2433 {
2434 ImageCtx *ictx = (ImageCtx *)ctx;
2435 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(),
2436 ictx->snap_name.c_str(),
2437 ictx->read_only, off, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
2438 bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
2439
2440 if (bl.length() < len) {
2441 tracepoint(librbd, compare_and_write_exit, -EINVAL);
2442 return -EINVAL;
2443 }
2444
2445 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(c), off, len,
2446 bufferlist{cmp_bl}, bufferlist{bl},
2447 mismatch_off, op_flags, false);
2448
2449 tracepoint(librbd, aio_compare_and_write_exit, 0);
2450
2451 return 0;
2452 }
2453
2454 int Image::invalidate_cache()
2455 {
2456 ImageCtx *ictx = (ImageCtx *)ctx;
2457 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2458 int r = librbd::invalidate_cache(ictx);
2459 tracepoint(librbd, invalidate_cache_exit, r);
2460 return r;
2461 }
2462
2463 int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp)
2464 {
2465 io::AioCompletion *cs[numcomp];
2466 ImageCtx *ictx = (ImageCtx *)ctx;
2467 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
2468 int r = librbd::poll_io_events(ictx, cs, numcomp);
2469 tracepoint(librbd, poll_io_events_exit, r);
2470 if (r > 0) {
2471 for (int i = 0; i < r; ++i)
2472 comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
2473 }
2474 return r;
2475 }
2476
2477 int Image::metadata_get(const std::string &key, std::string *value)
2478 {
2479 ImageCtx *ictx = (ImageCtx *)ctx;
2480 tracepoint(librbd, metadata_get_enter, ictx, key.c_str());
2481 int r = librbd::metadata_get(ictx, key, value);
2482 if (r < 0) {
2483 tracepoint(librbd, metadata_get_exit, r, key.c_str(), NULL);
2484 } else {
2485 tracepoint(librbd, metadata_get_exit, r, key.c_str(), value->c_str());
2486 }
2487 return r;
2488 }
2489
2490 int Image::metadata_set(const std::string &key, const std::string &value)
2491 {
2492 ImageCtx *ictx = (ImageCtx *)ctx;
2493 tracepoint(librbd, metadata_set_enter, ictx, key.c_str(), value.c_str());
2494 int r = ictx->operations->metadata_set(key, value);
2495 tracepoint(librbd, metadata_set_exit, r);
2496 return r;
2497 }
2498
2499 int Image::metadata_remove(const std::string &key)
2500 {
2501 ImageCtx *ictx = (ImageCtx *)ctx;
2502 tracepoint(librbd, metadata_remove_enter, ictx, key.c_str());
2503 int r = ictx->operations->metadata_remove(key);
2504 tracepoint(librbd, metadata_remove_exit, r);
2505 return r;
2506 }
2507
2508 int Image::metadata_list(const std::string &start, uint64_t max, map<string, bufferlist> *pairs)
2509 {
2510 ImageCtx *ictx = (ImageCtx *)ctx;
2511 tracepoint(librbd, metadata_list_enter, ictx);
2512 int r = librbd::metadata_list(ictx, start, max, pairs);
2513 if (r >= 0) {
2514 for (map<string, bufferlist>::iterator it = pairs->begin();
2515 it != pairs->end(); ++it) {
2516 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
2517 }
2518 }
2519 tracepoint(librbd, metadata_list_exit, r);
2520 return r;
2521 }
2522
2523 int Image::mirror_image_enable() {
2524 ImageCtx *ictx = (ImageCtx *)ctx;
2525 return librbd::api::Mirror<>::image_enable(ictx, false);
2526 }
2527
2528 int Image::mirror_image_disable(bool force) {
2529 ImageCtx *ictx = (ImageCtx *)ctx;
2530 return librbd::api::Mirror<>::image_disable(ictx, force);
2531 }
2532
2533 int Image::mirror_image_promote(bool force) {
2534 ImageCtx *ictx = (ImageCtx *)ctx;
2535 return librbd::api::Mirror<>::image_promote(ictx, force);
2536 }
2537
2538 int Image::mirror_image_demote() {
2539 ImageCtx *ictx = (ImageCtx *)ctx;
2540 return librbd::api::Mirror<>::image_demote(ictx);
2541 }
2542
2543 int Image::mirror_image_resync()
2544 {
2545 ImageCtx *ictx = (ImageCtx *)ctx;
2546 return librbd::api::Mirror<>::image_resync(ictx);
2547 }
2548
2549 int Image::mirror_image_get_info(mirror_image_info_t *mirror_image_info,
2550 size_t info_size) {
2551 ImageCtx *ictx = (ImageCtx *)ctx;
2552
2553 if (sizeof(mirror_image_info_t) != info_size) {
2554 return -ERANGE;
2555 }
2556
2557 return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info);
2558 }
2559
2560 int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
2561 size_t status_size) {
2562 ImageCtx *ictx = (ImageCtx *)ctx;
2563
2564 if (sizeof(mirror_image_status_t) != status_size) {
2565 return -ERANGE;
2566 }
2567
2568 return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status);
2569 }
2570
2571 int Image::mirror_image_get_instance_id(std::string *instance_id) {
2572 ImageCtx *ictx = (ImageCtx *)ctx;
2573
2574 return librbd::api::Mirror<>::image_get_instance_id(ictx, instance_id);
2575 }
2576
2577 int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
2578 ImageCtx *ictx = (ImageCtx *)ctx;
2579 librbd::api::Mirror<>::image_promote(
2580 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
2581 get_aio_completion(c)));
2582 return 0;
2583 }
2584
2585 int Image::aio_mirror_image_demote(RBD::AioCompletion *c) {
2586 ImageCtx *ictx = (ImageCtx *)ctx;
2587 librbd::api::Mirror<>::image_demote(
2588 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
2589 get_aio_completion(c)));
2590 return 0;
2591 }
2592
2593 int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
2594 size_t info_size,
2595 RBD::AioCompletion *c) {
2596 ImageCtx *ictx = (ImageCtx *)ctx;
2597
2598 if (sizeof(mirror_image_info_t) != info_size) {
2599 return -ERANGE;
2600 }
2601
2602 librbd::api::Mirror<>::image_get_info(
2603 ictx, mirror_image_info,
2604 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
2605 get_aio_completion(c)));
2606 return 0;
2607 }
2608
2609 int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
2610 size_t status_size,
2611 RBD::AioCompletion *c) {
2612 ImageCtx *ictx = (ImageCtx *)ctx;
2613
2614 if (sizeof(mirror_image_status_t) != status_size) {
2615 return -ERANGE;
2616 }
2617
2618 librbd::api::Mirror<>::image_get_status(
2619 ictx, status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
2620 get_aio_completion(c)));
2621 return 0;
2622 }
2623
2624 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
2625 ImageCtx *ictx = (ImageCtx *)ctx;
2626 tracepoint(librbd, update_watch_enter, ictx, wctx);
2627 int r = ictx->state->register_update_watcher(wctx, handle);
2628 tracepoint(librbd, update_watch_exit, r, *handle);
2629 return r;
2630 }
2631
2632 int Image::update_unwatch(uint64_t handle) {
2633 ImageCtx *ictx = (ImageCtx *)ctx;
2634 tracepoint(librbd, update_unwatch_enter, ictx, handle);
2635 int r = ictx->state->unregister_update_watcher(handle);
2636 tracepoint(librbd, update_unwatch_exit, r);
2637 return r;
2638 }
2639
2640 int Image::list_watchers(std::list<librbd::image_watcher_t> &watchers) {
2641 ImageCtx *ictx = (ImageCtx *)ctx;
2642 tracepoint(librbd, list_watchers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2643 int r = librbd::list_watchers(ictx, watchers);
2644 #ifdef WITH_LTTNG
2645 if (r >= 0) {
2646 for (auto &watcher : watchers) {
2647 tracepoint(librbd, list_watchers_entry, watcher.addr.c_str(), watcher.id, watcher.cookie);
2648 }
2649 }
2650 #endif
2651 tracepoint(librbd, list_watchers_exit, r, watchers.size());
2652 return r;
2653 }
2654
2655 int Image::config_list(std::vector<config_option_t> *options) {
2656 ImageCtx *ictx = (ImageCtx *)ctx;
2657 return librbd::api::Config<>::list(ictx, options);
2658 }
2659
2660 } // namespace librbd
2661
2662 extern "C" void rbd_version(int *major, int *minor, int *extra)
2663 {
2664 if (major)
2665 *major = LIBRBD_VER_MAJOR;
2666 if (minor)
2667 *minor = LIBRBD_VER_MINOR;
2668 if (extra)
2669 *extra = LIBRBD_VER_EXTRA;
2670 }
2671
2672 extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
2673 {
2674 librbd::image_options_create(opts);
2675 }
2676
2677 extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
2678 {
2679 librbd::image_options_destroy(opts);
2680 }
2681
2682 extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
2683 const char* optval)
2684 {
2685 return librbd::image_options_set(opts, optname, optval);
2686 }
2687
2688 extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
2689 uint64_t optval)
2690 {
2691 return librbd::image_options_set(opts, optname, optval);
2692 }
2693
2694 extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
2695 char* optval, size_t maxlen)
2696 {
2697 std::string optval_;
2698
2699 int r = librbd::image_options_get(opts, optname, &optval_);
2700
2701 if (r < 0) {
2702 return r;
2703 }
2704
2705 if (optval_.size() >= maxlen) {
2706 return -E2BIG;
2707 }
2708
2709 strncpy(optval, optval_.c_str(), maxlen);
2710
2711 return 0;
2712 }
2713
2714 extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
2715 uint64_t* optval)
2716 {
2717 return librbd::image_options_get(opts, optname, optval);
2718 }
2719
2720 extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
2721 bool* is_set)
2722 {
2723 return librbd::image_options_is_set(opts, optname, is_set);
2724 }
2725
2726 extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
2727 {
2728 return librbd::image_options_unset(opts, optname);
2729 }
2730
2731 extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
2732 {
2733 librbd::image_options_clear(opts);
2734 }
2735
2736 extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
2737 {
2738 return librbd::image_options_is_empty(opts);
2739 }
2740
2741 /* pool mirroring */
2742 extern "C" int rbd_mirror_site_name_get(rados_t cluster, char *name,
2743 size_t *max_len) {
2744 librados::Rados rados;
2745 librados::Rados::from_rados_t(cluster, rados);
2746
2747 std::string site_name;
2748 int r = librbd::api::Mirror<>::site_name_get(rados, &site_name);
2749 if (r < 0) {
2750 return r;
2751 }
2752
2753 auto total_len = site_name.size() + 1;
2754 if (*max_len < total_len) {
2755 *max_len = total_len;
2756 return -ERANGE;
2757 }
2758 *max_len = total_len;
2759
2760 strcpy(name, site_name.c_str());
2761 return 0;
2762 }
2763
2764 extern "C" int rbd_mirror_site_name_set(rados_t cluster, const char *name) {
2765 librados::Rados rados;
2766 librados::Rados::from_rados_t(cluster, rados);
2767 return librbd::api::Mirror<>::site_name_set(rados, name);
2768 }
2769
2770 extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
2771 rbd_mirror_mode_t *mirror_mode) {
2772 librados::IoCtx io_ctx;
2773 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2774 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
2775 }
2776
2777 extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
2778 rbd_mirror_mode_t mirror_mode) {
2779 librados::IoCtx io_ctx;
2780 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2781 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
2782 }
2783
2784 extern "C" int rbd_mirror_peer_bootstrap_create(rados_ioctx_t p, char *token,
2785 size_t *max_len) {
2786 librados::IoCtx io_ctx;
2787 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2788
2789 std::string token_str;
2790 int r = librbd::api::Mirror<>::peer_bootstrap_create(io_ctx, &token_str);
2791 if (r < 0) {
2792 return r;
2793 }
2794
2795 auto total_len = token_str.size() + 1;
2796 if (*max_len < total_len) {
2797 *max_len = total_len;
2798 return -ERANGE;
2799 }
2800 *max_len = total_len;
2801
2802 strcpy(token, token_str.c_str());
2803 return 0;
2804 }
2805
2806 extern "C" int rbd_mirror_peer_bootstrap_import(
2807 rados_ioctx_t p, rbd_mirror_peer_direction_t direction,
2808 const char *token) {
2809 librados::IoCtx io_ctx;
2810 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2811
2812 return librbd::api::Mirror<>::peer_bootstrap_import(io_ctx, direction, token);
2813 }
2814
2815 extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
2816 size_t uuid_max_length,
2817 const char *cluster_name,
2818 const char *client_name) {
2819 static const std::size_t UUID_LENGTH = 36;
2820
2821 librados::IoCtx io_ctx;
2822 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2823
2824 if (uuid_max_length < UUID_LENGTH + 1) {
2825 return -E2BIG;
2826 }
2827
2828 std::string uuid_str;
2829 int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
2830 client_name);
2831 if (r >= 0) {
2832 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
2833 uuid[uuid_max_length - 1] = '\0';
2834 }
2835 return r;
2836 }
2837
2838 extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
2839 librados::IoCtx io_ctx;
2840 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2841 int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
2842 return r;
2843 }
2844
2845 extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
2846 rbd_mirror_peer_t *peers, int *max_peers) {
2847 librados::IoCtx io_ctx;
2848 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2849
2850 std::vector<librbd::mirror_peer_t> peer_vector;
2851 int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
2852 if (r < 0) {
2853 return r;
2854 }
2855
2856 if (*max_peers < static_cast<int>(peer_vector.size())) {
2857 *max_peers = static_cast<int>(peer_vector.size());
2858 return -ERANGE;
2859 }
2860
2861 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
2862 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
2863 peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
2864 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
2865 }
2866 *max_peers = static_cast<int>(peer_vector.size());
2867 return 0;
2868 }
2869
2870 extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
2871 int max_peers) {
2872 for (int i = 0; i < max_peers; ++i) {
2873 free(peers[i].uuid);
2874 free(peers[i].cluster_name);
2875 free(peers[i].client_name);
2876 }
2877 }
2878
2879 extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
2880 const char *client_name) {
2881 librados::IoCtx io_ctx;
2882 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2883 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
2884 }
2885
2886 extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
2887 const char *cluster_name) {
2888 librados::IoCtx io_ctx;
2889 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2890 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
2891 }
2892
2893 extern "C" int rbd_mirror_peer_get_attributes(
2894 rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
2895 char *values, size_t *max_val_len, size_t *key_value_count) {
2896 librados::IoCtx io_ctx;
2897 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2898
2899 std::map<std::string, std::string> attributes;
2900 int r = librbd::api::Mirror<>::peer_get_attributes(io_ctx, uuid, &attributes);
2901 if (r < 0) {
2902 return r;
2903 }
2904
2905 size_t key_total_len = 0, val_total_len = 0;
2906 for (auto& it : attributes) {
2907 key_total_len += it.first.size() + 1;
2908 val_total_len += it.second.length() + 1;
2909 }
2910
2911 bool too_short = ((*max_key_len < key_total_len) ||
2912 (*max_val_len < val_total_len));
2913
2914 *max_key_len = key_total_len;
2915 *max_val_len = val_total_len;
2916 *key_value_count = attributes.size();
2917 if (too_short) {
2918 return -ERANGE;
2919 }
2920
2921 char *keys_p = keys;
2922 char *values_p = values;
2923 for (auto& it : attributes) {
2924 strncpy(keys_p, it.first.c_str(), it.first.size() + 1);
2925 keys_p += it.first.size() + 1;
2926
2927 strncpy(values_p, it.second.c_str(), it.second.length() + 1);
2928 values_p += it.second.length() + 1;
2929 }
2930
2931 return 0;
2932 }
2933
2934 extern "C" int rbd_mirror_peer_set_attributes(
2935 rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
2936 size_t count) {
2937 librados::IoCtx io_ctx;
2938 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2939
2940 std::map<std::string, std::string> attributes;
2941
2942 for (size_t i = 0; i < count; ++i) {
2943 const char* key = keys;
2944 keys += strlen(key) + 1;
2945 const char* value = values;
2946 values += strlen(value) + 1;
2947 attributes[key] = value;
2948 }
2949
2950 return librbd::api::Mirror<>::peer_set_attributes(io_ctx, uuid, attributes);
2951 }
2952
2953 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
2954 const char *start_id, size_t max, char **image_ids,
2955 rbd_mirror_image_status_t *images, size_t *len) {
2956 librados::IoCtx io_ctx;
2957 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2958 std::map<std::string, librbd::mirror_image_status_t> cpp_images;
2959
2960 int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
2961 &cpp_images);
2962 if (r < 0) {
2963 return r;
2964 }
2965
2966 size_t i = 0;
2967 for (auto &it : cpp_images) {
2968 ceph_assert(i < max);
2969 const std::string &image_id = it.first;
2970 image_ids[i] = strdup(image_id.c_str());
2971 mirror_image_status_cpp_to_c(it.second, &images[i]);
2972 i++;
2973 }
2974 *len = i;
2975 return 0;
2976 }
2977
2978 extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
2979 rbd_mirror_image_status_t *images, size_t len) {
2980 for (size_t i = 0; i < len; i++) {
2981 free(image_ids[i]);
2982 free(images[i].name);
2983 free(images[i].info.global_id);
2984 free(images[i].description);
2985 }
2986 }
2987
2988 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
2989 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
2990
2991 librados::IoCtx io_ctx;
2992 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2993
2994 std::map<librbd::mirror_image_status_state_t, int> states_;
2995 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
2996 if (r < 0) {
2997 return r;
2998 }
2999
3000 size_t i = 0;
3001 for (auto &it : states_) {
3002 if (i == *maxlen) {
3003 return -ERANGE;
3004 }
3005 states[i] = it.first;
3006 counts[i] = it.second;
3007 i++;
3008 }
3009 *maxlen = i;
3010 return 0;
3011 }
3012
3013 extern "C" int rbd_mirror_image_instance_id_list(
3014 rados_ioctx_t p, const char *start_id, size_t max, char **image_ids,
3015 char **instance_ids, size_t *len) {
3016 librados::IoCtx io_ctx;
3017 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3018 std::map<std::string, std::string> cpp_instance_ids;
3019
3020 int r = librbd::api::Mirror<>::image_instance_id_list(io_ctx, start_id, max,
3021 &cpp_instance_ids);
3022 if (r < 0) {
3023 return r;
3024 }
3025
3026 size_t i = 0;
3027 for (auto &it : cpp_instance_ids) {
3028 ceph_assert(i < max);
3029 image_ids[i] = strdup(it.first.c_str());
3030 instance_ids[i] = strdup(it.second.c_str());
3031 i++;
3032 }
3033 *len = i;
3034 return 0;
3035 }
3036
3037 extern "C" void rbd_mirror_image_instance_id_list_cleanup(
3038 char **image_ids, char **instance_ids, size_t len) {
3039 for (size_t i = 0; i < len; i++) {
3040 free(image_ids[i]);
3041 free(instance_ids[i]);
3042 }
3043 }
3044
3045 /* helpers */
3046
3047 extern "C" void rbd_image_spec_cleanup(rbd_image_spec_t *image)
3048 {
3049 free(image->id);
3050 free(image->name);
3051 }
3052
3053 extern "C" void rbd_image_spec_list_cleanup(rbd_image_spec_t *images,
3054 size_t num_images)
3055 {
3056 for (size_t idx = 0; idx < num_images; ++idx) {
3057 rbd_image_spec_cleanup(&images[idx]);
3058 }
3059 }
3060
3061 extern "C" void rbd_linked_image_spec_cleanup(rbd_linked_image_spec_t *image)
3062 {
3063 free(image->pool_name);
3064 free(image->pool_namespace);
3065 free(image->image_id);
3066 free(image->image_name);
3067 }
3068
3069 extern "C" void rbd_linked_image_spec_list_cleanup(
3070 rbd_linked_image_spec_t *images, size_t num_images)
3071 {
3072 for (size_t idx = 0; idx < num_images; ++idx) {
3073 rbd_linked_image_spec_cleanup(&images[idx]);
3074 }
3075 }
3076
3077 extern "C" void rbd_snap_spec_cleanup(rbd_snap_spec_t *snap)
3078 {
3079 free(snap->name);
3080 }
3081
3082 /* images */
3083 extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
3084 {
3085 librados::IoCtx io_ctx;
3086 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3087
3088 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3089 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(),
3090 io_ctx.get_id());
3091 std::vector<librbd::image_spec_t> cpp_image_specs;
3092 int r = librbd::api::Image<>::list_images(io_ctx, &cpp_image_specs);
3093 if (r < 0) {
3094 tracepoint(librbd, list_exit, r, *size);
3095 return r;
3096 }
3097
3098 size_t expected_size = 0;
3099
3100 for (auto& it : cpp_image_specs) {
3101 expected_size += it.name.size() + 1;
3102 }
3103 if (*size < expected_size) {
3104 *size = expected_size;
3105 tracepoint(librbd, list_exit, -ERANGE, *size);
3106 return -ERANGE;
3107 }
3108
3109 if (names == NULL) {
3110 tracepoint(librbd, list_exit, -EINVAL, *size);
3111 return -EINVAL;
3112 }
3113
3114 for (auto& it : cpp_image_specs) {
3115 const char* name = it.name.c_str();
3116 tracepoint(librbd, list_entry, name);
3117 strcpy(names, name);
3118 names += strlen(names) + 1;
3119 }
3120 tracepoint(librbd, list_exit, (int)expected_size, *size);
3121 return (int)expected_size;
3122 }
3123
3124 extern "C" int rbd_list2(rados_ioctx_t p, rbd_image_spec_t *images,
3125 size_t *size)
3126 {
3127 librados::IoCtx io_ctx;
3128 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3129
3130 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3131 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(),
3132 io_ctx.get_id());
3133 memset(images, 0, sizeof(*images) * *size);
3134 std::vector<librbd::image_spec_t> cpp_image_specs;
3135 int r = librbd::api::Image<>::list_images(io_ctx, &cpp_image_specs);
3136 if (r < 0) {
3137 tracepoint(librbd, list_exit, r, *size);
3138 return r;
3139 }
3140
3141 size_t expected_size = cpp_image_specs.size();
3142 if (*size < expected_size) {
3143 *size = expected_size;
3144 tracepoint(librbd, list_exit, -ERANGE, *size);
3145 return -ERANGE;
3146 }
3147
3148 *size = expected_size;
3149 for (size_t idx = 0; idx < expected_size; ++idx) {
3150 images[idx].id = strdup(cpp_image_specs[idx].id.c_str());
3151 images[idx].name = strdup(cpp_image_specs[idx].name.c_str());
3152 }
3153 tracepoint(librbd, list_exit, 0, *size);
3154 return 0;
3155 }
3156
3157 extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
3158 {
3159 librados::IoCtx io_ctx;
3160 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3161 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3162 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
3163 int r = librbd::create(io_ctx, name, size, order);
3164 tracepoint(librbd, create_exit, r, *order);
3165 return r;
3166 }
3167
3168 extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
3169 uint64_t size, uint64_t features,
3170 int *order)
3171 {
3172 librados::IoCtx io_ctx;
3173 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3174 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3175 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
3176 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
3177 tracepoint(librbd, create2_exit, r, *order);
3178 return r;
3179 }
3180
3181 extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
3182 uint64_t size, uint64_t features,
3183 int *order,
3184 uint64_t stripe_unit, uint64_t stripe_count)
3185 {
3186 librados::IoCtx io_ctx;
3187 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3188 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3189 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
3190 int r = librbd::create(io_ctx, name, size, false, features, order,
3191 stripe_unit, stripe_count);
3192 tracepoint(librbd, create3_exit, r, *order);
3193 return r;
3194 }
3195
3196 extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
3197 uint64_t size, rbd_image_options_t opts)
3198 {
3199 librados::IoCtx io_ctx;
3200 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3201 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3202 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
3203 librbd::ImageOptions opts_(opts);
3204 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
3205 tracepoint(librbd, create4_exit, r);
3206 return r;
3207 }
3208
3209 extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
3210 const char *p_snap_name, rados_ioctx_t c_ioctx,
3211 const char *c_name, uint64_t features, int *c_order)
3212 {
3213 librados::IoCtx p_ioc, c_ioc;
3214 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
3215 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
3216 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
3217 tracepoint(librbd, clone_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, features);
3218 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
3219 features, c_order, 0, 0);
3220 tracepoint(librbd, clone_exit, r, *c_order);
3221 return r;
3222 }
3223
3224 extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
3225 const char *p_snap_name, rados_ioctx_t c_ioctx,
3226 const char *c_name, uint64_t features, int *c_order,
3227 uint64_t stripe_unit, int stripe_count)
3228 {
3229 librados::IoCtx p_ioc, c_ioc;
3230 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
3231 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
3232 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
3233 tracepoint(librbd, clone2_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, features, stripe_unit, stripe_count);
3234 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
3235 features, c_order, stripe_unit, stripe_count);
3236 tracepoint(librbd, clone2_exit, r, *c_order);
3237 return r;
3238 }
3239
3240 extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
3241 const char *p_snap_name, rados_ioctx_t c_ioctx,
3242 const char *c_name, rbd_image_options_t c_opts)
3243 {
3244 librados::IoCtx p_ioc, c_ioc;
3245 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
3246 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
3247 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
3248 tracepoint(librbd, clone3_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, c_opts);
3249 librbd::ImageOptions c_opts_(c_opts);
3250 int r = librbd::clone(p_ioc, nullptr, p_name, p_snap_name, c_ioc, nullptr,
3251 c_name, c_opts_, "", "");
3252 tracepoint(librbd, clone3_exit, r);
3253 return r;
3254 }
3255
3256 extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
3257 {
3258 librados::IoCtx io_ctx;
3259 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3260 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3261 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
3262 librbd::NoOpProgressContext prog_ctx;
3263 int r = librbd::api::Image<>::remove(io_ctx, name, prog_ctx);
3264 tracepoint(librbd, remove_exit, r);
3265 return r;
3266 }
3267
3268 extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
3269 librbd_progress_fn_t cb, void *cbdata)
3270 {
3271 librados::IoCtx io_ctx;
3272 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3273 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3274 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
3275 librbd::CProgressContext prog_ctx(cb, cbdata);
3276 int r = librbd::api::Image<>::remove(io_ctx, name, prog_ctx);
3277 tracepoint(librbd, remove_exit, r);
3278 return r;
3279 }
3280
3281 extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
3282 uint64_t delay) {
3283 librados::IoCtx io_ctx;
3284 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3285 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3286 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
3287 io_ctx.get_id(), name);
3288 int r = librbd::api::Trash<>::move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name,
3289 delay);
3290 tracepoint(librbd, trash_move_exit, r);
3291 return r;
3292 }
3293
3294 extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
3295 rbd_trash_image_info_t *info) {
3296 librados::IoCtx io_ctx;
3297 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3298
3299 librbd::trash_image_info_t cpp_info;
3300 int r = librbd::api::Trash<>::get(io_ctx, id, &cpp_info);
3301 if (r < 0) {
3302 return r;
3303 }
3304
3305 trash_image_info_cpp_to_c(cpp_info, info);
3306 return 0;
3307 }
3308
3309 extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
3310 free(info->id);
3311 free(info->name);
3312 }
3313
3314 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
3315 size_t *num_entries) {
3316 librados::IoCtx io_ctx;
3317 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3318 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3319 tracepoint(librbd, trash_list_enter,
3320 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
3321 memset(entries, 0, sizeof(*entries) * *num_entries);
3322
3323 vector<librbd::trash_image_info_t> cpp_entries;
3324 int r = librbd::api::Trash<>::list(io_ctx, cpp_entries, true);
3325 if (r < 0) {
3326 tracepoint(librbd, trash_list_exit, r, *num_entries);
3327 return r;
3328 }
3329
3330 if (*num_entries < cpp_entries.size()) {
3331 *num_entries = cpp_entries.size();
3332 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
3333 return -ERANGE;
3334 }
3335
3336 int i=0;
3337 for (const auto &entry : cpp_entries) {
3338 trash_image_info_cpp_to_c(entry, &entries[i++]);
3339 }
3340 *num_entries = cpp_entries.size();
3341
3342 return *num_entries;
3343 }
3344
3345 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
3346 size_t num_entries) {
3347 for (size_t i=0; i < num_entries; i++) {
3348 rbd_trash_get_cleanup(&entries[i]);
3349 }
3350 }
3351
3352 extern "C" int rbd_trash_purge(rados_ioctx_t io, time_t expire_ts,
3353 float threshold) {
3354 librados::IoCtx io_ctx;
3355 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3356 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3357 tracepoint(librbd, trash_purge_enter, io_ctx.get_pool_name().c_str(),
3358 io_ctx.get_id(), expire_ts, threshold);
3359 librbd::NoOpProgressContext nop_pctx;
3360 int r = librbd::api::Trash<>::purge(io_ctx, expire_ts, threshold, nop_pctx);
3361 tracepoint(librbd, trash_purge_exit, r);
3362 return r;
3363 }
3364
3365 extern "C" int rbd_trash_purge_with_progress(rados_ioctx_t io, time_t expire_ts,
3366 float threshold, librbd_progress_fn_t cb, void* cbdata) {
3367 librados::IoCtx io_ctx;
3368 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3369 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3370 tracepoint(librbd, trash_purge_enter, io_ctx.get_pool_name().c_str(),
3371 io_ctx.get_id(), expire_ts, threshold);
3372 librbd::CProgressContext pctx(cb, cbdata);
3373 int r = librbd::api::Trash<>::purge(io_ctx, expire_ts, threshold, pctx);
3374 tracepoint(librbd, trash_purge_exit, r);
3375 return r;
3376 }
3377
3378 extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
3379 bool force) {
3380 librados::IoCtx io_ctx;
3381 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3382 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3383 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
3384 io_ctx.get_id(), image_id, force);
3385 librbd::NoOpProgressContext prog_ctx;
3386 int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx);
3387 tracepoint(librbd, trash_remove_exit, r);
3388 return r;
3389 }
3390
3391 extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
3392 const char *image_id,
3393 bool force,
3394 librbd_progress_fn_t cb,
3395 void *cbdata) {
3396 librados::IoCtx io_ctx;
3397 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3398 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3399 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
3400 io_ctx.get_id(), image_id, force);
3401 librbd::CProgressContext prog_ctx(cb, cbdata);
3402 int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx);
3403 tracepoint(librbd, trash_remove_exit, r);
3404 return r;
3405 }
3406
3407 extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
3408 const char *name) {
3409 librados::IoCtx io_ctx;
3410 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3411 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3412 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
3413 io_ctx.get_id(), id, name);
3414 int r = librbd::api::Trash<>::restore(
3415 io_ctx, librbd::api::Trash<>::RESTORE_SOURCE_WHITELIST, id, name);
3416 tracepoint(librbd, trash_undelete_exit, r);
3417 return r;
3418 }
3419
3420 extern "C" int rbd_namespace_create(rados_ioctx_t io,
3421 const char *namespace_name) {
3422 librados::IoCtx io_ctx;
3423 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3424
3425 return librbd::api::Namespace<>::create(io_ctx, namespace_name);
3426 }
3427
3428 extern "C" int rbd_namespace_remove(rados_ioctx_t io,
3429 const char *namespace_name) {
3430 librados::IoCtx io_ctx;
3431 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3432
3433 return librbd::api::Namespace<>::remove(io_ctx, namespace_name);
3434 }
3435
3436 extern "C" int rbd_namespace_list(rados_ioctx_t io, char *names, size_t *size) {
3437 librados::IoCtx io_ctx;
3438 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3439
3440 if (names == nullptr || size == nullptr) {
3441 return -EINVAL;
3442 }
3443
3444 std::vector<std::string> cpp_names;
3445 int r = librbd::api::Namespace<>::list(io_ctx, &cpp_names);
3446 if (r < 0) {
3447 return r;
3448 }
3449
3450 size_t expected_size = 0;
3451 for (size_t i = 0; i < cpp_names.size(); i++) {
3452 expected_size += cpp_names[i].size() + 1;
3453 }
3454 if (*size < expected_size) {
3455 *size = expected_size;
3456 return -ERANGE;
3457 }
3458
3459 *size = expected_size;
3460 for (int i = 0; i < (int)cpp_names.size(); i++) {
3461 const char* name = cpp_names[i].c_str();
3462 strcpy(names, name);
3463 names += strlen(names) + 1;
3464 }
3465
3466 return (int)expected_size;
3467 }
3468
3469 extern "C" int rbd_namespace_exists(rados_ioctx_t io,
3470 const char *namespace_name,
3471 bool *exists) {
3472 librados::IoCtx io_ctx;
3473 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3474
3475 return librbd::api::Namespace<>::exists(io_ctx, namespace_name, exists);
3476 }
3477
3478 extern "C" int rbd_pool_init(rados_ioctx_t io, bool force) {
3479 librados::IoCtx io_ctx;
3480 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3481
3482 return librbd::api::Pool<>::init(io_ctx, force);
3483 }
3484
3485 extern "C" void rbd_pool_stats_create(rbd_pool_stats_t *stats) {
3486 *stats = reinterpret_cast<rbd_pool_stats_t>(
3487 new librbd::api::Pool<>::StatOptions{});
3488 }
3489
3490 extern "C" void rbd_pool_stats_destroy(rbd_pool_stats_t stats) {
3491 auto pool_stat_options =
3492 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats);
3493 delete pool_stat_options;
3494 }
3495
3496 extern "C" int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
3497 int stat_option,
3498 uint64_t* stat_val) {
3499 auto pool_stat_options =
3500 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats);
3501 return librbd::api::Pool<>::add_stat_option(
3502 pool_stat_options, static_cast<rbd_pool_stat_option_t>(stat_option),
3503 stat_val);
3504 }
3505
3506 extern "C" int rbd_pool_stats_get(
3507 rados_ioctx_t io, rbd_pool_stats_t pool_stats) {
3508 librados::IoCtx io_ctx;
3509 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3510
3511 auto pool_stat_options =
3512 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(pool_stats);
3513 return librbd::api::Pool<>::get_stats(io_ctx, pool_stat_options);
3514 }
3515
3516 extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
3517 const char *destname)
3518 {
3519 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3520 librados::IoCtx dest_io_ctx;
3521 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3522 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
3523 librbd::ImageOptions opts;
3524 librbd::NoOpProgressContext prog_ctx;
3525 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
3526 tracepoint(librbd, copy_exit, r);
3527 return r;
3528 }
3529
3530 extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
3531 {
3532 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
3533 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
3534 tracepoint(librbd, copy2_enter, src, src->name.c_str(), src->snap_name.c_str(), src->read_only, dest, dest->name.c_str(), dest->snap_name.c_str(), dest->read_only);
3535 librbd::NoOpProgressContext prog_ctx;
3536 int r = librbd::copy(src, dest, prog_ctx, 0);
3537 tracepoint(librbd, copy2_exit, r);
3538 return r;
3539 }
3540
3541 extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
3542 const char *destname, rbd_image_options_t c_opts)
3543 {
3544 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3545 librados::IoCtx dest_io_ctx;
3546 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3547 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts);
3548 librbd::ImageOptions c_opts_(c_opts);
3549 librbd::NoOpProgressContext prog_ctx;
3550 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
3551 tracepoint(librbd, copy3_exit, r);
3552 return r;
3553 }
3554
3555 extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
3556 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
3557 {
3558 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3559 librados::IoCtx dest_io_ctx;
3560 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3561 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts, sparse_size);
3562 librbd::ImageOptions c_opts_(c_opts);
3563 librbd::NoOpProgressContext prog_ctx;
3564 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
3565 tracepoint(librbd, copy4_exit, r);
3566 return r;
3567 }
3568
3569 extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
3570 const char *destname,
3571 librbd_progress_fn_t fn, void *data)
3572 {
3573 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3574 librados::IoCtx dest_io_ctx;
3575 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3576 tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
3577 librbd::ImageOptions opts;
3578 librbd::CProgressContext prog_ctx(fn, data);
3579 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
3580 tracepoint(librbd, copy_exit, ret);
3581 return ret;
3582 }
3583
3584 extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
3585 librbd_progress_fn_t fn, void *data)
3586 {
3587 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
3588 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
3589 tracepoint(librbd, copy2_enter, src, src->name.c_str(), src->snap_name.c_str(), src->read_only, dest, dest->name.c_str(), dest->snap_name.c_str(), dest->read_only);
3590 librbd::CProgressContext prog_ctx(fn, data);
3591 int ret = librbd::copy(src, dest, prog_ctx, 0);
3592 tracepoint(librbd, copy2_exit, ret);
3593 return ret;
3594 }
3595
3596 extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
3597 const char *destname,
3598 rbd_image_options_t dest_opts,
3599 librbd_progress_fn_t fn, void *data)
3600 {
3601 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3602 librados::IoCtx dest_io_ctx;
3603 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3604 tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, dest_opts);
3605 librbd::ImageOptions dest_opts_(dest_opts);
3606 librbd::CProgressContext prog_ctx(fn, data);
3607 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
3608 tracepoint(librbd, copy3_exit, ret);
3609 return ret;
3610 }
3611
3612 extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
3613 const char *destname,
3614 rbd_image_options_t dest_opts,
3615 librbd_progress_fn_t fn, void *data, size_t sparse_size)
3616 {
3617 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3618 librados::IoCtx dest_io_ctx;
3619 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3620 tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, dest_opts, sparse_size);
3621 librbd::ImageOptions dest_opts_(dest_opts);
3622 librbd::CProgressContext prog_ctx(fn, data);
3623 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
3624 tracepoint(librbd, copy4_exit, ret);
3625 return ret;
3626 }
3627
3628 extern "C" int rbd_deep_copy(rbd_image_t image, rados_ioctx_t dest_p,
3629 const char *destname, rbd_image_options_t c_opts)
3630 {
3631 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3632 librados::IoCtx dest_io_ctx;
3633 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3634 tracepoint(librbd, deep_copy_enter, ictx, ictx->name.c_str(),
3635 ictx->snap_name.c_str(), ictx->read_only,
3636 dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(),
3637 destname, c_opts);
3638 librbd::ImageOptions opts(c_opts);
3639 librbd::NoOpProgressContext prog_ctx;
3640 int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
3641 prog_ctx);
3642 tracepoint(librbd, deep_copy_exit, r);
3643 return r;
3644 }
3645
3646 extern "C" int rbd_deep_copy_with_progress(rbd_image_t image,
3647 rados_ioctx_t dest_p,
3648 const char *destname,
3649 rbd_image_options_t dest_opts,
3650 librbd_progress_fn_t fn, void *data)
3651 {
3652 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3653 librados::IoCtx dest_io_ctx;
3654 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3655 tracepoint(librbd, deep_copy_enter, ictx, ictx->name.c_str(),
3656 ictx->snap_name.c_str(), ictx->read_only,
3657 dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(),
3658 destname, dest_opts);
3659 librbd::ImageOptions opts(dest_opts);
3660 librbd::CProgressContext prog_ctx(fn, data);
3661 int ret = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
3662 prog_ctx);
3663 tracepoint(librbd, deep_copy_exit, ret);
3664 return ret;
3665 }
3666
3667 extern "C" int rbd_flatten(rbd_image_t image)
3668 {
3669 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3670 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
3671 librbd::NoOpProgressContext prog_ctx;
3672 int r = ictx->operations->flatten(prog_ctx);
3673 tracepoint(librbd, flatten_exit, r);
3674 return r;
3675 }
3676
3677 extern "C" int rbd_flatten_with_progress(rbd_image_t image,
3678 librbd_progress_fn_t cb, void *cbdata)
3679 {
3680 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3681 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
3682 librbd::CProgressContext prog_ctx(cb, cbdata);
3683 int r = ictx->operations->flatten(prog_ctx);
3684 tracepoint(librbd, flatten_exit, r);
3685 return r;
3686 }
3687
3688 extern "C" int rbd_sparsify(rbd_image_t image, size_t sparse_size)
3689 {
3690 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3691 tracepoint(librbd, sparsify_enter, ictx, ictx->name.c_str(), sparse_size,
3692 ictx->id.c_str());
3693 librbd::NoOpProgressContext prog_ctx;
3694 int r = ictx->operations->sparsify(sparse_size, prog_ctx);
3695 tracepoint(librbd, sparsify_exit, r);
3696 return r;
3697 }
3698
3699 extern "C" int rbd_sparsify_with_progress(rbd_image_t image, size_t sparse_size,
3700 librbd_progress_fn_t cb, void *cbdata)
3701 {
3702 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3703 tracepoint(librbd, sparsify_enter, ictx, ictx->name.c_str(), sparse_size,
3704 ictx->id.c_str());
3705 librbd::CProgressContext prog_ctx(cb, cbdata);
3706 int r = ictx->operations->sparsify(sparse_size, prog_ctx);
3707 tracepoint(librbd, sparsify_exit, r);
3708 return r;
3709 }
3710
3711 extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
3712 const char *destname)
3713 {
3714 librados::IoCtx src_io_ctx;
3715 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
3716 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
3717 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
3718 int r = librbd::rename(src_io_ctx, srcname, destname);
3719 tracepoint(librbd, rename_exit, r);
3720 return r;
3721 }
3722
3723 extern "C" int rbd_migration_prepare(rados_ioctx_t p, const char *image_name,
3724 rados_ioctx_t dest_p,
3725 const char *dest_image_name,
3726 rbd_image_options_t opts_)
3727 {
3728 librados::IoCtx io_ctx;
3729 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3730 librados::IoCtx dest_io_ctx;
3731 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
3732 tracepoint(librbd, migration_prepare_enter, io_ctx.get_pool_name().c_str(),
3733 io_ctx.get_id(), image_name, dest_io_ctx.get_pool_name().c_str(),
3734 dest_io_ctx.get_id(), dest_image_name, opts_);
3735 librbd::ImageOptions opts(opts_);
3736 int r = librbd::api::Migration<>::prepare(io_ctx, image_name, dest_io_ctx,
3737 dest_image_name, opts);
3738 tracepoint(librbd, migration_prepare_exit, r);
3739 return r;
3740 }
3741
3742 extern "C" int rbd_migration_execute(rados_ioctx_t p, const char *image_name)
3743 {
3744 librados::IoCtx io_ctx;
3745 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3746 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3747 tracepoint(librbd, migration_execute_enter, io_ctx.get_pool_name().c_str(),
3748 io_ctx.get_id(), image_name);
3749 librbd::NoOpProgressContext prog_ctx;
3750 int r = librbd::api::Migration<>::execute(io_ctx, image_name, prog_ctx);
3751 tracepoint(librbd, migration_execute_exit, r);
3752 return r;
3753 }
3754
3755 extern "C" int rbd_migration_execute_with_progress(rados_ioctx_t p,
3756 const char *name,
3757 librbd_progress_fn_t fn,
3758 void *data)
3759 {
3760 librados::IoCtx io_ctx;
3761 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3762 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3763 tracepoint(librbd, migration_execute_enter, io_ctx.get_pool_name().c_str(),
3764 io_ctx.get_id(), name);
3765 librbd::CProgressContext prog_ctx(fn, data);
3766 int r = librbd::api::Migration<>::execute(io_ctx, name, prog_ctx);
3767 tracepoint(librbd, migration_execute_exit, r);
3768 return r;
3769 }
3770
3771 extern "C" int rbd_migration_abort(rados_ioctx_t p, const char *image_name)
3772 {
3773 librados::IoCtx io_ctx;
3774 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3775 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3776 tracepoint(librbd, migration_abort_enter, io_ctx.get_pool_name().c_str(),
3777 io_ctx.get_id(), image_name);
3778 librbd::NoOpProgressContext prog_ctx;
3779 int r = librbd::api::Migration<>::abort(io_ctx, image_name, prog_ctx);
3780 tracepoint(librbd, migration_abort_exit, r);
3781 return r;
3782 }
3783
3784 extern "C" int rbd_migration_abort_with_progress(rados_ioctx_t p,
3785 const char *name,
3786 librbd_progress_fn_t fn,
3787 void *data)
3788 {
3789 librados::IoCtx io_ctx;
3790 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3791 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3792 tracepoint(librbd, migration_abort_enter, io_ctx.get_pool_name().c_str(),
3793 io_ctx.get_id(), name);
3794 librbd::CProgressContext prog_ctx(fn, data);
3795 int r = librbd::api::Migration<>::abort(io_ctx, name, prog_ctx);
3796 tracepoint(librbd, migration_abort_exit, r);
3797 return r;
3798 }
3799
3800 extern "C" int rbd_migration_commit(rados_ioctx_t p, const char *image_name)
3801 {
3802 librados::IoCtx io_ctx;
3803 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3804 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3805 tracepoint(librbd, migration_commit_enter, io_ctx.get_pool_name().c_str(),
3806 io_ctx.get_id(), image_name);
3807 librbd::NoOpProgressContext prog_ctx;
3808 int r = librbd::api::Migration<>::commit(io_ctx, image_name, prog_ctx);
3809 tracepoint(librbd, migration_commit_exit, r);
3810 return r;
3811 }
3812
3813 extern "C" int rbd_migration_commit_with_progress(rados_ioctx_t p,
3814 const char *name,
3815 librbd_progress_fn_t fn,
3816 void *data)
3817 {
3818 librados::IoCtx io_ctx;
3819 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3820 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3821 tracepoint(librbd, migration_commit_enter, io_ctx.get_pool_name().c_str(),
3822 io_ctx.get_id(), name);
3823 librbd::CProgressContext prog_ctx(fn, data);
3824 int r = librbd::api::Migration<>::commit(io_ctx, name, prog_ctx);
3825 tracepoint(librbd, migration_commit_exit, r);
3826 return r;
3827 }
3828
3829 extern "C" int rbd_migration_status(rados_ioctx_t p, const char *image_name,
3830 rbd_image_migration_status_t *status,
3831 size_t status_size)
3832 {
3833 librados::IoCtx io_ctx;
3834 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3835 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3836 tracepoint(librbd, migration_status_enter, io_ctx.get_pool_name().c_str(),
3837 io_ctx.get_id(), image_name);
3838
3839 if (status_size != sizeof(rbd_image_migration_status_t)) {
3840 tracepoint(librbd, migration_status_exit, -ERANGE);
3841 return -ERANGE;
3842 }
3843
3844 librbd::image_migration_status_t cpp_status;
3845 int r = librbd::api::Migration<>::status(io_ctx, image_name, &cpp_status);
3846 if (r >= 0) {
3847 status->source_pool_id = cpp_status.source_pool_id;
3848 status->source_pool_namespace =
3849 strdup(cpp_status.source_pool_namespace.c_str());
3850 status->source_image_name = strdup(cpp_status.source_image_name.c_str());
3851 status->source_image_id = strdup(cpp_status.source_image_id.c_str());
3852 status->dest_pool_id = cpp_status.dest_pool_id;
3853 status->dest_pool_namespace =
3854 strdup(cpp_status.dest_pool_namespace.c_str());
3855 status->dest_image_name = strdup(cpp_status.dest_image_name.c_str());
3856 status->dest_image_id = strdup(cpp_status.dest_image_id.c_str());
3857 status->state = cpp_status.state;
3858 status->state_description = strdup(cpp_status.state_description.c_str());
3859 }
3860
3861 tracepoint(librbd, migration_status_exit, r);
3862 return r;
3863 }
3864
3865 extern "C" void rbd_migration_status_cleanup(rbd_image_migration_status_t *s)
3866 {
3867 free(s->source_pool_namespace);
3868 free(s->source_image_name);
3869 free(s->source_image_id);
3870 free(s->dest_pool_namespace);
3871 free(s->dest_image_name);
3872 free(s->dest_image_id);
3873 free(s->state_description);
3874 }
3875
3876 extern "C" int rbd_pool_metadata_get(rados_ioctx_t p, const char *key,
3877 char *value, size_t *vallen)
3878 {
3879 librados::IoCtx io_ctx;
3880 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3881 string val_s;
3882 int r = librbd::api::PoolMetadata<>::get(io_ctx, key, &val_s);
3883 if (*vallen < val_s.size() + 1) {
3884 r = -ERANGE;
3885 *vallen = val_s.size() + 1;
3886 } else {
3887 strncpy(value, val_s.c_str(), val_s.size() + 1);
3888 }
3889
3890 return r;
3891 }
3892
3893 extern "C" int rbd_pool_metadata_set(rados_ioctx_t p, const char *key,
3894 const char *value)
3895 {
3896 librados::IoCtx io_ctx;
3897 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3898 int r = librbd::api::PoolMetadata<>::set(io_ctx, key, value);
3899 return r;
3900 }
3901
3902 extern "C" int rbd_pool_metadata_remove(rados_ioctx_t p, const char *key)
3903 {
3904 librados::IoCtx io_ctx;
3905 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3906 int r = librbd::api::PoolMetadata<>::remove(io_ctx, key);
3907 return r;
3908 }
3909
3910 extern "C" int rbd_pool_metadata_list(rados_ioctx_t p, const char *start,
3911 uint64_t max, char *key, size_t *key_len,
3912 char *value, size_t *val_len)
3913 {
3914 librados::IoCtx io_ctx;
3915 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3916 map<string, bufferlist> pairs;
3917 int r = librbd::api::PoolMetadata<>::list(io_ctx, start, max, &pairs);
3918 if (r < 0) {
3919 return r;
3920 }
3921 size_t key_total_len = 0, val_total_len = 0;
3922 for (auto &it : pairs) {
3923 key_total_len += it.first.size() + 1;
3924 val_total_len += it.second.length() + 1;
3925 }
3926 if (*key_len < key_total_len || *val_len < val_total_len) {
3927 *key_len = key_total_len;
3928 *val_len = val_total_len;
3929 return -ERANGE;
3930 }
3931 *key_len = key_total_len;
3932 *val_len = val_total_len;
3933
3934 char *key_p = key, *value_p = value;
3935 for (auto &it : pairs) {
3936 strncpy(key_p, it.first.c_str(), it.first.size() + 1);
3937 key_p += it.first.size() + 1;
3938 strncpy(value_p, it.second.c_str(), it.second.length());
3939 value_p += it.second.length();
3940 *value_p = '\0';
3941 value_p++;
3942 }
3943 return 0;
3944 }
3945
3946 extern "C" int rbd_config_pool_list(rados_ioctx_t p,
3947 rbd_config_option_t *options,
3948 int *max_options) {
3949 librados::IoCtx io_ctx;
3950 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3951
3952 std::vector<librbd::config_option_t> option_vector;
3953 int r = librbd::api::Config<>::list(io_ctx, &option_vector);
3954 if (r < 0) {
3955 return r;
3956 }
3957
3958 if (*max_options < static_cast<int>(option_vector.size())) {
3959 *max_options = static_cast<int>(option_vector.size());
3960 return -ERANGE;
3961 }
3962
3963 for (int i = 0; i < static_cast<int>(option_vector.size()); ++i) {
3964 config_option_cpp_to_c(option_vector[i], &options[i]);
3965 }
3966 *max_options = static_cast<int>(option_vector.size());
3967 return 0;
3968 }
3969
3970 extern "C" void rbd_config_pool_list_cleanup(rbd_config_option_t *options,
3971 int max_options) {
3972 for (int i = 0; i < max_options; ++i) {
3973 config_option_cleanup(options[i]);
3974 }
3975 }
3976
3977 extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
3978 const char *snap_name)
3979 {
3980 librados::IoCtx io_ctx;
3981 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3982 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3983 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
3984 false);
3985 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3986
3987 int r = ictx->state->open(0);
3988 if (r >= 0) {
3989 *image = (rbd_image_t)ictx;
3990 }
3991 tracepoint(librbd, open_image_exit, r);
3992 return r;
3993 }
3994
3995 extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
3996 rbd_image_t *image, const char *snap_name)
3997 {
3998 librados::IoCtx io_ctx;
3999 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4000 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4001 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4002 false);
4003 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
4004 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4005
4006 int r = ictx->state->open(0);
4007 if (r < 0) {
4008 delete ictx;
4009 } else {
4010 *image = (rbd_image_t)ictx;
4011 }
4012 tracepoint(librbd, open_image_exit, r);
4013 return r;
4014 }
4015
4016 extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
4017 rbd_image_t *image, const char *snap_name,
4018 rbd_completion_t c)
4019 {
4020 librados::IoCtx io_ctx;
4021 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4022 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4023 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4024 false);
4025 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4026 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
4027 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4028 image));
4029 tracepoint(librbd, aio_open_image_exit, 0);
4030 return 0;
4031 }
4032
4033 extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
4034 rbd_image_t *image, const char *snap_name,
4035 rbd_completion_t c)
4036 {
4037 librados::IoCtx io_ctx;
4038 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4039 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4040 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4041 false);
4042 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4043 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
4044 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
4045 comp->pc);
4046 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4047 image));
4048 tracepoint(librbd, aio_open_image_exit, 0);
4049 return 0;
4050 }
4051
4052 extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
4053 rbd_image_t *image, const char *snap_name)
4054 {
4055 librados::IoCtx io_ctx;
4056 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4057 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4058 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4059 true);
4060 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4061
4062 int r = ictx->state->open(0);
4063 if (r >= 0) {
4064 *image = (rbd_image_t)ictx;
4065 }
4066 tracepoint(librbd, open_image_exit, r);
4067 return r;
4068 }
4069
4070 extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
4071 rbd_image_t *image, const char *snap_name)
4072 {
4073 librados::IoCtx io_ctx;
4074 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4075 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4076 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4077 true);
4078 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
4079 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4080
4081 int r = ictx->state->open(0);
4082 if (r < 0) {
4083 delete ictx;
4084 } else {
4085 *image = (rbd_image_t)ictx;
4086 }
4087 tracepoint(librbd, open_image_exit, r);
4088 return r;
4089 }
4090
4091 extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
4092 rbd_image_t *image, const char *snap_name,
4093 rbd_completion_t c)
4094 {
4095 librados::IoCtx io_ctx;
4096 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4097 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4098 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4099 true);
4100 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4101 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
4102 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4103 image));
4104 tracepoint(librbd, aio_open_image_exit, 0);
4105 return 0;
4106 }
4107
4108 extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
4109 rbd_image_t *image,
4110 const char *snap_name,
4111 rbd_completion_t c)
4112 {
4113 librados::IoCtx io_ctx;
4114 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4115 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4116 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4117 true);
4118 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4119 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
4120 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
4121 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4122 image));
4123 tracepoint(librbd, aio_open_image_exit, 0);
4124 return 0;
4125 }
4126
4127 extern "C" int rbd_close(rbd_image_t image)
4128 {
4129 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4130 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
4131
4132 int r = ictx->state->close();
4133
4134 tracepoint(librbd, close_image_exit, r);
4135 return r;
4136 }
4137
4138 extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
4139 {
4140 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4141 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4142 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
4143 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
4144 get_aio_completion(comp)));
4145 tracepoint(librbd, aio_close_image_exit, 0);
4146 return 0;
4147 }
4148
4149 extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
4150 {
4151 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4152 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
4153 librbd::NoOpProgressContext prog_ctx;
4154 int r = ictx->operations->resize(size, true, prog_ctx);
4155 tracepoint(librbd, resize_exit, r);
4156 return r;
4157 }
4158
4159 extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
4160 librbd_progress_fn_t cb, void *cbdata)
4161 {
4162 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4163 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
4164 librbd::CProgressContext prog_ctx(cb, cbdata);
4165 int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
4166 tracepoint(librbd, resize_exit, r);
4167 return r;
4168 }
4169
4170 extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
4171 librbd_progress_fn_t cb, void *cbdata)
4172 {
4173 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4174 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
4175 librbd::CProgressContext prog_ctx(cb, cbdata);
4176 int r = ictx->operations->resize(size, true, prog_ctx);
4177 tracepoint(librbd, resize_exit, r);
4178 return r;
4179 }
4180
4181 extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
4182 size_t infosize)
4183 {
4184 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4185 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4186 int r = librbd::info(ictx, *info, infosize);
4187 tracepoint(librbd, stat_exit, r, info);
4188 return r;
4189 }
4190
4191 extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
4192 {
4193 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4194 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4195 int r = librbd::get_old_format(ictx, old);
4196 tracepoint(librbd, get_old_format_exit, r, *old);
4197 return r;
4198 }
4199
4200 extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
4201 {
4202 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4203 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4204 int r = librbd::get_size(ictx, size);
4205 tracepoint(librbd, get_size_exit, r, *size);
4206 return r;
4207 }
4208
4209 extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
4210 {
4211 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4212 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4213 int r = librbd::get_features(ictx, features);
4214 tracepoint(librbd, get_features_exit, r, *features);
4215 return r;
4216 }
4217
4218 extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
4219 uint8_t enabled)
4220 {
4221 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4222 bool features_enabled = enabled != 0;
4223 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
4224 int r = ictx->operations->update_features(features, features_enabled);
4225 tracepoint(librbd, update_features_exit, r);
4226 return r;
4227 }
4228
4229 extern "C" int rbd_get_op_features(rbd_image_t image, uint64_t *op_features)
4230 {
4231 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4232 return librbd::api::Image<>::get_op_features(ictx, op_features);
4233 }
4234
4235 extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
4236 {
4237 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4238 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4239 *stripe_unit = ictx->get_stripe_unit();
4240 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
4241 return 0;
4242 }
4243
4244 extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
4245 {
4246 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4247 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4248 *stripe_count = ictx->get_stripe_count();
4249 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
4250 return 0;
4251 }
4252
4253 extern "C" int rbd_get_create_timestamp(rbd_image_t image,
4254 struct timespec *timestamp)
4255 {
4256 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4257 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
4258 ictx->read_only);
4259 utime_t time = ictx->get_create_timestamp();
4260 time.to_timespec(timestamp);
4261 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
4262 return 0;
4263 }
4264
4265 extern "C" int rbd_get_access_timestamp(rbd_image_t image,
4266 struct timespec *timestamp)
4267 {
4268 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4269 tracepoint(librbd, get_access_timestamp_enter, ictx, ictx->name.c_str(),
4270 ictx->read_only);
4271 utime_t time = ictx->get_access_timestamp();
4272 time.to_timespec(timestamp);
4273 tracepoint(librbd, get_access_timestamp_exit, 0, timestamp);
4274 return 0;
4275 }
4276
4277 extern "C" int rbd_get_modify_timestamp(rbd_image_t image,
4278 struct timespec *timestamp)
4279 {
4280 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4281 tracepoint(librbd, get_modify_timestamp_enter, ictx, ictx->name.c_str(),
4282 ictx->read_only);
4283 utime_t time = ictx->get_modify_timestamp();
4284 time.to_timespec(timestamp);
4285 tracepoint(librbd, get_modify_timestamp_exit, 0, timestamp);
4286 return 0;
4287 }
4288
4289
4290 extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
4291 {
4292 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4293 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4294 int r = librbd::get_overlap(ictx, overlap);
4295 tracepoint(librbd, get_overlap_exit, r, *overlap);
4296 return r;
4297 }
4298
4299 extern "C" int rbd_get_name(rbd_image_t image, char *name, size_t *name_len)
4300 {
4301 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4302 if (*name_len <= ictx->name.size()) {
4303 *name_len = ictx->name.size() + 1;
4304 return -ERANGE;
4305 }
4306
4307 strncpy(name, ictx->name.c_str(), ictx->name.size());
4308 name[ictx->name.size()] = '\0';
4309 *name_len = ictx->name.size() + 1;
4310 return 0;
4311 }
4312
4313 extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
4314 {
4315 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4316 if (ictx->old_format) {
4317 return -EINVAL;
4318 }
4319 if (ictx->id.size() >= id_len) {
4320 return -ERANGE;
4321 }
4322
4323 strncpy(id, ictx->id.c_str(), id_len - 1);
4324 id[id_len - 1] = '\0';
4325 return 0;
4326 }
4327
4328 extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
4329 size_t prefix_len)
4330 {
4331 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4332 if (ictx->object_prefix.size() >= prefix_len) {
4333 return -ERANGE;
4334 }
4335
4336 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
4337 prefix[prefix_len - 1] = '\0';
4338 return 0;
4339 }
4340
4341 extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
4342 {
4343 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4344 return librbd::api::Image<>::get_data_pool_id(ictx);
4345 }
4346
4347 extern "C" int rbd_get_parent_info(rbd_image_t image,
4348 char *parent_pool_name, size_t ppool_namelen,
4349 char *parent_name, size_t pnamelen,
4350 char *parent_snap_name, size_t psnap_namelen)
4351 {
4352 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4353 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
4354 ictx->snap_name.c_str(), ictx->read_only);
4355
4356 librbd::linked_image_spec_t parent_image;
4357 librbd::snap_spec_t parent_snap;
4358 int r = librbd::api::Image<>::get_parent(ictx, &parent_image, &parent_snap);
4359 if (r >= 0) {
4360 if (parent_pool_name) {
4361 if (parent_image.pool_name.length() + 1 > ppool_namelen) {
4362 r = -ERANGE;
4363 } else {
4364 strcpy(parent_pool_name, parent_image.pool_name.c_str());
4365 }
4366 }
4367 if (parent_name) {
4368 if (parent_image.image_name.length() + 1 > pnamelen) {
4369 r = -ERANGE;
4370 } else {
4371 strcpy(parent_name, parent_image.image_name.c_str());
4372 }
4373 }
4374 if (parent_snap_name) {
4375 if (parent_snap.name.length() + 1 > psnap_namelen) {
4376 r = -ERANGE;
4377 } else {
4378 strcpy(parent_snap_name, parent_snap.name.c_str());
4379 }
4380 }
4381 }
4382
4383 if (r < 0) {
4384 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
4385 return r;
4386 }
4387
4388 tracepoint(librbd, get_parent_info_exit, r,
4389 parent_image.pool_name.c_str(),
4390 parent_image.image_name.c_str(),
4391 parent_image.image_id.c_str(),
4392 parent_snap.name.c_str());
4393 return 0;
4394 }
4395
4396 extern "C" int rbd_get_parent_info2(rbd_image_t image,
4397 char *parent_pool_name,
4398 size_t ppool_namelen,
4399 char *parent_name, size_t pnamelen,
4400 char *parent_id, size_t pidlen,
4401 char *parent_snap_name,
4402 size_t psnap_namelen)
4403 {
4404 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4405 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
4406 ictx->snap_name.c_str(), ictx->read_only);
4407
4408 librbd::linked_image_spec_t parent_image;
4409 librbd::snap_spec_t parent_snap;
4410 int r = librbd::api::Image<>::get_parent(ictx, &parent_image, &parent_snap);
4411 if (r >= 0) {
4412 if (parent_pool_name) {
4413 if (parent_image.pool_name.length() + 1 > ppool_namelen) {
4414 r = -ERANGE;
4415 } else {
4416 strcpy(parent_pool_name, parent_image.pool_name.c_str());
4417 }
4418 }
4419 if (parent_name) {
4420 if (parent_image.image_name.length() + 1 > pnamelen) {
4421 r = -ERANGE;
4422 } else {
4423 strcpy(parent_name, parent_image.image_name.c_str());
4424 }
4425 }
4426 if (parent_id) {
4427 if (parent_image.image_id.length() + 1 > pidlen) {
4428 r = -ERANGE;
4429 } else {
4430 strcpy(parent_id, parent_image.image_id.c_str());
4431 }
4432 }
4433 if (parent_snap_name) {
4434 if (parent_snap.name.length() + 1 > psnap_namelen) {
4435 r = -ERANGE;
4436 } else {
4437 strcpy(parent_snap_name, parent_snap.name.c_str());
4438 }
4439 }
4440 }
4441
4442 if (r < 0) {
4443 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
4444 return r;
4445 }
4446
4447 tracepoint(librbd, get_parent_info_exit, r,
4448 parent_image.pool_name.c_str(),
4449 parent_image.image_name.c_str(),
4450 parent_image.image_id.c_str(),
4451 parent_snap.name.c_str());
4452 return 0;
4453 }
4454
4455 extern "C" int rbd_get_parent(rbd_image_t image,
4456 rbd_linked_image_spec_t *parent_image,
4457 rbd_snap_spec_t *parent_snap)
4458 {
4459 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4460 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
4461 ictx->snap_name.c_str(), ictx->read_only);
4462
4463 librbd::linked_image_spec_t cpp_parent_image;
4464 librbd::snap_spec_t cpp_parent_snap;
4465 int r = librbd::api::Image<>::get_parent(ictx, &cpp_parent_image,
4466 &cpp_parent_snap);
4467 if (r < 0) {
4468 memset(parent_image, 0, sizeof(rbd_linked_image_spec_t));
4469 memset(parent_snap, 0, sizeof(rbd_snap_spec_t));
4470 } else {
4471 *parent_image = {
4472 .pool_id = cpp_parent_image.pool_id,
4473 .pool_name = strdup(cpp_parent_image.pool_name.c_str()),
4474 .pool_namespace = strdup(cpp_parent_image.pool_namespace.c_str()),
4475 .image_id = strdup(cpp_parent_image.image_id.c_str()),
4476 .image_name = strdup(cpp_parent_image.image_name.c_str()),
4477 .trash = cpp_parent_image.trash};
4478 *parent_snap = {
4479 .id = cpp_parent_snap.id,
4480 .namespace_type = cpp_parent_snap.namespace_type,
4481 .name = strdup(cpp_parent_snap.name.c_str())};
4482 }
4483
4484 tracepoint(librbd, get_parent_info_exit, r,
4485 parent_image->pool_name,
4486 parent_image->image_name,
4487 parent_image->image_id,
4488 parent_snap->name);
4489 return r;
4490 }
4491
4492 extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
4493 {
4494 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4495 tracepoint(librbd, get_flags_enter, ictx);
4496 int r = librbd::get_flags(ictx, flags);
4497 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
4498 return r;
4499 }
4500
4501 extern "C" int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info,
4502 size_t group_info_size)
4503 {
4504 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4505 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
4506
4507 if (group_info_size != sizeof(rbd_group_info_t)) {
4508 tracepoint(librbd, image_get_group_exit, -ERANGE);
4509 return -ERANGE;
4510 }
4511
4512 librbd::group_info_t cpp_group_info;
4513 int r = librbd::api::Group<>::image_get_group(ictx, &cpp_group_info);
4514 if (r >= 0) {
4515 group_info_cpp_to_c(cpp_group_info, group_info);
4516 } else {
4517 group_info->name = NULL;
4518 }
4519
4520 tracepoint(librbd, image_get_group_exit, r);
4521 return r;
4522 }
4523
4524 extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
4525 {
4526 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4527 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
4528 int r = librbd::set_image_notification(ictx, fd, type);
4529 tracepoint(librbd, set_image_notification_exit, ictx, r);
4530 return r;
4531 }
4532
4533 extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
4534 {
4535 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4536 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
4537 bool owner;
4538 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
4539 *is_owner = owner ? 1 : 0;
4540 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
4541 return r;
4542 }
4543
4544 extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
4545 {
4546 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4547 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
4548 int r = librbd::lock_acquire(ictx, lock_mode);
4549 tracepoint(librbd, lock_acquire_exit, ictx, r);
4550 return r;
4551 }
4552
4553 extern "C" int rbd_lock_release(rbd_image_t image)
4554 {
4555 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4556 tracepoint(librbd, lock_release_enter, ictx);
4557 int r = librbd::lock_release(ictx);
4558 tracepoint(librbd, lock_release_exit, ictx, r);
4559 return r;
4560 }
4561
4562 extern "C" int rbd_lock_get_owners(rbd_image_t image,
4563 rbd_lock_mode_t *lock_mode,
4564 char **lock_owners,
4565 size_t *max_lock_owners)
4566 {
4567 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4568 tracepoint(librbd, lock_get_owners_enter, ictx);
4569 memset(lock_owners, 0, sizeof(*lock_owners) * *max_lock_owners);
4570 std::list<std::string> lock_owner_list;
4571 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
4572 if (r >= 0) {
4573 if (*max_lock_owners >= lock_owner_list.size()) {
4574 *max_lock_owners = 0;
4575 for (auto &lock_owner : lock_owner_list) {
4576 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
4577 }
4578 } else {
4579 *max_lock_owners = lock_owner_list.size();
4580 r = -ERANGE;
4581 }
4582 }
4583 tracepoint(librbd, lock_get_owners_exit, ictx, r);
4584 return r;
4585 }
4586
4587 extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
4588 size_t lock_owner_count)
4589 {
4590 for (size_t i = 0; i < lock_owner_count; ++i) {
4591 free(lock_owners[i]);
4592 }
4593 }
4594
4595 extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
4596 const char *lock_owner)
4597 {
4598 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4599 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
4600 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
4601 tracepoint(librbd, lock_break_exit, ictx, r);
4602 return r;
4603 }
4604
4605 extern "C" int rbd_rebuild_object_map(rbd_image_t image,
4606 librbd_progress_fn_t cb, void *cbdata)
4607 {
4608 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4609 librbd::CProgressContext prog_ctx(cb, cbdata);
4610 return ictx->operations->rebuild_object_map(prog_ctx);
4611 }
4612
4613 /* snapshots */
4614 extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
4615 {
4616 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4617 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4618 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
4619 snap_name);
4620 tracepoint(librbd, snap_create_exit, r);
4621 return r;
4622 }
4623
4624 extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
4625 {
4626 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4627 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
4628 int r = ictx->operations->snap_rename(srcname, dstname);
4629 tracepoint(librbd, snap_rename_exit, r);
4630 return r;
4631 }
4632
4633 extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
4634 {
4635 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4636 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4637 librbd::NoOpProgressContext prog_ctx;
4638 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
4639 tracepoint(librbd, snap_remove_exit, r);
4640 return r;
4641 }
4642
4643 extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
4644 librbd_progress_fn_t cb, void *cbdata)
4645 {
4646 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4647 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
4648 librbd::CProgressContext prog_ctx(cb, cbdata);
4649 int r = librbd::snap_remove(ictx, snap_name, flags, prog_ctx);
4650 tracepoint(librbd, snap_remove_exit, r);
4651 return r;
4652 }
4653
4654 extern "C" int rbd_snap_remove_by_id(rbd_image_t image, uint64_t snap_id)
4655 {
4656 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4657 return librbd::api::Snapshot<>::remove(ictx, snap_id);
4658 }
4659
4660 extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
4661 {
4662 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4663 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4664 librbd::NoOpProgressContext prog_ctx;
4665 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
4666 tracepoint(librbd, snap_rollback_exit, r);
4667 return r;
4668 }
4669
4670 extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
4671 const char *snap_name,
4672 librbd_progress_fn_t cb,
4673 void *cbdata)
4674 {
4675 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4676 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4677 librbd::CProgressContext prog_ctx(cb, cbdata);
4678 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
4679 tracepoint(librbd, snap_rollback_exit, r);
4680 return r;
4681 }
4682
4683 extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
4684 int *max_snaps)
4685 {
4686 vector<librbd::snap_info_t> cpp_snaps;
4687 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4688 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
4689
4690 if (!max_snaps) {
4691 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
4692 return -EINVAL;
4693 }
4694 memset(snaps, 0, sizeof(*snaps) * *max_snaps);
4695
4696 int r = librbd::snap_list(ictx, cpp_snaps);
4697 if (r == -ENOENT) {
4698 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
4699 return 0;
4700 }
4701 if (r < 0) {
4702 tracepoint(librbd, snap_list_exit, r, *max_snaps);
4703 return r;
4704 }
4705 if (*max_snaps < (int)cpp_snaps.size() + 1) {
4706 *max_snaps = (int)cpp_snaps.size() + 1;
4707 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
4708 return -ERANGE;
4709 }
4710
4711 int i;
4712
4713 for (i = 0; i < (int)cpp_snaps.size(); i++) {
4714 snaps[i].id = cpp_snaps[i].id;
4715 snaps[i].size = cpp_snaps[i].size;
4716 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
4717 if (!snaps[i].name) {
4718 for (int j = 0; j < i; j++)
4719 free((void *)snaps[j].name);
4720 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
4721 return -ENOMEM;
4722 }
4723 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
4724 }
4725 snaps[i].id = 0;
4726 snaps[i].size = 0;
4727 snaps[i].name = NULL;
4728
4729 r = (int)cpp_snaps.size();
4730 tracepoint(librbd, snap_list_exit, r, *max_snaps);
4731 return r;
4732 }
4733
4734 extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
4735 {
4736 tracepoint(librbd, snap_list_end_enter, snaps);
4737 while (snaps->name) {
4738 free((void *)snaps->name);
4739 snaps++;
4740 }
4741 tracepoint(librbd, snap_list_end_exit);
4742 }
4743
4744 extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
4745 {
4746 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4747 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4748 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
4749 tracepoint(librbd, snap_protect_exit, r);
4750 return r;
4751 }
4752
4753 extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
4754 {
4755 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4756 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4757 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
4758 tracepoint(librbd, snap_unprotect_exit, r);
4759 return r;
4760 }
4761
4762 extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
4763 int *is_protected)
4764 {
4765 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4766 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4767 bool protected_snap;
4768 int r = librbd::snap_is_protected(ictx, snap_name, &protected_snap);
4769 if (r < 0) {
4770 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
4771 return r;
4772 }
4773 *is_protected = protected_snap ? 1 : 0;
4774 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
4775 return 0;
4776 }
4777
4778 extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
4779 {
4780 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4781 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
4782 int r = librbd::snap_get_limit(ictx, limit);
4783 tracepoint(librbd, snap_get_limit_exit, r, *limit);
4784 return r;
4785 }
4786
4787 extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
4788 {
4789 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4790 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
4791 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
4792 tracepoint(librbd, snap_get_timestamp_exit, r);
4793 return r;
4794 }
4795
4796 extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
4797 {
4798 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4799 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
4800 int r = librbd::snap_set_limit(ictx, limit);
4801 tracepoint(librbd, snap_set_limit_exit, r);
4802 return r;
4803 }
4804
4805 extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
4806 {
4807 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4808 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
4809 int r = librbd::api::Image<>::snap_set(
4810 ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
4811 tracepoint(librbd, snap_set_exit, r);
4812 return r;
4813 }
4814
4815 extern "C" int rbd_snap_set_by_id(rbd_image_t image, uint64_t snap_id)
4816 {
4817 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4818 return librbd::api::Image<>::snap_set(ictx, snap_id);
4819 }
4820
4821 extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
4822 size_t *pools_len, char *images,
4823 size_t *images_len)
4824 {
4825 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4826 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
4827 ictx->snap_name.c_str(), ictx->read_only);
4828
4829 std::vector<librbd::linked_image_spec_t> cpp_images;
4830 int r = librbd::api::Image<>::list_children(ictx, &cpp_images);
4831 if (r < 0) {
4832 tracepoint(librbd, list_children_exit, r);
4833 return r;
4834 }
4835
4836 std::set<std::pair<std::string, std::string>> image_set;
4837 for (auto& image : cpp_images) {
4838 if (!image.trash) {
4839 image_set.insert({image.pool_name, image.image_name});
4840 }
4841 }
4842
4843 size_t pools_total = 0;
4844 size_t images_total = 0;
4845 for (auto it : image_set) {
4846 pools_total += it.first.length() + 1;
4847 images_total += it.second.length() + 1;
4848 }
4849
4850 bool too_short = false;
4851 if (pools_total > *pools_len)
4852 too_short = true;
4853 if (images_total > *images_len)
4854 too_short = true;
4855 *pools_len = pools_total;
4856 *images_len = images_total;
4857 if (too_short) {
4858 tracepoint(librbd, list_children_exit, -ERANGE);
4859 return -ERANGE;
4860 }
4861
4862 char *pools_p = pools;
4863 char *images_p = images;
4864 for (auto it : image_set) {
4865 const char* pool = it.first.c_str();
4866 strcpy(pools_p, pool);
4867 pools_p += it.first.length() + 1;
4868 const char* image = it.second.c_str();
4869 strcpy(images_p, image);
4870 images_p += it.second.length() + 1;
4871 tracepoint(librbd, list_children_entry, pool, image);
4872 }
4873
4874 ssize_t ret = image_set.size();
4875 tracepoint(librbd, list_children_exit, ret);
4876 return ret;
4877 }
4878
4879 extern "C" int rbd_list_children2(rbd_image_t image,
4880 rbd_child_info_t *children,
4881 int *max_children)
4882 {
4883 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4884 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
4885 ictx->snap_name.c_str(), ictx->read_only);
4886 memset(children, 0, sizeof(*children) * *max_children);
4887
4888 if (!max_children) {
4889 tracepoint(librbd, list_children_exit, -EINVAL);
4890 return -EINVAL;
4891 }
4892
4893 std::vector<librbd::linked_image_spec_t> cpp_children;
4894 int r = librbd::api::Image<>::list_children(ictx, &cpp_children);
4895 if (r < 0) {
4896 tracepoint(librbd, list_children_exit, r);
4897 return r;
4898 }
4899
4900 if (*max_children < (int)cpp_children.size() + 1) {
4901 *max_children = (int)cpp_children.size() + 1;
4902 tracepoint(librbd, list_children_exit, *max_children);
4903 return -ERANGE;
4904 }
4905
4906 int i;
4907 for (i = 0; i < (int)cpp_children.size(); i++) {
4908 children[i].pool_name = strdup(cpp_children[i].pool_name.c_str());
4909 children[i].image_name = strdup(cpp_children[i].image_name.c_str());
4910 children[i].image_id = strdup(cpp_children[i].image_id.c_str());
4911 children[i].trash = cpp_children[i].trash;
4912 tracepoint(librbd, list_children_entry, children[i].pool_name,
4913 children[i].image_name);
4914 }
4915 children[i].pool_name = NULL;
4916 children[i].image_name = NULL;
4917 children[i].image_id = NULL;
4918
4919 r = (int)cpp_children.size();
4920 tracepoint(librbd, list_children_exit, *max_children);
4921 return r;
4922 }
4923
4924 extern "C" void rbd_list_child_cleanup(rbd_child_info_t *child)
4925 {
4926 free((void *)child->pool_name);
4927 free((void *)child->image_name);
4928 free((void *)child->image_id);
4929 }
4930
4931 extern "C" void rbd_list_children_cleanup(rbd_child_info_t *children,
4932 size_t num_children)
4933 {
4934 for (size_t i=0; i < num_children; i++) {
4935 free((void *)children[i].pool_name);
4936 free((void *)children[i].image_name);
4937 free((void *)children[i].image_id);
4938 }
4939 }
4940
4941 extern "C" int rbd_list_children3(rbd_image_t image,
4942 rbd_linked_image_spec_t *images,
4943 size_t *max_images)
4944 {
4945 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4946 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
4947 ictx->snap_name.c_str(), ictx->read_only);
4948 memset(images, 0, sizeof(*images) * *max_images);
4949
4950 std::vector<librbd::linked_image_spec_t> cpp_children;
4951 int r = librbd::api::Image<>::list_children(ictx, &cpp_children);
4952 if (r < 0) {
4953 tracepoint(librbd, list_children_exit, r);
4954 return r;
4955 }
4956
4957 if (*max_images < cpp_children.size()) {
4958 *max_images = cpp_children.size();
4959 return -ERANGE;
4960 }
4961
4962 *max_images = cpp_children.size();
4963 for (size_t idx = 0; idx < cpp_children.size(); ++idx) {
4964 images[idx] = {
4965 .pool_id = cpp_children[idx].pool_id,
4966 .pool_name = strdup(cpp_children[idx].pool_name.c_str()),
4967 .pool_namespace = strdup(cpp_children[idx].pool_namespace.c_str()),
4968 .image_id = strdup(cpp_children[idx].image_id.c_str()),
4969 .image_name = strdup(cpp_children[idx].image_name.c_str()),
4970 .trash = cpp_children[idx].trash};
4971 tracepoint(librbd, list_children_entry, images[idx].pool_name,
4972 images[idx].image_name);
4973 }
4974 return 0;
4975 }
4976
4977 extern "C" int rbd_list_descendants(rbd_image_t image,
4978 rbd_linked_image_spec_t *images,
4979 size_t *max_images)
4980 {
4981 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4982 memset(images, 0, sizeof(*images) * *max_images);
4983
4984 std::vector<librbd::linked_image_spec_t> cpp_children;
4985 int r = librbd::api::Image<>::list_descendants(ictx, {}, &cpp_children);
4986 if (r < 0) {
4987 return r;
4988 }
4989
4990 if (*max_images < cpp_children.size()) {
4991 *max_images = cpp_children.size();
4992 return -ERANGE;
4993 }
4994
4995 *max_images = cpp_children.size();
4996 for (size_t idx = 0; idx < cpp_children.size(); ++idx) {
4997 images[idx] = {
4998 .pool_id = cpp_children[idx].pool_id,
4999 .pool_name = strdup(cpp_children[idx].pool_name.c_str()),
5000 .pool_namespace = strdup(cpp_children[idx].pool_namespace.c_str()),
5001 .image_id = strdup(cpp_children[idx].image_id.c_str()),
5002 .image_name = strdup(cpp_children[idx].image_name.c_str()),
5003 .trash = cpp_children[idx].trash};
5004 }
5005 return 0;
5006 }
5007
5008 extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
5009 char *tag, size_t *tag_len,
5010 char *clients, size_t *clients_len,
5011 char *cookies, size_t *cookies_len,
5012 char *addrs, size_t *addrs_len)
5013 {
5014 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5015 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
5016 std::list<librbd::locker_t> lockers;
5017 bool exclusive_bool;
5018 string tag_str;
5019
5020 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
5021 if (r < 0) {
5022 tracepoint(librbd, list_lockers_exit, r);
5023 return r;
5024 }
5025
5026 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
5027
5028 *exclusive = (int)exclusive_bool;
5029 size_t clients_total = 0;
5030 size_t cookies_total = 0;
5031 size_t addrs_total = 0;
5032 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
5033 it != lockers.end(); ++it) {
5034 clients_total += it->client.length() + 1;
5035 cookies_total += it->cookie.length() + 1;
5036 addrs_total += it->address.length() + 1;
5037 }
5038
5039 bool too_short = ((clients_total > *clients_len) ||
5040 (cookies_total > *cookies_len) ||
5041 (addrs_total > *addrs_len) ||
5042 (tag_str.length() + 1 > *tag_len));
5043 *clients_len = clients_total;
5044 *cookies_len = cookies_total;
5045 *addrs_len = addrs_total;
5046 *tag_len = tag_str.length() + 1;
5047 if (too_short) {
5048 tracepoint(librbd, list_lockers_exit, -ERANGE);
5049 return -ERANGE;
5050 }
5051
5052 strcpy(tag, tag_str.c_str());
5053 char *clients_p = clients;
5054 char *cookies_p = cookies;
5055 char *addrs_p = addrs;
5056 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
5057 it != lockers.end(); ++it) {
5058 const char* client = it->client.c_str();
5059 strcpy(clients_p, client);
5060 clients_p += it->client.length() + 1;
5061 const char* cookie = it->cookie.c_str();
5062 strcpy(cookies_p, cookie);
5063 cookies_p += it->cookie.length() + 1;
5064 const char* address = it->address.c_str();
5065 strcpy(addrs_p, address);
5066 addrs_p += it->address.length() + 1;
5067 tracepoint(librbd, list_lockers_entry, client, cookie, address);
5068 }
5069
5070 ssize_t ret = lockers.size();
5071 tracepoint(librbd, list_lockers_exit, ret);
5072 return ret;
5073 }
5074
5075 extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
5076 {
5077 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5078 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
5079 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
5080 tracepoint(librbd, lock_exclusive_exit, r);
5081 return r;
5082 }
5083
5084 extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
5085 const char *tag)
5086 {
5087 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5088 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
5089 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
5090 tracepoint(librbd, lock_shared_exit, r);
5091 return r;
5092 }
5093
5094 extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
5095 {
5096 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5097 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
5098 int r = librbd::unlock(ictx, cookie ? cookie : "");
5099 tracepoint(librbd, unlock_exit, r);
5100 return r;
5101 }
5102
5103 extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
5104 const char *cookie)
5105 {
5106 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5107 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
5108 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
5109 tracepoint(librbd, break_lock_exit, r);
5110 return r;
5111 }
5112
5113 /* I/O */
5114 extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
5115 char *buf)
5116 {
5117 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5118 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5119 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
5120 0);
5121 tracepoint(librbd, read_exit, r);
5122 return r;
5123 }
5124
5125 extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
5126 char *buf, int op_flags)
5127 {
5128 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5129 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
5130 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
5131 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
5132 op_flags);
5133 tracepoint(librbd, read_exit, r);
5134 return r;
5135 }
5136
5137
5138 extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_t len,
5139 int (*cb)(uint64_t, size_t, const char *, void *),
5140 void *arg)
5141 {
5142 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5143 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5144 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
5145 tracepoint(librbd, read_iterate_exit, r);
5146 return r;
5147 }
5148
5149 extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
5150 int (*cb)(uint64_t, size_t, const char *, void *),
5151 void *arg)
5152 {
5153 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5154 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5155 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
5156 if (r > 0)
5157 r = 0;
5158 tracepoint(librbd, read_iterate2_exit, r);
5159 return (int)r;
5160 }
5161
5162 extern "C" int rbd_diff_iterate(rbd_image_t image,
5163 const char *fromsnapname,
5164 uint64_t ofs, uint64_t len,
5165 int (*cb)(uint64_t, size_t, int, void *),
5166 void *arg)
5167 {
5168 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5169 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
5170 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
5171 true, false);
5172 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
5173 cls::rbd::UserSnapshotNamespace(),
5174 fromsnapname, ofs, len,
5175 true, false, cb, arg);
5176 tracepoint(librbd, diff_iterate_exit, r);
5177 return r;
5178 }
5179
5180 extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
5181 uint64_t ofs, uint64_t len,
5182 uint8_t include_parent, uint8_t whole_object,
5183 int (*cb)(uint64_t, size_t, int, void *),
5184 void *arg)
5185 {
5186 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5187 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
5188 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
5189 include_parent != 0, whole_object != 0);
5190 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
5191 cls::rbd::UserSnapshotNamespace(),
5192 fromsnapname, ofs, len,
5193 include_parent, whole_object,
5194 cb, arg);
5195 tracepoint(librbd, diff_iterate_exit, r);
5196 return r;
5197 }
5198
5199 extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
5200 const char *buf)
5201 {
5202 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5203 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
5204
5205 bufferlist bl;
5206 bl.push_back(create_write_raw(ictx, buf, len, nullptr));
5207 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
5208 tracepoint(librbd, write_exit, r);
5209 return r;
5210 }
5211
5212 extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
5213 const char *buf, int op_flags)
5214 {
5215 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5216 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
5217 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
5218
5219 bufferlist bl;
5220 bl.push_back(create_write_raw(ictx, buf, len, nullptr));
5221 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
5222 tracepoint(librbd, write_exit, r);
5223 return r;
5224 }
5225
5226
5227 extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
5228 {
5229 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5230 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(),
5231 ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5232 if (len > static_cast<uint64_t>(std::numeric_limits<int>::max())) {
5233 tracepoint(librbd, discard_exit, -EINVAL);
5234 return -EINVAL;
5235 }
5236
5237 int r = ictx->io_work_queue->discard(
5238 ofs, len, ictx->discard_granularity_bytes);
5239 tracepoint(librbd, discard_exit, r);
5240 return r;
5241 }
5242
5243 extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
5244 const char *buf, size_t data_len, int op_flags)
5245 {
5246 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5247 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5248 ictx->read_only, ofs, len, data_len == 0 ? NULL : buf, data_len, op_flags);
5249
5250 if (data_len == 0 || len % data_len ||
5251 len > static_cast<uint64_t>(std::numeric_limits<int>::max())) {
5252 tracepoint(librbd, writesame_exit, -EINVAL);
5253 return -EINVAL;
5254 }
5255
5256 bool discard_zero = ictx->config.get_val<bool>("rbd_discard_on_zeroed_write_same");
5257 if (discard_zero && mem_is_zero(buf, data_len)) {
5258 int r = ictx->io_work_queue->discard(ofs, len, 0);
5259 tracepoint(librbd, writesame_exit, r);
5260 return r;
5261 }
5262
5263 bufferlist bl;
5264 bl.push_back(create_write_raw(ictx, buf, data_len, nullptr));
5265 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
5266 tracepoint(librbd, writesame_exit, r);
5267 return r;
5268 }
5269
5270 extern "C" ssize_t rbd_compare_and_write(rbd_image_t image,
5271 uint64_t ofs, size_t len,
5272 const char *cmp_buf,
5273 const char *buf,
5274 uint64_t *mismatch_off,
5275 int op_flags)
5276 {
5277 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5278 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
5279 ictx->snap_name.c_str(), ictx->read_only, ofs,
5280 len, cmp_buf, buf, op_flags);
5281
5282 bufferlist cmp_bl;
5283 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len, nullptr));
5284 bufferlist bl;
5285 bl.push_back(create_write_raw(ictx, buf, len, nullptr));
5286
5287 int r = ictx->io_work_queue->compare_and_write(ofs, len, std::move(cmp_bl),
5288 std::move(bl), mismatch_off,
5289 op_flags);
5290 tracepoint(librbd, compare_and_write_exit, r);
5291 return r;
5292 }
5293
5294 extern "C" int rbd_aio_create_completion(void *cb_arg,
5295 rbd_callback_t complete_cb,
5296 rbd_completion_t *c)
5297 {
5298 librbd::RBD::AioCompletion *rbd_comp =
5299 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
5300 *c = (rbd_completion_t) rbd_comp;
5301 return 0;
5302 }
5303
5304 extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
5305 const char *buf, rbd_completion_t c)
5306 {
5307 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5308 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5309 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
5310
5311 auto aio_completion = get_aio_completion(comp);
5312 bufferlist bl;
5313 bl.push_back(create_write_raw(ictx, buf, len, aio_completion));
5314 ictx->io_work_queue->aio_write(aio_completion, off, len, std::move(bl), 0);
5315 tracepoint(librbd, aio_write_exit, 0);
5316 return 0;
5317 }
5318
5319 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
5320 const char *buf, rbd_completion_t c, int op_flags)
5321 {
5322 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5323 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5324 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5325 ictx->read_only, off, len, buf, comp->pc, op_flags);
5326
5327 auto aio_completion = get_aio_completion(comp);
5328 bufferlist bl;
5329 bl.push_back(create_write_raw(ictx, buf, len, aio_completion));
5330 ictx->io_work_queue->aio_write(aio_completion, off, len, std::move(bl),
5331 op_flags);
5332 tracepoint(librbd, aio_write_exit, 0);
5333 return 0;
5334 }
5335
5336 extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
5337 int iovcnt, uint64_t off, rbd_completion_t c)
5338 {
5339 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5340 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5341
5342 // convert the scatter list into a bufferlist
5343 auto aio_completion = get_aio_completion(comp);
5344 ssize_t len = 0;
5345 bufferlist bl;
5346 for (int i = 0; i < iovcnt; ++i) {
5347 const struct iovec &io = iov[i];
5348 len += io.iov_len;
5349 if (len < 0) {
5350 break;
5351 }
5352
5353 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
5354 io.iov_len, aio_completion));
5355 }
5356
5357 int r = 0;
5358 if (iovcnt <= 0 || len < 0) {
5359 r = -EINVAL;
5360 }
5361
5362 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
5363 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
5364 comp->pc);
5365 if (r == 0) {
5366 ictx->io_work_queue->aio_write(aio_completion, off, len, std::move(bl), 0);
5367 }
5368 tracepoint(librbd, aio_write_exit, r);
5369 return r;
5370 }
5371
5372 extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
5373 rbd_completion_t c)
5374 {
5375 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5376 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5377 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
5378 ictx->io_work_queue->aio_discard(
5379 get_aio_completion(comp), off, len, ictx->discard_granularity_bytes);
5380 tracepoint(librbd, aio_discard_exit, 0);
5381 return 0;
5382 }
5383
5384 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
5385 char *buf, rbd_completion_t c)
5386 {
5387 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5388 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5389 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
5390 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
5391 librbd::io::ReadResult{buf, len}, 0);
5392 tracepoint(librbd, aio_read_exit, 0);
5393 return 0;
5394 }
5395
5396 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
5397 char *buf, rbd_completion_t c, int op_flags)
5398 {
5399 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5400 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5401 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5402 ictx->read_only, off, len, buf, comp->pc, op_flags);
5403 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
5404 librbd::io::ReadResult{buf, len},op_flags);
5405 tracepoint(librbd, aio_read_exit, 0);
5406 return 0;
5407 }
5408
5409 extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
5410 int iovcnt, uint64_t off, rbd_completion_t c)
5411 {
5412 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5413 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5414
5415 ssize_t len = 0;
5416 for (int i = 0; i < iovcnt; ++i) {
5417 len += iov[i].iov_len;
5418 if (len < 0) {
5419 break;
5420 }
5421 }
5422
5423 int r = 0;
5424 if (iovcnt == 0 || len < 0) {
5425 r = -EINVAL;
5426 }
5427
5428 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
5429 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
5430 comp->pc);
5431 if (r == 0) {
5432 librbd::io::ReadResult read_result;
5433 if (iovcnt == 1) {
5434 read_result = librbd::io::ReadResult(
5435 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
5436 } else {
5437 read_result = librbd::io::ReadResult(iov, iovcnt);
5438 }
5439 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
5440 std::move(read_result), 0);
5441 }
5442 tracepoint(librbd, aio_read_exit, r);
5443 return r;
5444 }
5445
5446 extern "C" int rbd_flush(rbd_image_t image)
5447 {
5448 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5449 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
5450 int r = ictx->io_work_queue->flush();
5451 tracepoint(librbd, flush_exit, r);
5452 return r;
5453 }
5454
5455 extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
5456 {
5457 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5458 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5459 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
5460 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
5461 tracepoint(librbd, aio_flush_exit, 0);
5462 return 0;
5463 }
5464
5465 extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
5466 const char *buf, size_t data_len, rbd_completion_t c,
5467 int op_flags)
5468 {
5469 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5470 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5471 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5472 ictx->read_only, off, len, data_len == 0 ? NULL : buf, data_len, comp->pc,
5473 op_flags);
5474
5475 if (data_len == 0 || len % data_len) {
5476 tracepoint(librbd, aio_writesame_exit, -EINVAL);
5477 return -EINVAL;
5478 }
5479
5480 bool discard_zero = ictx->config.get_val<bool>("rbd_discard_on_zeroed_write_same");
5481 if (discard_zero && mem_is_zero(buf, data_len)) {
5482 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, 0);
5483 tracepoint(librbd, aio_writesame_exit, 0);
5484 return 0;
5485 }
5486
5487 auto aio_completion = get_aio_completion(comp);
5488 bufferlist bl;
5489 bl.push_back(create_write_raw(ictx, buf, data_len, aio_completion));
5490 ictx->io_work_queue->aio_writesame(aio_completion, off, len, std::move(bl),
5491 op_flags);
5492 tracepoint(librbd, aio_writesame_exit, 0);
5493 return 0;
5494 }
5495
5496 extern "C" ssize_t rbd_aio_compare_and_write(rbd_image_t image, uint64_t off,
5497 size_t len, const char *cmp_buf,
5498 const char *buf, rbd_completion_t c,
5499 uint64_t *mismatch_off,
5500 int op_flags)
5501 {
5502 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5503 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5504 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5505 ictx->read_only, off, len, cmp_buf, buf, comp->pc, op_flags);
5506
5507 auto aio_completion = get_aio_completion(comp);
5508 bufferlist cmp_bl;
5509 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len, aio_completion));
5510 bufferlist bl;
5511 bl.push_back(create_write_raw(ictx, buf, len, aio_completion));
5512 ictx->io_work_queue->aio_compare_and_write(aio_completion, off, len,
5513 std::move(cmp_bl), std::move(bl),
5514 mismatch_off, op_flags, false);
5515
5516 tracepoint(librbd, aio_compare_and_write_exit, 0);
5517 return 0;
5518 }
5519
5520 extern "C" int rbd_invalidate_cache(rbd_image_t image)
5521 {
5522 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5523 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
5524 int r = librbd::invalidate_cache(ictx);
5525 tracepoint(librbd, invalidate_cache_exit, r);
5526 return r;
5527 }
5528
5529 extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
5530 {
5531 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5532 librbd::io::AioCompletion *cs[numcomp];
5533 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
5534 int r = librbd::poll_io_events(ictx, cs, numcomp);
5535 tracepoint(librbd, poll_io_events_exit, r);
5536 if (r > 0) {
5537 for (int i = 0; i < r; ++i)
5538 comps[i] = cs[i]->rbd_comp;
5539 }
5540 return r;
5541 }
5542
5543 extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
5544 {
5545 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5546 string val_s;
5547 tracepoint(librbd, metadata_get_enter, ictx, key);
5548 int r = librbd::metadata_get(ictx, key, &val_s);
5549 if (r < 0) {
5550 tracepoint(librbd, metadata_get_exit, r, key, NULL);
5551 return r;
5552 }
5553 if (*vallen < val_s.size() + 1) {
5554 r = -ERANGE;
5555 *vallen = val_s.size() + 1;
5556 tracepoint(librbd, metadata_get_exit, r, key, NULL);
5557 } else {
5558 strncpy(value, val_s.c_str(), val_s.size() + 1);
5559 tracepoint(librbd, metadata_get_exit, r, key, value);
5560 }
5561 return r;
5562 }
5563
5564 extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
5565 {
5566 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5567 tracepoint(librbd, metadata_set_enter, ictx, key, value);
5568 int r = ictx->operations->metadata_set(key, value);
5569 tracepoint(librbd, metadata_set_exit, r);
5570 return r;
5571 }
5572
5573 extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
5574 {
5575 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5576 tracepoint(librbd, metadata_remove_enter, ictx, key);
5577 int r = ictx->operations->metadata_remove(key);
5578 tracepoint(librbd, metadata_remove_exit, r);
5579 return r;
5580 }
5581
5582 extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
5583 char *key, size_t *key_len, char *value, size_t *val_len)
5584 {
5585 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5586 tracepoint(librbd, metadata_list_enter, ictx);
5587 map<string, bufferlist> pairs;
5588 int r = librbd::metadata_list(ictx, start, max, &pairs);
5589 size_t key_total_len = 0, val_total_len = 0;
5590 bool too_short = false;
5591 for (map<string, bufferlist>::iterator it = pairs.begin();
5592 it != pairs.end(); ++it) {
5593 key_total_len += it->first.size() + 1;
5594 val_total_len += it->second.length() + 1;
5595 }
5596 if (*key_len < key_total_len || *val_len < val_total_len)
5597 too_short = true;
5598 *key_len = key_total_len;
5599 *val_len = val_total_len;
5600 if (too_short) {
5601 tracepoint(librbd, metadata_list_exit, -ERANGE);
5602 return -ERANGE;
5603 }
5604
5605 char *key_p = key, *value_p = value;
5606
5607 for (map<string, bufferlist>::iterator it = pairs.begin();
5608 it != pairs.end(); ++it) {
5609 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
5610 key_p += it->first.size() + 1;
5611 strncpy(value_p, it->second.c_str(), it->second.length());
5612 value_p += it->second.length();
5613 *value_p = '\0';
5614 value_p++;
5615 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
5616 }
5617 tracepoint(librbd, metadata_list_exit, r);
5618 return r;
5619 }
5620
5621 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
5622 {
5623 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5624 return librbd::api::Mirror<>::image_enable(ictx, false);
5625 }
5626
5627 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
5628 {
5629 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5630 return librbd::api::Mirror<>::image_disable(ictx, force);
5631 }
5632
5633 extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
5634 {
5635 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5636 return librbd::api::Mirror<>::image_promote(ictx, force);
5637 }
5638
5639 extern "C" int rbd_mirror_image_demote(rbd_image_t image)
5640 {
5641 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5642 return librbd::api::Mirror<>::image_demote(ictx);
5643 }
5644
5645 extern "C" int rbd_mirror_image_resync(rbd_image_t image)
5646 {
5647 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5648 return librbd::api::Mirror<>::image_resync(ictx);
5649 }
5650
5651 extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
5652 rbd_mirror_image_info_t *mirror_image_info,
5653 size_t info_size)
5654 {
5655 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5656
5657 if (sizeof(rbd_mirror_image_info_t) != info_size) {
5658 return -ERANGE;
5659 }
5660
5661 librbd::mirror_image_info_t cpp_mirror_image;
5662 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image);
5663 if (r < 0) {
5664 return r;
5665 }
5666
5667 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
5668 return 0;
5669 }
5670
5671 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
5672 rbd_mirror_image_status_t *status,
5673 size_t status_size)
5674 {
5675 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5676
5677 if (sizeof(rbd_mirror_image_status_t) != status_size) {
5678 return -ERANGE;
5679 }
5680
5681 librbd::mirror_image_status_t cpp_status;
5682 int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status);
5683 if (r < 0) {
5684 return r;
5685 }
5686
5687 mirror_image_status_cpp_to_c(cpp_status, status);
5688 return 0;
5689 }
5690
5691 extern "C" int rbd_mirror_image_get_instance_id(rbd_image_t image,
5692 char *instance_id,
5693 size_t *instance_id_max_length)
5694 {
5695 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5696
5697 std::string cpp_instance_id;
5698 int r = librbd::api::Mirror<>::image_get_instance_id(ictx, &cpp_instance_id);
5699 if (r < 0) {
5700 return r;
5701 }
5702
5703 if (cpp_instance_id.size() >= *instance_id_max_length) {
5704 *instance_id_max_length = cpp_instance_id.size() + 1;
5705 return -ERANGE;
5706 }
5707
5708 strcpy(instance_id, cpp_instance_id.c_str());
5709 *instance_id_max_length = cpp_instance_id.size() + 1;
5710 return 0;
5711 }
5712
5713 extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
5714 rbd_completion_t c) {
5715 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5716 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5717 librbd::api::Mirror<>::image_promote(
5718 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
5719 get_aio_completion(comp)));
5720 return 0;
5721 }
5722
5723 extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
5724 rbd_completion_t c) {
5725 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5726 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5727 librbd::api::Mirror<>::image_demote(
5728 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
5729 get_aio_completion(comp)));
5730 return 0;
5731 }
5732
5733 extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
5734 rbd_mirror_image_info_t *info,
5735 size_t info_size,
5736 rbd_completion_t c) {
5737 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5738 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5739
5740 if (sizeof(rbd_mirror_image_info_t) != info_size) {
5741 return -ERANGE;
5742 }
5743
5744 auto ctx = new C_MirrorImageGetInfo(
5745 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
5746 get_aio_completion(comp)));
5747 librbd::api::Mirror<>::image_get_info(
5748 ictx, &ctx->cpp_mirror_image_info, ctx);
5749 return 0;
5750 }
5751
5752 extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
5753 rbd_mirror_image_status_t *status,
5754 size_t status_size,
5755 rbd_completion_t c) {
5756 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5757 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5758
5759 if (sizeof(rbd_mirror_image_status_t) != status_size) {
5760 return -ERANGE;
5761 }
5762
5763 auto ctx = new C_MirrorImageGetStatus(
5764 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
5765 get_aio_completion(comp)));
5766 librbd::api::Mirror<>::image_get_status(ictx, &ctx->cpp_mirror_image_status,
5767 ctx);
5768 return 0;
5769 }
5770
5771 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
5772 rbd_update_callback_t watch_cb, void *arg)
5773 {
5774 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5775 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
5776 tracepoint(librbd, update_watch_enter, ictx, wctx);
5777 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
5778 tracepoint(librbd, update_watch_exit, r, wctx->handle);
5779 *handle = reinterpret_cast<uint64_t>(wctx);
5780 return r;
5781 }
5782
5783 extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
5784 {
5785 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5786 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
5787 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
5788 int r = ictx->state->unregister_update_watcher(wctx->handle);
5789 delete wctx;
5790 tracepoint(librbd, update_unwatch_exit, r);
5791 return r;
5792 }
5793
5794 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
5795 {
5796 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5797 return comp->is_complete();
5798 }
5799
5800 extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
5801 {
5802 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5803 return comp->wait_for_complete();
5804 }
5805
5806 extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
5807 {
5808 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5809 return comp->get_return_value();
5810 }
5811
5812 extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
5813 {
5814 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5815 return comp->get_arg();
5816 }
5817
5818 extern "C" void rbd_aio_release(rbd_completion_t c)
5819 {
5820 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5821 comp->release();
5822 }
5823
5824 extern "C" int rbd_group_create(rados_ioctx_t p, const char *name)
5825 {
5826 librados::IoCtx io_ctx;
5827 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
5828 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
5829 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
5830 io_ctx.get_id(), name);
5831 int r = librbd::api::Group<>::create(io_ctx, name);
5832 tracepoint(librbd, group_create_exit, r);
5833 return r;
5834 }
5835
5836 extern "C" int rbd_group_remove(rados_ioctx_t p, const char *name)
5837 {
5838 librados::IoCtx io_ctx;
5839 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
5840 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
5841 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
5842 io_ctx.get_id(), name);
5843 int r = librbd::api::Group<>::remove(io_ctx, name);
5844 tracepoint(librbd, group_remove_exit, r);
5845 return r;
5846 }
5847
5848 extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size)
5849 {
5850 librados::IoCtx io_ctx;
5851 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
5852 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
5853 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
5854 io_ctx.get_id());
5855
5856 vector<string> cpp_names;
5857 int r = librbd::api::Group<>::list(io_ctx, &cpp_names);
5858
5859 if (r < 0) {
5860 tracepoint(librbd, group_list_exit, r);
5861 return r;
5862 }
5863
5864 size_t expected_size = 0;
5865
5866 for (size_t i = 0; i < cpp_names.size(); i++) {
5867 expected_size += cpp_names[i].size() + 1;
5868 }
5869 if (*size < expected_size) {
5870 *size = expected_size;
5871 tracepoint(librbd, group_list_exit, -ERANGE);
5872 return -ERANGE;
5873 }
5874
5875 if (names == NULL) {
5876 tracepoint(librbd, group_list_exit, -EINVAL);
5877 return -EINVAL;
5878 }
5879
5880 for (int i = 0; i < (int)cpp_names.size(); i++) {
5881 const char* name = cpp_names[i].c_str();
5882 tracepoint(librbd, group_list_entry, name);
5883 strcpy(names, name);
5884 names += strlen(names) + 1;
5885 }
5886 tracepoint(librbd, group_list_exit, (int)expected_size);
5887 return (int)expected_size;
5888 }
5889
5890 extern "C" int rbd_group_rename(rados_ioctx_t p, const char *src_name,
5891 const char *dest_name)
5892 {
5893 librados::IoCtx io_ctx;
5894 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
5895 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
5896 tracepoint(librbd, group_rename_enter, io_ctx.get_pool_name().c_str(),
5897 io_ctx.get_id(), src_name, dest_name);
5898 int r = librbd::api::Group<>::rename(io_ctx, src_name, dest_name);
5899 tracepoint(librbd, group_rename_exit, r);
5900 return r;
5901 }
5902
5903 extern "C" int rbd_group_image_add(rados_ioctx_t group_p,
5904 const char *group_name,
5905 rados_ioctx_t image_p,
5906 const char *image_name)
5907 {
5908 librados::IoCtx group_ioctx;
5909 librados::IoCtx image_ioctx;
5910
5911 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
5912 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
5913
5914 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
5915 tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(),
5916 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
5917 image_ioctx.get_id(), image_name);
5918
5919 int r = librbd::api::Group<>::image_add(group_ioctx, group_name, image_ioctx,
5920 image_name);
5921
5922 tracepoint(librbd, group_image_add_exit, r);
5923 return r;
5924 }
5925
5926 extern "C" int rbd_group_image_remove(rados_ioctx_t group_p,
5927 const char *group_name,
5928 rados_ioctx_t image_p,
5929 const char *image_name)
5930 {
5931 librados::IoCtx group_ioctx;
5932 librados::IoCtx image_ioctx;
5933
5934 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
5935 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
5936
5937 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
5938 tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(),
5939 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
5940 image_ioctx.get_id(), image_name);
5941
5942 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
5943 image_ioctx, image_name);
5944
5945 tracepoint(librbd, group_image_remove_exit, r);
5946 return r;
5947 }
5948
5949 extern "C" int rbd_group_image_remove_by_id(rados_ioctx_t group_p,
5950 const char *group_name,
5951 rados_ioctx_t image_p,
5952 const char *image_id)
5953 {
5954 librados::IoCtx group_ioctx;
5955 librados::IoCtx image_ioctx;
5956
5957 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
5958 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
5959
5960 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
5961 tracepoint(librbd, group_image_remove_by_id_enter,
5962 group_ioctx.get_pool_name().c_str(),
5963 group_ioctx.get_id(), group_name,
5964 image_ioctx.get_pool_name().c_str(),
5965 image_ioctx.get_id(), image_id);
5966
5967 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
5968 image_ioctx, image_id);
5969
5970 tracepoint(librbd, group_image_remove_by_id_exit, r);
5971 return r;
5972 }
5973
5974 extern "C" int rbd_group_image_list(rados_ioctx_t group_p,
5975 const char *group_name,
5976 rbd_group_image_info_t *images,
5977 size_t group_image_info_size,
5978 size_t *image_size)
5979 {
5980 librados::IoCtx group_ioctx;
5981 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
5982
5983 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
5984 tracepoint(librbd, group_image_list_enter,
5985 group_ioctx.get_pool_name().c_str(),
5986 group_ioctx.get_id(), group_name);
5987 memset(images, 0, sizeof(*images) * *image_size);
5988
5989 if (group_image_info_size != sizeof(rbd_group_image_info_t)) {
5990 *image_size = 0;
5991 tracepoint(librbd, group_image_list_exit, -ERANGE);
5992 return -ERANGE;
5993 }
5994
5995 std::vector<librbd::group_image_info_t> cpp_images;
5996 int r = librbd::api::Group<>::image_list(group_ioctx, group_name,
5997 &cpp_images);
5998
5999 if (r == -ENOENT) {
6000 tracepoint(librbd, group_image_list_exit, 0);
6001 *image_size = 0;
6002 return 0;
6003 }
6004
6005 if (r < 0) {
6006 tracepoint(librbd, group_image_list_exit, r);
6007 return r;
6008 }
6009
6010 if (*image_size < cpp_images.size()) {
6011 *image_size = cpp_images.size();
6012 tracepoint(librbd, group_image_list_exit, -ERANGE);
6013 return -ERANGE;
6014 }
6015
6016 for (size_t i = 0; i < cpp_images.size(); ++i) {
6017 group_image_status_cpp_to_c(cpp_images[i], &images[i]);
6018 }
6019
6020 r = *image_size = cpp_images.size();
6021 tracepoint(librbd, group_image_list_exit, r);
6022 return r;
6023 }
6024
6025 extern "C" int rbd_group_info_cleanup(rbd_group_info_t *group_info,
6026 size_t group_info_size) {
6027 if (group_info_size != sizeof(rbd_group_info_t)) {
6028 return -ERANGE;
6029 }
6030
6031 free(group_info->name);
6032 return 0;
6033 }
6034
6035 extern "C" int rbd_group_image_list_cleanup(rbd_group_image_info_t *images,
6036 size_t group_image_info_size,
6037 size_t len) {
6038 if (group_image_info_size != sizeof(rbd_group_image_info_t)) {
6039 return -ERANGE;
6040 }
6041
6042 for (size_t i = 0; i < len; ++i) {
6043 free(images[i].name);
6044 }
6045 return 0;
6046 }
6047
6048 extern "C" int rbd_group_snap_create(rados_ioctx_t group_p,
6049 const char *group_name,
6050 const char *snap_name)
6051 {
6052 librados::IoCtx group_ioctx;
6053 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6054
6055 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6056 tracepoint(librbd, group_snap_create_enter,
6057 group_ioctx.get_pool_name().c_str(),
6058 group_ioctx.get_id(), group_name, snap_name);
6059
6060 int r = librbd::api::Group<>::snap_create(group_ioctx, group_name, snap_name);
6061
6062 tracepoint(librbd, group_snap_create_exit, r);
6063
6064 return r;
6065 }
6066
6067 extern "C" int rbd_group_snap_remove(rados_ioctx_t group_p,
6068 const char *group_name,
6069 const char *snap_name)
6070 {
6071 librados::IoCtx group_ioctx;
6072 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6073
6074 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6075 tracepoint(librbd, group_snap_remove_enter,
6076 group_ioctx.get_pool_name().c_str(),
6077 group_ioctx.get_id(), group_name, snap_name);
6078
6079 int r = librbd::api::Group<>::snap_remove(group_ioctx, group_name, snap_name);
6080
6081 tracepoint(librbd, group_snap_remove_exit, r);
6082
6083 return r;
6084 }
6085
6086 extern "C" int rbd_group_snap_rename(rados_ioctx_t group_p,
6087 const char *group_name,
6088 const char *old_snap_name,
6089 const char *new_snap_name)
6090 {
6091 librados::IoCtx group_ioctx;
6092 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6093
6094 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6095 tracepoint(librbd, group_snap_rename_enter,
6096 group_ioctx.get_pool_name().c_str(), group_ioctx.get_id(),
6097 group_name, old_snap_name, new_snap_name);
6098
6099 int r = librbd::api::Group<>::snap_rename(group_ioctx, group_name,
6100 old_snap_name, new_snap_name);
6101
6102 tracepoint(librbd, group_snap_list_exit, r);
6103 return r;
6104 }
6105
6106 extern "C" int rbd_group_snap_list(rados_ioctx_t group_p,
6107 const char *group_name,
6108 rbd_group_snap_info_t *snaps,
6109 size_t group_snap_info_size,
6110 size_t *snaps_size)
6111 {
6112 librados::IoCtx group_ioctx;
6113 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6114
6115 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6116 tracepoint(librbd, group_snap_list_enter, group_ioctx.get_pool_name().c_str(),
6117 group_ioctx.get_id(), group_name);
6118 memset(snaps, 0, sizeof(*snaps) * *snaps_size);
6119
6120 if (group_snap_info_size != sizeof(rbd_group_snap_info_t)) {
6121 *snaps_size = 0;
6122 tracepoint(librbd, group_snap_list_exit, -ERANGE);
6123 return -ERANGE;
6124 }
6125
6126 std::vector<librbd::group_snap_info_t> cpp_snaps;
6127 int r = librbd::api::Group<>::snap_list(group_ioctx, group_name, &cpp_snaps);
6128
6129 if (r == -ENOENT) {
6130 *snaps_size = 0;
6131 tracepoint(librbd, group_snap_list_exit, 0);
6132 return 0;
6133 }
6134
6135 if (r < 0) {
6136 tracepoint(librbd, group_snap_list_exit, r);
6137 return r;
6138 }
6139
6140 if (*snaps_size < cpp_snaps.size()) {
6141 *snaps_size = cpp_snaps.size();
6142 tracepoint(librbd, group_snap_list_exit, -ERANGE);
6143 return -ERANGE;
6144 }
6145
6146 for (size_t i = 0; i < cpp_snaps.size(); ++i) {
6147 group_snap_info_cpp_to_c(cpp_snaps[i], &snaps[i]);
6148 }
6149
6150 r = *snaps_size = cpp_snaps.size();
6151 tracepoint(librbd, group_snap_list_exit, r);
6152 return r;
6153 }
6154
6155 extern "C" int rbd_group_snap_list_cleanup(rbd_group_snap_info_t *snaps,
6156 size_t group_snap_info_size,
6157 size_t len) {
6158 if (group_snap_info_size != sizeof(rbd_group_snap_info_t)) {
6159 return -ERANGE;
6160 }
6161
6162 for (size_t i = 0; i < len; ++i) {
6163 free(snaps[i].name);
6164 }
6165 return 0;
6166 }
6167
6168 extern "C" int rbd_group_snap_rollback(rados_ioctx_t group_p,
6169 const char *group_name,
6170 const char *snap_name)
6171 {
6172 librados::IoCtx group_ioctx;
6173 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6174
6175 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6176 tracepoint(librbd, group_snap_rollback_enter,
6177 group_ioctx.get_pool_name().c_str(),
6178 group_ioctx.get_id(), group_name, snap_name);
6179
6180 librbd::NoOpProgressContext prog_ctx;
6181 int r = librbd::api::Group<>::snap_rollback(group_ioctx, group_name,
6182 snap_name, prog_ctx);
6183
6184 tracepoint(librbd, group_snap_rollback_exit, r);
6185
6186 return r;
6187 }
6188
6189 extern "C" int rbd_group_snap_rollback_with_progress(rados_ioctx_t group_p,
6190 const char *group_name,
6191 const char *snap_name,
6192 librbd_progress_fn_t cb,
6193 void *cbdata)
6194 {
6195 librados::IoCtx group_ioctx;
6196 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6197
6198 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6199 tracepoint(librbd, group_snap_rollback_enter,
6200 group_ioctx.get_pool_name().c_str(),
6201 group_ioctx.get_id(), group_name, snap_name);
6202
6203 librbd::CProgressContext prog_ctx(cb, cbdata);
6204 int r = librbd::api::Group<>::snap_rollback(group_ioctx, group_name,
6205 snap_name, prog_ctx);
6206
6207 tracepoint(librbd, group_snap_rollback_exit, r);
6208
6209 return r;
6210 }
6211
6212 extern "C" int rbd_snap_get_namespace_type(rbd_image_t image,
6213 uint64_t snap_id,
6214 rbd_snap_namespace_type_t *namespace_type) {
6215 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6216 tracepoint(librbd, snap_get_namespace_type_enter, ictx, ictx->name.c_str());
6217 int r = librbd::api::Snapshot<>::get_namespace_type(ictx, snap_id,
6218 namespace_type);
6219 tracepoint(librbd, snap_get_namespace_type_exit, r);
6220 return r;
6221 }
6222
6223 extern "C" int rbd_snap_get_group_namespace(rbd_image_t image, uint64_t snap_id,
6224 rbd_snap_group_namespace_t *group_snap,
6225 size_t snap_group_namespace_size) {
6226 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6227 tracepoint(librbd, snap_get_group_namespace_enter, ictx,
6228 ictx->name.c_str());
6229
6230 if (snap_group_namespace_size != sizeof(rbd_snap_group_namespace_t)) {
6231 tracepoint(librbd, snap_get_group_namespace_exit, -ERANGE);
6232 return -ERANGE;
6233 }
6234
6235 librbd::snap_group_namespace_t group_namespace;
6236 int r = librbd::api::Snapshot<>::get_group_namespace(ictx, snap_id,
6237 &group_namespace);
6238 if (r >= 0) {
6239 group_snap->group_pool = group_namespace.group_pool;
6240 group_snap->group_name = strdup(group_namespace.group_name.c_str());
6241 group_snap->group_snap_name =
6242 strdup(group_namespace.group_snap_name.c_str());
6243 }
6244
6245 tracepoint(librbd, snap_get_group_namespace_exit, r);
6246 return r;
6247 }
6248
6249 extern "C" int rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *group_snap,
6250 size_t snap_group_namespace_size) {
6251 if (snap_group_namespace_size != sizeof(rbd_snap_group_namespace_t)) {
6252 tracepoint(librbd, snap_get_group_namespace_exit, -ERANGE);
6253 return -ERANGE;
6254 }
6255
6256 free(group_snap->group_name);
6257 free(group_snap->group_snap_name);
6258 return 0;
6259 }
6260
6261 extern "C" int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id,
6262 char *original_name,
6263 size_t max_length) {
6264 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6265
6266 std::string cpp_original_name;
6267 int r = librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
6268 &cpp_original_name);
6269 if (r < 0) {
6270 return r;
6271 }
6272
6273 if (cpp_original_name.length() >= max_length) {
6274 return -ERANGE;
6275 }
6276
6277 strcpy(original_name, cpp_original_name.c_str());
6278 return 0;
6279 }
6280 extern "C" int rbd_watchers_list(rbd_image_t image,
6281 rbd_image_watcher_t *watchers,
6282 size_t *max_watchers) {
6283 std::list<librbd::image_watcher_t> watcher_list;
6284 librbd::ImageCtx *ictx = (librbd::ImageCtx*)image;
6285
6286 tracepoint(librbd, list_watchers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
6287 memset(watchers, 0, sizeof(*watchers) * *max_watchers);
6288 int r = librbd::list_watchers(ictx, watcher_list);
6289 if (r < 0) {
6290 tracepoint(librbd, list_watchers_exit, r, 0);
6291 return r;
6292 }
6293
6294 if (watcher_list.size() > *max_watchers) {
6295 *max_watchers = watcher_list.size();
6296 tracepoint(librbd, list_watchers_exit, -ERANGE, watcher_list.size());
6297 return -ERANGE;
6298 }
6299
6300 *max_watchers = 0;
6301 for (auto &watcher : watcher_list) {
6302 tracepoint(librbd, list_watchers_entry, watcher.addr.c_str(), watcher.id, watcher.cookie);
6303 watchers[*max_watchers].addr = strdup(watcher.addr.c_str());
6304 watchers[*max_watchers].id = watcher.id;
6305 watchers[*max_watchers].cookie = watcher.cookie;
6306 *max_watchers += 1;
6307 }
6308
6309 tracepoint(librbd, list_watchers_exit, r, watcher_list.size());
6310 return 0;
6311 }
6312
6313 extern "C" void rbd_watchers_list_cleanup(rbd_image_watcher_t *watchers,
6314 size_t num_watchers) {
6315 for (size_t i = 0; i < num_watchers; ++i) {
6316 free(watchers[i].addr);
6317 }
6318 }
6319
6320 extern "C" int rbd_config_image_list(rbd_image_t image,
6321 rbd_config_option_t *options,
6322 int *max_options) {
6323 librbd::ImageCtx *ictx = (librbd::ImageCtx*)image;
6324
6325 std::vector<librbd::config_option_t> option_vector;
6326 int r = librbd::api::Config<>::list(ictx, &option_vector);
6327 if (r < 0) {
6328 return r;
6329 }
6330
6331 if (*max_options < static_cast<int>(option_vector.size())) {
6332 *max_options = static_cast<int>(option_vector.size());
6333 return -ERANGE;
6334 }
6335
6336 for (int i = 0; i < static_cast<int>(option_vector.size()); ++i) {
6337 config_option_cpp_to_c(option_vector[i], &options[i]);
6338 }
6339 *max_options = static_cast<int>(option_vector.size());
6340 return 0;
6341 }
6342
6343 extern "C" void rbd_config_image_list_cleanup(rbd_config_option_t *options,
6344 int max_options) {
6345 for (int i = 0; i < max_options; ++i) {
6346 config_option_cleanup(options[i]);
6347 }
6348 }
6349