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