]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/librbd.cc
438b58716837502fe4a66e1800b9d912ab24651c
[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, 0U, 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::aio_mirror_image_create_snapshot(uint32_t flags, uint64_t *snap_id,
2990 RBD::AioCompletion *c) {
2991 ImageCtx *ictx = (ImageCtx *)ctx;
2992
2993 librbd::api::Mirror<>::image_snapshot_create(
2994 ictx, flags, snap_id, new C_AioCompletion(ictx,
2995 librbd::io::AIO_TYPE_GENERIC,
2996 get_aio_completion(c)));
2997 return 0;
2998 }
2999
3000 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
3001 ImageCtx *ictx = (ImageCtx *)ctx;
3002 tracepoint(librbd, update_watch_enter, ictx, wctx);
3003 int r = ictx->state->register_update_watcher(wctx, handle);
3004 tracepoint(librbd, update_watch_exit, r, *handle);
3005 return r;
3006 }
3007
3008 int Image::update_unwatch(uint64_t handle) {
3009 ImageCtx *ictx = (ImageCtx *)ctx;
3010 tracepoint(librbd, update_unwatch_enter, ictx, handle);
3011 int r = ictx->state->unregister_update_watcher(handle);
3012 tracepoint(librbd, update_unwatch_exit, r);
3013 return r;
3014 }
3015
3016 int Image::list_watchers(std::list<librbd::image_watcher_t> &watchers) {
3017 ImageCtx *ictx = (ImageCtx *)ctx;
3018 tracepoint(librbd, list_watchers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3019 int r = librbd::list_watchers(ictx, watchers);
3020 #ifdef WITH_LTTNG
3021 if (r >= 0) {
3022 for (auto &watcher : watchers) {
3023 tracepoint(librbd, list_watchers_entry, watcher.addr.c_str(), watcher.id, watcher.cookie);
3024 }
3025 }
3026 #endif
3027 tracepoint(librbd, list_watchers_exit, r, watchers.size());
3028 return r;
3029 }
3030
3031 int Image::config_list(std::vector<config_option_t> *options) {
3032 ImageCtx *ictx = (ImageCtx *)ctx;
3033 return librbd::api::Config<>::list(ictx, options);
3034 }
3035
3036 } // namespace librbd
3037
3038 extern "C" void rbd_version(int *major, int *minor, int *extra)
3039 {
3040 if (major)
3041 *major = LIBRBD_VER_MAJOR;
3042 if (minor)
3043 *minor = LIBRBD_VER_MINOR;
3044 if (extra)
3045 *extra = LIBRBD_VER_EXTRA;
3046 }
3047
3048 extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
3049 {
3050 librbd::image_options_create(opts);
3051 }
3052
3053 extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
3054 {
3055 librbd::image_options_destroy(opts);
3056 }
3057
3058 extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
3059 const char* optval)
3060 {
3061 return librbd::image_options_set(opts, optname, optval);
3062 }
3063
3064 extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
3065 uint64_t optval)
3066 {
3067 return librbd::image_options_set(opts, optname, optval);
3068 }
3069
3070 extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
3071 char* optval, size_t maxlen)
3072 {
3073 std::string optval_;
3074
3075 int r = librbd::image_options_get(opts, optname, &optval_);
3076
3077 if (r < 0) {
3078 return r;
3079 }
3080
3081 if (optval_.size() >= maxlen) {
3082 return -E2BIG;
3083 }
3084
3085 strncpy(optval, optval_.c_str(), maxlen);
3086
3087 return 0;
3088 }
3089
3090 extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
3091 uint64_t* optval)
3092 {
3093 return librbd::image_options_get(opts, optname, optval);
3094 }
3095
3096 extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
3097 bool* is_set)
3098 {
3099 return librbd::image_options_is_set(opts, optname, is_set);
3100 }
3101
3102 extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
3103 {
3104 return librbd::image_options_unset(opts, optname);
3105 }
3106
3107 extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
3108 {
3109 librbd::image_options_clear(opts);
3110 }
3111
3112 extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
3113 {
3114 return librbd::image_options_is_empty(opts);
3115 }
3116
3117 /* pool mirroring */
3118 extern "C" int rbd_mirror_site_name_get(rados_t cluster, char *name,
3119 size_t *max_len) {
3120 librados::Rados rados;
3121 librados::Rados::from_rados_t(cluster, rados);
3122
3123 std::string site_name;
3124 int r = librbd::api::Mirror<>::site_name_get(rados, &site_name);
3125 if (r < 0) {
3126 return r;
3127 }
3128
3129 auto total_len = site_name.size() + 1;
3130 if (*max_len < total_len) {
3131 *max_len = total_len;
3132 return -ERANGE;
3133 }
3134 *max_len = total_len;
3135
3136 strcpy(name, site_name.c_str());
3137 return 0;
3138 }
3139
3140 extern "C" int rbd_mirror_site_name_set(rados_t cluster, const char *name) {
3141 librados::Rados rados;
3142 librados::Rados::from_rados_t(cluster, rados);
3143 return librbd::api::Mirror<>::site_name_set(rados, name);
3144 }
3145
3146 extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
3147 rbd_mirror_mode_t *mirror_mode) {
3148 librados::IoCtx io_ctx;
3149 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3150 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
3151 }
3152
3153 extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
3154 rbd_mirror_mode_t mirror_mode) {
3155 librados::IoCtx io_ctx;
3156 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3157 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
3158 }
3159
3160 extern "C" int rbd_mirror_uuid_get(rados_ioctx_t p,
3161 char *mirror_uuid, size_t *max_len) {
3162 librados::IoCtx io_ctx;
3163 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3164
3165 std::string mirror_uuid_str;
3166 int r = librbd::api::Mirror<>::uuid_get(io_ctx, &mirror_uuid_str);
3167 if (r < 0) {
3168 return r;
3169 }
3170
3171 auto total_len = mirror_uuid_str.size() + 1;
3172 if (*max_len < total_len) {
3173 *max_len = total_len;
3174 return -ERANGE;
3175 }
3176 *max_len = total_len;
3177
3178 strcpy(mirror_uuid, mirror_uuid_str.c_str());
3179 return 0;
3180 }
3181
3182 extern "C" int rbd_mirror_peer_bootstrap_create(rados_ioctx_t p, char *token,
3183 size_t *max_len) {
3184 librados::IoCtx io_ctx;
3185 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3186
3187 std::string token_str;
3188 int r = librbd::api::Mirror<>::peer_bootstrap_create(io_ctx, &token_str);
3189 if (r < 0) {
3190 return r;
3191 }
3192
3193 auto total_len = token_str.size() + 1;
3194 if (*max_len < total_len) {
3195 *max_len = total_len;
3196 return -ERANGE;
3197 }
3198 *max_len = total_len;
3199
3200 strcpy(token, token_str.c_str());
3201 return 0;
3202 }
3203
3204 extern "C" int rbd_mirror_peer_bootstrap_import(
3205 rados_ioctx_t p, rbd_mirror_peer_direction_t direction,
3206 const char *token) {
3207 librados::IoCtx io_ctx;
3208 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3209
3210 return librbd::api::Mirror<>::peer_bootstrap_import(io_ctx, direction, token);
3211 }
3212
3213 extern "C" int rbd_mirror_peer_site_add(rados_ioctx_t p, char *uuid,
3214 size_t uuid_max_length,
3215 rbd_mirror_peer_direction_t direction,
3216 const char *site_name,
3217 const char *client_name) {
3218 static const std::size_t UUID_LENGTH = 36;
3219
3220 librados::IoCtx io_ctx;
3221 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3222
3223 if (uuid_max_length < UUID_LENGTH + 1) {
3224 return -E2BIG;
3225 }
3226
3227 std::string uuid_str;
3228 int r = librbd::api::Mirror<>::peer_site_add(io_ctx, &uuid_str, direction,
3229 site_name, client_name);
3230 if (r >= 0) {
3231 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
3232 uuid[uuid_max_length - 1] = '\0';
3233 }
3234 return r;
3235 }
3236
3237 extern "C" int rbd_mirror_peer_site_remove(rados_ioctx_t p, const char *uuid) {
3238 librados::IoCtx io_ctx;
3239 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3240 int r = librbd::api::Mirror<>::peer_site_remove(io_ctx, uuid);
3241 return r;
3242 }
3243
3244 extern "C" int rbd_mirror_peer_site_list(
3245 rados_ioctx_t p, rbd_mirror_peer_site_t *peers, int *max_peers) {
3246 librados::IoCtx io_ctx;
3247 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3248
3249 std::vector<librbd::mirror_peer_site_t> peer_vector;
3250 int r = librbd::api::Mirror<>::peer_site_list(io_ctx, &peer_vector);
3251 if (r < 0) {
3252 return r;
3253 }
3254
3255 if (*max_peers < static_cast<int>(peer_vector.size())) {
3256 *max_peers = static_cast<int>(peer_vector.size());
3257 return -ERANGE;
3258 }
3259
3260 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
3261 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
3262 peers[i].direction = peer_vector[i].direction;
3263 peers[i].site_name = strdup(peer_vector[i].site_name.c_str());
3264 peers[i].mirror_uuid = strdup(peer_vector[i].mirror_uuid.c_str());
3265 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
3266 }
3267 *max_peers = static_cast<int>(peer_vector.size());
3268 return 0;
3269 }
3270
3271 extern "C" void rbd_mirror_peer_site_list_cleanup(rbd_mirror_peer_site_t *peers,
3272 int max_peers) {
3273 for (int i = 0; i < max_peers; ++i) {
3274 free(peers[i].uuid);
3275 free(peers[i].site_name);
3276 free(peers[i].mirror_uuid);
3277 free(peers[i].client_name);
3278 }
3279 }
3280
3281 extern "C" int rbd_mirror_peer_site_set_client_name(
3282 rados_ioctx_t p, const char *uuid, const char *client_name) {
3283 librados::IoCtx io_ctx;
3284 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3285 return librbd::api::Mirror<>::peer_site_set_client(io_ctx, uuid, client_name);
3286 }
3287
3288 extern "C" int rbd_mirror_peer_site_set_name(
3289 rados_ioctx_t p, const char *uuid, const char *site_name) {
3290 librados::IoCtx io_ctx;
3291 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3292 return librbd::api::Mirror<>::peer_site_set_name(io_ctx, uuid, site_name);
3293 }
3294
3295 extern "C" int rbd_mirror_peer_site_set_direction(
3296 rados_ioctx_t p, const char *uuid, rbd_mirror_peer_direction_t direction) {
3297 librados::IoCtx io_ctx;
3298 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3299 return librbd::api::Mirror<>::peer_site_set_direction(io_ctx, uuid,
3300 direction);
3301 }
3302
3303 extern "C" int rbd_mirror_peer_site_get_attributes(
3304 rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
3305 char *values, size_t *max_val_len, size_t *key_value_count) {
3306 librados::IoCtx io_ctx;
3307 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3308
3309 std::map<std::string, std::string> attributes;
3310 int r = librbd::api::Mirror<>::peer_site_get_attributes(
3311 io_ctx, uuid, &attributes);
3312 if (r < 0) {
3313 return r;
3314 }
3315
3316 size_t key_total_len = 0, val_total_len = 0;
3317 for (auto& it : attributes) {
3318 key_total_len += it.first.size() + 1;
3319 val_total_len += it.second.length() + 1;
3320 }
3321
3322 bool too_short = ((*max_key_len < key_total_len) ||
3323 (*max_val_len < val_total_len));
3324
3325 *max_key_len = key_total_len;
3326 *max_val_len = val_total_len;
3327 *key_value_count = attributes.size();
3328 if (too_short) {
3329 return -ERANGE;
3330 }
3331
3332 char *keys_p = keys;
3333 char *values_p = values;
3334 for (auto& it : attributes) {
3335 strncpy(keys_p, it.first.c_str(), it.first.size() + 1);
3336 keys_p += it.first.size() + 1;
3337
3338 strncpy(values_p, it.second.c_str(), it.second.length() + 1);
3339 values_p += it.second.length() + 1;
3340 }
3341
3342 return 0;
3343 }
3344
3345 extern "C" int rbd_mirror_peer_site_set_attributes(
3346 rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
3347 size_t count) {
3348 librados::IoCtx io_ctx;
3349 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3350
3351 std::map<std::string, std::string> attributes;
3352
3353 for (size_t i = 0; i < count; ++i) {
3354 const char* key = keys;
3355 keys += strlen(key) + 1;
3356 const char* value = values;
3357 values += strlen(value) + 1;
3358 attributes[key] = value;
3359 }
3360
3361 return librbd::api::Mirror<>::peer_site_set_attributes(
3362 io_ctx, uuid, attributes);
3363 }
3364
3365 extern "C" int rbd_mirror_image_global_status_list(rados_ioctx_t p,
3366 const char *start_id, size_t max, char **image_ids,
3367 rbd_mirror_image_global_status_t *images, size_t *len) {
3368 librados::IoCtx io_ctx;
3369 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3370 std::map<std::string, librbd::mirror_image_global_status_t> cpp_images;
3371
3372 int r = librbd::api::Mirror<>::image_global_status_list(
3373 io_ctx, start_id, max, &cpp_images);
3374 if (r < 0) {
3375 return r;
3376 }
3377
3378 size_t i = 0;
3379 for (auto &it : cpp_images) {
3380 ceph_assert(i < max);
3381 const std::string &image_id = it.first;
3382 image_ids[i] = strdup(image_id.c_str());
3383 mirror_image_global_status_cpp_to_c(it.second, &images[i]);
3384 i++;
3385 }
3386 *len = i;
3387 return 0;
3388 }
3389
3390 extern "C" void rbd_mirror_image_global_status_cleanup(
3391 rbd_mirror_image_global_status_t *global_status) {
3392 free(global_status->name);
3393 rbd_mirror_image_get_info_cleanup(&global_status->info);
3394 for (auto idx = 0U; idx < global_status->site_statuses_count; ++idx) {
3395 free(global_status->site_statuses[idx].mirror_uuid);
3396 free(global_status->site_statuses[idx].description);
3397 }
3398 free(global_status->site_statuses);
3399 }
3400
3401 extern "C" void rbd_mirror_image_global_status_list_cleanup(
3402 char **image_ids, rbd_mirror_image_global_status_t *images, size_t len) {
3403 for (size_t i = 0; i < len; i++) {
3404 free(image_ids[i]);
3405 rbd_mirror_image_global_status_cleanup(&images[i]);
3406 }
3407 }
3408
3409 #pragma GCC diagnostic push
3410 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
3411
3412 extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
3413 size_t uuid_max_length,
3414 const char *cluster_name,
3415 const char *client_name) {
3416 return rbd_mirror_peer_site_add(
3417 p, uuid, uuid_max_length, RBD_MIRROR_PEER_DIRECTION_RX_TX, cluster_name,
3418 client_name);
3419 }
3420
3421 extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
3422 return rbd_mirror_peer_site_remove(p, uuid);
3423 }
3424
3425 extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
3426 rbd_mirror_peer_t *peers, int *max_peers) {
3427 librados::IoCtx io_ctx;
3428 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3429
3430 std::vector<librbd::mirror_peer_site_t> peer_vector;
3431 int r = librbd::api::Mirror<>::peer_site_list(io_ctx, &peer_vector);
3432 if (r < 0) {
3433 return r;
3434 }
3435
3436 if (*max_peers < static_cast<int>(peer_vector.size())) {
3437 *max_peers = static_cast<int>(peer_vector.size());
3438 return -ERANGE;
3439 }
3440
3441 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
3442 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
3443 peers[i].cluster_name = strdup(peer_vector[i].site_name.c_str());
3444 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
3445 }
3446 *max_peers = static_cast<int>(peer_vector.size());
3447 return 0;
3448 }
3449
3450 extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
3451 int max_peers) {
3452 for (int i = 0; i < max_peers; ++i) {
3453 free(peers[i].uuid);
3454 free(peers[i].cluster_name);
3455 free(peers[i].client_name);
3456 }
3457 }
3458
3459 extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
3460 const char *client_name) {
3461 return rbd_mirror_peer_site_set_client_name(p, uuid, client_name);
3462 }
3463
3464 extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
3465 const char *cluster_name) {
3466 return rbd_mirror_peer_site_set_name(p, uuid, cluster_name);
3467 }
3468
3469 extern "C" int rbd_mirror_peer_get_attributes(
3470 rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
3471 char *values, size_t *max_val_len, size_t *key_value_count) {
3472 return rbd_mirror_peer_site_get_attributes(
3473 p, uuid, keys, max_key_len, values, max_val_len, key_value_count);
3474 }
3475
3476 extern "C" int rbd_mirror_peer_set_attributes(
3477 rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
3478 size_t count) {
3479 return rbd_mirror_peer_site_set_attributes(
3480 p, uuid, keys, values, count);
3481 }
3482
3483 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
3484 const char *start_id, size_t max, char **image_ids,
3485 rbd_mirror_image_status_t *images, size_t *len) {
3486 librados::IoCtx io_ctx;
3487 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3488 std::map<std::string, librbd::mirror_image_global_status_t> cpp_images;
3489
3490 int r = librbd::api::Mirror<>::image_global_status_list(
3491 io_ctx, start_id, max, &cpp_images);
3492 if (r < 0) {
3493 return r;
3494 }
3495
3496 size_t i = 0;
3497 for (auto &it : cpp_images) {
3498 ceph_assert(i < max);
3499 const std::string &image_id = it.first;
3500 image_ids[i] = strdup(image_id.c_str());
3501 mirror_image_global_status_cpp_to_c(it.second, &images[i]);
3502 i++;
3503 }
3504 *len = i;
3505 return 0;
3506 }
3507
3508 extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
3509 rbd_mirror_image_status_t *images, size_t len) {
3510 for (size_t i = 0; i < len; i++) {
3511 free(image_ids[i]);
3512 free(images[i].name);
3513 rbd_mirror_image_get_info_cleanup(&images[i].info);
3514 free(images[i].description);
3515 }
3516 }
3517
3518 #pragma GCC diagnostic pop
3519
3520 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
3521 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
3522
3523 librados::IoCtx io_ctx;
3524 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3525
3526 std::map<librbd::mirror_image_status_state_t, int> states_;
3527 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
3528 if (r < 0) {
3529 return r;
3530 }
3531
3532 size_t i = 0;
3533 for (auto &it : states_) {
3534 if (i == *maxlen) {
3535 return -ERANGE;
3536 }
3537 states[i] = it.first;
3538 counts[i] = it.second;
3539 i++;
3540 }
3541 *maxlen = i;
3542 return 0;
3543 }
3544
3545 extern "C" int rbd_mirror_image_instance_id_list(
3546 rados_ioctx_t p, const char *start_id, size_t max, char **image_ids,
3547 char **instance_ids, size_t *len) {
3548 librados::IoCtx io_ctx;
3549 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3550 std::map<std::string, std::string> cpp_instance_ids;
3551
3552 int r = librbd::api::Mirror<>::image_instance_id_list(io_ctx, start_id, max,
3553 &cpp_instance_ids);
3554 if (r < 0) {
3555 return r;
3556 }
3557
3558 size_t i = 0;
3559 for (auto &it : cpp_instance_ids) {
3560 ceph_assert(i < max);
3561 image_ids[i] = strdup(it.first.c_str());
3562 instance_ids[i] = strdup(it.second.c_str());
3563 i++;
3564 }
3565 *len = i;
3566 return 0;
3567 }
3568
3569 extern "C" void rbd_mirror_image_instance_id_list_cleanup(
3570 char **image_ids, char **instance_ids, size_t len) {
3571 for (size_t i = 0; i < len; i++) {
3572 free(image_ids[i]);
3573 free(instance_ids[i]);
3574 }
3575 }
3576
3577 extern "C" int rbd_mirror_image_info_list(
3578 rados_ioctx_t p, rbd_mirror_image_mode_t *mode_filter,
3579 const char *start_id, size_t max, char **image_ids,
3580 rbd_mirror_image_mode_t *mode_entries,
3581 rbd_mirror_image_info_t *info_entries, size_t *num_entries) {
3582 librados::IoCtx io_ctx;
3583 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3584 std::map<std::string, std::pair<librbd::mirror_image_mode_t,
3585 librbd::mirror_image_info_t>> cpp_entries;
3586
3587 int r = librbd::api::Mirror<>::image_info_list(io_ctx, mode_filter, start_id,
3588 max, &cpp_entries);
3589 if (r < 0) {
3590 return r;
3591 }
3592
3593 ceph_assert(cpp_entries.size() <= max);
3594
3595 for (auto &it : cpp_entries) {
3596 *(image_ids++) = strdup(it.first.c_str());
3597 *(mode_entries++) = it.second.first;
3598 mirror_image_info_cpp_to_c(it.second.second, info_entries++);
3599 }
3600 *num_entries = cpp_entries.size();
3601
3602 return 0;
3603 }
3604
3605 extern "C" void rbd_mirror_image_info_list_cleanup(
3606 char **image_ids, rbd_mirror_image_info_t *info_entries,
3607 size_t num_entries) {
3608 for (size_t i = 0; i < num_entries; i++) {
3609 free(*(image_ids++));
3610 rbd_mirror_image_get_info_cleanup(info_entries++);
3611 }
3612 }
3613
3614 /* helpers */
3615
3616 extern "C" void rbd_image_spec_cleanup(rbd_image_spec_t *image)
3617 {
3618 free(image->id);
3619 free(image->name);
3620 }
3621
3622 extern "C" void rbd_image_spec_list_cleanup(rbd_image_spec_t *images,
3623 size_t num_images)
3624 {
3625 for (size_t idx = 0; idx < num_images; ++idx) {
3626 rbd_image_spec_cleanup(&images[idx]);
3627 }
3628 }
3629
3630 extern "C" void rbd_linked_image_spec_cleanup(rbd_linked_image_spec_t *image)
3631 {
3632 free(image->pool_name);
3633 free(image->pool_namespace);
3634 free(image->image_id);
3635 free(image->image_name);
3636 }
3637
3638 extern "C" void rbd_linked_image_spec_list_cleanup(
3639 rbd_linked_image_spec_t *images, size_t num_images)
3640 {
3641 for (size_t idx = 0; idx < num_images; ++idx) {
3642 rbd_linked_image_spec_cleanup(&images[idx]);
3643 }
3644 }
3645
3646 extern "C" void rbd_snap_spec_cleanup(rbd_snap_spec_t *snap)
3647 {
3648 free(snap->name);
3649 }
3650
3651 /* images */
3652 extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
3653 {
3654 librados::IoCtx io_ctx;
3655 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3656
3657 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3658 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(),
3659 io_ctx.get_id());
3660 std::vector<librbd::image_spec_t> cpp_image_specs;
3661 int r = librbd::api::Image<>::list_images(io_ctx, &cpp_image_specs);
3662 if (r < 0) {
3663 tracepoint(librbd, list_exit, r, *size);
3664 return r;
3665 }
3666
3667 size_t expected_size = 0;
3668
3669 for (auto& it : cpp_image_specs) {
3670 expected_size += it.name.size() + 1;
3671 }
3672 if (*size < expected_size) {
3673 *size = expected_size;
3674 tracepoint(librbd, list_exit, -ERANGE, *size);
3675 return -ERANGE;
3676 }
3677
3678 if (names == NULL) {
3679 tracepoint(librbd, list_exit, -EINVAL, *size);
3680 return -EINVAL;
3681 }
3682
3683 for (auto& it : cpp_image_specs) {
3684 const char* name = it.name.c_str();
3685 tracepoint(librbd, list_entry, name);
3686 strcpy(names, name);
3687 names += strlen(names) + 1;
3688 }
3689 tracepoint(librbd, list_exit, (int)expected_size, *size);
3690 return (int)expected_size;
3691 }
3692
3693 extern "C" int rbd_list2(rados_ioctx_t p, rbd_image_spec_t *images,
3694 size_t *size)
3695 {
3696 librados::IoCtx io_ctx;
3697 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3698
3699 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3700 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(),
3701 io_ctx.get_id());
3702 // FIPS zeroization audit 20191117: this memset is not security related.
3703 memset(images, 0, sizeof(*images) * *size);
3704 std::vector<librbd::image_spec_t> cpp_image_specs;
3705 int r = librbd::api::Image<>::list_images(io_ctx, &cpp_image_specs);
3706 if (r < 0) {
3707 tracepoint(librbd, list_exit, r, *size);
3708 return r;
3709 }
3710
3711 size_t expected_size = cpp_image_specs.size();
3712 if (*size < expected_size) {
3713 *size = expected_size;
3714 tracepoint(librbd, list_exit, -ERANGE, *size);
3715 return -ERANGE;
3716 }
3717
3718 *size = expected_size;
3719 for (size_t idx = 0; idx < expected_size; ++idx) {
3720 images[idx].id = strdup(cpp_image_specs[idx].id.c_str());
3721 images[idx].name = strdup(cpp_image_specs[idx].name.c_str());
3722 }
3723 tracepoint(librbd, list_exit, 0, *size);
3724 return 0;
3725 }
3726
3727 extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
3728 {
3729 librados::IoCtx io_ctx;
3730 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3731 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3732 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
3733 int r = librbd::create(io_ctx, name, size, order);
3734 tracepoint(librbd, create_exit, r, *order);
3735 return r;
3736 }
3737
3738 extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
3739 uint64_t size, uint64_t features,
3740 int *order)
3741 {
3742 librados::IoCtx io_ctx;
3743 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3744 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3745 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
3746 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
3747 tracepoint(librbd, create2_exit, r, *order);
3748 return r;
3749 }
3750
3751 extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
3752 uint64_t size, uint64_t features,
3753 int *order,
3754 uint64_t stripe_unit, uint64_t stripe_count)
3755 {
3756 librados::IoCtx io_ctx;
3757 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3758 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3759 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
3760 int r = librbd::create(io_ctx, name, size, false, features, order,
3761 stripe_unit, stripe_count);
3762 tracepoint(librbd, create3_exit, r, *order);
3763 return r;
3764 }
3765
3766 extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
3767 uint64_t size, rbd_image_options_t opts)
3768 {
3769 librados::IoCtx io_ctx;
3770 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3771 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3772 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
3773 librbd::ImageOptions opts_(opts);
3774 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
3775 tracepoint(librbd, create4_exit, r);
3776 return r;
3777 }
3778
3779 extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
3780 const char *p_snap_name, rados_ioctx_t c_ioctx,
3781 const char *c_name, uint64_t features, int *c_order)
3782 {
3783 librados::IoCtx p_ioc, c_ioc;
3784 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
3785 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
3786 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
3787 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);
3788 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
3789 features, c_order, 0, 0);
3790 tracepoint(librbd, clone_exit, r, *c_order);
3791 return r;
3792 }
3793
3794 extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
3795 const char *p_snap_name, rados_ioctx_t c_ioctx,
3796 const char *c_name, uint64_t features, int *c_order,
3797 uint64_t stripe_unit, int stripe_count)
3798 {
3799 librados::IoCtx p_ioc, c_ioc;
3800 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
3801 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
3802 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
3803 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);
3804 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
3805 features, c_order, stripe_unit, stripe_count);
3806 tracepoint(librbd, clone2_exit, r, *c_order);
3807 return r;
3808 }
3809
3810 extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
3811 const char *p_snap_name, rados_ioctx_t c_ioctx,
3812 const char *c_name, rbd_image_options_t c_opts)
3813 {
3814 librados::IoCtx p_ioc, c_ioc;
3815 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
3816 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
3817 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
3818 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);
3819 librbd::ImageOptions c_opts_(c_opts);
3820 int r = librbd::clone(p_ioc, nullptr, p_name, p_snap_name, c_ioc, nullptr,
3821 c_name, c_opts_, "", "");
3822 tracepoint(librbd, clone3_exit, r);
3823 return r;
3824 }
3825
3826 extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
3827 {
3828 librados::IoCtx io_ctx;
3829 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3830 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3831 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
3832 librbd::NoOpProgressContext prog_ctx;
3833 int r = librbd::api::Image<>::remove(io_ctx, name, prog_ctx);
3834 tracepoint(librbd, remove_exit, r);
3835 return r;
3836 }
3837
3838 extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
3839 librbd_progress_fn_t cb, void *cbdata)
3840 {
3841 librados::IoCtx io_ctx;
3842 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3843 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3844 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
3845 librbd::CProgressContext prog_ctx(cb, cbdata);
3846 int r = librbd::api::Image<>::remove(io_ctx, name, prog_ctx);
3847 tracepoint(librbd, remove_exit, r);
3848 return r;
3849 }
3850
3851 extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
3852 uint64_t delay) {
3853 librados::IoCtx io_ctx;
3854 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3855 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3856 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
3857 io_ctx.get_id(), name);
3858 int r = librbd::api::Trash<>::move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name,
3859 delay);
3860 tracepoint(librbd, trash_move_exit, r);
3861 return r;
3862 }
3863
3864 extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
3865 rbd_trash_image_info_t *info) {
3866 librados::IoCtx io_ctx;
3867 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3868
3869 librbd::trash_image_info_t cpp_info;
3870 int r = librbd::api::Trash<>::get(io_ctx, id, &cpp_info);
3871 if (r < 0) {
3872 return r;
3873 }
3874
3875 trash_image_info_cpp_to_c(cpp_info, info);
3876 return 0;
3877 }
3878
3879 extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
3880 free(info->id);
3881 free(info->name);
3882 }
3883
3884 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
3885 size_t *num_entries) {
3886 librados::IoCtx io_ctx;
3887 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3888 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3889 tracepoint(librbd, trash_list_enter,
3890 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
3891 // FIPS zeroization audit 20191117: this memset is not security related.
3892 memset(entries, 0, sizeof(*entries) * *num_entries);
3893
3894 vector<librbd::trash_image_info_t> cpp_entries;
3895 int r = librbd::api::Trash<>::list(io_ctx, cpp_entries, true);
3896 if (r < 0) {
3897 tracepoint(librbd, trash_list_exit, r, *num_entries);
3898 return r;
3899 }
3900
3901 if (*num_entries < cpp_entries.size()) {
3902 *num_entries = cpp_entries.size();
3903 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
3904 return -ERANGE;
3905 }
3906
3907 int i=0;
3908 for (const auto &entry : cpp_entries) {
3909 trash_image_info_cpp_to_c(entry, &entries[i++]);
3910 }
3911 *num_entries = cpp_entries.size();
3912
3913 return *num_entries;
3914 }
3915
3916 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
3917 size_t num_entries) {
3918 for (size_t i=0; i < num_entries; i++) {
3919 rbd_trash_get_cleanup(&entries[i]);
3920 }
3921 }
3922
3923 extern "C" int rbd_trash_purge(rados_ioctx_t io, time_t expire_ts,
3924 float threshold) {
3925 librados::IoCtx io_ctx;
3926 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3927 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3928 tracepoint(librbd, trash_purge_enter, io_ctx.get_pool_name().c_str(),
3929 io_ctx.get_id(), expire_ts, threshold);
3930 librbd::NoOpProgressContext nop_pctx;
3931 int r = librbd::api::Trash<>::purge(io_ctx, expire_ts, threshold, nop_pctx);
3932 tracepoint(librbd, trash_purge_exit, r);
3933 return r;
3934 }
3935
3936 extern "C" int rbd_trash_purge_with_progress(rados_ioctx_t io, time_t expire_ts,
3937 float threshold, librbd_progress_fn_t cb, void* cbdata) {
3938 librados::IoCtx io_ctx;
3939 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3940 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3941 tracepoint(librbd, trash_purge_enter, io_ctx.get_pool_name().c_str(),
3942 io_ctx.get_id(), expire_ts, threshold);
3943 librbd::CProgressContext pctx(cb, cbdata);
3944 int r = librbd::api::Trash<>::purge(io_ctx, expire_ts, threshold, pctx);
3945 tracepoint(librbd, trash_purge_exit, r);
3946 return r;
3947 }
3948
3949 extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
3950 bool force) {
3951 librados::IoCtx io_ctx;
3952 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3953 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3954 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
3955 io_ctx.get_id(), image_id, force);
3956 librbd::NoOpProgressContext prog_ctx;
3957 int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx);
3958 tracepoint(librbd, trash_remove_exit, r);
3959 return r;
3960 }
3961
3962 extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
3963 const char *image_id,
3964 bool force,
3965 librbd_progress_fn_t cb,
3966 void *cbdata) {
3967 librados::IoCtx io_ctx;
3968 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3969 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3970 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
3971 io_ctx.get_id(), image_id, force);
3972 librbd::CProgressContext prog_ctx(cb, cbdata);
3973 int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx);
3974 tracepoint(librbd, trash_remove_exit, r);
3975 return r;
3976 }
3977
3978 extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
3979 const char *name) {
3980 librados::IoCtx io_ctx;
3981 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
3982 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
3983 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
3984 io_ctx.get_id(), id, name);
3985 int r = librbd::api::Trash<>::restore(
3986 io_ctx, librbd::api::Trash<>::RESTORE_SOURCE_WHITELIST, id, name);
3987 tracepoint(librbd, trash_undelete_exit, r);
3988 return r;
3989 }
3990
3991 extern "C" int rbd_namespace_create(rados_ioctx_t io,
3992 const char *namespace_name) {
3993 librados::IoCtx io_ctx;
3994 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
3995
3996 return librbd::api::Namespace<>::create(io_ctx, namespace_name);
3997 }
3998
3999 extern "C" int rbd_namespace_remove(rados_ioctx_t io,
4000 const char *namespace_name) {
4001 librados::IoCtx io_ctx;
4002 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
4003
4004 return librbd::api::Namespace<>::remove(io_ctx, namespace_name);
4005 }
4006
4007 extern "C" int rbd_namespace_list(rados_ioctx_t io, char *names, size_t *size) {
4008 librados::IoCtx io_ctx;
4009 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
4010
4011 if (names == nullptr || size == nullptr) {
4012 return -EINVAL;
4013 }
4014
4015 std::vector<std::string> cpp_names;
4016 int r = librbd::api::Namespace<>::list(io_ctx, &cpp_names);
4017 if (r < 0) {
4018 return r;
4019 }
4020
4021 size_t expected_size = 0;
4022 for (size_t i = 0; i < cpp_names.size(); i++) {
4023 expected_size += cpp_names[i].size() + 1;
4024 }
4025 if (*size < expected_size) {
4026 *size = expected_size;
4027 return -ERANGE;
4028 }
4029
4030 *size = expected_size;
4031 for (int i = 0; i < (int)cpp_names.size(); i++) {
4032 const char* name = cpp_names[i].c_str();
4033 strcpy(names, name);
4034 names += strlen(names) + 1;
4035 }
4036
4037 return (int)expected_size;
4038 }
4039
4040 extern "C" int rbd_namespace_exists(rados_ioctx_t io,
4041 const char *namespace_name,
4042 bool *exists) {
4043 librados::IoCtx io_ctx;
4044 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
4045
4046 return librbd::api::Namespace<>::exists(io_ctx, namespace_name, exists);
4047 }
4048
4049 extern "C" int rbd_pool_init(rados_ioctx_t io, bool force) {
4050 librados::IoCtx io_ctx;
4051 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
4052
4053 return librbd::api::Pool<>::init(io_ctx, force);
4054 }
4055
4056 extern "C" void rbd_pool_stats_create(rbd_pool_stats_t *stats) {
4057 *stats = reinterpret_cast<rbd_pool_stats_t>(
4058 new librbd::api::Pool<>::StatOptions{});
4059 }
4060
4061 extern "C" void rbd_pool_stats_destroy(rbd_pool_stats_t stats) {
4062 auto pool_stat_options =
4063 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats);
4064 delete pool_stat_options;
4065 }
4066
4067 extern "C" int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
4068 int stat_option,
4069 uint64_t* stat_val) {
4070 auto pool_stat_options =
4071 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(stats);
4072 return librbd::api::Pool<>::add_stat_option(
4073 pool_stat_options, static_cast<rbd_pool_stat_option_t>(stat_option),
4074 stat_val);
4075 }
4076
4077 extern "C" int rbd_pool_stats_get(
4078 rados_ioctx_t io, rbd_pool_stats_t pool_stats) {
4079 librados::IoCtx io_ctx;
4080 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
4081
4082 auto pool_stat_options =
4083 reinterpret_cast<librbd::api::Pool<>::StatOptions*>(pool_stats);
4084 return librbd::api::Pool<>::get_stats(io_ctx, pool_stat_options);
4085 }
4086
4087 extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
4088 const char *destname)
4089 {
4090 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4091 librados::IoCtx dest_io_ctx;
4092 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4093 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);
4094 librbd::ImageOptions opts;
4095 librbd::NoOpProgressContext prog_ctx;
4096 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
4097 tracepoint(librbd, copy_exit, r);
4098 return r;
4099 }
4100
4101 extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
4102 {
4103 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
4104 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
4105 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);
4106 librbd::NoOpProgressContext prog_ctx;
4107 int r = librbd::copy(src, dest, prog_ctx, 0);
4108 tracepoint(librbd, copy2_exit, r);
4109 return r;
4110 }
4111
4112 extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
4113 const char *destname, rbd_image_options_t c_opts)
4114 {
4115 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4116 librados::IoCtx dest_io_ctx;
4117 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4118 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);
4119 librbd::ImageOptions c_opts_(c_opts);
4120 librbd::NoOpProgressContext prog_ctx;
4121 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
4122 tracepoint(librbd, copy3_exit, r);
4123 return r;
4124 }
4125
4126 extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
4127 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
4128 {
4129 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4130 librados::IoCtx dest_io_ctx;
4131 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4132 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);
4133 librbd::ImageOptions c_opts_(c_opts);
4134 librbd::NoOpProgressContext prog_ctx;
4135 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
4136 tracepoint(librbd, copy4_exit, r);
4137 return r;
4138 }
4139
4140 extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
4141 const char *destname,
4142 librbd_progress_fn_t fn, void *data)
4143 {
4144 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4145 librados::IoCtx dest_io_ctx;
4146 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4147 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);
4148 librbd::ImageOptions opts;
4149 librbd::CProgressContext prog_ctx(fn, data);
4150 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
4151 tracepoint(librbd, copy_exit, ret);
4152 return ret;
4153 }
4154
4155 extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
4156 librbd_progress_fn_t fn, void *data)
4157 {
4158 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
4159 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
4160 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);
4161 librbd::CProgressContext prog_ctx(fn, data);
4162 int ret = librbd::copy(src, dest, prog_ctx, 0);
4163 tracepoint(librbd, copy2_exit, ret);
4164 return ret;
4165 }
4166
4167 extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
4168 const char *destname,
4169 rbd_image_options_t dest_opts,
4170 librbd_progress_fn_t fn, void *data)
4171 {
4172 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4173 librados::IoCtx dest_io_ctx;
4174 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4175 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);
4176 librbd::ImageOptions dest_opts_(dest_opts);
4177 librbd::CProgressContext prog_ctx(fn, data);
4178 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
4179 tracepoint(librbd, copy3_exit, ret);
4180 return ret;
4181 }
4182
4183 extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
4184 const char *destname,
4185 rbd_image_options_t dest_opts,
4186 librbd_progress_fn_t fn, void *data, size_t sparse_size)
4187 {
4188 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4189 librados::IoCtx dest_io_ctx;
4190 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4191 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);
4192 librbd::ImageOptions dest_opts_(dest_opts);
4193 librbd::CProgressContext prog_ctx(fn, data);
4194 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
4195 tracepoint(librbd, copy4_exit, ret);
4196 return ret;
4197 }
4198
4199 extern "C" int rbd_deep_copy(rbd_image_t image, rados_ioctx_t dest_p,
4200 const char *destname, rbd_image_options_t c_opts)
4201 {
4202 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4203 librados::IoCtx dest_io_ctx;
4204 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4205 tracepoint(librbd, deep_copy_enter, ictx, ictx->name.c_str(),
4206 ictx->snap_name.c_str(), ictx->read_only,
4207 dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(),
4208 destname, c_opts);
4209 librbd::ImageOptions opts(c_opts);
4210 librbd::NoOpProgressContext prog_ctx;
4211 int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
4212 prog_ctx);
4213 tracepoint(librbd, deep_copy_exit, r);
4214 return r;
4215 }
4216
4217 extern "C" int rbd_deep_copy_with_progress(rbd_image_t image,
4218 rados_ioctx_t dest_p,
4219 const char *destname,
4220 rbd_image_options_t dest_opts,
4221 librbd_progress_fn_t fn, void *data)
4222 {
4223 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4224 librados::IoCtx dest_io_ctx;
4225 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4226 tracepoint(librbd, deep_copy_enter, ictx, ictx->name.c_str(),
4227 ictx->snap_name.c_str(), ictx->read_only,
4228 dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(),
4229 destname, dest_opts);
4230 librbd::ImageOptions opts(dest_opts);
4231 librbd::CProgressContext prog_ctx(fn, data);
4232 int ret = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
4233 prog_ctx);
4234 tracepoint(librbd, deep_copy_exit, ret);
4235 return ret;
4236 }
4237
4238 extern "C" int rbd_flatten(rbd_image_t image)
4239 {
4240 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4241 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
4242 librbd::NoOpProgressContext prog_ctx;
4243 int r = ictx->operations->flatten(prog_ctx);
4244 tracepoint(librbd, flatten_exit, r);
4245 return r;
4246 }
4247
4248 extern "C" int rbd_flatten_with_progress(rbd_image_t image,
4249 librbd_progress_fn_t cb, void *cbdata)
4250 {
4251 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4252 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
4253 librbd::CProgressContext prog_ctx(cb, cbdata);
4254 int r = ictx->operations->flatten(prog_ctx);
4255 tracepoint(librbd, flatten_exit, r);
4256 return r;
4257 }
4258
4259 extern "C" int rbd_sparsify(rbd_image_t image, size_t sparse_size)
4260 {
4261 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4262 tracepoint(librbd, sparsify_enter, ictx, ictx->name.c_str(), sparse_size,
4263 ictx->id.c_str());
4264 librbd::NoOpProgressContext prog_ctx;
4265 int r = ictx->operations->sparsify(sparse_size, prog_ctx);
4266 tracepoint(librbd, sparsify_exit, r);
4267 return r;
4268 }
4269
4270 extern "C" int rbd_sparsify_with_progress(rbd_image_t image, size_t sparse_size,
4271 librbd_progress_fn_t cb, void *cbdata)
4272 {
4273 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4274 tracepoint(librbd, sparsify_enter, ictx, ictx->name.c_str(), sparse_size,
4275 ictx->id.c_str());
4276 librbd::CProgressContext prog_ctx(cb, cbdata);
4277 int r = ictx->operations->sparsify(sparse_size, prog_ctx);
4278 tracepoint(librbd, sparsify_exit, r);
4279 return r;
4280 }
4281
4282 extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
4283 const char *destname)
4284 {
4285 librados::IoCtx src_io_ctx;
4286 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
4287 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
4288 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
4289 int r = librbd::rename(src_io_ctx, srcname, destname);
4290 tracepoint(librbd, rename_exit, r);
4291 return r;
4292 }
4293
4294 extern "C" int rbd_migration_prepare(rados_ioctx_t p, const char *image_name,
4295 rados_ioctx_t dest_p,
4296 const char *dest_image_name,
4297 rbd_image_options_t opts_)
4298 {
4299 librados::IoCtx io_ctx;
4300 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4301 librados::IoCtx dest_io_ctx;
4302 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
4303 tracepoint(librbd, migration_prepare_enter, io_ctx.get_pool_name().c_str(),
4304 io_ctx.get_id(), image_name, dest_io_ctx.get_pool_name().c_str(),
4305 dest_io_ctx.get_id(), dest_image_name, opts_);
4306 librbd::ImageOptions opts(opts_);
4307 int r = librbd::api::Migration<>::prepare(io_ctx, image_name, dest_io_ctx,
4308 dest_image_name, opts);
4309 tracepoint(librbd, migration_prepare_exit, r);
4310 return r;
4311 }
4312
4313 extern "C" int rbd_migration_execute(rados_ioctx_t p, const char *image_name)
4314 {
4315 librados::IoCtx io_ctx;
4316 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4317 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4318 tracepoint(librbd, migration_execute_enter, io_ctx.get_pool_name().c_str(),
4319 io_ctx.get_id(), image_name);
4320 librbd::NoOpProgressContext prog_ctx;
4321 int r = librbd::api::Migration<>::execute(io_ctx, image_name, prog_ctx);
4322 tracepoint(librbd, migration_execute_exit, r);
4323 return r;
4324 }
4325
4326 extern "C" int rbd_migration_execute_with_progress(rados_ioctx_t p,
4327 const char *name,
4328 librbd_progress_fn_t fn,
4329 void *data)
4330 {
4331 librados::IoCtx io_ctx;
4332 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4333 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4334 tracepoint(librbd, migration_execute_enter, io_ctx.get_pool_name().c_str(),
4335 io_ctx.get_id(), name);
4336 librbd::CProgressContext prog_ctx(fn, data);
4337 int r = librbd::api::Migration<>::execute(io_ctx, name, prog_ctx);
4338 tracepoint(librbd, migration_execute_exit, r);
4339 return r;
4340 }
4341
4342 extern "C" int rbd_migration_abort(rados_ioctx_t p, const char *image_name)
4343 {
4344 librados::IoCtx io_ctx;
4345 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4346 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4347 tracepoint(librbd, migration_abort_enter, io_ctx.get_pool_name().c_str(),
4348 io_ctx.get_id(), image_name);
4349 librbd::NoOpProgressContext prog_ctx;
4350 int r = librbd::api::Migration<>::abort(io_ctx, image_name, prog_ctx);
4351 tracepoint(librbd, migration_abort_exit, r);
4352 return r;
4353 }
4354
4355 extern "C" int rbd_migration_abort_with_progress(rados_ioctx_t p,
4356 const char *name,
4357 librbd_progress_fn_t fn,
4358 void *data)
4359 {
4360 librados::IoCtx io_ctx;
4361 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4362 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4363 tracepoint(librbd, migration_abort_enter, io_ctx.get_pool_name().c_str(),
4364 io_ctx.get_id(), name);
4365 librbd::CProgressContext prog_ctx(fn, data);
4366 int r = librbd::api::Migration<>::abort(io_ctx, name, prog_ctx);
4367 tracepoint(librbd, migration_abort_exit, r);
4368 return r;
4369 }
4370
4371 extern "C" int rbd_migration_commit(rados_ioctx_t p, const char *image_name)
4372 {
4373 librados::IoCtx io_ctx;
4374 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4375 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4376 tracepoint(librbd, migration_commit_enter, io_ctx.get_pool_name().c_str(),
4377 io_ctx.get_id(), image_name);
4378 librbd::NoOpProgressContext prog_ctx;
4379 int r = librbd::api::Migration<>::commit(io_ctx, image_name, prog_ctx);
4380 tracepoint(librbd, migration_commit_exit, r);
4381 return r;
4382 }
4383
4384 extern "C" int rbd_migration_commit_with_progress(rados_ioctx_t p,
4385 const char *name,
4386 librbd_progress_fn_t fn,
4387 void *data)
4388 {
4389 librados::IoCtx io_ctx;
4390 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4391 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4392 tracepoint(librbd, migration_commit_enter, io_ctx.get_pool_name().c_str(),
4393 io_ctx.get_id(), name);
4394 librbd::CProgressContext prog_ctx(fn, data);
4395 int r = librbd::api::Migration<>::commit(io_ctx, name, prog_ctx);
4396 tracepoint(librbd, migration_commit_exit, r);
4397 return r;
4398 }
4399
4400 extern "C" int rbd_migration_status(rados_ioctx_t p, const char *image_name,
4401 rbd_image_migration_status_t *status,
4402 size_t status_size)
4403 {
4404 librados::IoCtx io_ctx;
4405 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4406 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4407 tracepoint(librbd, migration_status_enter, io_ctx.get_pool_name().c_str(),
4408 io_ctx.get_id(), image_name);
4409
4410 if (status_size != sizeof(rbd_image_migration_status_t)) {
4411 tracepoint(librbd, migration_status_exit, -ERANGE);
4412 return -ERANGE;
4413 }
4414
4415 librbd::image_migration_status_t cpp_status;
4416 int r = librbd::api::Migration<>::status(io_ctx, image_name, &cpp_status);
4417 if (r >= 0) {
4418 status->source_pool_id = cpp_status.source_pool_id;
4419 status->source_pool_namespace =
4420 strdup(cpp_status.source_pool_namespace.c_str());
4421 status->source_image_name = strdup(cpp_status.source_image_name.c_str());
4422 status->source_image_id = strdup(cpp_status.source_image_id.c_str());
4423 status->dest_pool_id = cpp_status.dest_pool_id;
4424 status->dest_pool_namespace =
4425 strdup(cpp_status.dest_pool_namespace.c_str());
4426 status->dest_image_name = strdup(cpp_status.dest_image_name.c_str());
4427 status->dest_image_id = strdup(cpp_status.dest_image_id.c_str());
4428 status->state = cpp_status.state;
4429 status->state_description = strdup(cpp_status.state_description.c_str());
4430 }
4431
4432 tracepoint(librbd, migration_status_exit, r);
4433 return r;
4434 }
4435
4436 extern "C" void rbd_migration_status_cleanup(rbd_image_migration_status_t *s)
4437 {
4438 free(s->source_pool_namespace);
4439 free(s->source_image_name);
4440 free(s->source_image_id);
4441 free(s->dest_pool_namespace);
4442 free(s->dest_image_name);
4443 free(s->dest_image_id);
4444 free(s->state_description);
4445 }
4446
4447 extern "C" int rbd_pool_metadata_get(rados_ioctx_t p, const char *key,
4448 char *value, size_t *vallen)
4449 {
4450 librados::IoCtx io_ctx;
4451 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4452 string val_s;
4453 int r = librbd::api::PoolMetadata<>::get(io_ctx, key, &val_s);
4454 if (*vallen < val_s.size() + 1) {
4455 r = -ERANGE;
4456 *vallen = val_s.size() + 1;
4457 } else {
4458 strncpy(value, val_s.c_str(), val_s.size() + 1);
4459 }
4460
4461 return r;
4462 }
4463
4464 extern "C" int rbd_pool_metadata_set(rados_ioctx_t p, const char *key,
4465 const char *value)
4466 {
4467 librados::IoCtx io_ctx;
4468 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4469 int r = librbd::api::PoolMetadata<>::set(io_ctx, key, value);
4470 return r;
4471 }
4472
4473 extern "C" int rbd_pool_metadata_remove(rados_ioctx_t p, const char *key)
4474 {
4475 librados::IoCtx io_ctx;
4476 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4477 int r = librbd::api::PoolMetadata<>::remove(io_ctx, key);
4478 return r;
4479 }
4480
4481 extern "C" int rbd_pool_metadata_list(rados_ioctx_t p, const char *start,
4482 uint64_t max, char *key, size_t *key_len,
4483 char *value, size_t *val_len)
4484 {
4485 librados::IoCtx io_ctx;
4486 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4487 map<string, bufferlist> pairs;
4488 int r = librbd::api::PoolMetadata<>::list(io_ctx, start, max, &pairs);
4489 if (r < 0) {
4490 return r;
4491 }
4492 size_t key_total_len = 0, val_total_len = 0;
4493 for (auto &it : pairs) {
4494 key_total_len += it.first.size() + 1;
4495 val_total_len += it.second.length() + 1;
4496 }
4497 if (*key_len < key_total_len || *val_len < val_total_len) {
4498 *key_len = key_total_len;
4499 *val_len = val_total_len;
4500 return -ERANGE;
4501 }
4502 *key_len = key_total_len;
4503 *val_len = val_total_len;
4504
4505 char *key_p = key, *value_p = value;
4506 for (auto &it : pairs) {
4507 strncpy(key_p, it.first.c_str(), it.first.size() + 1);
4508 key_p += it.first.size() + 1;
4509 strncpy(value_p, it.second.c_str(), it.second.length());
4510 value_p += it.second.length();
4511 *value_p = '\0';
4512 value_p++;
4513 }
4514 return 0;
4515 }
4516
4517 extern "C" int rbd_config_pool_list(rados_ioctx_t p,
4518 rbd_config_option_t *options,
4519 int *max_options) {
4520 librados::IoCtx io_ctx;
4521 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4522
4523 std::vector<librbd::config_option_t> option_vector;
4524 int r = librbd::api::Config<>::list(io_ctx, &option_vector);
4525 if (r < 0) {
4526 return r;
4527 }
4528
4529 if (*max_options < static_cast<int>(option_vector.size())) {
4530 *max_options = static_cast<int>(option_vector.size());
4531 return -ERANGE;
4532 }
4533
4534 for (int i = 0; i < static_cast<int>(option_vector.size()); ++i) {
4535 config_option_cpp_to_c(option_vector[i], &options[i]);
4536 }
4537 *max_options = static_cast<int>(option_vector.size());
4538 return 0;
4539 }
4540
4541 extern "C" void rbd_config_pool_list_cleanup(rbd_config_option_t *options,
4542 int max_options) {
4543 for (int i = 0; i < max_options; ++i) {
4544 config_option_cleanup(options[i]);
4545 }
4546 }
4547
4548 extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
4549 const char *snap_name)
4550 {
4551 librados::IoCtx io_ctx;
4552 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4553 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4554 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4555 false);
4556 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4557
4558 int r = ictx->state->open(0);
4559 if (r >= 0) {
4560 *image = (rbd_image_t)ictx;
4561 }
4562 tracepoint(librbd, open_image_exit, r);
4563 return r;
4564 }
4565
4566 extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
4567 rbd_image_t *image, const char *snap_name)
4568 {
4569 librados::IoCtx io_ctx;
4570 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4571 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4572 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4573 false);
4574 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
4575 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4576
4577 int r = ictx->state->open(0);
4578 if (r >= 0) {
4579 *image = (rbd_image_t)ictx;
4580 }
4581 tracepoint(librbd, open_image_exit, r);
4582 return r;
4583 }
4584
4585 extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
4586 rbd_image_t *image, const char *snap_name,
4587 rbd_completion_t c)
4588 {
4589 librados::IoCtx io_ctx;
4590 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4591 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4592 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4593 false);
4594 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4595 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);
4596 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4597 image));
4598 tracepoint(librbd, aio_open_image_exit, 0);
4599 return 0;
4600 }
4601
4602 extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
4603 rbd_image_t *image, const char *snap_name,
4604 rbd_completion_t c)
4605 {
4606 librados::IoCtx io_ctx;
4607 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4608 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4609 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4610 false);
4611 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4612 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
4613 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
4614 comp->pc);
4615 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4616 image));
4617 tracepoint(librbd, aio_open_image_exit, 0);
4618 return 0;
4619 }
4620
4621 extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
4622 rbd_image_t *image, const char *snap_name)
4623 {
4624 librados::IoCtx io_ctx;
4625 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4626 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4627 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4628 true);
4629 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4630
4631 int r = ictx->state->open(0);
4632 if (r >= 0) {
4633 *image = (rbd_image_t)ictx;
4634 }
4635 tracepoint(librbd, open_image_exit, r);
4636 return r;
4637 }
4638
4639 extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
4640 rbd_image_t *image, const char *snap_name)
4641 {
4642 librados::IoCtx io_ctx;
4643 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4644 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4645 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4646 true);
4647 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
4648 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4649
4650 int r = ictx->state->open(0);
4651 if (r >= 0) {
4652 *image = (rbd_image_t)ictx;
4653 }
4654 tracepoint(librbd, open_image_exit, r);
4655 return r;
4656 }
4657
4658 extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
4659 rbd_image_t *image, const char *snap_name,
4660 rbd_completion_t c)
4661 {
4662 librados::IoCtx io_ctx;
4663 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4664 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4665 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
4666 true);
4667 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4668 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);
4669 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4670 image));
4671 tracepoint(librbd, aio_open_image_exit, 0);
4672 return 0;
4673 }
4674
4675 extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
4676 rbd_image_t *image,
4677 const char *snap_name,
4678 rbd_completion_t c)
4679 {
4680 librados::IoCtx io_ctx;
4681 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4682 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4683 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
4684 true);
4685 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4686 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
4687 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
4688 ictx->state->open(0, new C_OpenComplete(ictx, get_aio_completion(comp),
4689 image));
4690 tracepoint(librbd, aio_open_image_exit, 0);
4691 return 0;
4692 }
4693
4694 extern "C" int rbd_features_to_string(uint64_t features, char *str_features, size_t *size)
4695 {
4696 std::stringstream err;
4697 std::string get_str_features = librbd::rbd_features_to_string(features, &err);
4698 if (!err.str().empty()) {
4699 return -EINVAL;
4700 }
4701 uint64_t expected_size = get_str_features.size();
4702 if (*size <= expected_size) {
4703 *size = expected_size + 1;
4704 return -ERANGE;
4705 }
4706 strncpy(str_features, get_str_features.c_str(), expected_size);
4707 str_features[expected_size] = '\0';
4708 *size = expected_size + 1;
4709 return 0;
4710 }
4711
4712 extern "C" int rbd_features_from_string(const char *str_features, uint64_t *features)
4713 {
4714 std::stringstream err;
4715 *features = librbd::rbd_features_from_string(str_features, &err);
4716 if (!err.str().empty()) {
4717 return -EINVAL;
4718 }
4719
4720 return 0;
4721 }
4722
4723 extern "C" int rbd_close(rbd_image_t image)
4724 {
4725 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4726 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
4727
4728 int r = ictx->state->close();
4729
4730 tracepoint(librbd, close_image_exit, r);
4731 return r;
4732 }
4733
4734 extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
4735 {
4736 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4737 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4738 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
4739 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
4740 get_aio_completion(comp)));
4741 tracepoint(librbd, aio_close_image_exit, 0);
4742 return 0;
4743 }
4744
4745 extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
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::NoOpProgressContext prog_ctx;
4750 int r = ictx->operations->resize(size, true, prog_ctx);
4751 tracepoint(librbd, resize_exit, r);
4752 return r;
4753 }
4754
4755 extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
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, allow_shrink, prog_ctx);
4762 tracepoint(librbd, resize_exit, r);
4763 return r;
4764 }
4765
4766 extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
4767 librbd_progress_fn_t cb, void *cbdata)
4768 {
4769 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4770 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
4771 librbd::CProgressContext prog_ctx(cb, cbdata);
4772 int r = ictx->operations->resize(size, true, prog_ctx);
4773 tracepoint(librbd, resize_exit, r);
4774 return r;
4775 }
4776
4777 extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
4778 size_t infosize)
4779 {
4780 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4781 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4782 int r = librbd::info(ictx, *info, infosize);
4783 tracepoint(librbd, stat_exit, r, info);
4784 return r;
4785 }
4786
4787 extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
4788 {
4789 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4790 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4791 int r = librbd::get_old_format(ictx, old);
4792 tracepoint(librbd, get_old_format_exit, r, *old);
4793 return r;
4794 }
4795
4796 extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
4797 {
4798 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4799 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4800 int r = librbd::get_size(ictx, size);
4801 tracepoint(librbd, get_size_exit, r, *size);
4802 return r;
4803 }
4804
4805 extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
4806 {
4807 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4808 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4809 int r = librbd::get_features(ictx, features);
4810 tracepoint(librbd, get_features_exit, r, *features);
4811 return r;
4812 }
4813
4814 extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
4815 uint8_t enabled)
4816 {
4817 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4818 bool features_enabled = enabled != 0;
4819 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
4820 int r = ictx->operations->update_features(features, features_enabled);
4821 tracepoint(librbd, update_features_exit, r);
4822 return r;
4823 }
4824
4825 extern "C" int rbd_get_op_features(rbd_image_t image, uint64_t *op_features)
4826 {
4827 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4828 return librbd::api::Image<>::get_op_features(ictx, op_features);
4829 }
4830
4831 extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
4832 {
4833 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4834 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4835 *stripe_unit = ictx->get_stripe_unit();
4836 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
4837 return 0;
4838 }
4839
4840 extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
4841 {
4842 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4843 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4844 *stripe_count = ictx->get_stripe_count();
4845 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
4846 return 0;
4847 }
4848
4849 extern "C" int rbd_get_create_timestamp(rbd_image_t image,
4850 struct timespec *timestamp)
4851 {
4852 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4853 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
4854 ictx->read_only);
4855 utime_t time = ictx->get_create_timestamp();
4856 time.to_timespec(timestamp);
4857 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
4858 return 0;
4859 }
4860
4861 extern "C" int rbd_get_access_timestamp(rbd_image_t image,
4862 struct timespec *timestamp)
4863 {
4864 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4865 tracepoint(librbd, get_access_timestamp_enter, ictx, ictx->name.c_str(),
4866 ictx->read_only);
4867 utime_t time = ictx->get_access_timestamp();
4868 time.to_timespec(timestamp);
4869 tracepoint(librbd, get_access_timestamp_exit, 0, timestamp);
4870 return 0;
4871 }
4872
4873 extern "C" int rbd_get_modify_timestamp(rbd_image_t image,
4874 struct timespec *timestamp)
4875 {
4876 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4877 tracepoint(librbd, get_modify_timestamp_enter, ictx, ictx->name.c_str(),
4878 ictx->read_only);
4879 utime_t time = ictx->get_modify_timestamp();
4880 time.to_timespec(timestamp);
4881 tracepoint(librbd, get_modify_timestamp_exit, 0, timestamp);
4882 return 0;
4883 }
4884
4885
4886 extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
4887 {
4888 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4889 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
4890 int r = librbd::get_overlap(ictx, overlap);
4891 tracepoint(librbd, get_overlap_exit, r, *overlap);
4892 return r;
4893 }
4894
4895 extern "C" int rbd_get_name(rbd_image_t image, char *name, size_t *name_len)
4896 {
4897 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4898 if (*name_len <= ictx->name.size()) {
4899 *name_len = ictx->name.size() + 1;
4900 return -ERANGE;
4901 }
4902
4903 strncpy(name, ictx->name.c_str(), ictx->name.size());
4904 name[ictx->name.size()] = '\0';
4905 *name_len = ictx->name.size() + 1;
4906 return 0;
4907 }
4908
4909 extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
4910 {
4911 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4912 if (ictx->old_format) {
4913 return -EINVAL;
4914 }
4915 if (ictx->id.size() >= id_len) {
4916 return -ERANGE;
4917 }
4918
4919 strncpy(id, ictx->id.c_str(), id_len - 1);
4920 id[id_len - 1] = '\0';
4921 return 0;
4922 }
4923
4924 extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
4925 size_t prefix_len)
4926 {
4927 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4928 if (ictx->object_prefix.size() >= prefix_len) {
4929 return -ERANGE;
4930 }
4931
4932 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
4933 prefix[prefix_len - 1] = '\0';
4934 return 0;
4935 }
4936
4937 extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
4938 {
4939 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
4940 return librbd::api::Image<>::get_data_pool_id(ictx);
4941 }
4942
4943 extern "C" int rbd_get_parent_info(rbd_image_t image,
4944 char *parent_pool_name, size_t ppool_namelen,
4945 char *parent_name, size_t pnamelen,
4946 char *parent_snap_name, size_t psnap_namelen)
4947 {
4948 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
4949 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
4950 ictx->snap_name.c_str(), ictx->read_only);
4951
4952 librbd::linked_image_spec_t parent_image;
4953 librbd::snap_spec_t parent_snap;
4954 int r = librbd::api::Image<>::get_parent(ictx, &parent_image, &parent_snap);
4955 if (r >= 0) {
4956 if (parent_pool_name) {
4957 if (parent_image.pool_name.length() + 1 > ppool_namelen) {
4958 r = -ERANGE;
4959 } else {
4960 strcpy(parent_pool_name, parent_image.pool_name.c_str());
4961 }
4962 }
4963 if (parent_name) {
4964 if (parent_image.image_name.length() + 1 > pnamelen) {
4965 r = -ERANGE;
4966 } else {
4967 strcpy(parent_name, parent_image.image_name.c_str());
4968 }
4969 }
4970 if (parent_snap_name) {
4971 if (parent_snap.name.length() + 1 > psnap_namelen) {
4972 r = -ERANGE;
4973 } else {
4974 strcpy(parent_snap_name, parent_snap.name.c_str());
4975 }
4976 }
4977 }
4978
4979 if (r < 0) {
4980 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
4981 return r;
4982 }
4983
4984 tracepoint(librbd, get_parent_info_exit, r,
4985 parent_image.pool_name.c_str(),
4986 parent_image.image_name.c_str(),
4987 parent_image.image_id.c_str(),
4988 parent_snap.name.c_str());
4989 return 0;
4990 }
4991
4992 extern "C" int rbd_get_parent_info2(rbd_image_t image,
4993 char *parent_pool_name,
4994 size_t ppool_namelen,
4995 char *parent_name, size_t pnamelen,
4996 char *parent_id, size_t pidlen,
4997 char *parent_snap_name,
4998 size_t psnap_namelen)
4999 {
5000 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5001 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
5002 ictx->snap_name.c_str(), ictx->read_only);
5003
5004 librbd::linked_image_spec_t parent_image;
5005 librbd::snap_spec_t parent_snap;
5006 int r = librbd::api::Image<>::get_parent(ictx, &parent_image, &parent_snap);
5007 if (r >= 0) {
5008 if (parent_pool_name) {
5009 if (parent_image.pool_name.length() + 1 > ppool_namelen) {
5010 r = -ERANGE;
5011 } else {
5012 strcpy(parent_pool_name, parent_image.pool_name.c_str());
5013 }
5014 }
5015 if (parent_name) {
5016 if (parent_image.image_name.length() + 1 > pnamelen) {
5017 r = -ERANGE;
5018 } else {
5019 strcpy(parent_name, parent_image.image_name.c_str());
5020 }
5021 }
5022 if (parent_id) {
5023 if (parent_image.image_id.length() + 1 > pidlen) {
5024 r = -ERANGE;
5025 } else {
5026 strcpy(parent_id, parent_image.image_id.c_str());
5027 }
5028 }
5029 if (parent_snap_name) {
5030 if (parent_snap.name.length() + 1 > psnap_namelen) {
5031 r = -ERANGE;
5032 } else {
5033 strcpy(parent_snap_name, parent_snap.name.c_str());
5034 }
5035 }
5036 }
5037
5038 if (r < 0) {
5039 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
5040 return r;
5041 }
5042
5043 tracepoint(librbd, get_parent_info_exit, r,
5044 parent_image.pool_name.c_str(),
5045 parent_image.image_name.c_str(),
5046 parent_image.image_id.c_str(),
5047 parent_snap.name.c_str());
5048 return 0;
5049 }
5050
5051 extern "C" int rbd_get_parent(rbd_image_t image,
5052 rbd_linked_image_spec_t *parent_image,
5053 rbd_snap_spec_t *parent_snap)
5054 {
5055 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5056 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
5057 ictx->snap_name.c_str(), ictx->read_only);
5058
5059 librbd::linked_image_spec_t cpp_parent_image;
5060 librbd::snap_spec_t cpp_parent_snap;
5061 int r = librbd::api::Image<>::get_parent(ictx, &cpp_parent_image,
5062 &cpp_parent_snap);
5063 if (r < 0) {
5064 // FIPS zeroization audit 20191117: these memsets are not security related.
5065 memset(parent_image, 0, sizeof(rbd_linked_image_spec_t));
5066 memset(parent_snap, 0, sizeof(rbd_snap_spec_t));
5067 } else {
5068 *parent_image = {
5069 .pool_id = cpp_parent_image.pool_id,
5070 .pool_name = strdup(cpp_parent_image.pool_name.c_str()),
5071 .pool_namespace = strdup(cpp_parent_image.pool_namespace.c_str()),
5072 .image_id = strdup(cpp_parent_image.image_id.c_str()),
5073 .image_name = strdup(cpp_parent_image.image_name.c_str()),
5074 .trash = cpp_parent_image.trash};
5075 *parent_snap = {
5076 .id = cpp_parent_snap.id,
5077 .namespace_type = cpp_parent_snap.namespace_type,
5078 .name = strdup(cpp_parent_snap.name.c_str())};
5079 }
5080
5081 tracepoint(librbd, get_parent_info_exit, r,
5082 parent_image->pool_name,
5083 parent_image->image_name,
5084 parent_image->image_id,
5085 parent_snap->name);
5086 return r;
5087 }
5088
5089 extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
5090 {
5091 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5092 tracepoint(librbd, get_flags_enter, ictx);
5093 int r = librbd::get_flags(ictx, flags);
5094 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
5095 return r;
5096 }
5097
5098 extern "C" int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info,
5099 size_t group_info_size)
5100 {
5101 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5102 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
5103
5104 if (group_info_size != sizeof(rbd_group_info_t)) {
5105 tracepoint(librbd, image_get_group_exit, -ERANGE);
5106 return -ERANGE;
5107 }
5108
5109 librbd::group_info_t cpp_group_info;
5110 int r = librbd::api::Group<>::image_get_group(ictx, &cpp_group_info);
5111 if (r >= 0) {
5112 group_info_cpp_to_c(cpp_group_info, group_info);
5113 } else {
5114 group_info->name = NULL;
5115 }
5116
5117 tracepoint(librbd, image_get_group_exit, r);
5118 return r;
5119 }
5120
5121 extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
5122 {
5123 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5124 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
5125 int r = librbd::set_image_notification(ictx, fd, type);
5126 tracepoint(librbd, set_image_notification_exit, ictx, r);
5127 return r;
5128 }
5129
5130 extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
5131 {
5132 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5133 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
5134 bool owner;
5135 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
5136 *is_owner = owner ? 1 : 0;
5137 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
5138 return r;
5139 }
5140
5141 extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
5142 {
5143 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5144 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
5145 int r = librbd::lock_acquire(ictx, lock_mode);
5146 tracepoint(librbd, lock_acquire_exit, ictx, r);
5147 return r;
5148 }
5149
5150 extern "C" int rbd_lock_release(rbd_image_t image)
5151 {
5152 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5153 tracepoint(librbd, lock_release_enter, ictx);
5154 int r = librbd::lock_release(ictx);
5155 tracepoint(librbd, lock_release_exit, ictx, r);
5156 return r;
5157 }
5158
5159 extern "C" int rbd_lock_get_owners(rbd_image_t image,
5160 rbd_lock_mode_t *lock_mode,
5161 char **lock_owners,
5162 size_t *max_lock_owners)
5163 {
5164 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5165 tracepoint(librbd, lock_get_owners_enter, ictx);
5166 // FIPS zeroization audit 20191117: this memset is not security related.
5167 memset(lock_owners, 0, sizeof(*lock_owners) * *max_lock_owners);
5168 std::list<std::string> lock_owner_list;
5169 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
5170 if (r >= 0) {
5171 if (*max_lock_owners >= lock_owner_list.size()) {
5172 *max_lock_owners = 0;
5173 for (auto &lock_owner : lock_owner_list) {
5174 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
5175 }
5176 } else {
5177 *max_lock_owners = lock_owner_list.size();
5178 r = -ERANGE;
5179 }
5180 }
5181 tracepoint(librbd, lock_get_owners_exit, ictx, r);
5182 return r;
5183 }
5184
5185 extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
5186 size_t lock_owner_count)
5187 {
5188 for (size_t i = 0; i < lock_owner_count; ++i) {
5189 free(lock_owners[i]);
5190 }
5191 }
5192
5193 extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
5194 const char *lock_owner)
5195 {
5196 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5197 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
5198 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
5199 tracepoint(librbd, lock_break_exit, ictx, r);
5200 return r;
5201 }
5202
5203 extern "C" int rbd_rebuild_object_map(rbd_image_t image,
5204 librbd_progress_fn_t cb, void *cbdata)
5205 {
5206 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5207 librbd::CProgressContext prog_ctx(cb, cbdata);
5208 return ictx->operations->rebuild_object_map(prog_ctx);
5209 }
5210
5211 /* snapshots */
5212 extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
5213 {
5214 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5215 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5216 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
5217 snap_name);
5218 tracepoint(librbd, snap_create_exit, r);
5219 return r;
5220 }
5221
5222 extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
5223 {
5224 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5225 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
5226 int r = ictx->operations->snap_rename(srcname, dstname);
5227 tracepoint(librbd, snap_rename_exit, r);
5228 return r;
5229 }
5230
5231 extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
5232 {
5233 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5234 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5235 librbd::NoOpProgressContext prog_ctx;
5236 int r = librbd::api::Snapshot<>::remove(ictx, snap_name, 0, prog_ctx);
5237 tracepoint(librbd, snap_remove_exit, r);
5238 return r;
5239 }
5240
5241 extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
5242 librbd_progress_fn_t cb, void *cbdata)
5243 {
5244 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5245 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
5246 librbd::CProgressContext prog_ctx(cb, cbdata);
5247 int r = librbd::api::Snapshot<>::remove(ictx, snap_name, flags, prog_ctx);
5248 tracepoint(librbd, snap_remove_exit, r);
5249 return r;
5250 }
5251
5252 extern "C" int rbd_snap_remove_by_id(rbd_image_t image, uint64_t snap_id)
5253 {
5254 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5255 return librbd::api::Snapshot<>::remove(ictx, snap_id);
5256 }
5257
5258 extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
5259 {
5260 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5261 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5262 librbd::NoOpProgressContext prog_ctx;
5263 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
5264 tracepoint(librbd, snap_rollback_exit, r);
5265 return r;
5266 }
5267
5268 extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
5269 const char *snap_name,
5270 librbd_progress_fn_t cb,
5271 void *cbdata)
5272 {
5273 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5274 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5275 librbd::CProgressContext prog_ctx(cb, cbdata);
5276 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
5277 tracepoint(librbd, snap_rollback_exit, r);
5278 return r;
5279 }
5280
5281 extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
5282 int *max_snaps)
5283 {
5284 vector<librbd::snap_info_t> cpp_snaps;
5285 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5286 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
5287
5288 if (!max_snaps) {
5289 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
5290 return -EINVAL;
5291 }
5292 // FIPS zeroization audit 20191117: this memset is not security related.
5293 memset(snaps, 0, sizeof(*snaps) * *max_snaps);
5294
5295 int r = librbd::api::Snapshot<>::list(ictx, cpp_snaps);
5296 if (r == -ENOENT) {
5297 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
5298 return 0;
5299 }
5300 if (r < 0) {
5301 tracepoint(librbd, snap_list_exit, r, *max_snaps);
5302 return r;
5303 }
5304 if (*max_snaps < (int)cpp_snaps.size() + 1) {
5305 *max_snaps = (int)cpp_snaps.size() + 1;
5306 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
5307 return -ERANGE;
5308 }
5309
5310 int i;
5311
5312 for (i = 0; i < (int)cpp_snaps.size(); i++) {
5313 snaps[i].id = cpp_snaps[i].id;
5314 snaps[i].size = cpp_snaps[i].size;
5315 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
5316 if (!snaps[i].name) {
5317 for (int j = 0; j < i; j++)
5318 free((void *)snaps[j].name);
5319 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
5320 return -ENOMEM;
5321 }
5322 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
5323 }
5324 snaps[i].id = 0;
5325 snaps[i].size = 0;
5326 snaps[i].name = NULL;
5327
5328 r = (int)cpp_snaps.size();
5329 tracepoint(librbd, snap_list_exit, r, *max_snaps);
5330 return r;
5331 }
5332
5333 extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
5334 {
5335 tracepoint(librbd, snap_list_end_enter, snaps);
5336 while (snaps->name) {
5337 free((void *)snaps->name);
5338 snaps++;
5339 }
5340 tracepoint(librbd, snap_list_end_exit);
5341 }
5342
5343 extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
5344 {
5345 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5346 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5347 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
5348 tracepoint(librbd, snap_protect_exit, r);
5349 return r;
5350 }
5351
5352 extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
5353 {
5354 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5355 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5356 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
5357 tracepoint(librbd, snap_unprotect_exit, r);
5358 return r;
5359 }
5360
5361 extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
5362 int *is_protected)
5363 {
5364 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5365 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5366 bool protected_snap;
5367 int r = librbd::api::Snapshot<>::is_protected(ictx, snap_name, &protected_snap);
5368 if (r < 0) {
5369 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
5370 return r;
5371 }
5372 *is_protected = protected_snap ? 1 : 0;
5373 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
5374 return 0;
5375 }
5376
5377 extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
5378 {
5379 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5380 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
5381 int r = librbd::api::Snapshot<>::get_limit(ictx, limit);
5382 tracepoint(librbd, snap_get_limit_exit, r, *limit);
5383 return r;
5384 }
5385
5386 extern "C" int rbd_snap_exists(rbd_image_t image, const char *snapname, bool *exists)
5387 {
5388 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5389 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
5390 ictx->snap_name.c_str(), ictx->read_only, snapname);
5391 int r = librbd::api::Snapshot<>::exists(ictx, cls::rbd::UserSnapshotNamespace(), snapname, exists);
5392 tracepoint(librbd, snap_exists_exit, r, *exists);
5393 return r;
5394 }
5395
5396 extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
5397 {
5398 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5399 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
5400 int r = librbd::api::Snapshot<>::get_timestamp(ictx, snap_id, timestamp);
5401 tracepoint(librbd, snap_get_timestamp_exit, r);
5402 return r;
5403 }
5404
5405 extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
5406 {
5407 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5408 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
5409 int r = librbd::api::Snapshot<>::set_limit(ictx, limit);
5410 tracepoint(librbd, snap_set_limit_exit, r);
5411 return r;
5412 }
5413
5414 extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
5415 {
5416 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5417 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
5418 int r = librbd::api::Image<>::snap_set(
5419 ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
5420 tracepoint(librbd, snap_set_exit, r);
5421 return r;
5422 }
5423
5424 extern "C" int rbd_snap_set_by_id(rbd_image_t image, uint64_t snap_id)
5425 {
5426 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5427 return librbd::api::Image<>::snap_set(ictx, snap_id);
5428 }
5429
5430 extern "C" int rbd_snap_get_name(rbd_image_t image, uint64_t snap_id, char *snapname, size_t *name_len)
5431 {
5432 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5433 std::string snap_name;
5434 int r = librbd::api::Snapshot<>::get_name(ictx, snap_id, &snap_name);
5435 size_t expected_size = snap_name.size();
5436 if (*name_len <= expected_size) {
5437 *name_len = expected_size + 1;
5438 return -ERANGE;
5439 }
5440 strncpy(snapname, snap_name.c_str(), expected_size);
5441 snapname[expected_size] = '\0';
5442 *name_len = expected_size + 1;
5443 return r;
5444 }
5445
5446 extern "C" int rbd_snap_get_id(rbd_image_t image, const char *snapname, uint64_t *snap_id)
5447 {
5448 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5449 return librbd::api::Snapshot<>::get_id(ictx, snapname, snap_id);
5450 }
5451
5452 extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
5453 size_t *pools_len, char *images,
5454 size_t *images_len)
5455 {
5456 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5457 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
5458 ictx->snap_name.c_str(), ictx->read_only);
5459
5460 std::vector<librbd::linked_image_spec_t> cpp_images;
5461 int r = librbd::api::Image<>::list_children(ictx, &cpp_images);
5462 if (r < 0) {
5463 tracepoint(librbd, list_children_exit, r);
5464 return r;
5465 }
5466
5467 std::set<std::pair<std::string, std::string>> image_set;
5468 for (auto& image : cpp_images) {
5469 if (!image.trash) {
5470 image_set.insert({image.pool_name, image.image_name});
5471 }
5472 }
5473
5474 size_t pools_total = 0;
5475 size_t images_total = 0;
5476 for (auto it : image_set) {
5477 pools_total += it.first.length() + 1;
5478 images_total += it.second.length() + 1;
5479 }
5480
5481 bool too_short = false;
5482 if (pools_total > *pools_len)
5483 too_short = true;
5484 if (images_total > *images_len)
5485 too_short = true;
5486 *pools_len = pools_total;
5487 *images_len = images_total;
5488 if (too_short) {
5489 tracepoint(librbd, list_children_exit, -ERANGE);
5490 return -ERANGE;
5491 }
5492
5493 char *pools_p = pools;
5494 char *images_p = images;
5495 for (auto it : image_set) {
5496 const char* pool = it.first.c_str();
5497 strcpy(pools_p, pool);
5498 pools_p += it.first.length() + 1;
5499 const char* image = it.second.c_str();
5500 strcpy(images_p, image);
5501 images_p += it.second.length() + 1;
5502 tracepoint(librbd, list_children_entry, pool, image);
5503 }
5504
5505 ssize_t ret = image_set.size();
5506 tracepoint(librbd, list_children_exit, ret);
5507 return ret;
5508 }
5509
5510 extern "C" int rbd_list_children2(rbd_image_t image,
5511 rbd_child_info_t *children,
5512 int *max_children)
5513 {
5514 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5515 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
5516 ictx->snap_name.c_str(), ictx->read_only);
5517 // FIPS zeroization audit 20191117: this memset is not security related.
5518 memset(children, 0, sizeof(*children) * *max_children);
5519
5520 if (!max_children) {
5521 tracepoint(librbd, list_children_exit, -EINVAL);
5522 return -EINVAL;
5523 }
5524
5525 std::vector<librbd::linked_image_spec_t> cpp_children;
5526 int r = librbd::api::Image<>::list_children(ictx, &cpp_children);
5527 if (r < 0) {
5528 tracepoint(librbd, list_children_exit, r);
5529 return r;
5530 }
5531
5532 if (*max_children < (int)cpp_children.size() + 1) {
5533 *max_children = (int)cpp_children.size() + 1;
5534 tracepoint(librbd, list_children_exit, *max_children);
5535 return -ERANGE;
5536 }
5537
5538 int i;
5539 for (i = 0; i < (int)cpp_children.size(); i++) {
5540 children[i].pool_name = strdup(cpp_children[i].pool_name.c_str());
5541 children[i].image_name = strdup(cpp_children[i].image_name.c_str());
5542 children[i].image_id = strdup(cpp_children[i].image_id.c_str());
5543 children[i].trash = cpp_children[i].trash;
5544 tracepoint(librbd, list_children_entry, children[i].pool_name,
5545 children[i].image_name);
5546 }
5547 children[i].pool_name = NULL;
5548 children[i].image_name = NULL;
5549 children[i].image_id = NULL;
5550
5551 r = (int)cpp_children.size();
5552 tracepoint(librbd, list_children_exit, *max_children);
5553 return r;
5554 }
5555
5556 extern "C" void rbd_list_child_cleanup(rbd_child_info_t *child)
5557 {
5558 free((void *)child->pool_name);
5559 free((void *)child->image_name);
5560 free((void *)child->image_id);
5561 }
5562
5563 extern "C" void rbd_list_children_cleanup(rbd_child_info_t *children,
5564 size_t num_children)
5565 {
5566 for (size_t i=0; i < num_children; i++) {
5567 free((void *)children[i].pool_name);
5568 free((void *)children[i].image_name);
5569 free((void *)children[i].image_id);
5570 }
5571 }
5572
5573 extern "C" int rbd_list_children3(rbd_image_t image,
5574 rbd_linked_image_spec_t *images,
5575 size_t *max_images)
5576 {
5577 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5578 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(),
5579 ictx->snap_name.c_str(), ictx->read_only);
5580 // FIPS zeroization audit 20191117: this memset is not security related.
5581 memset(images, 0, sizeof(*images) * *max_images);
5582
5583 std::vector<librbd::linked_image_spec_t> cpp_children;
5584 int r = librbd::api::Image<>::list_children(ictx, &cpp_children);
5585 if (r < 0) {
5586 tracepoint(librbd, list_children_exit, r);
5587 return r;
5588 }
5589
5590 if (*max_images < cpp_children.size()) {
5591 *max_images = cpp_children.size();
5592 return -ERANGE;
5593 }
5594
5595 *max_images = cpp_children.size();
5596 for (size_t idx = 0; idx < cpp_children.size(); ++idx) {
5597 images[idx] = {
5598 .pool_id = cpp_children[idx].pool_id,
5599 .pool_name = strdup(cpp_children[idx].pool_name.c_str()),
5600 .pool_namespace = strdup(cpp_children[idx].pool_namespace.c_str()),
5601 .image_id = strdup(cpp_children[idx].image_id.c_str()),
5602 .image_name = strdup(cpp_children[idx].image_name.c_str()),
5603 .trash = cpp_children[idx].trash};
5604 tracepoint(librbd, list_children_entry, images[idx].pool_name,
5605 images[idx].image_name);
5606 }
5607 return 0;
5608 }
5609
5610 extern "C" int rbd_list_descendants(rbd_image_t image,
5611 rbd_linked_image_spec_t *images,
5612 size_t *max_images)
5613 {
5614 auto ictx = reinterpret_cast<librbd::ImageCtx*>(image);
5615 // FIPS zeroization audit 20191117: this memset is not security related.
5616 memset(images, 0, sizeof(*images) * *max_images);
5617
5618 std::vector<librbd::linked_image_spec_t> cpp_children;
5619 int r = librbd::api::Image<>::list_descendants(ictx, {}, &cpp_children);
5620 if (r < 0) {
5621 return r;
5622 }
5623
5624 if (*max_images < cpp_children.size()) {
5625 *max_images = cpp_children.size();
5626 return -ERANGE;
5627 }
5628
5629 *max_images = cpp_children.size();
5630 for (size_t idx = 0; idx < cpp_children.size(); ++idx) {
5631 images[idx] = {
5632 .pool_id = cpp_children[idx].pool_id,
5633 .pool_name = strdup(cpp_children[idx].pool_name.c_str()),
5634 .pool_namespace = strdup(cpp_children[idx].pool_namespace.c_str()),
5635 .image_id = strdup(cpp_children[idx].image_id.c_str()),
5636 .image_name = strdup(cpp_children[idx].image_name.c_str()),
5637 .trash = cpp_children[idx].trash};
5638 }
5639 return 0;
5640 }
5641
5642 extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
5643 char *tag, size_t *tag_len,
5644 char *clients, size_t *clients_len,
5645 char *cookies, size_t *cookies_len,
5646 char *addrs, size_t *addrs_len)
5647 {
5648 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5649 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
5650 std::list<librbd::locker_t> lockers;
5651 bool exclusive_bool;
5652 string tag_str;
5653
5654 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
5655 if (r < 0) {
5656 tracepoint(librbd, list_lockers_exit, r);
5657 return r;
5658 }
5659
5660 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
5661
5662 *exclusive = (int)exclusive_bool;
5663 size_t clients_total = 0;
5664 size_t cookies_total = 0;
5665 size_t addrs_total = 0;
5666 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
5667 it != lockers.end(); ++it) {
5668 clients_total += it->client.length() + 1;
5669 cookies_total += it->cookie.length() + 1;
5670 addrs_total += it->address.length() + 1;
5671 }
5672
5673 bool too_short = ((clients_total > *clients_len) ||
5674 (cookies_total > *cookies_len) ||
5675 (addrs_total > *addrs_len) ||
5676 (tag_str.length() + 1 > *tag_len));
5677 *clients_len = clients_total;
5678 *cookies_len = cookies_total;
5679 *addrs_len = addrs_total;
5680 *tag_len = tag_str.length() + 1;
5681 if (too_short) {
5682 tracepoint(librbd, list_lockers_exit, -ERANGE);
5683 return -ERANGE;
5684 }
5685
5686 strcpy(tag, tag_str.c_str());
5687 char *clients_p = clients;
5688 char *cookies_p = cookies;
5689 char *addrs_p = addrs;
5690 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
5691 it != lockers.end(); ++it) {
5692 const char* client = it->client.c_str();
5693 strcpy(clients_p, client);
5694 clients_p += it->client.length() + 1;
5695 const char* cookie = it->cookie.c_str();
5696 strcpy(cookies_p, cookie);
5697 cookies_p += it->cookie.length() + 1;
5698 const char* address = it->address.c_str();
5699 strcpy(addrs_p, address);
5700 addrs_p += it->address.length() + 1;
5701 tracepoint(librbd, list_lockers_entry, client, cookie, address);
5702 }
5703
5704 ssize_t ret = lockers.size();
5705 tracepoint(librbd, list_lockers_exit, ret);
5706 return ret;
5707 }
5708
5709 extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
5710 {
5711 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5712 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
5713 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
5714 tracepoint(librbd, lock_exclusive_exit, r);
5715 return r;
5716 }
5717
5718 extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
5719 const char *tag)
5720 {
5721 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5722 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
5723 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
5724 tracepoint(librbd, lock_shared_exit, r);
5725 return r;
5726 }
5727
5728 extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
5729 {
5730 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5731 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
5732 int r = librbd::unlock(ictx, cookie ? cookie : "");
5733 tracepoint(librbd, unlock_exit, r);
5734 return r;
5735 }
5736
5737 extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
5738 const char *cookie)
5739 {
5740 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5741 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
5742 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
5743 tracepoint(librbd, break_lock_exit, r);
5744 return r;
5745 }
5746
5747 /* I/O */
5748 extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
5749 char *buf)
5750 {
5751 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5752 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5753 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
5754 0);
5755 tracepoint(librbd, read_exit, r);
5756 return r;
5757 }
5758
5759 extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
5760 char *buf, int op_flags)
5761 {
5762 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5763 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
5764 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
5765 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
5766 op_flags);
5767 tracepoint(librbd, read_exit, r);
5768 return r;
5769 }
5770
5771
5772 extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_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_iterate_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 tracepoint(librbd, read_iterate_exit, r);
5780 return r;
5781 }
5782
5783 extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
5784 int (*cb)(uint64_t, size_t, const char *, void *),
5785 void *arg)
5786 {
5787 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5788 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5789 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
5790 if (r > 0)
5791 r = 0;
5792 tracepoint(librbd, read_iterate2_exit, r);
5793 return (int)r;
5794 }
5795
5796 extern "C" int rbd_diff_iterate(rbd_image_t image,
5797 const char *fromsnapname,
5798 uint64_t ofs, uint64_t len,
5799 int (*cb)(uint64_t, size_t, int, void *),
5800 void *arg)
5801 {
5802 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5803 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
5804 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
5805 true, false);
5806 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
5807 cls::rbd::UserSnapshotNamespace(),
5808 fromsnapname, ofs, len,
5809 true, false, cb, arg);
5810 tracepoint(librbd, diff_iterate_exit, r);
5811 return r;
5812 }
5813
5814 extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
5815 uint64_t ofs, uint64_t len,
5816 uint8_t include_parent, uint8_t whole_object,
5817 int (*cb)(uint64_t, size_t, int, void *),
5818 void *arg)
5819 {
5820 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5821 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
5822 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
5823 include_parent != 0, whole_object != 0);
5824 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
5825 cls::rbd::UserSnapshotNamespace(),
5826 fromsnapname, ofs, len,
5827 include_parent, whole_object,
5828 cb, arg);
5829 tracepoint(librbd, diff_iterate_exit, r);
5830 return r;
5831 }
5832
5833 extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
5834 const char *buf)
5835 {
5836 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5837 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
5838
5839 bufferlist bl;
5840 bl.push_back(create_write_raw(ictx, buf, len, nullptr));
5841 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
5842 tracepoint(librbd, write_exit, r);
5843 return r;
5844 }
5845
5846 extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
5847 const char *buf, int op_flags)
5848 {
5849 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5850 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
5851 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
5852
5853 bufferlist bl;
5854 bl.push_back(create_write_raw(ictx, buf, len, nullptr));
5855 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
5856 tracepoint(librbd, write_exit, r);
5857 return r;
5858 }
5859
5860
5861 extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
5862 {
5863 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5864 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(),
5865 ictx->snap_name.c_str(), ictx->read_only, ofs, len);
5866 if (len > static_cast<uint64_t>(std::numeric_limits<int>::max())) {
5867 tracepoint(librbd, discard_exit, -EINVAL);
5868 return -EINVAL;
5869 }
5870
5871 int r = ictx->io_work_queue->discard(
5872 ofs, len, ictx->discard_granularity_bytes);
5873 tracepoint(librbd, discard_exit, r);
5874 return r;
5875 }
5876
5877 extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
5878 const char *buf, size_t data_len, int op_flags)
5879 {
5880 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5881 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5882 ictx->read_only, ofs, len, data_len == 0 ? NULL : buf, data_len, op_flags);
5883
5884 if (data_len == 0 || len % data_len ||
5885 len > static_cast<uint64_t>(std::numeric_limits<int>::max())) {
5886 tracepoint(librbd, writesame_exit, -EINVAL);
5887 return -EINVAL;
5888 }
5889
5890 bool discard_zero = ictx->config.get_val<bool>("rbd_discard_on_zeroed_write_same");
5891 if (discard_zero && mem_is_zero(buf, data_len)) {
5892 int r = ictx->io_work_queue->write_zeroes(ofs, len, 0, op_flags);
5893 tracepoint(librbd, writesame_exit, r);
5894 return r;
5895 }
5896
5897 bufferlist bl;
5898 bl.push_back(create_write_raw(ictx, buf, data_len, nullptr));
5899 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
5900 tracepoint(librbd, writesame_exit, r);
5901 return r;
5902 }
5903
5904 extern "C" ssize_t rbd_write_zeroes(rbd_image_t image, uint64_t ofs, size_t len,
5905 int zero_flags, int op_flags)
5906 {
5907 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5908 return ictx->io_work_queue->write_zeroes(ofs, len, zero_flags, op_flags);
5909 }
5910
5911 extern "C" ssize_t rbd_compare_and_write(rbd_image_t image,
5912 uint64_t ofs, size_t len,
5913 const char *cmp_buf,
5914 const char *buf,
5915 uint64_t *mismatch_off,
5916 int op_flags)
5917 {
5918 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5919 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
5920 ictx->snap_name.c_str(), ictx->read_only, ofs,
5921 len, cmp_buf, buf, op_flags);
5922
5923 bufferlist cmp_bl;
5924 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len, nullptr));
5925 bufferlist bl;
5926 bl.push_back(create_write_raw(ictx, buf, len, nullptr));
5927
5928 int r = ictx->io_work_queue->compare_and_write(ofs, len, std::move(cmp_bl),
5929 std::move(bl), mismatch_off,
5930 op_flags);
5931 tracepoint(librbd, compare_and_write_exit, r);
5932 return r;
5933 }
5934
5935 extern "C" int rbd_aio_create_completion(void *cb_arg,
5936 rbd_callback_t complete_cb,
5937 rbd_completion_t *c)
5938 {
5939 librbd::RBD::AioCompletion *rbd_comp =
5940 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
5941 *c = (rbd_completion_t) rbd_comp;
5942 return 0;
5943 }
5944
5945 extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
5946 const char *buf, rbd_completion_t c)
5947 {
5948 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5949 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5950 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
5951
5952 auto aio_completion = get_aio_completion(comp);
5953 bufferlist bl;
5954 bl.push_back(create_write_raw(ictx, buf, len, aio_completion));
5955 ictx->io_work_queue->aio_write(aio_completion, off, len, std::move(bl), 0);
5956 tracepoint(librbd, aio_write_exit, 0);
5957 return 0;
5958 }
5959
5960 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
5961 const char *buf, rbd_completion_t c, int op_flags)
5962 {
5963 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5964 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5965 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
5966 ictx->read_only, off, len, buf, comp->pc, op_flags);
5967
5968 auto aio_completion = get_aio_completion(comp);
5969 bufferlist bl;
5970 bl.push_back(create_write_raw(ictx, buf, len, aio_completion));
5971 ictx->io_work_queue->aio_write(aio_completion, off, len, std::move(bl),
5972 op_flags);
5973 tracepoint(librbd, aio_write_exit, 0);
5974 return 0;
5975 }
5976
5977 extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
5978 int iovcnt, uint64_t off, rbd_completion_t c)
5979 {
5980 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
5981 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
5982
5983 // convert the scatter list into a bufferlist
5984 auto aio_completion = get_aio_completion(comp);
5985 ssize_t len = 0;
5986 bufferlist bl;
5987 for (int i = 0; i < iovcnt; ++i) {
5988 const struct iovec &io = iov[i];
5989 len += io.iov_len;
5990 if (len < 0) {
5991 break;
5992 }
5993
5994 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
5995 io.iov_len, aio_completion));
5996 }
5997
5998 int r = 0;
5999 if (iovcnt <= 0 || len < 0) {
6000 r = -EINVAL;
6001 }
6002
6003 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
6004 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
6005 comp->pc);
6006 if (r == 0) {
6007 ictx->io_work_queue->aio_write(aio_completion, off, len, std::move(bl), 0);
6008 }
6009 tracepoint(librbd, aio_write_exit, r);
6010 return r;
6011 }
6012
6013 extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
6014 rbd_completion_t c)
6015 {
6016 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6017 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6018 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
6019 ictx->io_work_queue->aio_discard(
6020 get_aio_completion(comp), off, len, ictx->discard_granularity_bytes);
6021 tracepoint(librbd, aio_discard_exit, 0);
6022 return 0;
6023 }
6024
6025 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
6026 char *buf, rbd_completion_t c)
6027 {
6028 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6029 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6030 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
6031 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
6032 librbd::io::ReadResult{buf, len}, 0);
6033 tracepoint(librbd, aio_read_exit, 0);
6034 return 0;
6035 }
6036
6037 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
6038 char *buf, rbd_completion_t c, int op_flags)
6039 {
6040 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6041 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6042 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
6043 ictx->read_only, off, len, buf, comp->pc, op_flags);
6044 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
6045 librbd::io::ReadResult{buf, len},op_flags);
6046 tracepoint(librbd, aio_read_exit, 0);
6047 return 0;
6048 }
6049
6050 extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
6051 int iovcnt, uint64_t off, rbd_completion_t c)
6052 {
6053 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6054 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6055
6056 ssize_t len = 0;
6057 for (int i = 0; i < iovcnt; ++i) {
6058 len += iov[i].iov_len;
6059 if (len < 0) {
6060 break;
6061 }
6062 }
6063
6064 int r = 0;
6065 if (iovcnt == 0 || len < 0) {
6066 r = -EINVAL;
6067 }
6068
6069 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
6070 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
6071 comp->pc);
6072 if (r == 0) {
6073 librbd::io::ReadResult read_result;
6074 if (iovcnt == 1) {
6075 read_result = librbd::io::ReadResult(
6076 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
6077 } else {
6078 read_result = librbd::io::ReadResult(iov, iovcnt);
6079 }
6080 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
6081 std::move(read_result), 0);
6082 }
6083 tracepoint(librbd, aio_read_exit, r);
6084 return r;
6085 }
6086
6087 extern "C" int rbd_flush(rbd_image_t image)
6088 {
6089 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6090 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
6091 int r = ictx->io_work_queue->flush();
6092 tracepoint(librbd, flush_exit, r);
6093 return r;
6094 }
6095
6096 extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
6097 {
6098 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6099 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6100 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
6101 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
6102 tracepoint(librbd, aio_flush_exit, 0);
6103 return 0;
6104 }
6105
6106 extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
6107 const char *buf, size_t data_len, rbd_completion_t c,
6108 int op_flags)
6109 {
6110 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6111 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6112 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
6113 ictx->read_only, off, len, data_len == 0 ? NULL : buf, data_len, comp->pc,
6114 op_flags);
6115
6116 if (data_len == 0 || len % data_len) {
6117 tracepoint(librbd, aio_writesame_exit, -EINVAL);
6118 return -EINVAL;
6119 }
6120
6121 bool discard_zero = ictx->config.get_val<bool>("rbd_discard_on_zeroed_write_same");
6122 if (discard_zero && mem_is_zero(buf, data_len)) {
6123 ictx->io_work_queue->aio_write_zeroes(get_aio_completion(comp), off, len, 0,
6124 op_flags, true);
6125 tracepoint(librbd, aio_writesame_exit, 0);
6126 return 0;
6127 }
6128
6129 auto aio_completion = get_aio_completion(comp);
6130 bufferlist bl;
6131 bl.push_back(create_write_raw(ictx, buf, data_len, aio_completion));
6132 ictx->io_work_queue->aio_writesame(aio_completion, off, len, std::move(bl),
6133 op_flags);
6134 tracepoint(librbd, aio_writesame_exit, 0);
6135 return 0;
6136 }
6137
6138 extern "C" int rbd_aio_write_zeroes(rbd_image_t image, uint64_t off, size_t len,
6139 rbd_completion_t c, int zero_flags,
6140 int op_flags)
6141 {
6142 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6143 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6144
6145 ictx->io_work_queue->aio_write_zeroes(
6146 get_aio_completion(comp), off, len, zero_flags, op_flags, true);
6147 return 0;
6148 }
6149
6150 extern "C" ssize_t rbd_aio_compare_and_write(rbd_image_t image, uint64_t off,
6151 size_t len, const char *cmp_buf,
6152 const char *buf, rbd_completion_t c,
6153 uint64_t *mismatch_off,
6154 int op_flags)
6155 {
6156 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6157 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6158 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
6159 ictx->read_only, off, len, cmp_buf, buf, comp->pc, op_flags);
6160
6161 auto aio_completion = get_aio_completion(comp);
6162 bufferlist cmp_bl;
6163 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len, aio_completion));
6164 bufferlist bl;
6165 bl.push_back(create_write_raw(ictx, buf, len, aio_completion));
6166 ictx->io_work_queue->aio_compare_and_write(aio_completion, off, len,
6167 std::move(cmp_bl), std::move(bl),
6168 mismatch_off, op_flags, false);
6169
6170 tracepoint(librbd, aio_compare_and_write_exit, 0);
6171 return 0;
6172 }
6173
6174 extern "C" int rbd_invalidate_cache(rbd_image_t image)
6175 {
6176 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6177 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
6178 int r = librbd::invalidate_cache(ictx);
6179 tracepoint(librbd, invalidate_cache_exit, r);
6180 return r;
6181 }
6182
6183 extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
6184 {
6185 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6186 librbd::io::AioCompletion *cs[numcomp];
6187 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
6188 int r = librbd::poll_io_events(ictx, cs, numcomp);
6189 tracepoint(librbd, poll_io_events_exit, r);
6190 if (r > 0) {
6191 for (int i = 0; i < r; ++i)
6192 comps[i] = cs[i]->rbd_comp;
6193 }
6194 return r;
6195 }
6196
6197 extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
6198 {
6199 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6200 string val_s;
6201 tracepoint(librbd, metadata_get_enter, ictx, key);
6202 int r = librbd::metadata_get(ictx, key, &val_s);
6203 if (r < 0) {
6204 tracepoint(librbd, metadata_get_exit, r, key, NULL);
6205 return r;
6206 }
6207 if (*vallen < val_s.size() + 1) {
6208 r = -ERANGE;
6209 *vallen = val_s.size() + 1;
6210 tracepoint(librbd, metadata_get_exit, r, key, NULL);
6211 } else {
6212 strncpy(value, val_s.c_str(), val_s.size() + 1);
6213 tracepoint(librbd, metadata_get_exit, r, key, value);
6214 }
6215 return r;
6216 }
6217
6218 extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
6219 {
6220 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6221 tracepoint(librbd, metadata_set_enter, ictx, key, value);
6222 int r = ictx->operations->metadata_set(key, value);
6223 tracepoint(librbd, metadata_set_exit, r);
6224 return r;
6225 }
6226
6227 extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
6228 {
6229 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6230 tracepoint(librbd, metadata_remove_enter, ictx, key);
6231 int r = ictx->operations->metadata_remove(key);
6232 tracepoint(librbd, metadata_remove_exit, r);
6233 return r;
6234 }
6235
6236 extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
6237 char *key, size_t *key_len, char *value, size_t *val_len)
6238 {
6239 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6240 tracepoint(librbd, metadata_list_enter, ictx);
6241 map<string, bufferlist> pairs;
6242 int r = librbd::metadata_list(ictx, start, max, &pairs);
6243 size_t key_total_len = 0, val_total_len = 0;
6244 bool too_short = false;
6245 for (map<string, bufferlist>::iterator it = pairs.begin();
6246 it != pairs.end(); ++it) {
6247 key_total_len += it->first.size() + 1;
6248 val_total_len += it->second.length() + 1;
6249 }
6250 if (*key_len < key_total_len || *val_len < val_total_len)
6251 too_short = true;
6252 *key_len = key_total_len;
6253 *val_len = val_total_len;
6254 if (too_short) {
6255 tracepoint(librbd, metadata_list_exit, -ERANGE);
6256 return -ERANGE;
6257 }
6258
6259 char *key_p = key, *value_p = value;
6260
6261 for (map<string, bufferlist>::iterator it = pairs.begin();
6262 it != pairs.end(); ++it) {
6263 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
6264 key_p += it->first.size() + 1;
6265 strncpy(value_p, it->second.c_str(), it->second.length());
6266 value_p += it->second.length();
6267 *value_p = '\0';
6268 value_p++;
6269 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
6270 }
6271 tracepoint(librbd, metadata_list_exit, r);
6272 return r;
6273 }
6274
6275 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
6276 {
6277 return rbd_mirror_image_enable2(image, RBD_MIRROR_IMAGE_MODE_JOURNAL);
6278 }
6279
6280 extern "C" int rbd_mirror_image_enable2(rbd_image_t image,
6281 rbd_mirror_image_mode_t mode)
6282 {
6283 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6284 return librbd::api::Mirror<>::image_enable(ictx, mode, false);
6285 }
6286
6287 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
6288 {
6289 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6290 return librbd::api::Mirror<>::image_disable(ictx, force);
6291 }
6292
6293 extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
6294 {
6295 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6296 return librbd::api::Mirror<>::image_promote(ictx, force);
6297 }
6298
6299 extern "C" int rbd_mirror_image_demote(rbd_image_t image)
6300 {
6301 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6302 return librbd::api::Mirror<>::image_demote(ictx);
6303 }
6304
6305 extern "C" int rbd_mirror_image_resync(rbd_image_t image)
6306 {
6307 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6308 return librbd::api::Mirror<>::image_resync(ictx);
6309 }
6310
6311 extern "C" int rbd_mirror_image_create_snapshot(rbd_image_t image,
6312 uint64_t *snap_id)
6313 {
6314 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6315 return librbd::api::Mirror<>::image_snapshot_create(ictx, 0U, snap_id);
6316 }
6317
6318 extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
6319 rbd_mirror_image_info_t *mirror_image_info,
6320 size_t info_size)
6321 {
6322 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6323
6324 if (sizeof(rbd_mirror_image_info_t) != info_size) {
6325 return -ERANGE;
6326 }
6327
6328 librbd::mirror_image_info_t cpp_mirror_image;
6329 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image);
6330 if (r < 0) {
6331 return r;
6332 }
6333
6334 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
6335 return 0;
6336 }
6337
6338 extern "C" void rbd_mirror_image_get_info_cleanup(
6339 rbd_mirror_image_info_t *mirror_image_info)
6340 {
6341 free(mirror_image_info->global_id);
6342 }
6343
6344 extern "C" int rbd_mirror_image_get_mode(rbd_image_t image,
6345 rbd_mirror_image_mode_t *mode)
6346 {
6347 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6348
6349 return librbd::api::Mirror<>::image_get_mode(ictx, mode);
6350 }
6351
6352 extern "C" int rbd_mirror_image_get_global_status(
6353 rbd_image_t image, rbd_mirror_image_global_status_t *status,
6354 size_t status_size)
6355 {
6356 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6357
6358 if (sizeof(rbd_mirror_image_global_status_t) != status_size) {
6359 return -ERANGE;
6360 }
6361
6362 librbd::mirror_image_global_status_t cpp_status;
6363 int r = librbd::api::Mirror<>::image_get_global_status(ictx, &cpp_status);
6364 if (r < 0) {
6365 return r;
6366 }
6367
6368 mirror_image_global_status_cpp_to_c(cpp_status, status);
6369 return 0;
6370 }
6371
6372 #pragma GCC diagnostic push
6373 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
6374
6375 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
6376 rbd_mirror_image_status_t *status,
6377 size_t status_size)
6378 {
6379 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6380
6381 if (sizeof(rbd_mirror_image_status_t) != status_size) {
6382 return -ERANGE;
6383 }
6384
6385 librbd::mirror_image_global_status_t cpp_status;
6386 int r = librbd::api::Mirror<>::image_get_global_status(ictx, &cpp_status);
6387 if (r < 0) {
6388 return r;
6389 }
6390
6391 mirror_image_global_status_cpp_to_c(cpp_status, status);
6392 return 0;
6393 }
6394
6395 #pragma GCC diagnostic pop
6396
6397 extern "C" int rbd_mirror_image_get_instance_id(rbd_image_t image,
6398 char *instance_id,
6399 size_t *instance_id_max_length)
6400 {
6401 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6402
6403 std::string cpp_instance_id;
6404 int r = librbd::api::Mirror<>::image_get_instance_id(ictx, &cpp_instance_id);
6405 if (r < 0) {
6406 return r;
6407 }
6408
6409 if (cpp_instance_id.size() >= *instance_id_max_length) {
6410 *instance_id_max_length = cpp_instance_id.size() + 1;
6411 return -ERANGE;
6412 }
6413
6414 strcpy(instance_id, cpp_instance_id.c_str());
6415 *instance_id_max_length = cpp_instance_id.size() + 1;
6416 return 0;
6417 }
6418
6419 extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
6420 rbd_completion_t c) {
6421 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6422 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6423 librbd::api::Mirror<>::image_promote(
6424 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
6425 get_aio_completion(comp)));
6426 return 0;
6427 }
6428
6429 extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
6430 rbd_completion_t c) {
6431 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6432 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6433 librbd::api::Mirror<>::image_demote(
6434 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
6435 get_aio_completion(comp)));
6436 return 0;
6437 }
6438
6439 extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
6440 rbd_mirror_image_info_t *info,
6441 size_t info_size,
6442 rbd_completion_t c) {
6443 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6444 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6445
6446 if (sizeof(rbd_mirror_image_info_t) != info_size) {
6447 return -ERANGE;
6448 }
6449
6450 auto ctx = new C_MirrorImageGetInfo(
6451 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
6452 get_aio_completion(comp)));
6453 librbd::api::Mirror<>::image_get_info(
6454 ictx, &ctx->cpp_mirror_image_info, ctx);
6455 return 0;
6456 }
6457
6458 extern "C" int rbd_aio_mirror_image_get_mode(rbd_image_t image,
6459 rbd_mirror_image_mode_t *mode,
6460 rbd_completion_t c) {
6461 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6462 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6463
6464 librbd::api::Mirror<>::image_get_mode(
6465 ictx, mode, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
6466 get_aio_completion(comp)));
6467 return 0;
6468 }
6469
6470 extern "C" int rbd_aio_mirror_image_get_global_status(
6471 rbd_image_t image, rbd_mirror_image_global_status_t *status,
6472 size_t status_size, rbd_completion_t c) {
6473 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6474 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6475
6476 if (sizeof(rbd_mirror_image_global_status_t) != status_size) {
6477 return -ERANGE;
6478 }
6479
6480 auto ctx = new C_MirrorImageGetGlobalStatus(
6481 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
6482 get_aio_completion(comp)));
6483 librbd::api::Mirror<>::image_get_global_status(
6484 ictx, &ctx->cpp_mirror_image_global_status, ctx);
6485 return 0;
6486 }
6487
6488 #pragma GCC diagnostic push
6489 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
6490
6491 extern "C" int rbd_aio_mirror_image_get_status(
6492 rbd_image_t image, rbd_mirror_image_status_t *status, size_t status_size,
6493 rbd_completion_t c) {
6494 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6495 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6496
6497 if (sizeof(rbd_mirror_image_status_t) != status_size) {
6498 return -ERANGE;
6499 }
6500
6501 auto ctx = new C_MirrorImageGetStatus(
6502 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
6503 get_aio_completion(comp)));
6504 librbd::api::Mirror<>::image_get_global_status(
6505 ictx, &ctx->cpp_mirror_image_global_status, ctx);
6506 return 0;
6507 }
6508
6509 #pragma GCC diagnostic pop
6510
6511 extern "C" int rbd_aio_mirror_image_create_snapshot(rbd_image_t image,
6512 uint32_t flags,
6513 uint64_t *snap_id,
6514 rbd_completion_t c) {
6515 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6516 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6517
6518 librbd::api::Mirror<>::image_snapshot_create(
6519 ictx, flags, snap_id, new C_AioCompletion(ictx,
6520 librbd::io::AIO_TYPE_GENERIC,
6521 get_aio_completion(comp)));
6522 return 0;
6523 }
6524
6525 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
6526 rbd_update_callback_t watch_cb, void *arg)
6527 {
6528 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6529 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
6530 tracepoint(librbd, update_watch_enter, ictx, wctx);
6531 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
6532 tracepoint(librbd, update_watch_exit, r, wctx->handle);
6533 *handle = reinterpret_cast<uint64_t>(wctx);
6534 return r;
6535 }
6536
6537 extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
6538 {
6539 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6540 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
6541 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
6542 int r = ictx->state->unregister_update_watcher(wctx->handle);
6543 delete wctx;
6544 tracepoint(librbd, update_unwatch_exit, r);
6545 return r;
6546 }
6547
6548 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
6549 {
6550 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6551 return comp->is_complete();
6552 }
6553
6554 extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
6555 {
6556 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6557 return comp->wait_for_complete();
6558 }
6559
6560 extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
6561 {
6562 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6563 return comp->get_return_value();
6564 }
6565
6566 extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
6567 {
6568 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6569 return comp->get_arg();
6570 }
6571
6572 extern "C" void rbd_aio_release(rbd_completion_t c)
6573 {
6574 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
6575 comp->release();
6576 }
6577
6578 extern "C" int rbd_group_create(rados_ioctx_t p, const char *name)
6579 {
6580 librados::IoCtx io_ctx;
6581 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
6582 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
6583 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
6584 io_ctx.get_id(), name);
6585 int r = librbd::api::Group<>::create(io_ctx, name);
6586 tracepoint(librbd, group_create_exit, r);
6587 return r;
6588 }
6589
6590 extern "C" int rbd_group_remove(rados_ioctx_t p, const char *name)
6591 {
6592 librados::IoCtx io_ctx;
6593 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
6594 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
6595 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
6596 io_ctx.get_id(), name);
6597 int r = librbd::api::Group<>::remove(io_ctx, name);
6598 tracepoint(librbd, group_remove_exit, r);
6599 return r;
6600 }
6601
6602 extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size)
6603 {
6604 librados::IoCtx io_ctx;
6605 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
6606 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
6607 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
6608 io_ctx.get_id());
6609
6610 vector<string> cpp_names;
6611 int r = librbd::api::Group<>::list(io_ctx, &cpp_names);
6612
6613 if (r < 0) {
6614 tracepoint(librbd, group_list_exit, r);
6615 return r;
6616 }
6617
6618 size_t expected_size = 0;
6619
6620 for (size_t i = 0; i < cpp_names.size(); i++) {
6621 expected_size += cpp_names[i].size() + 1;
6622 }
6623 if (*size < expected_size) {
6624 *size = expected_size;
6625 tracepoint(librbd, group_list_exit, -ERANGE);
6626 return -ERANGE;
6627 }
6628
6629 if (names == NULL) {
6630 tracepoint(librbd, group_list_exit, -EINVAL);
6631 return -EINVAL;
6632 }
6633
6634 for (int i = 0; i < (int)cpp_names.size(); i++) {
6635 const char* name = cpp_names[i].c_str();
6636 tracepoint(librbd, group_list_entry, name);
6637 strcpy(names, name);
6638 names += strlen(names) + 1;
6639 }
6640 tracepoint(librbd, group_list_exit, (int)expected_size);
6641 return (int)expected_size;
6642 }
6643
6644 extern "C" int rbd_group_rename(rados_ioctx_t p, const char *src_name,
6645 const char *dest_name)
6646 {
6647 librados::IoCtx io_ctx;
6648 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
6649 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
6650 tracepoint(librbd, group_rename_enter, io_ctx.get_pool_name().c_str(),
6651 io_ctx.get_id(), src_name, dest_name);
6652 int r = librbd::api::Group<>::rename(io_ctx, src_name, dest_name);
6653 tracepoint(librbd, group_rename_exit, r);
6654 return r;
6655 }
6656
6657 extern "C" int rbd_group_image_add(rados_ioctx_t group_p,
6658 const char *group_name,
6659 rados_ioctx_t image_p,
6660 const char *image_name)
6661 {
6662 librados::IoCtx group_ioctx;
6663 librados::IoCtx image_ioctx;
6664
6665 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6666 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
6667
6668 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6669 tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(),
6670 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
6671 image_ioctx.get_id(), image_name);
6672
6673 int r = librbd::api::Group<>::image_add(group_ioctx, group_name, image_ioctx,
6674 image_name);
6675
6676 tracepoint(librbd, group_image_add_exit, r);
6677 return r;
6678 }
6679
6680 extern "C" int rbd_group_image_remove(rados_ioctx_t group_p,
6681 const char *group_name,
6682 rados_ioctx_t image_p,
6683 const char *image_name)
6684 {
6685 librados::IoCtx group_ioctx;
6686 librados::IoCtx image_ioctx;
6687
6688 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6689 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
6690
6691 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6692 tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(),
6693 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
6694 image_ioctx.get_id(), image_name);
6695
6696 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
6697 image_ioctx, image_name);
6698
6699 tracepoint(librbd, group_image_remove_exit, r);
6700 return r;
6701 }
6702
6703 extern "C" int rbd_group_image_remove_by_id(rados_ioctx_t group_p,
6704 const char *group_name,
6705 rados_ioctx_t image_p,
6706 const char *image_id)
6707 {
6708 librados::IoCtx group_ioctx;
6709 librados::IoCtx image_ioctx;
6710
6711 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6712 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
6713
6714 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6715 tracepoint(librbd, group_image_remove_by_id_enter,
6716 group_ioctx.get_pool_name().c_str(),
6717 group_ioctx.get_id(), group_name,
6718 image_ioctx.get_pool_name().c_str(),
6719 image_ioctx.get_id(), image_id);
6720
6721 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
6722 image_ioctx, image_id);
6723
6724 tracepoint(librbd, group_image_remove_by_id_exit, r);
6725 return r;
6726 }
6727
6728 extern "C" int rbd_group_image_list(rados_ioctx_t group_p,
6729 const char *group_name,
6730 rbd_group_image_info_t *images,
6731 size_t group_image_info_size,
6732 size_t *image_size)
6733 {
6734 librados::IoCtx group_ioctx;
6735 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6736
6737 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6738 tracepoint(librbd, group_image_list_enter,
6739 group_ioctx.get_pool_name().c_str(),
6740 group_ioctx.get_id(), group_name);
6741 // FIPS zeroization audit 20191117: this memset is not security related.
6742 memset(images, 0, sizeof(*images) * *image_size);
6743
6744 if (group_image_info_size != sizeof(rbd_group_image_info_t)) {
6745 *image_size = 0;
6746 tracepoint(librbd, group_image_list_exit, -ERANGE);
6747 return -ERANGE;
6748 }
6749
6750 std::vector<librbd::group_image_info_t> cpp_images;
6751 int r = librbd::api::Group<>::image_list(group_ioctx, group_name,
6752 &cpp_images);
6753
6754 if (r == -ENOENT) {
6755 tracepoint(librbd, group_image_list_exit, 0);
6756 *image_size = 0;
6757 return 0;
6758 }
6759
6760 if (r < 0) {
6761 tracepoint(librbd, group_image_list_exit, r);
6762 return r;
6763 }
6764
6765 if (*image_size < cpp_images.size()) {
6766 *image_size = cpp_images.size();
6767 tracepoint(librbd, group_image_list_exit, -ERANGE);
6768 return -ERANGE;
6769 }
6770
6771 for (size_t i = 0; i < cpp_images.size(); ++i) {
6772 group_image_status_cpp_to_c(cpp_images[i], &images[i]);
6773 }
6774
6775 r = *image_size = cpp_images.size();
6776 tracepoint(librbd, group_image_list_exit, r);
6777 return r;
6778 }
6779
6780 extern "C" int rbd_group_info_cleanup(rbd_group_info_t *group_info,
6781 size_t group_info_size) {
6782 if (group_info_size != sizeof(rbd_group_info_t)) {
6783 return -ERANGE;
6784 }
6785
6786 free(group_info->name);
6787 return 0;
6788 }
6789
6790 extern "C" int rbd_group_image_list_cleanup(rbd_group_image_info_t *images,
6791 size_t group_image_info_size,
6792 size_t len) {
6793 if (group_image_info_size != sizeof(rbd_group_image_info_t)) {
6794 return -ERANGE;
6795 }
6796
6797 for (size_t i = 0; i < len; ++i) {
6798 free(images[i].name);
6799 }
6800 return 0;
6801 }
6802
6803 extern "C" int rbd_group_snap_create(rados_ioctx_t group_p,
6804 const char *group_name,
6805 const char *snap_name)
6806 {
6807 librados::IoCtx group_ioctx;
6808 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6809
6810 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6811 tracepoint(librbd, group_snap_create_enter,
6812 group_ioctx.get_pool_name().c_str(),
6813 group_ioctx.get_id(), group_name, snap_name);
6814
6815 int r = librbd::api::Group<>::snap_create(group_ioctx, group_name, snap_name);
6816
6817 tracepoint(librbd, group_snap_create_exit, r);
6818
6819 return r;
6820 }
6821
6822 extern "C" int rbd_group_snap_remove(rados_ioctx_t group_p,
6823 const char *group_name,
6824 const char *snap_name)
6825 {
6826 librados::IoCtx group_ioctx;
6827 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6828
6829 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6830 tracepoint(librbd, group_snap_remove_enter,
6831 group_ioctx.get_pool_name().c_str(),
6832 group_ioctx.get_id(), group_name, snap_name);
6833
6834 int r = librbd::api::Group<>::snap_remove(group_ioctx, group_name, snap_name);
6835
6836 tracepoint(librbd, group_snap_remove_exit, r);
6837
6838 return r;
6839 }
6840
6841 extern "C" int rbd_group_snap_rename(rados_ioctx_t group_p,
6842 const char *group_name,
6843 const char *old_snap_name,
6844 const char *new_snap_name)
6845 {
6846 librados::IoCtx group_ioctx;
6847 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6848
6849 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6850 tracepoint(librbd, group_snap_rename_enter,
6851 group_ioctx.get_pool_name().c_str(), group_ioctx.get_id(),
6852 group_name, old_snap_name, new_snap_name);
6853
6854 int r = librbd::api::Group<>::snap_rename(group_ioctx, group_name,
6855 old_snap_name, new_snap_name);
6856
6857 tracepoint(librbd, group_snap_list_exit, r);
6858 return r;
6859 }
6860
6861 extern "C" int rbd_group_snap_list(rados_ioctx_t group_p,
6862 const char *group_name,
6863 rbd_group_snap_info_t *snaps,
6864 size_t group_snap_info_size,
6865 size_t *snaps_size)
6866 {
6867 librados::IoCtx group_ioctx;
6868 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6869
6870 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6871 tracepoint(librbd, group_snap_list_enter, group_ioctx.get_pool_name().c_str(),
6872 group_ioctx.get_id(), group_name);
6873 // FIPS zeroization audit 20191117: this memset is not security related.
6874 memset(snaps, 0, sizeof(*snaps) * *snaps_size);
6875
6876 if (group_snap_info_size != sizeof(rbd_group_snap_info_t)) {
6877 *snaps_size = 0;
6878 tracepoint(librbd, group_snap_list_exit, -ERANGE);
6879 return -ERANGE;
6880 }
6881
6882 std::vector<librbd::group_snap_info_t> cpp_snaps;
6883 int r = librbd::api::Group<>::snap_list(group_ioctx, group_name, &cpp_snaps);
6884
6885 if (r == -ENOENT) {
6886 *snaps_size = 0;
6887 tracepoint(librbd, group_snap_list_exit, 0);
6888 return 0;
6889 }
6890
6891 if (r < 0) {
6892 tracepoint(librbd, group_snap_list_exit, r);
6893 return r;
6894 }
6895
6896 if (*snaps_size < cpp_snaps.size()) {
6897 *snaps_size = cpp_snaps.size();
6898 tracepoint(librbd, group_snap_list_exit, -ERANGE);
6899 return -ERANGE;
6900 }
6901
6902 for (size_t i = 0; i < cpp_snaps.size(); ++i) {
6903 group_snap_info_cpp_to_c(cpp_snaps[i], &snaps[i]);
6904 }
6905
6906 r = *snaps_size = cpp_snaps.size();
6907 tracepoint(librbd, group_snap_list_exit, r);
6908 return r;
6909 }
6910
6911 extern "C" int rbd_group_snap_list_cleanup(rbd_group_snap_info_t *snaps,
6912 size_t group_snap_info_size,
6913 size_t len) {
6914 if (group_snap_info_size != sizeof(rbd_group_snap_info_t)) {
6915 return -ERANGE;
6916 }
6917
6918 for (size_t i = 0; i < len; ++i) {
6919 free(snaps[i].name);
6920 }
6921 return 0;
6922 }
6923
6924 extern "C" int rbd_group_snap_rollback(rados_ioctx_t group_p,
6925 const char *group_name,
6926 const char *snap_name)
6927 {
6928 librados::IoCtx group_ioctx;
6929 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6930
6931 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6932 tracepoint(librbd, group_snap_rollback_enter,
6933 group_ioctx.get_pool_name().c_str(),
6934 group_ioctx.get_id(), group_name, snap_name);
6935
6936 librbd::NoOpProgressContext prog_ctx;
6937 int r = librbd::api::Group<>::snap_rollback(group_ioctx, group_name,
6938 snap_name, prog_ctx);
6939
6940 tracepoint(librbd, group_snap_rollback_exit, r);
6941
6942 return r;
6943 }
6944
6945 extern "C" int rbd_group_snap_rollback_with_progress(rados_ioctx_t group_p,
6946 const char *group_name,
6947 const char *snap_name,
6948 librbd_progress_fn_t cb,
6949 void *cbdata)
6950 {
6951 librados::IoCtx group_ioctx;
6952 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
6953
6954 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
6955 tracepoint(librbd, group_snap_rollback_enter,
6956 group_ioctx.get_pool_name().c_str(),
6957 group_ioctx.get_id(), group_name, snap_name);
6958
6959 librbd::CProgressContext prog_ctx(cb, cbdata);
6960 int r = librbd::api::Group<>::snap_rollback(group_ioctx, group_name,
6961 snap_name, prog_ctx);
6962
6963 tracepoint(librbd, group_snap_rollback_exit, r);
6964
6965 return r;
6966 }
6967
6968 extern "C" int rbd_snap_get_namespace_type(rbd_image_t image,
6969 uint64_t snap_id,
6970 rbd_snap_namespace_type_t *namespace_type) {
6971 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6972 tracepoint(librbd, snap_get_namespace_type_enter, ictx, ictx->name.c_str());
6973 int r = librbd::api::Snapshot<>::get_namespace_type(ictx, snap_id,
6974 namespace_type);
6975 tracepoint(librbd, snap_get_namespace_type_exit, r);
6976 return r;
6977 }
6978
6979 extern "C" int rbd_snap_get_group_namespace(rbd_image_t image, uint64_t snap_id,
6980 rbd_snap_group_namespace_t *group_snap,
6981 size_t snap_group_namespace_size) {
6982 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
6983 tracepoint(librbd, snap_get_group_namespace_enter, ictx,
6984 ictx->name.c_str());
6985
6986 if (snap_group_namespace_size != sizeof(rbd_snap_group_namespace_t)) {
6987 tracepoint(librbd, snap_get_group_namespace_exit, -ERANGE);
6988 return -ERANGE;
6989 }
6990
6991 librbd::snap_group_namespace_t group_namespace;
6992 int r = librbd::api::Snapshot<>::get_group_namespace(ictx, snap_id,
6993 &group_namespace);
6994 if (r >= 0) {
6995 group_snap->group_pool = group_namespace.group_pool;
6996 group_snap->group_name = strdup(group_namespace.group_name.c_str());
6997 group_snap->group_snap_name =
6998 strdup(group_namespace.group_snap_name.c_str());
6999 }
7000
7001 tracepoint(librbd, snap_get_group_namespace_exit, r);
7002 return r;
7003 }
7004
7005 extern "C" int rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *group_snap,
7006 size_t snap_group_namespace_size) {
7007 if (snap_group_namespace_size != sizeof(rbd_snap_group_namespace_t)) {
7008 return -ERANGE;
7009 }
7010
7011 free(group_snap->group_name);
7012 free(group_snap->group_snap_name);
7013 return 0;
7014 }
7015
7016 extern "C" int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id,
7017 char *original_name,
7018 size_t max_length) {
7019 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
7020
7021 std::string cpp_original_name;
7022 int r = librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
7023 &cpp_original_name);
7024 if (r < 0) {
7025 return r;
7026 }
7027
7028 if (cpp_original_name.length() >= max_length) {
7029 return -ERANGE;
7030 }
7031
7032 strcpy(original_name, cpp_original_name.c_str());
7033 return 0;
7034 }
7035
7036 extern "C" int rbd_snap_get_mirror_namespace(
7037 rbd_image_t image, uint64_t snap_id,
7038 rbd_snap_mirror_namespace_t *mirror_snap,
7039 size_t mirror_snap_size) {
7040 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
7041
7042 if (mirror_snap_size != sizeof(rbd_snap_mirror_namespace_t)) {
7043 return -ERANGE;
7044 }
7045
7046 librbd::snap_mirror_namespace_t mirror_namespace;
7047 int r = librbd::api::Snapshot<>::get_mirror_namespace(
7048 ictx, snap_id, &mirror_namespace);
7049 if (r < 0) {
7050 return r;
7051 }
7052
7053 mirror_snap->state = mirror_namespace.state;
7054 mirror_snap->primary_mirror_uuid =
7055 strdup(mirror_namespace.primary_mirror_uuid.c_str());
7056 mirror_snap->primary_snap_id = mirror_namespace.primary_snap_id;
7057 mirror_snap->mirror_peer_uuids_count =
7058 mirror_namespace.mirror_peer_uuids.size();
7059 size_t len = 0;
7060 for (auto &peer : mirror_namespace.mirror_peer_uuids) {
7061 len += peer.size() + 1;
7062 }
7063 mirror_snap->mirror_peer_uuids = (char *)malloc(len);
7064 char *p = mirror_snap->mirror_peer_uuids;
7065 for (auto &peer : mirror_namespace.mirror_peer_uuids) {
7066 strncpy(p, peer.c_str(), peer.size() + 1);
7067 p += peer.size() + 1;
7068 }
7069 mirror_snap->complete = mirror_namespace.complete;
7070 mirror_snap->last_copied_object_number =
7071 mirror_namespace.last_copied_object_number;
7072
7073 return 0;
7074 }
7075
7076 extern "C" int rbd_snap_mirror_namespace_cleanup(
7077 rbd_snap_mirror_namespace_t *mirror_snap,
7078 size_t mirror_snap_size) {
7079 if (mirror_snap_size != sizeof(rbd_snap_mirror_namespace_t)) {
7080 return -ERANGE;
7081 }
7082
7083 free(mirror_snap->primary_mirror_uuid);
7084 free(mirror_snap->mirror_peer_uuids);
7085 return 0;
7086 }
7087
7088 extern "C" int rbd_watchers_list(rbd_image_t image,
7089 rbd_image_watcher_t *watchers,
7090 size_t *max_watchers) {
7091 std::list<librbd::image_watcher_t> watcher_list;
7092 librbd::ImageCtx *ictx = (librbd::ImageCtx*)image;
7093
7094 tracepoint(librbd, list_watchers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
7095 // FIPS zeroization audit 20191117: this memset is not security related.
7096 memset(watchers, 0, sizeof(*watchers) * *max_watchers);
7097 int r = librbd::list_watchers(ictx, watcher_list);
7098 if (r < 0) {
7099 tracepoint(librbd, list_watchers_exit, r, 0);
7100 return r;
7101 }
7102
7103 if (watcher_list.size() > *max_watchers) {
7104 *max_watchers = watcher_list.size();
7105 tracepoint(librbd, list_watchers_exit, -ERANGE, watcher_list.size());
7106 return -ERANGE;
7107 }
7108
7109 *max_watchers = 0;
7110 for (auto &watcher : watcher_list) {
7111 tracepoint(librbd, list_watchers_entry, watcher.addr.c_str(), watcher.id, watcher.cookie);
7112 watchers[*max_watchers].addr = strdup(watcher.addr.c_str());
7113 watchers[*max_watchers].id = watcher.id;
7114 watchers[*max_watchers].cookie = watcher.cookie;
7115 *max_watchers += 1;
7116 }
7117
7118 tracepoint(librbd, list_watchers_exit, r, watcher_list.size());
7119 return 0;
7120 }
7121
7122 extern "C" void rbd_watchers_list_cleanup(rbd_image_watcher_t *watchers,
7123 size_t num_watchers) {
7124 for (size_t i = 0; i < num_watchers; ++i) {
7125 free(watchers[i].addr);
7126 }
7127 }
7128
7129 extern "C" int rbd_config_image_list(rbd_image_t image,
7130 rbd_config_option_t *options,
7131 int *max_options) {
7132 librbd::ImageCtx *ictx = (librbd::ImageCtx*)image;
7133
7134 std::vector<librbd::config_option_t> option_vector;
7135 int r = librbd::api::Config<>::list(ictx, &option_vector);
7136 if (r < 0) {
7137 return r;
7138 }
7139
7140 if (*max_options < static_cast<int>(option_vector.size())) {
7141 *max_options = static_cast<int>(option_vector.size());
7142 return -ERANGE;
7143 }
7144
7145 for (int i = 0; i < static_cast<int>(option_vector.size()); ++i) {
7146 config_option_cpp_to_c(option_vector[i], &options[i]);
7147 }
7148 *max_options = static_cast<int>(option_vector.size());
7149 return 0;
7150 }
7151
7152 extern "C" void rbd_config_image_list_cleanup(rbd_config_option_t *options,
7153 int max_options) {
7154 for (int i = 0; i < max_options; ++i) {
7155 config_option_cleanup(options[i]);
7156 }
7157 }