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