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