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