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