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