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