]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/librbd.cc
bump version to 12.0.3-pve3
[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 "cls/rbd/cls_rbd_types.h"
19 #include "common/dout.h"
20 #include "common/errno.h"
21 #include "common/TracepointProvider.h"
22 #include "include/Context.h"
23
24 #include "cls/rbd/cls_rbd_client.h"
25 #include "cls/rbd/cls_rbd_types.h"
26 #include "librbd/ImageCtx.h"
27 #include "librbd/ImageState.h"
28 #include "librbd/internal.h"
29 #include "librbd/Operations.h"
30 #include "librbd/api/DiffIterate.h"
31 #include "librbd/api/Group.h"
32 #include "librbd/api/Mirror.h"
33 #include "librbd/io/AioCompletion.h"
34 #include "librbd/io/ImageRequestWQ.h"
35 #include "librbd/io/ReadResult.h"
36 #include <algorithm>
37 #include <string>
38 #include <vector>
39
40 #ifdef WITH_LTTNG
41 #define TRACEPOINT_DEFINE
42 #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
43 #include "tracing/librbd.h"
44 #undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
45 #undef TRACEPOINT_DEFINE
46 #else
47 #define tracepoint(...)
48 #endif
49
50 #define dout_subsys ceph_subsys_rbd
51 #undef dout_prefix
52 #define dout_prefix *_dout << "librbd: "
53
54 using std::string;
55 using std::vector;
56
57 using ceph::bufferlist;
58 using librados::snap_t;
59 using librados::IoCtx;
60
61 namespace {
62
63 TracepointProvider::Traits tracepoint_traits("librbd_tp.so", "rbd_tracing");
64
65 buffer::raw* create_write_raw(librbd::ImageCtx *ictx, const char *buf,
66 size_t len) {
67 // TODO: until librados can guarantee memory won't be referenced after
68 // it ACKs a request, always make a copy of the user-provided memory
69 return buffer::copy(buf, len);
70 }
71
72 CephContext* get_cct(IoCtx &io_ctx) {
73 return reinterpret_cast<CephContext*>(io_ctx.cct());
74 }
75
76 librbd::io::AioCompletion* get_aio_completion(librbd::RBD::AioCompletion *comp) {
77 return reinterpret_cast<librbd::io::AioCompletion *>(comp->pc);
78 }
79
80 struct C_AioCompletion : public Context {
81 CephContext *cct;
82 librbd::io::aio_type_t aio_type;
83 librbd::io::AioCompletion* aio_comp;
84
85 C_AioCompletion(librbd::ImageCtx *ictx, librbd::io::aio_type_t aio_type,
86 librbd::io::AioCompletion* aio_comp)
87 : cct(ictx->cct), aio_type(aio_type), aio_comp(aio_comp) {
88 aio_comp->init_time(ictx, aio_type);
89 aio_comp->get();
90 }
91
92 void finish(int r) override {
93 ldout(cct, 20) << "C_AioComplete::finish: r=" << r << dendl;
94 if (r < 0) {
95 aio_comp->fail(r);
96 } else {
97 aio_comp->lock.Lock();
98 aio_comp->complete();
99 aio_comp->put_unlock();
100 }
101 }
102 };
103
104 struct C_OpenComplete : public C_AioCompletion {
105 librbd::ImageCtx *ictx;
106 void **ictxp;
107 bool reopen;
108 C_OpenComplete(librbd::ImageCtx *ictx, librbd::io::AioCompletion* comp,
109 void **ictxp)
110 : C_AioCompletion(ictx, librbd::io::AIO_TYPE_OPEN, comp),
111 ictx(ictx), ictxp(ictxp) {
112 }
113 void finish(int r) override {
114 ldout(ictx->cct, 20) << "C_OpenComplete::finish: r=" << r << dendl;
115 if (r < 0) {
116 *ictxp = nullptr;
117 } else {
118 *ictxp = ictx;
119 }
120
121 C_AioCompletion::finish(r);
122 }
123 };
124
125 struct C_OpenAfterCloseComplete : public Context {
126 librbd::ImageCtx *ictx;
127 librbd::io::AioCompletion* comp;
128 void **ictxp;
129 C_OpenAfterCloseComplete(librbd::ImageCtx *ictx,
130 librbd::io::AioCompletion* comp,
131 void **ictxp)
132 : ictx(ictx), comp(comp), ictxp(ictxp) {
133 }
134 void finish(int r) override {
135 ldout(ictx->cct, 20) << "C_OpenAfterCloseComplete::finish: r=" << r
136 << dendl;
137 delete reinterpret_cast<librbd::ImageCtx*>(*ictxp);
138 *ictxp = nullptr;
139
140 ictx->state->open(false, new C_OpenComplete(ictx, comp, ictxp));
141 }
142 };
143
144 struct C_UpdateWatchCB : public librbd::UpdateWatchCtx {
145 rbd_update_callback_t watch_cb;
146 void *arg;
147 uint64_t handle = 0;
148
149 C_UpdateWatchCB(rbd_update_callback_t watch_cb, void *arg) :
150 watch_cb(watch_cb), arg(arg) {
151 }
152 void handle_notify() override {
153 watch_cb(arg);
154 }
155 };
156
157 void group_image_status_cpp_to_c(const librbd::group_image_status_t &cpp_status,
158 rbd_group_image_status_t *c_status) {
159 c_status->spec.name = strdup(cpp_status.name.c_str());
160 c_status->spec.pool = cpp_status.pool;
161 c_status->state = cpp_status.state;
162 }
163
164 void group_spec_cpp_to_c(const librbd::group_spec_t &cpp_spec,
165 rbd_group_spec_t *c_spec) {
166 c_spec->name = strdup(cpp_spec.name.c_str());
167 c_spec->pool = cpp_spec.pool;
168 }
169
170 void mirror_image_info_cpp_to_c(const librbd::mirror_image_info_t &cpp_info,
171 rbd_mirror_image_info_t *c_info) {
172 c_info->global_id = strdup(cpp_info.global_id.c_str());
173 c_info->state = cpp_info.state;
174 c_info->primary = cpp_info.primary;
175 }
176
177 void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_status,
178 rbd_mirror_image_status_t *c_status) {
179 c_status->name = strdup(cpp_status.name.c_str());
180 mirror_image_info_cpp_to_c(cpp_status.info, &c_status->info);
181 c_status->state = cpp_status.state;
182 c_status->description = strdup(cpp_status.description.c_str());
183 c_status->last_update = cpp_status.last_update;
184 c_status->up = cpp_status.up;
185 }
186
187 void trash_image_info_cpp_to_c(const librbd::trash_image_info_t &cpp_info,
188 rbd_trash_image_info_t *c_info) {
189 c_info->id = strdup(cpp_info.id.c_str());
190 c_info->name = strdup(cpp_info.name.c_str());
191 c_info->source = cpp_info.source;
192 c_info->deletion_time = cpp_info.deletion_time;
193 c_info->deferment_end_time = cpp_info.deferment_end_time;
194 }
195
196 struct C_MirrorImageGetInfo : public Context {
197 rbd_mirror_image_info_t *mirror_image_info;
198 Context *on_finish;
199
200 librbd::mirror_image_info_t cpp_mirror_image_info;
201
202 C_MirrorImageGetInfo(rbd_mirror_image_info_t *mirror_image_info,
203 Context *on_finish)
204 : mirror_image_info(mirror_image_info), on_finish(on_finish) {
205 }
206
207 void finish(int r) override {
208 if (r < 0) {
209 on_finish->complete(r);
210 return;
211 }
212
213 mirror_image_info_cpp_to_c(cpp_mirror_image_info, mirror_image_info);
214 on_finish->complete(0);
215 }
216 };
217
218 struct C_MirrorImageGetStatus : public Context {
219 rbd_mirror_image_status_t *mirror_image_status;
220 Context *on_finish;
221
222 librbd::mirror_image_status_t cpp_mirror_image_status;
223
224 C_MirrorImageGetStatus(rbd_mirror_image_status_t *mirror_image_status,
225 Context *on_finish)
226 : mirror_image_status(mirror_image_status), on_finish(on_finish) {
227 }
228
229 void finish(int r) override {
230 if (r < 0) {
231 on_finish->complete(r);
232 return;
233 }
234
235 mirror_image_status_cpp_to_c(cpp_mirror_image_status, mirror_image_status);
236 on_finish->complete(0);
237 }
238 };
239
240 } // anonymous namespace
241
242 namespace librbd {
243 ProgressContext::~ProgressContext()
244 {
245 }
246
247 class CProgressContext : public ProgressContext
248 {
249 public:
250 CProgressContext(librbd_progress_fn_t fn, void *data)
251 : m_fn(fn), m_data(data)
252 {
253 }
254 int update_progress(uint64_t offset, uint64_t src_size) override
255 {
256 return m_fn(offset, src_size, m_data);
257 }
258 private:
259 librbd_progress_fn_t m_fn;
260 void *m_data;
261 };
262
263 /*
264 RBD
265 */
266 RBD::RBD()
267 {
268 }
269
270 RBD::~RBD()
271 {
272 }
273
274 void RBD::version(int *major, int *minor, int *extra)
275 {
276 rbd_version(major, minor, extra);
277 }
278
279 int RBD::open(IoCtx& io_ctx, Image& image, const char *name)
280 {
281 return open(io_ctx, image, name, NULL);
282 }
283
284 int RBD::open_by_id(IoCtx& io_ctx, Image& image, const char *id)
285 {
286 return open_by_id(io_ctx, image, id, nullptr);
287 }
288
289 int RBD::open(IoCtx& io_ctx, Image& image, const char *name,
290 const char *snap_name)
291 {
292 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
293 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
294 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
295
296 if (image.ctx != NULL) {
297 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
298 image.ctx = NULL;
299 }
300
301 int r = ictx->state->open(false);
302 if (r < 0) {
303 tracepoint(librbd, open_image_exit, r);
304 return r;
305 }
306
307 image.ctx = (image_ctx_t) ictx;
308 tracepoint(librbd, open_image_exit, 0);
309 return 0;
310 }
311
312 int RBD::open_by_id(IoCtx& io_ctx, Image& image, const char *id,
313 const char *snap_name)
314 {
315 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, false);
316 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
317 tracepoint(librbd, open_image_by_id_enter, ictx, ictx->id.c_str(),
318 ictx->snap_name.c_str(), ictx->read_only);
319
320 if (image.ctx != nullptr) {
321 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
322 image.ctx = nullptr;
323 }
324
325 int r = ictx->state->open(false);
326 if (r < 0) {
327 tracepoint(librbd, open_image_by_id_exit, r);
328 return r;
329 }
330
331 image.ctx = (image_ctx_t) ictx;
332 tracepoint(librbd, open_image_by_id_exit, 0);
333 return 0;
334 }
335
336 int RBD::aio_open(IoCtx& io_ctx, Image& image, const char *name,
337 const char *snap_name, RBD::AioCompletion *c)
338 {
339 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
340 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
341 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);
342
343 if (image.ctx != NULL) {
344 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
345 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
346 } else {
347 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
348 &image.ctx));
349 }
350 tracepoint(librbd, aio_open_image_exit, 0);
351 return 0;
352 }
353
354 int RBD::aio_open_by_id(IoCtx& io_ctx, Image& image, const char *id,
355 const char *snap_name, RBD::AioCompletion *c)
356 {
357 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, false);
358 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
359 tracepoint(librbd, aio_open_image_by_id_enter, ictx, ictx->id.c_str(),
360 ictx->snap_name.c_str(), ictx->read_only, c->pc);
361
362 if (image.ctx != nullptr) {
363 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
364 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
365 } else {
366 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
367 &image.ctx));
368 }
369 tracepoint(librbd, aio_open_image_by_id_exit, 0);
370 return 0;
371 }
372
373 int RBD::open_read_only(IoCtx& io_ctx, Image& image, const char *name,
374 const char *snap_name)
375 {
376 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, true);
377 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
378 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
379
380 if (image.ctx != NULL) {
381 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
382 image.ctx = NULL;
383 }
384
385 int r = ictx->state->open(false);
386 if (r < 0) {
387 tracepoint(librbd, open_image_exit, r);
388 return r;
389 }
390
391 image.ctx = (image_ctx_t) ictx;
392 tracepoint(librbd, open_image_exit, 0);
393 return 0;
394 }
395
396 int RBD::open_by_id_read_only(IoCtx& io_ctx, Image& image, const char *id,
397 const char *snap_name)
398 {
399 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, true);
400 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
401 tracepoint(librbd, open_image_by_id_enter, ictx, ictx->id.c_str(),
402 ictx->snap_name.c_str(), ictx->read_only);
403
404 if (image.ctx != nullptr) {
405 reinterpret_cast<ImageCtx*>(image.ctx)->state->close();
406 image.ctx = nullptr;
407 }
408
409 int r = ictx->state->open(false);
410 if (r < 0) {
411 tracepoint(librbd, open_image_by_id_exit, r);
412 return r;
413 }
414
415 image.ctx = (image_ctx_t) ictx;
416 tracepoint(librbd, open_image_by_id_exit, 0);
417 return 0;
418 }
419
420 int RBD::aio_open_read_only(IoCtx& io_ctx, Image& image, const char *name,
421 const char *snap_name, RBD::AioCompletion *c)
422 {
423 ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, true);
424 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
425 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);
426
427 if (image.ctx != NULL) {
428 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
429 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
430 } else {
431 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
432 &image.ctx));
433 }
434 tracepoint(librbd, aio_open_image_exit, 0);
435 return 0;
436 }
437
438 int RBD::aio_open_by_id_read_only(IoCtx& io_ctx, Image& image, const char *id,
439 const char *snap_name, RBD::AioCompletion *c)
440 {
441 ImageCtx *ictx = new ImageCtx("", id, snap_name, io_ctx, true);
442 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
443 tracepoint(librbd, aio_open_image_by_id_enter, ictx, ictx->id.c_str(),
444 ictx->snap_name.c_str(), ictx->read_only, c->pc);
445
446 if (image.ctx != nullptr) {
447 reinterpret_cast<ImageCtx*>(image.ctx)->state->close(
448 new C_OpenAfterCloseComplete(ictx, get_aio_completion(c), &image.ctx));
449 } else {
450 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(c),
451 &image.ctx));
452 }
453 tracepoint(librbd, aio_open_image_by_id_exit, 0);
454 return 0;
455 }
456
457 int RBD::create(IoCtx& io_ctx, const char *name, uint64_t size, int *order)
458 {
459 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
460 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
461 int r = librbd::create(io_ctx, name, size, order);
462 tracepoint(librbd, create_exit, r, *order);
463 return r;
464 }
465
466 int RBD::create2(IoCtx& io_ctx, const char *name, uint64_t size,
467 uint64_t features, int *order)
468 {
469 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
470 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
471 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
472 tracepoint(librbd, create2_exit, r, *order);
473 return r;
474 }
475
476 int RBD::create3(IoCtx& io_ctx, const char *name, uint64_t size,
477 uint64_t features, int *order, uint64_t stripe_unit,
478 uint64_t stripe_count)
479 {
480 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
481 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
482 int r = librbd::create(io_ctx, name, size, false, features, order,
483 stripe_unit, stripe_count);
484 tracepoint(librbd, create3_exit, r, *order);
485 return r;
486 }
487
488 int RBD::create4(IoCtx& io_ctx, const char *name, uint64_t size,
489 ImageOptions& opts)
490 {
491 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
492 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts.opts);
493 int r = librbd::create(io_ctx, name, "", size, opts, "", "", false);
494 tracepoint(librbd, create4_exit, r);
495 return r;
496 }
497
498 int RBD::clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
499 IoCtx& c_ioctx, const char *c_name, uint64_t features,
500 int *c_order)
501 {
502 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
503 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);
504 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
505 features, c_order, 0, 0);
506 tracepoint(librbd, clone_exit, r, *c_order);
507 return r;
508 }
509
510 int RBD::clone2(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
511 IoCtx& c_ioctx, const char *c_name, uint64_t features,
512 int *c_order, uint64_t stripe_unit, int stripe_count)
513 {
514 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
515 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);
516 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
517 features, c_order, stripe_unit, stripe_count);
518 tracepoint(librbd, clone2_exit, r, *c_order);
519 return r;
520 }
521
522 int RBD::clone3(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
523 IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts)
524 {
525 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx));
526 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);
527 int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name,
528 c_opts);
529 tracepoint(librbd, clone3_exit, r);
530 return r;
531 }
532
533 int RBD::remove(IoCtx& io_ctx, const char *name)
534 {
535 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
536 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
537 librbd::NoOpProgressContext prog_ctx;
538 int r = librbd::remove(io_ctx, name, "", prog_ctx);
539 tracepoint(librbd, remove_exit, r);
540 return r;
541 }
542
543 int RBD::remove_with_progress(IoCtx& io_ctx, const char *name,
544 ProgressContext& pctx)
545 {
546 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
547 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
548 int r = librbd::remove(io_ctx, name, "", pctx);
549 tracepoint(librbd, remove_exit, r);
550 return r;
551 }
552
553 int RBD::trash_move(IoCtx &io_ctx, const char *name, uint64_t delay) {
554 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
555 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
556 io_ctx.get_id(), name);
557 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name,
558 delay);
559 tracepoint(librbd, trash_move_exit, r);
560 return r;
561 }
562
563 int RBD::trash_get(IoCtx &io_ctx, const char *id, trash_image_info_t *info) {
564 return librbd::trash_get(io_ctx, id, info);
565 }
566
567 int RBD::trash_list(IoCtx &io_ctx, vector<trash_image_info_t> &entries) {
568 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
569 tracepoint(librbd, trash_list_enter,
570 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
571 int r = librbd::trash_list(io_ctx, entries);
572 #ifdef WITH_LTTNG
573 if (r >= 0) {
574 for (const auto& entry : entries) {
575 tracepoint(librbd, trash_list_entry, entry.id.c_str());
576 }
577 }
578 #endif
579 tracepoint(librbd, trash_list_exit, r, r);
580 return r;
581 }
582
583 int RBD::trash_remove(IoCtx &io_ctx, const char *image_id, bool force) {
584 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
585 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
586 io_ctx.get_id(), image_id, force);
587 librbd::NoOpProgressContext prog_ctx;
588 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
589 tracepoint(librbd, trash_remove_exit, r);
590 return r;
591 }
592
593 int RBD::trash_remove_with_progress(IoCtx &io_ctx, const char *image_id,
594 bool force, ProgressContext &pctx) {
595 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
596 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
597 io_ctx.get_id(), image_id, force);
598 int r = librbd::trash_remove(io_ctx, image_id, force, pctx);
599 tracepoint(librbd, trash_remove_exit, r);
600 return r;
601 }
602
603 int RBD::trash_restore(IoCtx &io_ctx, const char *id, const char *name) {
604 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
605 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
606 io_ctx.get_id(), id, name);
607 int r = librbd::trash_restore(io_ctx, id, name);
608 tracepoint(librbd, trash_undelete_exit, r);
609 return r;
610 }
611
612 int RBD::list(IoCtx& io_ctx, vector<string>& names)
613 {
614 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
615 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
616 int r = librbd::list(io_ctx, names);
617 if (r >= 0) {
618 for (vector<string>::iterator itr = names.begin(), end = names.end(); itr != end; ++itr) {
619 tracepoint(librbd, list_entry, itr->c_str());
620 }
621 }
622 tracepoint(librbd, list_exit, r, r);
623 return r;
624 }
625
626 int RBD::rename(IoCtx& src_io_ctx, const char *srcname, const char *destname)
627 {
628 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
629 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
630 int r = librbd::rename(src_io_ctx, srcname, destname);
631 tracepoint(librbd, rename_exit, r);
632 return r;
633 }
634
635 int RBD::mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) {
636 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
637 }
638
639 int RBD::mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) {
640 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
641 }
642
643 int RBD::mirror_peer_add(IoCtx& io_ctx, std::string *uuid,
644 const std::string &cluster_name,
645 const std::string &client_name) {
646 return librbd::api::Mirror<>::peer_add(io_ctx, uuid, cluster_name,
647 client_name);
648 }
649
650 int RBD::mirror_peer_remove(IoCtx& io_ctx, const std::string &uuid) {
651 return librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
652 }
653
654 int RBD::mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers) {
655 return librbd::api::Mirror<>::peer_list(io_ctx, peers);
656 }
657
658 int RBD::mirror_peer_set_client(IoCtx& io_ctx, const std::string &uuid,
659 const std::string &client_name) {
660 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
661 }
662
663 int RBD::mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
664 const std::string &cluster_name) {
665 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
666 }
667
668 int RBD::mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
669 size_t max, std::map<std::string, mirror_image_status_t> *images) {
670 return librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
671 images);
672 }
673
674 int RBD::mirror_image_status_summary(IoCtx& io_ctx,
675 std::map<mirror_image_status_state_t, int> *states) {
676 return librbd::api::Mirror<>::image_status_summary(io_ctx, states);
677 }
678
679 int RBD::group_create(IoCtx& io_ctx, const char *group_name)
680 {
681 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
682 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
683 io_ctx.get_id(), group_name);
684 int r = librbd::api::Group<>::create(io_ctx, group_name);
685 tracepoint(librbd, group_create_exit, r);
686 return r;
687 }
688
689 int RBD::group_remove(IoCtx& io_ctx, const char *group_name)
690 {
691 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
692 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
693 io_ctx.get_id(), group_name);
694 int r = librbd::api::Group<>::remove(io_ctx, group_name);
695 tracepoint(librbd, group_remove_exit, r);
696 return r;
697 }
698
699 int RBD::group_list(IoCtx& io_ctx, vector<string> *names)
700 {
701 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
702 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
703 io_ctx.get_id());
704
705 int r = librbd::api::Group<>::list(io_ctx, names);
706 if (r >= 0) {
707 for (auto itr : *names) {
708 tracepoint(librbd, group_list_entry, itr.c_str());
709 }
710 }
711 tracepoint(librbd, group_list_exit, r);
712 return r;
713 }
714
715 int RBD::group_image_add(IoCtx& group_ioctx, const char *group_name,
716 IoCtx& image_ioctx, const char *image_name)
717 {
718 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
719 tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(),
720 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
721 image_ioctx.get_id(), image_name);
722 int r = librbd::api::Group<>::image_add(group_ioctx, group_name,
723 image_ioctx, image_name);
724 tracepoint(librbd, group_image_add_exit, r);
725 return r;
726 }
727
728 int RBD::group_image_remove(IoCtx& group_ioctx, const char *group_name,
729 IoCtx& image_ioctx, const char *image_name)
730 {
731 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
732 tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(),
733 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
734 image_ioctx.get_id(), image_name);
735 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
736 image_ioctx, image_name);
737 tracepoint(librbd, group_image_remove_exit, r);
738 return r;
739 }
740
741 int RBD::group_image_remove_by_id(IoCtx& group_ioctx, const char *group_name,
742 IoCtx& image_ioctx, const char *image_id)
743 {
744 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
745 tracepoint(librbd, group_image_remove_by_id_enter,
746 group_ioctx.get_pool_name().c_str(),
747 group_ioctx.get_id(), group_name,
748 image_ioctx.get_pool_name().c_str(),
749 image_ioctx.get_id(), image_id);
750 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
751 image_ioctx, image_id);
752 tracepoint(librbd, group_image_remove_by_id_exit, r);
753 return r;
754 }
755
756 int RBD::group_image_list(IoCtx& group_ioctx, const char *group_name,
757 std::vector<group_image_status_t> *images)
758 {
759 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
760 tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(),
761 group_ioctx.get_id(), group_name);
762 int r = librbd::api::Group<>::image_list(group_ioctx, group_name, images);
763 tracepoint(librbd, group_image_list_exit, r);
764 return r;
765 }
766
767
768 RBD::AioCompletion::AioCompletion(void *cb_arg, callback_t complete_cb)
769 {
770 pc = reinterpret_cast<void*>(librbd::io::AioCompletion::create(
771 cb_arg, complete_cb, this));
772 }
773
774 bool RBD::AioCompletion::is_complete()
775 {
776 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
777 return c->is_complete();
778 }
779
780 int RBD::AioCompletion::wait_for_complete()
781 {
782 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
783 return c->wait_for_complete();
784 }
785
786 ssize_t RBD::AioCompletion::get_return_value()
787 {
788 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
789 return c->get_return_value();
790 }
791
792 void *RBD::AioCompletion::get_arg()
793 {
794 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
795 return c->get_arg();
796 }
797
798 void RBD::AioCompletion::release()
799 {
800 librbd::io::AioCompletion *c = (librbd::io::AioCompletion *)pc;
801 c->release();
802 delete this;
803 }
804
805 /*
806 ImageOptions
807 */
808
809 ImageOptions::ImageOptions()
810 {
811 librbd::image_options_create(&opts);
812 }
813
814 ImageOptions::ImageOptions(rbd_image_options_t opts_)
815 {
816 librbd::image_options_create_ref(&opts, opts_);
817 }
818
819 ImageOptions::ImageOptions(const ImageOptions &imgopts)
820 {
821 librbd::image_options_copy(&opts, imgopts);
822 }
823
824 ImageOptions::~ImageOptions()
825 {
826 librbd::image_options_destroy(opts);
827 }
828
829 int ImageOptions::set(int optname, const std::string& optval)
830 {
831 return librbd::image_options_set(opts, optname, optval);
832 }
833
834 int ImageOptions::set(int optname, uint64_t optval)
835 {
836 return librbd::image_options_set(opts, optname, optval);
837 }
838
839 int ImageOptions::get(int optname, std::string* optval) const
840 {
841 return librbd::image_options_get(opts, optname, optval);
842 }
843
844 int ImageOptions::get(int optname, uint64_t* optval) const
845 {
846 return librbd::image_options_get(opts, optname, optval);
847 }
848
849 int ImageOptions::is_set(int optname, bool* is_set)
850 {
851 return librbd::image_options_is_set(opts, optname, is_set);
852 }
853
854 int ImageOptions::unset(int optname)
855 {
856 return librbd::image_options_unset(opts, optname);
857 }
858
859 void ImageOptions::clear()
860 {
861 librbd::image_options_clear(opts);
862 }
863
864 bool ImageOptions::empty() const
865 {
866 return librbd::image_options_is_empty(opts);
867 }
868
869 /*
870 Image
871 */
872
873 Image::Image() : ctx(NULL)
874 {
875 }
876
877 Image::~Image()
878 {
879 close();
880 }
881
882 int Image::close()
883 {
884 int r = 0;
885 if (ctx) {
886 ImageCtx *ictx = (ImageCtx *)ctx;
887 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
888
889 r = ictx->state->close();
890 ctx = NULL;
891
892 tracepoint(librbd, close_image_exit, r);
893 }
894 return r;
895 }
896
897 int Image::aio_close(RBD::AioCompletion *c)
898 {
899 if (!ctx) {
900 return -EINVAL;
901 }
902
903 ImageCtx *ictx = (ImageCtx *)ctx;
904 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), c->pc);
905
906 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
907 get_aio_completion(c)));
908 ctx = NULL;
909
910 tracepoint(librbd, aio_close_image_exit, 0);
911 return 0;
912 }
913
914 int Image::resize(uint64_t size)
915 {
916 ImageCtx *ictx = (ImageCtx *)ctx;
917 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
918 librbd::NoOpProgressContext prog_ctx;
919 int r = ictx->operations->resize(size, true, prog_ctx);
920 tracepoint(librbd, resize_exit, r);
921 return r;
922 }
923
924 int Image::resize2(uint64_t size, bool allow_shrink, librbd::ProgressContext& pctx)
925 {
926 ImageCtx *ictx = (ImageCtx *)ctx;
927 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
928 int r = ictx->operations->resize(size, allow_shrink, pctx);
929 tracepoint(librbd, resize_exit, r);
930 return r;
931 }
932
933 int Image::resize_with_progress(uint64_t size, librbd::ProgressContext& pctx)
934 {
935 ImageCtx *ictx = (ImageCtx *)ctx;
936 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
937 int r = ictx->operations->resize(size, true, pctx);
938 tracepoint(librbd, resize_exit, r);
939 return r;
940 }
941
942 int Image::stat(image_info_t& info, size_t infosize)
943 {
944 ImageCtx *ictx = (ImageCtx *)ctx;
945 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
946 int r = librbd::info(ictx, info, infosize);
947 tracepoint(librbd, stat_exit, r, &info);
948 return r;
949 }
950
951 int Image::old_format(uint8_t *old)
952 {
953 ImageCtx *ictx = (ImageCtx *)ctx;
954 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
955 int r = librbd::get_old_format(ictx, old);
956 tracepoint(librbd, get_old_format_exit, r, *old);
957 return r;
958 }
959
960 int Image::size(uint64_t *size)
961 {
962 ImageCtx *ictx = (ImageCtx *)ctx;
963 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
964 int r = librbd::get_size(ictx, size);
965 tracepoint(librbd, get_size_exit, r, *size);
966 return r;
967 }
968
969 int Image::get_group(group_spec_t *group_spec)
970 {
971 ImageCtx *ictx = (ImageCtx *)ctx;
972 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
973 int r = librbd::api::Group<>::image_get_group(ictx, group_spec);
974 tracepoint(librbd, image_get_group_exit, r);
975 return r;
976 }
977
978 int Image::features(uint64_t *features)
979 {
980 ImageCtx *ictx = (ImageCtx *)ctx;
981 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
982 int r = librbd::get_features(ictx, features);
983 tracepoint(librbd, get_features_exit, r, *features);
984 return r;
985 }
986
987 int Image::update_features(uint64_t features, bool enabled)
988 {
989 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
990 tracepoint(librbd, update_features_enter, ictx, features, enabled);
991 int r = ictx->operations->update_features(features, enabled);
992 tracepoint(librbd, update_features_exit, r);
993 return r;
994 }
995
996 uint64_t Image::get_stripe_unit() const
997 {
998 ImageCtx *ictx = (ImageCtx *)ctx;
999 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1000 uint64_t stripe_unit = ictx->get_stripe_unit();
1001 tracepoint(librbd, get_stripe_unit_exit, 0, stripe_unit);
1002 return stripe_unit;
1003 }
1004
1005 uint64_t Image::get_stripe_count() const
1006 {
1007 ImageCtx *ictx = (ImageCtx *)ctx;
1008 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1009 uint64_t stripe_count = ictx->get_stripe_count();
1010 tracepoint(librbd, get_stripe_count_exit, 0, stripe_count);
1011 return stripe_count;
1012 }
1013
1014 int Image::overlap(uint64_t *overlap)
1015 {
1016 ImageCtx *ictx = (ImageCtx *)ctx;
1017 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1018 int r = librbd::get_overlap(ictx, overlap);
1019 tracepoint(librbd, get_overlap_exit, r, *overlap);
1020 return r;
1021 }
1022
1023 int Image::get_id(std::string *id)
1024 {
1025 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1026 if (ictx->old_format) {
1027 return -EINVAL;
1028 }
1029 *id = ictx->id;
1030 return 0;
1031 }
1032
1033 std::string Image::get_block_name_prefix()
1034 {
1035 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1036 return ictx->object_prefix;
1037 }
1038
1039 int64_t Image::get_data_pool_id()
1040 {
1041 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1042 return ictx->data_ctx.get_id();
1043 }
1044
1045 int Image::parent_info(string *parent_pool_name, string *parent_name,
1046 string *parent_snap_name)
1047 {
1048 return parent_info2(parent_pool_name, parent_name, nullptr,
1049 parent_snap_name);
1050 }
1051
1052 int Image::parent_info2(string *parent_pool_name, string *parent_name,
1053 string *parent_id, string *parent_snap_name)
1054 {
1055 ImageCtx *ictx = (ImageCtx *)ctx;
1056 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
1057 ictx->snap_name.c_str(), ictx->read_only);
1058 int r = librbd::get_parent_info(ictx, parent_pool_name, parent_name,
1059 parent_id, parent_snap_name);
1060 tracepoint(librbd, get_parent_info_exit, r,
1061 parent_pool_name ? parent_pool_name->c_str() : NULL,
1062 parent_name ? parent_name->c_str() : NULL,
1063 parent_id ? parent_id->c_str() : NULL,
1064 parent_snap_name ? parent_snap_name->c_str() : NULL);
1065 return r;
1066 }
1067
1068 int Image::get_flags(uint64_t *flags)
1069 {
1070 ImageCtx *ictx = (ImageCtx *)ctx;
1071 tracepoint(librbd, get_flags_enter, ictx);
1072 int r = librbd::get_flags(ictx, flags);
1073 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
1074 return r;
1075 }
1076
1077 int Image::set_image_notification(int fd, int type)
1078 {
1079 ImageCtx *ictx = (ImageCtx *)ctx;
1080 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
1081 int r = librbd::set_image_notification(ictx, fd, type);
1082 tracepoint(librbd, set_image_notification_exit, ictx, r);
1083 return r;
1084 }
1085
1086 int Image::is_exclusive_lock_owner(bool *is_owner)
1087 {
1088 ImageCtx *ictx = (ImageCtx *)ctx;
1089 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
1090 int r = librbd::is_exclusive_lock_owner(ictx, is_owner);
1091 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
1092 return r;
1093 }
1094
1095 int Image::lock_acquire(rbd_lock_mode_t lock_mode)
1096 {
1097 ImageCtx *ictx = (ImageCtx *)ctx;
1098 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
1099 int r = librbd::lock_acquire(ictx, lock_mode);
1100 tracepoint(librbd, lock_acquire_exit, ictx, r);
1101 return r;
1102 }
1103
1104 int Image::lock_release()
1105 {
1106 ImageCtx *ictx = (ImageCtx *)ctx;
1107 tracepoint(librbd, lock_release_enter, ictx);
1108 int r = librbd::lock_release(ictx);
1109 tracepoint(librbd, lock_release_exit, ictx, r);
1110 return r;
1111 }
1112
1113 int Image::lock_get_owners(rbd_lock_mode_t *lock_mode,
1114 std::list<std::string> *lock_owners)
1115 {
1116 ImageCtx *ictx = (ImageCtx *)ctx;
1117 tracepoint(librbd, lock_get_owners_enter, ictx);
1118 int r = librbd::lock_get_owners(ictx, lock_mode, lock_owners);
1119 tracepoint(librbd, lock_get_owners_exit, ictx, r);
1120 return r;
1121 }
1122
1123 int Image::lock_break(rbd_lock_mode_t lock_mode,
1124 const std::string &lock_owner)
1125 {
1126 ImageCtx *ictx = (ImageCtx *)ctx;
1127 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner.c_str());
1128 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
1129 tracepoint(librbd, lock_break_exit, ictx, r);
1130 return r;
1131 }
1132
1133 int Image::rebuild_object_map(ProgressContext &prog_ctx)
1134 {
1135 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1136 return ictx->operations->rebuild_object_map(prog_ctx);
1137 }
1138
1139 int Image::check_object_map(ProgressContext &prog_ctx)
1140 {
1141 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1142 return ictx->operations->check_object_map(prog_ctx);
1143 }
1144
1145 int Image::copy(IoCtx& dest_io_ctx, const char *destname)
1146 {
1147 ImageCtx *ictx = (ImageCtx *)ctx;
1148 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);
1149 ImageOptions opts;
1150 librbd::NoOpProgressContext prog_ctx;
1151 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1152 tracepoint(librbd, copy_exit, r);
1153 return r;
1154 }
1155
1156 int Image::copy2(Image& dest)
1157 {
1158 ImageCtx *srcctx = (ImageCtx *)ctx;
1159 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1160 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);
1161 librbd::NoOpProgressContext prog_ctx;
1162 int r = librbd::copy(srcctx, destctx, prog_ctx, 0);
1163 tracepoint(librbd, copy2_exit, r);
1164 return r;
1165 }
1166
1167 int Image::copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts)
1168 {
1169 ImageCtx *ictx = (ImageCtx *)ctx;
1170 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);
1171 librbd::NoOpProgressContext prog_ctx;
1172 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1173 tracepoint(librbd, copy3_exit, r);
1174 return r;
1175 }
1176
1177 int Image::copy4(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts, size_t sparse_size)
1178 {
1179 ImageCtx *ictx = (ImageCtx *)ctx;
1180 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);
1181 librbd::NoOpProgressContext prog_ctx;
1182 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, sparse_size);
1183 tracepoint(librbd, copy4_exit, r);
1184 return r;
1185 }
1186
1187 int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
1188 librbd::ProgressContext &pctx)
1189 {
1190 ImageCtx *ictx = (ImageCtx *)ctx;
1191 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);
1192 ImageOptions opts;
1193 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1194 tracepoint(librbd, copy_exit, r);
1195 return r;
1196 }
1197
1198 int Image::copy_with_progress2(Image& dest, librbd::ProgressContext &pctx)
1199 {
1200 ImageCtx *srcctx = (ImageCtx *)ctx;
1201 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1202 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);
1203 int r = librbd::copy(srcctx, destctx, pctx, 0);
1204 tracepoint(librbd, copy2_exit, r);
1205 return r;
1206 }
1207
1208 int Image::copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
1209 ImageOptions& opts,
1210 librbd::ProgressContext &pctx)
1211 {
1212 ImageCtx *ictx = (ImageCtx *)ctx;
1213 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);
1214 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1215 tracepoint(librbd, copy3_exit, r);
1216 return r;
1217 }
1218
1219 int Image::copy_with_progress4(IoCtx& dest_io_ctx, const char *destname,
1220 ImageOptions& opts,
1221 librbd::ProgressContext &pctx,
1222 size_t sparse_size)
1223 {
1224 ImageCtx *ictx = (ImageCtx *)ctx;
1225 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);
1226 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, sparse_size);
1227 tracepoint(librbd, copy4_exit, r);
1228 return r;
1229 }
1230
1231 int Image::flatten()
1232 {
1233 ImageCtx *ictx = (ImageCtx *)ctx;
1234 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1235 librbd::NoOpProgressContext prog_ctx;
1236 int r = ictx->operations->flatten(prog_ctx);
1237 tracepoint(librbd, flatten_exit, r);
1238 return r;
1239 }
1240
1241 int Image::flatten_with_progress(librbd::ProgressContext& prog_ctx)
1242 {
1243 ImageCtx *ictx = (ImageCtx *)ctx;
1244 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1245 int r = ictx->operations->flatten(prog_ctx);
1246 tracepoint(librbd, flatten_exit, r);
1247 return r;
1248 }
1249
1250 int Image::list_children(set<pair<string, string> > *children)
1251 {
1252 ImageCtx *ictx = (ImageCtx *)ctx;
1253 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1254 int r = librbd::list_children(ictx, *children);
1255 if (r >= 0) {
1256 for (set<pair<string, string> >::const_iterator it = children->begin();
1257 it != children->end(); ++it) {
1258 tracepoint(librbd, list_children_entry, it->first.c_str(), it->second.c_str());
1259 }
1260 }
1261 tracepoint(librbd, list_children_exit, r);
1262 return r;
1263 }
1264
1265 int Image::list_lockers(std::list<librbd::locker_t> *lockers,
1266 bool *exclusive, string *tag)
1267 {
1268 ImageCtx *ictx = (ImageCtx *)ctx;
1269 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1270 int r = librbd::list_lockers(ictx, lockers, exclusive, tag);
1271 if (r >= 0) {
1272 for (std::list<librbd::locker_t>::const_iterator it = lockers->begin();
1273 it != lockers->end(); ++it) {
1274 tracepoint(librbd, list_lockers_entry, it->client.c_str(), it->cookie.c_str(), it->address.c_str());
1275 }
1276 }
1277 tracepoint(librbd, list_lockers_exit, r);
1278 return r;
1279 }
1280
1281 int Image::lock_exclusive(const string& cookie)
1282 {
1283 ImageCtx *ictx = (ImageCtx *)ctx;
1284 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1285 int r = librbd::lock(ictx, true, cookie, "");
1286 tracepoint(librbd, lock_exclusive_exit, r);
1287 return r;
1288 }
1289
1290 int Image::lock_shared(const string& cookie, const std::string& tag)
1291 {
1292 ImageCtx *ictx = (ImageCtx *)ctx;
1293 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str(), tag.c_str());
1294 int r = librbd::lock(ictx, false, cookie, tag);
1295 tracepoint(librbd, lock_shared_exit, r);
1296 return r;
1297 }
1298
1299 int Image::unlock(const string& cookie)
1300 {
1301 ImageCtx *ictx = (ImageCtx *)ctx;
1302 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1303 int r = librbd::unlock(ictx, cookie);
1304 tracepoint(librbd, unlock_exit, r);
1305 return r;
1306 }
1307
1308 int Image::break_lock(const string& client, const string& cookie)
1309 {
1310 ImageCtx *ictx = (ImageCtx *)ctx;
1311 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client.c_str(), cookie.c_str());
1312 int r = librbd::break_lock(ictx, client, cookie);
1313 tracepoint(librbd, break_lock_exit, r);
1314 return r;
1315 }
1316
1317 int Image::snap_create(const char *snap_name)
1318 {
1319 ImageCtx *ictx = (ImageCtx *)ctx;
1320 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1321 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
1322 snap_name);
1323 tracepoint(librbd, snap_create_exit, r);
1324 return r;
1325 }
1326
1327 int Image::snap_remove(const char *snap_name)
1328 {
1329 ImageCtx *ictx = (ImageCtx *)ctx;
1330 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1331 librbd::NoOpProgressContext prog_ctx;
1332 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
1333 tracepoint(librbd, snap_remove_exit, r);
1334 return r;
1335 }
1336
1337 int Image::snap_remove2(const char *snap_name, uint32_t flags, ProgressContext& pctx)
1338 {
1339 ImageCtx *ictx = (ImageCtx *)ctx;
1340 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
1341 int r = librbd::snap_remove(ictx, snap_name, flags, pctx);
1342 tracepoint(librbd, snap_remove_exit, r);
1343 return r;
1344 }
1345
1346 int Image::snap_rollback(const char *snap_name)
1347 {
1348 ImageCtx *ictx = (ImageCtx *)ctx;
1349 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1350 librbd::NoOpProgressContext prog_ctx;
1351 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1352 tracepoint(librbd, snap_rollback_exit, r);
1353 return r;
1354 }
1355
1356 int Image::snap_rename(const char *srcname, const char *dstname)
1357 {
1358 ImageCtx *ictx = (ImageCtx *)ctx;
1359 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
1360 int r = ictx->operations->snap_rename(srcname, dstname);
1361 tracepoint(librbd, snap_rename_exit, r);
1362 return r;
1363 }
1364
1365 int Image::snap_rollback_with_progress(const char *snap_name,
1366 ProgressContext& prog_ctx)
1367 {
1368 ImageCtx *ictx = (ImageCtx *)ctx;
1369 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1370 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1371 tracepoint(librbd, snap_rollback_exit, r);
1372 return r;
1373 }
1374
1375 int Image::snap_protect(const char *snap_name)
1376 {
1377 ImageCtx *ictx = (ImageCtx *)ctx;
1378 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1379 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
1380 tracepoint(librbd, snap_protect_exit, r);
1381 return r;
1382 }
1383
1384 int Image::snap_unprotect(const char *snap_name)
1385 {
1386 ImageCtx *ictx = (ImageCtx *)ctx;
1387 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1388 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
1389 tracepoint(librbd, snap_unprotect_exit, r);
1390 return r;
1391 }
1392
1393 int Image::snap_is_protected(const char *snap_name, bool *is_protected)
1394 {
1395 ImageCtx *ictx = (ImageCtx *)ctx;
1396 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1397 int r = librbd::snap_is_protected(ictx, snap_name, is_protected);
1398 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
1399 return r;
1400 }
1401
1402 int Image::snap_list(vector<librbd::snap_info_t>& snaps)
1403 {
1404 ImageCtx *ictx = (ImageCtx *)ctx;
1405 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, &snaps);
1406 int r = librbd::snap_list(ictx, snaps);
1407 if (r >= 0) {
1408 for (int i = 0, n = snaps.size(); i < n; i++) {
1409 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name.c_str());
1410 }
1411 }
1412 tracepoint(librbd, snap_list_exit, r, snaps.size());
1413 if (r >= 0) {
1414 // A little ugly, but the C++ API doesn't need a Image::snap_list_end,
1415 // and we want the tracepoints to mirror the C API
1416 tracepoint(librbd, snap_list_end_enter, &snaps);
1417 tracepoint(librbd, snap_list_end_exit);
1418 }
1419 return r;
1420 }
1421
1422 bool Image::snap_exists(const char *snap_name)
1423 {
1424 ImageCtx *ictx = (ImageCtx *)ctx;
1425 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
1426 ictx->snap_name.c_str(), ictx->read_only, snap_name);
1427 bool exists;
1428 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, &exists);
1429 tracepoint(librbd, snap_exists_exit, r, exists);
1430 if (r < 0) {
1431 // lie to caller since we don't know the real answer yet.
1432 return false;
1433 }
1434 return exists;
1435 }
1436
1437 // A safer verion of snap_exists.
1438 int Image::snap_exists2(const char *snap_name, bool *exists)
1439 {
1440 ImageCtx *ictx = (ImageCtx *)ctx;
1441 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
1442 ictx->snap_name.c_str(), ictx->read_only, snap_name);
1443 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, exists);
1444 tracepoint(librbd, snap_exists_exit, r, *exists);
1445 return r;
1446 }
1447
1448 int Image::snap_get_timestamp(uint64_t snap_id, struct timespec *timestamp)
1449 {
1450 ImageCtx *ictx = (ImageCtx *)ctx;
1451 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
1452 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
1453 tracepoint(librbd, snap_get_timestamp_exit, r);
1454 return r;
1455 }
1456
1457 int Image::snap_get_limit(uint64_t *limit)
1458 {
1459 ImageCtx *ictx = (ImageCtx *)ctx;
1460 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
1461 int r = librbd::snap_get_limit(ictx, limit);
1462 tracepoint(librbd, snap_get_limit_exit, r, *limit);
1463 return r;
1464 }
1465
1466 int Image::snap_set_limit(uint64_t limit)
1467 {
1468 ImageCtx *ictx = (ImageCtx *)ctx;
1469
1470 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
1471 int r = ictx->operations->snap_set_limit(limit);
1472 tracepoint(librbd, snap_set_limit_exit, r);
1473 return r;
1474 }
1475
1476 int Image::snap_set(const char *snap_name)
1477 {
1478 ImageCtx *ictx = (ImageCtx *)ctx;
1479 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1480 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
1481 tracepoint(librbd, snap_set_exit, r);
1482 return r;
1483 }
1484
1485 ssize_t Image::read(uint64_t ofs, size_t len, bufferlist& bl)
1486 {
1487 ImageCtx *ictx = (ImageCtx *)ctx;
1488 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1489 bufferptr ptr(len);
1490 bl.push_back(std::move(ptr));
1491 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, 0);
1492 tracepoint(librbd, read_exit, r);
1493 return r;
1494 }
1495
1496 ssize_t Image::read2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1497 {
1498 ImageCtx *ictx = (ImageCtx *)ctx;
1499 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1500 ictx->read_only, ofs, len, op_flags);
1501 bufferptr ptr(len);
1502 bl.push_back(std::move(ptr));
1503 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, op_flags);
1504 tracepoint(librbd, read_exit, r);
1505 return r;
1506 }
1507
1508 int64_t Image::read_iterate(uint64_t ofs, size_t len,
1509 int (*cb)(uint64_t, size_t, const char *, void *),
1510 void *arg)
1511 {
1512 ImageCtx *ictx = (ImageCtx *)ctx;
1513 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1514 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
1515 tracepoint(librbd, read_iterate_exit, r);
1516 return r;
1517 }
1518
1519 int Image::read_iterate2(uint64_t ofs, uint64_t len,
1520 int (*cb)(uint64_t, size_t, const char *, void *),
1521 void *arg)
1522 {
1523 ImageCtx *ictx = (ImageCtx *)ctx;
1524 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1525 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
1526 if (r > 0)
1527 r = 0;
1528 tracepoint(librbd, read_iterate2_exit, r);
1529 return (int)r;
1530 }
1531
1532 int Image::diff_iterate(const char *fromsnapname,
1533 uint64_t ofs, uint64_t len,
1534 int (*cb)(uint64_t, size_t, int, void *),
1535 void *arg)
1536 {
1537 ImageCtx *ictx = (ImageCtx *)ctx;
1538 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
1539 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
1540 true, false);
1541 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
1542 cls::rbd::UserSnapshotNamespace(),
1543 fromsnapname, ofs,
1544 len, true, false, cb, arg);
1545 tracepoint(librbd, diff_iterate_exit, r);
1546 return r;
1547 }
1548
1549 int Image::diff_iterate2(const char *fromsnapname, uint64_t ofs, uint64_t len,
1550 bool include_parent, bool whole_object,
1551 int (*cb)(uint64_t, size_t, int, void *), void *arg)
1552 {
1553 ImageCtx *ictx = (ImageCtx *)ctx;
1554 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
1555 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
1556 include_parent, whole_object);
1557 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
1558 cls::rbd::UserSnapshotNamespace(),
1559 fromsnapname, ofs,
1560 len, include_parent,
1561 whole_object, cb, arg);
1562 tracepoint(librbd, diff_iterate_exit, r);
1563 return r;
1564 }
1565
1566 ssize_t Image::write(uint64_t ofs, size_t len, bufferlist& bl)
1567 {
1568 ImageCtx *ictx = (ImageCtx *)ctx;
1569 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());
1570 if (bl.length() < len) {
1571 tracepoint(librbd, write_exit, -EINVAL);
1572 return -EINVAL;
1573 }
1574 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, 0);
1575 tracepoint(librbd, write_exit, r);
1576 return r;
1577 }
1578
1579 ssize_t Image::write2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1580 {
1581 ImageCtx *ictx = (ImageCtx *)ctx;
1582 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only,
1583 ofs, len, bl.length() < len ? NULL : bl.c_str(), op_flags);
1584 if (bl.length() < len) {
1585 tracepoint(librbd, write_exit, -EINVAL);
1586 return -EINVAL;
1587 }
1588 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, op_flags);
1589 tracepoint(librbd, write_exit, r);
1590 return r;
1591 }
1592
1593 int Image::discard(uint64_t ofs, uint64_t len)
1594 {
1595 ImageCtx *ictx = (ImageCtx *)ctx;
1596 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1597 if (len > std::numeric_limits<int32_t>::max()) {
1598 tracepoint(librbd, discard_exit, -EINVAL);
1599 return -EINVAL;
1600 }
1601 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
1602 tracepoint(librbd, discard_exit, r);
1603 return r;
1604 }
1605
1606 ssize_t Image::writesame(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1607 {
1608 ImageCtx *ictx = (ImageCtx *)ctx;
1609 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1610 ictx->read_only, ofs, len, bl.length() <= 0 ? NULL : bl.c_str(), bl.length(),
1611 op_flags);
1612 if (bl.length() <= 0 || len % bl.length()) {
1613 tracepoint(librbd, writesame_exit, -EINVAL);
1614 return -EINVAL;
1615 }
1616
1617 if (mem_is_zero(bl.c_str(), bl.length())) {
1618 int r = ictx->io_work_queue->discard(ofs, len, false);
1619 tracepoint(librbd, writesame_exit, r);
1620 return r;
1621 }
1622
1623 int r = ictx->io_work_queue->writesame(ofs, len, bufferlist{bl}, op_flags);
1624 tracepoint(librbd, writesame_exit, r);
1625 return r;
1626 }
1627
1628 int Image::aio_write(uint64_t off, size_t len, bufferlist& bl,
1629 RBD::AioCompletion *c)
1630 {
1631 ImageCtx *ictx = (ImageCtx *)ctx;
1632 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);
1633 if (bl.length() < len) {
1634 tracepoint(librbd, aio_write_exit, -EINVAL);
1635 return -EINVAL;
1636 }
1637 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1638 bufferlist{bl}, 0);
1639 tracepoint(librbd, aio_write_exit, 0);
1640 return 0;
1641 }
1642
1643 int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
1644 RBD::AioCompletion *c, int op_flags)
1645 {
1646 ImageCtx *ictx = (ImageCtx *)ctx;
1647 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1648 ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1649 if (bl.length() < len) {
1650 tracepoint(librbd, aio_write_exit, -EINVAL);
1651 return -EINVAL;
1652 }
1653 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1654 bufferlist{bl}, op_flags);
1655 tracepoint(librbd, aio_write_exit, 0);
1656 return 0;
1657 }
1658
1659 int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
1660 {
1661 ImageCtx *ictx = (ImageCtx *)ctx;
1662 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
1663 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard);
1664 tracepoint(librbd, aio_discard_exit, 0);
1665 return 0;
1666 }
1667
1668 int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
1669 RBD::AioCompletion *c)
1670 {
1671 ImageCtx *ictx = (ImageCtx *)ctx;
1672 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);
1673 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1674 << (void *)(bl.c_str() + len - 1) << dendl;
1675 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1676 io::ReadResult{&bl}, 0);
1677 tracepoint(librbd, aio_read_exit, 0);
1678 return 0;
1679 }
1680
1681 int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
1682 RBD::AioCompletion *c, int op_flags)
1683 {
1684 ImageCtx *ictx = (ImageCtx *)ctx;
1685 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1686 ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
1687 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1688 << (void *)(bl.c_str() + len - 1) << dendl;
1689 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1690 io::ReadResult{&bl}, op_flags);
1691 tracepoint(librbd, aio_read_exit, 0);
1692 return 0;
1693 }
1694
1695 int Image::flush()
1696 {
1697 ImageCtx *ictx = (ImageCtx *)ctx;
1698 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1699 int r = librbd::flush(ictx);
1700 tracepoint(librbd, flush_exit, r);
1701 return r;
1702 }
1703
1704 int Image::aio_flush(RBD::AioCompletion *c)
1705 {
1706 ImageCtx *ictx = (ImageCtx *)ctx;
1707 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
1708 ictx->io_work_queue->aio_flush(get_aio_completion(c));
1709 tracepoint(librbd, aio_flush_exit, 0);
1710 return 0;
1711 }
1712
1713 int Image::aio_writesame(uint64_t off, size_t len, bufferlist& bl,
1714 RBD::AioCompletion *c, int op_flags)
1715 {
1716 ImageCtx *ictx = (ImageCtx *)ctx;
1717 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1718 ictx->read_only, off, len, bl.length() <= len ? NULL : bl.c_str(), bl.length(),
1719 c->pc, op_flags);
1720 if (bl.length() <= 0 || len % bl.length()) {
1721 tracepoint(librbd, aio_writesame_exit, -EINVAL);
1722 return -EINVAL;
1723 }
1724
1725 if (mem_is_zero(bl.c_str(), bl.length())) {
1726 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false);
1727 tracepoint(librbd, aio_writesame_exit, 0);
1728 return 0;
1729 }
1730
1731 ictx->io_work_queue->aio_writesame(get_aio_completion(c), off, len,
1732 bufferlist{bl}, op_flags);
1733 tracepoint(librbd, aio_writesame_exit, 0);
1734 return 0;
1735 }
1736
1737
1738 int Image::invalidate_cache()
1739 {
1740 ImageCtx *ictx = (ImageCtx *)ctx;
1741 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1742 int r = librbd::invalidate_cache(ictx);
1743 tracepoint(librbd, invalidate_cache_exit, r);
1744 return r;
1745 }
1746
1747 int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp)
1748 {
1749 io::AioCompletion *cs[numcomp];
1750 ImageCtx *ictx = (ImageCtx *)ctx;
1751 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
1752 int r = librbd::poll_io_events(ictx, cs, numcomp);
1753 tracepoint(librbd, poll_io_events_exit, r);
1754 if (r > 0) {
1755 for (int i = 0; i < numcomp; ++i)
1756 comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
1757 }
1758 return r;
1759 }
1760
1761 int Image::metadata_get(const std::string &key, std::string *value)
1762 {
1763 ImageCtx *ictx = (ImageCtx *)ctx;
1764 tracepoint(librbd, metadata_get_enter, ictx, key.c_str());
1765 int r = librbd::metadata_get(ictx, key, value);
1766 if (r < 0) {
1767 tracepoint(librbd, metadata_get_exit, r, key.c_str(), NULL);
1768 } else {
1769 tracepoint(librbd, metadata_get_exit, r, key.c_str(), value->c_str());
1770 }
1771 return r;
1772 }
1773
1774 int Image::metadata_set(const std::string &key, const std::string &value)
1775 {
1776 ImageCtx *ictx = (ImageCtx *)ctx;
1777 tracepoint(librbd, metadata_set_enter, ictx, key.c_str(), value.c_str());
1778 int r = ictx->operations->metadata_set(key, value);
1779 tracepoint(librbd, metadata_set_exit, r);
1780 return r;
1781 }
1782
1783 int Image::metadata_remove(const std::string &key)
1784 {
1785 ImageCtx *ictx = (ImageCtx *)ctx;
1786 tracepoint(librbd, metadata_remove_enter, ictx, key.c_str());
1787 int r = ictx->operations->metadata_remove(key);
1788 tracepoint(librbd, metadata_remove_exit, r);
1789 return r;
1790 }
1791
1792 int Image::metadata_list(const std::string &start, uint64_t max, map<string, bufferlist> *pairs)
1793 {
1794 ImageCtx *ictx = (ImageCtx *)ctx;
1795 tracepoint(librbd, metadata_list_enter, ictx);
1796 int r = librbd::metadata_list(ictx, start, max, pairs);
1797 if (r >= 0) {
1798 for (map<string, bufferlist>::iterator it = pairs->begin();
1799 it != pairs->end(); ++it) {
1800 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
1801 }
1802 }
1803 tracepoint(librbd, metadata_list_exit, r);
1804 return r;
1805 }
1806
1807 int Image::mirror_image_enable() {
1808 ImageCtx *ictx = (ImageCtx *)ctx;
1809 return librbd::api::Mirror<>::image_enable(ictx, false);
1810 }
1811
1812 int Image::mirror_image_disable(bool force) {
1813 ImageCtx *ictx = (ImageCtx *)ctx;
1814 return librbd::api::Mirror<>::image_disable(ictx, force);
1815 }
1816
1817 int Image::mirror_image_promote(bool force) {
1818 ImageCtx *ictx = (ImageCtx *)ctx;
1819 return librbd::api::Mirror<>::image_promote(ictx, force);
1820 }
1821
1822 int Image::mirror_image_demote() {
1823 ImageCtx *ictx = (ImageCtx *)ctx;
1824 return librbd::api::Mirror<>::image_demote(ictx);
1825 }
1826
1827 int Image::mirror_image_resync()
1828 {
1829 ImageCtx *ictx = (ImageCtx *)ctx;
1830 return librbd::api::Mirror<>::image_resync(ictx);
1831 }
1832
1833 int Image::mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1834 size_t info_size) {
1835 ImageCtx *ictx = (ImageCtx *)ctx;
1836 return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info,
1837 info_size);
1838 }
1839
1840 int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
1841 size_t status_size) {
1842 ImageCtx *ictx = (ImageCtx *)ctx;
1843 return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status,
1844 status_size);
1845 }
1846
1847 int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
1848 ImageCtx *ictx = (ImageCtx *)ctx;
1849 librbd::api::Mirror<>::image_promote(
1850 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1851 get_aio_completion(c)));
1852 return 0;
1853 }
1854
1855 int Image::aio_mirror_image_demote(RBD::AioCompletion *c) {
1856 ImageCtx *ictx = (ImageCtx *)ctx;
1857 librbd::api::Mirror<>::image_demote(
1858 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1859 get_aio_completion(c)));
1860 return 0;
1861 }
1862
1863 int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1864 size_t info_size,
1865 RBD::AioCompletion *c) {
1866 ImageCtx *ictx = (ImageCtx *)ctx;
1867 librbd::api::Mirror<>::image_get_info(
1868 ictx, mirror_image_info, info_size,
1869 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1870 get_aio_completion(c)));
1871 return 0;
1872 }
1873
1874 int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
1875 size_t status_size,
1876 RBD::AioCompletion *c) {
1877 ImageCtx *ictx = (ImageCtx *)ctx;
1878 librbd::api::Mirror<>::image_get_status(
1879 ictx, status, status_size,
1880 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1881 get_aio_completion(c)));
1882 return 0;
1883 }
1884
1885 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
1886 ImageCtx *ictx = (ImageCtx *)ctx;
1887 tracepoint(librbd, update_watch_enter, ictx, wctx);
1888 int r = ictx->state->register_update_watcher(wctx, handle);
1889 tracepoint(librbd, update_watch_exit, r, *handle);
1890 return r;
1891 }
1892
1893 int Image::update_unwatch(uint64_t handle) {
1894 ImageCtx *ictx = (ImageCtx *)ctx;
1895 tracepoint(librbd, update_unwatch_enter, ictx, handle);
1896 int r = ictx->state->unregister_update_watcher(handle);
1897 tracepoint(librbd, update_unwatch_exit, r);
1898 return r;
1899 }
1900
1901 } // namespace librbd
1902
1903 extern "C" void rbd_version(int *major, int *minor, int *extra)
1904 {
1905 if (major)
1906 *major = LIBRBD_VER_MAJOR;
1907 if (minor)
1908 *minor = LIBRBD_VER_MINOR;
1909 if (extra)
1910 *extra = LIBRBD_VER_EXTRA;
1911 }
1912
1913 extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
1914 {
1915 librbd::image_options_create(opts);
1916 }
1917
1918 extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
1919 {
1920 librbd::image_options_destroy(opts);
1921 }
1922
1923 extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
1924 const char* optval)
1925 {
1926 return librbd::image_options_set(opts, optname, optval);
1927 }
1928
1929 extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
1930 uint64_t optval)
1931 {
1932 return librbd::image_options_set(opts, optname, optval);
1933 }
1934
1935 extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
1936 char* optval, size_t maxlen)
1937 {
1938 std::string optval_;
1939
1940 int r = librbd::image_options_get(opts, optname, &optval_);
1941
1942 if (r < 0) {
1943 return r;
1944 }
1945
1946 if (optval_.size() >= maxlen) {
1947 return -E2BIG;
1948 }
1949
1950 strncpy(optval, optval_.c_str(), maxlen);
1951
1952 return 0;
1953 }
1954
1955 extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
1956 uint64_t* optval)
1957 {
1958 return librbd::image_options_get(opts, optname, optval);
1959 }
1960
1961 extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
1962 bool* is_set)
1963 {
1964 return librbd::image_options_is_set(opts, optname, is_set);
1965 }
1966
1967 extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
1968 {
1969 return librbd::image_options_unset(opts, optname);
1970 }
1971
1972 extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
1973 {
1974 librbd::image_options_clear(opts);
1975 }
1976
1977 extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
1978 {
1979 return librbd::image_options_is_empty(opts);
1980 }
1981
1982 /* pool mirroring */
1983 extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
1984 rbd_mirror_mode_t *mirror_mode) {
1985 librados::IoCtx io_ctx;
1986 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1987 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
1988 }
1989
1990 extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
1991 rbd_mirror_mode_t mirror_mode) {
1992 librados::IoCtx io_ctx;
1993 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1994 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
1995 }
1996
1997 extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
1998 size_t uuid_max_length,
1999 const char *cluster_name,
2000 const char *client_name) {
2001 static const std::size_t UUID_LENGTH = 36;
2002
2003 librados::IoCtx io_ctx;
2004 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2005
2006 if (uuid_max_length < UUID_LENGTH + 1) {
2007 return -E2BIG;
2008 }
2009
2010 std::string uuid_str;
2011 int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
2012 client_name);
2013 if (r >= 0) {
2014 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
2015 uuid[uuid_max_length - 1] = '\0';
2016 }
2017 return r;
2018 }
2019
2020 extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
2021 librados::IoCtx io_ctx;
2022 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2023 int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
2024 return r;
2025 }
2026
2027 extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
2028 rbd_mirror_peer_t *peers, int *max_peers) {
2029 librados::IoCtx io_ctx;
2030 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2031
2032 std::vector<librbd::mirror_peer_t> peer_vector;
2033 int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
2034 if (r < 0) {
2035 return r;
2036 }
2037
2038 if (*max_peers < static_cast<int>(peer_vector.size())) {
2039 *max_peers = static_cast<int>(peer_vector.size());
2040 return -ERANGE;
2041 }
2042
2043 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
2044 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
2045 peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
2046 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
2047 }
2048 *max_peers = static_cast<int>(peer_vector.size());
2049 return 0;
2050 }
2051
2052 extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
2053 int max_peers) {
2054 for (int i = 0; i < max_peers; ++i) {
2055 free(peers[i].uuid);
2056 free(peers[i].cluster_name);
2057 free(peers[i].client_name);
2058 }
2059 }
2060
2061 extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
2062 const char *client_name) {
2063 librados::IoCtx io_ctx;
2064 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2065 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
2066 }
2067
2068 extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
2069 const char *cluster_name) {
2070 librados::IoCtx io_ctx;
2071 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2072 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
2073 }
2074
2075 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
2076 const char *start_id, size_t max, char **image_ids,
2077 rbd_mirror_image_status_t *images, size_t *len) {
2078 librados::IoCtx io_ctx;
2079 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2080 std::map<std::string, librbd::mirror_image_status_t> cpp_images;
2081
2082 int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
2083 &cpp_images);
2084 if (r < 0) {
2085 return r;
2086 }
2087
2088 size_t i = 0;
2089 for (auto &it : cpp_images) {
2090 assert(i < max);
2091 const std::string &image_id = it.first;
2092 image_ids[i] = strdup(image_id.c_str());
2093 mirror_image_status_cpp_to_c(it.second, &images[i]);
2094 i++;
2095 }
2096 *len = i;
2097 return 0;
2098 }
2099
2100 extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
2101 rbd_mirror_image_status_t *images, size_t len) {
2102 for (size_t i = 0; i < len; i++) {
2103 free(image_ids[i]);
2104 free(images[i].name);
2105 free(images[i].info.global_id);
2106 free(images[i].description);
2107 }
2108 }
2109
2110 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
2111 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
2112
2113 librados::IoCtx io_ctx;
2114 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2115
2116 std::map<librbd::mirror_image_status_state_t, int> states_;
2117 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
2118 if (r < 0) {
2119 return r;
2120 }
2121
2122 size_t i = 0;
2123 for (auto &it : states_) {
2124 if (i == *maxlen) {
2125 return -ERANGE;
2126 }
2127 states[i] = it.first;
2128 counts[i] = it.second;
2129 i++;
2130 }
2131 *maxlen = i;
2132 return 0;
2133 }
2134
2135 /* images */
2136 extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
2137 {
2138 librados::IoCtx io_ctx;
2139 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2140 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2141 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2142 vector<string> cpp_names;
2143 int r = librbd::list(io_ctx, cpp_names);
2144 if (r == -ENOENT) {
2145 tracepoint(librbd, list_exit, 0, *size);
2146 return 0;
2147 }
2148
2149 if (r < 0) {
2150 tracepoint(librbd, list_exit, r, *size);
2151 return r;
2152 }
2153
2154 size_t expected_size = 0;
2155
2156 for (size_t i = 0; i < cpp_names.size(); i++) {
2157 expected_size += cpp_names[i].size() + 1;
2158 }
2159 if (*size < expected_size) {
2160 *size = expected_size;
2161 tracepoint(librbd, list_exit, -ERANGE, *size);
2162 return -ERANGE;
2163 }
2164
2165 if (!names)
2166 return -EINVAL;
2167
2168 for (int i = 0; i < (int)cpp_names.size(); i++) {
2169 const char* name = cpp_names[i].c_str();
2170 tracepoint(librbd, list_entry, name);
2171 strcpy(names, name);
2172 names += strlen(names) + 1;
2173 }
2174 tracepoint(librbd, list_exit, (int)expected_size, *size);
2175 return (int)expected_size;
2176 }
2177
2178 extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
2179 {
2180 librados::IoCtx io_ctx;
2181 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2182 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2183 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
2184 int r = librbd::create(io_ctx, name, size, order);
2185 tracepoint(librbd, create_exit, r, *order);
2186 return r;
2187 }
2188
2189 extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
2190 uint64_t size, uint64_t features,
2191 int *order)
2192 {
2193 librados::IoCtx io_ctx;
2194 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2195 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2196 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
2197 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
2198 tracepoint(librbd, create2_exit, r, *order);
2199 return r;
2200 }
2201
2202 extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
2203 uint64_t size, uint64_t features,
2204 int *order,
2205 uint64_t stripe_unit, uint64_t stripe_count)
2206 {
2207 librados::IoCtx io_ctx;
2208 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2209 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2210 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
2211 int r = librbd::create(io_ctx, name, size, false, features, order,
2212 stripe_unit, stripe_count);
2213 tracepoint(librbd, create3_exit, r, *order);
2214 return r;
2215 }
2216
2217 extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
2218 uint64_t size, rbd_image_options_t opts)
2219 {
2220 librados::IoCtx io_ctx;
2221 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2222 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2223 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
2224 librbd::ImageOptions opts_(opts);
2225 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
2226 tracepoint(librbd, create4_exit, r);
2227 return r;
2228 }
2229
2230 extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
2231 const char *p_snap_name, rados_ioctx_t c_ioctx,
2232 const char *c_name, uint64_t features, int *c_order)
2233 {
2234 librados::IoCtx p_ioc, c_ioc;
2235 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2236 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2237 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2238 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);
2239 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2240 features, c_order, 0, 0);
2241 tracepoint(librbd, clone_exit, r, *c_order);
2242 return r;
2243 }
2244
2245 extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
2246 const char *p_snap_name, rados_ioctx_t c_ioctx,
2247 const char *c_name, uint64_t features, int *c_order,
2248 uint64_t stripe_unit, int stripe_count)
2249 {
2250 librados::IoCtx p_ioc, c_ioc;
2251 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2252 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2253 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2254 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);
2255 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2256 features, c_order, stripe_unit, stripe_count);
2257 tracepoint(librbd, clone2_exit, r, *c_order);
2258 return r;
2259 }
2260
2261 extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
2262 const char *p_snap_name, rados_ioctx_t c_ioctx,
2263 const char *c_name, rbd_image_options_t c_opts)
2264 {
2265 librados::IoCtx p_ioc, c_ioc;
2266 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2267 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2268 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2269 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);
2270 librbd::ImageOptions c_opts_(c_opts);
2271 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_);
2272 tracepoint(librbd, clone3_exit, r);
2273 return r;
2274 }
2275
2276 extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
2277 {
2278 librados::IoCtx io_ctx;
2279 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2280 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2281 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2282 librbd::NoOpProgressContext prog_ctx;
2283 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2284 tracepoint(librbd, remove_exit, r);
2285 return r;
2286 }
2287
2288 extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
2289 librbd_progress_fn_t cb, void *cbdata)
2290 {
2291 librados::IoCtx io_ctx;
2292 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2293 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2294 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2295 librbd::CProgressContext prog_ctx(cb, cbdata);
2296 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2297 tracepoint(librbd, remove_exit, r);
2298 return r;
2299 }
2300
2301 extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
2302 uint64_t delay) {
2303 librados::IoCtx io_ctx;
2304 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2305 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2306 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
2307 io_ctx.get_id(), name);
2308 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, delay);
2309 tracepoint(librbd, trash_move_exit, r);
2310 return r;
2311 }
2312
2313 extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
2314 rbd_trash_image_info_t *info) {
2315 librados::IoCtx io_ctx;
2316 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
2317
2318 librbd::trash_image_info_t cpp_info;
2319 int r = librbd::trash_get(io_ctx, id, &cpp_info);
2320 if (r < 0) {
2321 return r;
2322 }
2323
2324 trash_image_info_cpp_to_c(cpp_info, info);
2325 return 0;
2326 }
2327
2328 extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
2329 free(info->id);
2330 free(info->name);
2331 }
2332
2333 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
2334 size_t *num_entries) {
2335 librados::IoCtx io_ctx;
2336 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2337 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2338 tracepoint(librbd, trash_list_enter,
2339 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2340
2341 vector<librbd::trash_image_info_t> cpp_entries;
2342 int r = librbd::trash_list(io_ctx, cpp_entries);
2343 if (r < 0) {
2344 tracepoint(librbd, trash_list_exit, r, *num_entries);
2345 return r;
2346 }
2347
2348 if (*num_entries < cpp_entries.size()) {
2349 *num_entries = cpp_entries.size();
2350 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
2351 return -ERANGE;
2352 }
2353
2354 int i=0;
2355 for (const auto &entry : cpp_entries) {
2356 trash_image_info_cpp_to_c(entry, &entries[i++]);
2357 }
2358 *num_entries = cpp_entries.size();
2359
2360 return *num_entries;
2361 }
2362
2363 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
2364 size_t num_entries) {
2365 for (size_t i=0; i < num_entries; i++) {
2366 rbd_trash_get_cleanup(&entries[i]);
2367 }
2368 }
2369
2370 extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
2371 bool force) {
2372 librados::IoCtx io_ctx;
2373 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2374 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2375 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2376 io_ctx.get_id(), image_id, force);
2377 librbd::NoOpProgressContext prog_ctx;
2378 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2379 tracepoint(librbd, trash_remove_exit, r);
2380 return r;
2381 }
2382
2383 extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
2384 const char *image_id,
2385 bool force,
2386 librbd_progress_fn_t cb,
2387 void *cbdata) {
2388 librados::IoCtx io_ctx;
2389 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2390 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2391 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2392 io_ctx.get_id(), image_id, force);
2393 librbd::CProgressContext prog_ctx(cb, cbdata);
2394 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2395 tracepoint(librbd, trash_remove_exit, r);
2396 return r;
2397 }
2398
2399 extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
2400 const char *name) {
2401 librados::IoCtx io_ctx;
2402 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2403 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2404 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
2405 io_ctx.get_id(), id, name);
2406 int r = librbd::trash_restore(io_ctx, id, name);
2407 tracepoint(librbd, trash_undelete_exit, r);
2408 return r;
2409 }
2410
2411 extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
2412 const char *destname)
2413 {
2414 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2415 librados::IoCtx dest_io_ctx;
2416 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2417 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);
2418 librbd::ImageOptions opts;
2419 librbd::NoOpProgressContext prog_ctx;
2420 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2421 tracepoint(librbd, copy_exit, r);
2422 return r;
2423 }
2424
2425 extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
2426 {
2427 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2428 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2429 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);
2430 librbd::NoOpProgressContext prog_ctx;
2431 int r = librbd::copy(src, dest, prog_ctx, 0);
2432 tracepoint(librbd, copy2_exit, r);
2433 return r;
2434 }
2435
2436 extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
2437 const char *destname, rbd_image_options_t c_opts)
2438 {
2439 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2440 librados::IoCtx dest_io_ctx;
2441 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2442 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);
2443 librbd::ImageOptions c_opts_(c_opts);
2444 librbd::NoOpProgressContext prog_ctx;
2445 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
2446 tracepoint(librbd, copy3_exit, r);
2447 return r;
2448 }
2449
2450 extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
2451 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
2452 {
2453 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2454 librados::IoCtx dest_io_ctx;
2455 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2456 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);
2457 librbd::ImageOptions c_opts_(c_opts);
2458 librbd::NoOpProgressContext prog_ctx;
2459 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
2460 tracepoint(librbd, copy4_exit, r);
2461 return r;
2462 }
2463
2464 extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
2465 const char *destname,
2466 librbd_progress_fn_t fn, void *data)
2467 {
2468 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2469 librados::IoCtx dest_io_ctx;
2470 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2471 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);
2472 librbd::ImageOptions opts;
2473 librbd::CProgressContext prog_ctx(fn, data);
2474 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2475 tracepoint(librbd, copy_exit, ret);
2476 return ret;
2477 }
2478
2479 extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
2480 librbd_progress_fn_t fn, void *data)
2481 {
2482 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2483 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2484 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);
2485 librbd::CProgressContext prog_ctx(fn, data);
2486 int ret = librbd::copy(src, dest, prog_ctx, 0);
2487 tracepoint(librbd, copy2_exit, ret);
2488 return ret;
2489 }
2490
2491 extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
2492 const char *destname,
2493 rbd_image_options_t dest_opts,
2494 librbd_progress_fn_t fn, void *data)
2495 {
2496 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2497 librados::IoCtx dest_io_ctx;
2498 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2499 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);
2500 librbd::ImageOptions dest_opts_(dest_opts);
2501 librbd::CProgressContext prog_ctx(fn, data);
2502 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
2503 tracepoint(librbd, copy3_exit, ret);
2504 return ret;
2505 }
2506
2507 extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
2508 const char *destname,
2509 rbd_image_options_t dest_opts,
2510 librbd_progress_fn_t fn, void *data, size_t sparse_size)
2511 {
2512 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2513 librados::IoCtx dest_io_ctx;
2514 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2515 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);
2516 librbd::ImageOptions dest_opts_(dest_opts);
2517 librbd::CProgressContext prog_ctx(fn, data);
2518 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
2519 tracepoint(librbd, copy4_exit, ret);
2520 return ret;
2521 }
2522
2523
2524 extern "C" int rbd_flatten(rbd_image_t image)
2525 {
2526 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2527 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2528 librbd::NoOpProgressContext prog_ctx;
2529 int r = ictx->operations->flatten(prog_ctx);
2530 tracepoint(librbd, flatten_exit, r);
2531 return r;
2532 }
2533
2534 extern "C" int rbd_flatten_with_progress(rbd_image_t image,
2535 librbd_progress_fn_t cb, void *cbdata)
2536 {
2537 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2538 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2539 librbd::CProgressContext prog_ctx(cb, cbdata);
2540 int r = ictx->operations->flatten(prog_ctx);
2541 tracepoint(librbd, flatten_exit, r);
2542 return r;
2543 }
2544
2545 extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
2546 const char *destname)
2547 {
2548 librados::IoCtx src_io_ctx;
2549 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
2550 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
2551 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
2552 int r = librbd::rename(src_io_ctx, srcname, destname);
2553 tracepoint(librbd, rename_exit, r);
2554 return r;
2555 }
2556
2557 extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
2558 const char *snap_name)
2559 {
2560 librados::IoCtx io_ctx;
2561 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2562 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2563 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2564 false);
2565 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2566
2567 int r = ictx->state->open(false);
2568 if (r >= 0) {
2569 *image = (rbd_image_t)ictx;
2570 }
2571 tracepoint(librbd, open_image_exit, r);
2572 return r;
2573 }
2574
2575 extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
2576 rbd_image_t *image, const char *snap_name)
2577 {
2578 librados::IoCtx io_ctx;
2579 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2580 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2581 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2582 false);
2583 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2584 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2585
2586 int r = ictx->state->open(false);
2587 if (r < 0) {
2588 delete ictx;
2589 } else {
2590 *image = (rbd_image_t)ictx;
2591 }
2592 tracepoint(librbd, open_image_exit, r);
2593 return r;
2594 }
2595
2596 extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
2597 rbd_image_t *image, const char *snap_name,
2598 rbd_completion_t c)
2599 {
2600 librados::IoCtx io_ctx;
2601 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2602 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2603 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2604 false);
2605 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2606 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);
2607 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2608 tracepoint(librbd, aio_open_image_exit, 0);
2609 return 0;
2610 }
2611
2612 extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
2613 rbd_image_t *image, const char *snap_name,
2614 rbd_completion_t c)
2615 {
2616 librados::IoCtx io_ctx;
2617 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2618 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2619 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2620 false);
2621 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2622 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2623 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
2624 comp->pc);
2625 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2626 tracepoint(librbd, aio_open_image_exit, 0);
2627 return 0;
2628 }
2629
2630 extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
2631 rbd_image_t *image, const char *snap_name)
2632 {
2633 librados::IoCtx io_ctx;
2634 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2635 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2636 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2637 true);
2638 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2639
2640 int r = ictx->state->open(false);
2641 if (r >= 0) {
2642 *image = (rbd_image_t)ictx;
2643 }
2644 tracepoint(librbd, open_image_exit, r);
2645 return r;
2646 }
2647
2648 extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
2649 rbd_image_t *image, const char *snap_name)
2650 {
2651 librados::IoCtx io_ctx;
2652 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2653 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2654 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2655 true);
2656 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2657 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2658
2659 int r = ictx->state->open(false);
2660 if (r < 0) {
2661 delete ictx;
2662 } else {
2663 *image = (rbd_image_t)ictx;
2664 }
2665 tracepoint(librbd, open_image_exit, r);
2666 return r;
2667 }
2668
2669 extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
2670 rbd_image_t *image, const char *snap_name,
2671 rbd_completion_t c)
2672 {
2673 librados::IoCtx io_ctx;
2674 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2675 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2676 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2677 true);
2678 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2679 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);
2680 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2681 image));
2682 tracepoint(librbd, aio_open_image_exit, 0);
2683 return 0;
2684 }
2685
2686 extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
2687 rbd_image_t *image,
2688 const char *snap_name,
2689 rbd_completion_t c)
2690 {
2691 librados::IoCtx io_ctx;
2692 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2693 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2694 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2695 true);
2696 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2697 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2698 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2699 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2700 image));
2701 tracepoint(librbd, aio_open_image_exit, 0);
2702 return 0;
2703 }
2704
2705 extern "C" int rbd_close(rbd_image_t image)
2706 {
2707 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2708 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2709
2710 int r = ictx->state->close();
2711
2712 tracepoint(librbd, close_image_exit, r);
2713 return r;
2714 }
2715
2716 extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
2717 {
2718 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2719 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2720 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
2721 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
2722 get_aio_completion(comp)));
2723 tracepoint(librbd, aio_close_image_exit, 0);
2724 return 0;
2725 }
2726
2727 extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
2728 {
2729 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2730 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2731 librbd::NoOpProgressContext prog_ctx;
2732 int r = ictx->operations->resize(size, true, prog_ctx);
2733 tracepoint(librbd, resize_exit, r);
2734 return r;
2735 }
2736
2737 extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
2738 librbd_progress_fn_t cb, void *cbdata)
2739 {
2740 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2741 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2742 librbd::CProgressContext prog_ctx(cb, cbdata);
2743 int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
2744 tracepoint(librbd, resize_exit, r);
2745 return r;
2746 }
2747
2748 extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
2749 librbd_progress_fn_t cb, void *cbdata)
2750 {
2751 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2752 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2753 librbd::CProgressContext prog_ctx(cb, cbdata);
2754 int r = ictx->operations->resize(size, true, prog_ctx);
2755 tracepoint(librbd, resize_exit, r);
2756 return r;
2757 }
2758
2759 extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
2760 size_t infosize)
2761 {
2762 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2763 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2764 int r = librbd::info(ictx, *info, infosize);
2765 tracepoint(librbd, stat_exit, r, info);
2766 return r;
2767 }
2768
2769 extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
2770 {
2771 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2772 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2773 int r = librbd::get_old_format(ictx, old);
2774 tracepoint(librbd, get_old_format_exit, r, *old);
2775 return r;
2776 }
2777
2778 extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
2779 {
2780 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2781 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2782 int r = librbd::get_size(ictx, size);
2783 tracepoint(librbd, get_size_exit, r, *size);
2784 return r;
2785 }
2786
2787 extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
2788 {
2789 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2790 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2791 int r = librbd::get_features(ictx, features);
2792 tracepoint(librbd, get_features_exit, r, *features);
2793 return r;
2794 }
2795
2796 extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
2797 uint8_t enabled)
2798 {
2799 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2800 bool features_enabled = enabled != 0;
2801 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
2802 int r = ictx->operations->update_features(features, features_enabled);
2803 tracepoint(librbd, update_features_exit, r);
2804 return r;
2805 }
2806
2807 extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
2808 {
2809 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2810 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2811 *stripe_unit = ictx->get_stripe_unit();
2812 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
2813 return 0;
2814 }
2815
2816 extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
2817 {
2818 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2819 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2820 *stripe_count = ictx->get_stripe_count();
2821 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
2822 return 0;
2823 }
2824
2825 extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
2826 {
2827 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2828 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2829 int r = librbd::get_overlap(ictx, overlap);
2830 tracepoint(librbd, get_overlap_exit, r, *overlap);
2831 return r;
2832 }
2833
2834 extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
2835 {
2836 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2837 if (ictx->old_format) {
2838 return -EINVAL;
2839 }
2840 if (ictx->id.size() >= id_len) {
2841 return -ERANGE;
2842 }
2843
2844 strncpy(id, ictx->id.c_str(), id_len - 1);
2845 id[id_len - 1] = '\0';
2846 return 0;
2847 }
2848
2849 extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
2850 size_t prefix_len)
2851 {
2852 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2853 if (ictx->object_prefix.size() >= prefix_len) {
2854 return -ERANGE;
2855 }
2856
2857 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
2858 prefix[prefix_len - 1] = '\0';
2859 return 0;
2860 }
2861
2862 extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
2863 {
2864 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2865 return ictx->data_ctx.get_id();
2866 }
2867
2868 extern "C" int rbd_get_parent_info(rbd_image_t image,
2869 char *parent_pool_name, size_t ppool_namelen,
2870 char *parent_name, size_t pnamelen,
2871 char *parent_snap_name, size_t psnap_namelen)
2872 {
2873 return rbd_get_parent_info2(image, parent_pool_name, ppool_namelen,
2874 parent_name, pnamelen, nullptr, 0,
2875 parent_snap_name, psnap_namelen);
2876 }
2877
2878 extern "C" int rbd_get_parent_info2(rbd_image_t image,
2879 char *parent_pool_name,
2880 size_t ppool_namelen,
2881 char *parent_name, size_t pnamelen,
2882 char *parent_id, size_t pidlen,
2883 char *parent_snap_name,
2884 size_t psnap_namelen)
2885 {
2886 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2887 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
2888 ictx->snap_name.c_str(), ictx->read_only);
2889 string p_pool_name, p_name, p_id, p_snap_name;
2890
2891 int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_id,
2892 &p_snap_name);
2893 if (r < 0) {
2894 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
2895 return r;
2896 }
2897
2898 if (parent_pool_name) {
2899 if (p_pool_name.length() + 1 > ppool_namelen) {
2900 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2901 return -ERANGE;
2902 }
2903
2904 strcpy(parent_pool_name, p_pool_name.c_str());
2905 }
2906 if (parent_name) {
2907 if (p_name.length() + 1 > pnamelen) {
2908 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2909 return -ERANGE;
2910 }
2911
2912 strcpy(parent_name, p_name.c_str());
2913 }
2914 if (parent_id) {
2915 if (p_id.length() + 1 > pidlen) {
2916 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2917 return -ERANGE;
2918 }
2919
2920 strcpy(parent_id, p_id.c_str());
2921 }
2922 if (parent_snap_name) {
2923 if (p_snap_name.length() + 1 > psnap_namelen) {
2924 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2925 return -ERANGE;
2926 }
2927
2928 strcpy(parent_snap_name, p_snap_name.c_str());
2929 }
2930
2931 tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name,
2932 parent_id, parent_snap_name);
2933 return 0;
2934 }
2935
2936 extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
2937 {
2938 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2939 tracepoint(librbd, get_flags_enter, ictx);
2940 int r = librbd::get_flags(ictx, flags);
2941 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
2942 return r;
2943 }
2944
2945 extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
2946 {
2947 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2948 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
2949 int r = librbd::set_image_notification(ictx, fd, type);
2950 tracepoint(librbd, set_image_notification_exit, ictx, r);
2951 return r;
2952 }
2953
2954 extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
2955 {
2956 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2957 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
2958 bool owner;
2959 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
2960 *is_owner = owner ? 1 : 0;
2961 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
2962 return r;
2963 }
2964
2965 extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
2966 {
2967 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2968 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
2969 int r = librbd::lock_acquire(ictx, lock_mode);
2970 tracepoint(librbd, lock_acquire_exit, ictx, r);
2971 return r;
2972 }
2973
2974 extern "C" int rbd_lock_release(rbd_image_t image)
2975 {
2976 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2977 tracepoint(librbd, lock_release_enter, ictx);
2978 int r = librbd::lock_release(ictx);
2979 tracepoint(librbd, lock_release_exit, ictx, r);
2980 return r;
2981 }
2982
2983 extern "C" int rbd_lock_get_owners(rbd_image_t image,
2984 rbd_lock_mode_t *lock_mode,
2985 char **lock_owners,
2986 size_t *max_lock_owners)
2987 {
2988 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
2989 tracepoint(librbd, lock_get_owners_enter, ictx);
2990 std::list<std::string> lock_owner_list;
2991 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
2992 if (r >= 0) {
2993 if (*max_lock_owners >= lock_owner_list.size()) {
2994 *max_lock_owners = 0;
2995 for (auto &lock_owner : lock_owner_list) {
2996 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
2997 }
2998 } else {
2999 *max_lock_owners = lock_owner_list.size();
3000 r = -ERANGE;
3001 }
3002 }
3003 tracepoint(librbd, lock_get_owners_exit, ictx, r);
3004 return r;
3005 }
3006
3007 extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
3008 size_t lock_owner_count)
3009 {
3010 for (size_t i = 0; i < lock_owner_count; ++i) {
3011 free(lock_owners[i]);
3012 }
3013 }
3014
3015 extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
3016 const char *lock_owner)
3017 {
3018 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3019 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
3020 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
3021 tracepoint(librbd, lock_break_exit, ictx, r);
3022 return r;
3023 }
3024
3025 extern "C" int rbd_rebuild_object_map(rbd_image_t image,
3026 librbd_progress_fn_t cb, void *cbdata)
3027 {
3028 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3029 librbd::CProgressContext prog_ctx(cb, cbdata);
3030 return ictx->operations->rebuild_object_map(prog_ctx);
3031 }
3032
3033 /* snapshots */
3034 extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
3035 {
3036 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3037 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3038 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
3039 snap_name);
3040 tracepoint(librbd, snap_create_exit, r);
3041 return r;
3042 }
3043
3044 extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
3045 {
3046 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3047 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
3048 int r = ictx->operations->snap_rename(srcname, dstname);
3049 tracepoint(librbd, snap_rename_exit, r);
3050 return r;
3051 }
3052
3053 extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
3054 {
3055 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3056 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3057 librbd::NoOpProgressContext prog_ctx;
3058 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
3059 tracepoint(librbd, snap_remove_exit, r);
3060 return r;
3061 }
3062
3063 extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
3064 librbd_progress_fn_t cb, void *cbdata)
3065 {
3066 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3067 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
3068 librbd::CProgressContext prog_ctx(cb, cbdata);
3069 int r = librbd::snap_remove(ictx, snap_name, flags, prog_ctx);
3070 tracepoint(librbd, snap_remove_exit, r);
3071 return r;
3072 }
3073
3074 extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
3075 {
3076 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3077 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3078 librbd::NoOpProgressContext prog_ctx;
3079 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3080 tracepoint(librbd, snap_rollback_exit, r);
3081 return r;
3082 }
3083
3084 extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
3085 const char *snap_name,
3086 librbd_progress_fn_t cb,
3087 void *cbdata)
3088 {
3089 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3090 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3091 librbd::CProgressContext prog_ctx(cb, cbdata);
3092 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3093 tracepoint(librbd, snap_rollback_exit, r);
3094 return r;
3095 }
3096
3097 extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
3098 int *max_snaps)
3099 {
3100 vector<librbd::snap_info_t> cpp_snaps;
3101 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3102 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
3103
3104 if (!max_snaps) {
3105 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
3106 return -EINVAL;
3107 }
3108
3109 int r = librbd::snap_list(ictx, cpp_snaps);
3110 if (r == -ENOENT) {
3111 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
3112 return 0;
3113 }
3114 if (r < 0) {
3115 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3116 return r;
3117 }
3118 if (*max_snaps < (int)cpp_snaps.size() + 1) {
3119 *max_snaps = (int)cpp_snaps.size() + 1;
3120 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
3121 return -ERANGE;
3122 }
3123
3124 int i;
3125
3126 for (i = 0; i < (int)cpp_snaps.size(); i++) {
3127 snaps[i].id = cpp_snaps[i].id;
3128 snaps[i].size = cpp_snaps[i].size;
3129 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
3130 if (!snaps[i].name) {
3131 for (int j = 0; j < i; j++)
3132 free((void *)snaps[j].name);
3133 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
3134 return -ENOMEM;
3135 }
3136 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
3137 }
3138 snaps[i].id = 0;
3139 snaps[i].size = 0;
3140 snaps[i].name = NULL;
3141
3142 r = (int)cpp_snaps.size();
3143 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3144 return r;
3145 }
3146
3147 extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
3148 {
3149 tracepoint(librbd, snap_list_end_enter, snaps);
3150 while (snaps->name) {
3151 free((void *)snaps->name);
3152 snaps++;
3153 }
3154 tracepoint(librbd, snap_list_end_exit);
3155 }
3156
3157 extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
3158 {
3159 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3160 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3161 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
3162 tracepoint(librbd, snap_protect_exit, r);
3163 return r;
3164 }
3165
3166 extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
3167 {
3168 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3169 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3170 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
3171 tracepoint(librbd, snap_unprotect_exit, r);
3172 return r;
3173 }
3174
3175 extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
3176 int *is_protected)
3177 {
3178 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3179 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3180 bool protected_snap;
3181 int r = librbd::snap_is_protected(ictx, snap_name, &protected_snap);
3182 if (r < 0) {
3183 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
3184 return r;
3185 }
3186 *is_protected = protected_snap ? 1 : 0;
3187 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
3188 return 0;
3189 }
3190
3191 extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
3192 {
3193 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3194 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
3195 int r = librbd::snap_get_limit(ictx, limit);
3196 tracepoint(librbd, snap_get_limit_exit, r, *limit);
3197 return r;
3198 }
3199
3200 extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
3201 {
3202 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3203 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
3204 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
3205 tracepoint(librbd, snap_get_timestamp_exit, r);
3206 return r;
3207 }
3208
3209 extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
3210 {
3211 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3212 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
3213 int r = librbd::snap_set_limit(ictx, limit);
3214 tracepoint(librbd, snap_set_limit_exit, r);
3215 return r;
3216 }
3217
3218 extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
3219 {
3220 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3221 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3222 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
3223 tracepoint(librbd, snap_set_exit, r);
3224 return r;
3225 }
3226
3227 extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
3228 size_t *pools_len, char *images,
3229 size_t *images_len)
3230 {
3231 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3232 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3233 set<pair<string, string> > image_set;
3234
3235 int r = librbd::list_children(ictx, image_set);
3236 if (r < 0) {
3237 tracepoint(librbd, list_children_exit, r);
3238 return r;
3239 }
3240
3241 size_t pools_total = 0;
3242 size_t images_total = 0;
3243 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3244 it != image_set.end(); ++it) {
3245 pools_total += it->first.length() + 1;
3246 images_total += it->second.length() + 1;
3247 }
3248
3249 bool too_short = false;
3250 if (pools_total > *pools_len)
3251 too_short = true;
3252 if (images_total > *images_len)
3253 too_short = true;
3254 *pools_len = pools_total;
3255 *images_len = images_total;
3256 if (too_short) {
3257 tracepoint(librbd, list_children_exit, -ERANGE);
3258 return -ERANGE;
3259 }
3260
3261 char *pools_p = pools;
3262 char *images_p = images;
3263 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3264 it != image_set.end(); ++it) {
3265 const char* pool = it->first.c_str();
3266 strcpy(pools_p, pool);
3267 pools_p += it->first.length() + 1;
3268 const char* image = it->second.c_str();
3269 strcpy(images_p, image);
3270 images_p += it->second.length() + 1;
3271 tracepoint(librbd, list_children_entry, pool, image);
3272 }
3273
3274 ssize_t ret = image_set.size();
3275 tracepoint(librbd, list_children_exit, ret);
3276 return ret;
3277 }
3278
3279 extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
3280 char *tag, size_t *tag_len,
3281 char *clients, size_t *clients_len,
3282 char *cookies, size_t *cookies_len,
3283 char *addrs, size_t *addrs_len)
3284 {
3285 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3286 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3287 std::list<librbd::locker_t> lockers;
3288 bool exclusive_bool;
3289 string tag_str;
3290
3291 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
3292 if (r < 0) {
3293 tracepoint(librbd, list_lockers_exit, r);
3294 return r;
3295 }
3296
3297 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
3298
3299 *exclusive = (int)exclusive_bool;
3300 size_t clients_total = 0;
3301 size_t cookies_total = 0;
3302 size_t addrs_total = 0;
3303 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3304 it != lockers.end(); ++it) {
3305 clients_total += it->client.length() + 1;
3306 cookies_total += it->cookie.length() + 1;
3307 addrs_total += it->address.length() + 1;
3308 }
3309
3310 bool too_short = ((clients_total > *clients_len) ||
3311 (cookies_total > *cookies_len) ||
3312 (addrs_total > *addrs_len) ||
3313 (tag_str.length() + 1 > *tag_len));
3314 *clients_len = clients_total;
3315 *cookies_len = cookies_total;
3316 *addrs_len = addrs_total;
3317 *tag_len = tag_str.length() + 1;
3318 if (too_short) {
3319 tracepoint(librbd, list_lockers_exit, -ERANGE);
3320 return -ERANGE;
3321 }
3322
3323 strcpy(tag, tag_str.c_str());
3324 char *clients_p = clients;
3325 char *cookies_p = cookies;
3326 char *addrs_p = addrs;
3327 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3328 it != lockers.end(); ++it) {
3329 const char* client = it->client.c_str();
3330 strcpy(clients_p, client);
3331 clients_p += it->client.length() + 1;
3332 const char* cookie = it->cookie.c_str();
3333 strcpy(cookies_p, cookie);
3334 cookies_p += it->cookie.length() + 1;
3335 const char* address = it->address.c_str();
3336 strcpy(addrs_p, address);
3337 addrs_p += it->address.length() + 1;
3338 tracepoint(librbd, list_lockers_entry, client, cookie, address);
3339 }
3340
3341 ssize_t ret = lockers.size();
3342 tracepoint(librbd, list_lockers_exit, ret);
3343 return ret;
3344 }
3345
3346 extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
3347 {
3348 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3349 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3350 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
3351 tracepoint(librbd, lock_exclusive_exit, r);
3352 return r;
3353 }
3354
3355 extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
3356 const char *tag)
3357 {
3358 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3359 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
3360 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
3361 tracepoint(librbd, lock_shared_exit, r);
3362 return r;
3363 }
3364
3365 extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
3366 {
3367 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3368 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3369 int r = librbd::unlock(ictx, cookie ? cookie : "");
3370 tracepoint(librbd, unlock_exit, r);
3371 return r;
3372 }
3373
3374 extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
3375 const char *cookie)
3376 {
3377 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3378 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
3379 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
3380 tracepoint(librbd, break_lock_exit, r);
3381 return r;
3382 }
3383
3384 /* I/O */
3385 extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
3386 char *buf)
3387 {
3388 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3389 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3390 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3391 0);
3392 tracepoint(librbd, read_exit, r);
3393 return r;
3394 }
3395
3396 extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
3397 char *buf, int op_flags)
3398 {
3399 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3400 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
3401 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
3402 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3403 op_flags);
3404 tracepoint(librbd, read_exit, r);
3405 return r;
3406 }
3407
3408
3409 extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_t len,
3410 int (*cb)(uint64_t, size_t, const char *, void *),
3411 void *arg)
3412 {
3413 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3414 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3415 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3416 tracepoint(librbd, read_iterate_exit, r);
3417 return r;
3418 }
3419
3420 extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
3421 int (*cb)(uint64_t, size_t, const char *, void *),
3422 void *arg)
3423 {
3424 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3425 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3426 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3427 if (r > 0)
3428 r = 0;
3429 tracepoint(librbd, read_iterate2_exit, r);
3430 return (int)r;
3431 }
3432
3433 extern "C" int rbd_diff_iterate(rbd_image_t image,
3434 const char *fromsnapname,
3435 uint64_t ofs, uint64_t len,
3436 int (*cb)(uint64_t, size_t, int, void *),
3437 void *arg)
3438 {
3439 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3440 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3441 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3442 true, false);
3443 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3444 cls::rbd::UserSnapshotNamespace(),
3445 fromsnapname, ofs, len,
3446 true, false, cb, arg);
3447 tracepoint(librbd, diff_iterate_exit, r);
3448 return r;
3449 }
3450
3451 extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
3452 uint64_t ofs, uint64_t len,
3453 uint8_t include_parent, uint8_t whole_object,
3454 int (*cb)(uint64_t, size_t, int, void *),
3455 void *arg)
3456 {
3457 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3458 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3459 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3460 include_parent != 0, whole_object != 0);
3461 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3462 cls::rbd::UserSnapshotNamespace(),
3463 fromsnapname, ofs, len,
3464 include_parent, whole_object,
3465 cb, arg);
3466 tracepoint(librbd, diff_iterate_exit, r);
3467 return r;
3468 }
3469
3470 extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
3471 const char *buf)
3472 {
3473 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3474 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
3475
3476 bufferlist bl;
3477 bl.push_back(create_write_raw(ictx, buf, len));
3478 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
3479 tracepoint(librbd, write_exit, r);
3480 return r;
3481 }
3482
3483 extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
3484 const char *buf, int op_flags)
3485 {
3486 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3487 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
3488 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
3489
3490 bufferlist bl;
3491 bl.push_back(create_write_raw(ictx, buf, len));
3492 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
3493 tracepoint(librbd, write_exit, r);
3494 return r;
3495 }
3496
3497
3498 extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
3499 {
3500 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3501 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3502 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
3503 tracepoint(librbd, discard_exit, r);
3504 return r;
3505 }
3506
3507 extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
3508 const char *buf, size_t data_len, int op_flags)
3509 {
3510 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3511 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3512 ictx->read_only, ofs, len, data_len <= 0 ? NULL : buf, data_len, op_flags);
3513
3514 if (data_len <= 0 || len % data_len) {
3515 tracepoint(librbd, writesame_exit, -EINVAL);
3516 return -EINVAL;
3517 }
3518
3519 if (mem_is_zero(buf, data_len)) {
3520 int r = ictx->io_work_queue->discard(ofs, len, false);
3521 tracepoint(librbd, writesame_exit, r);
3522 return r;
3523 }
3524
3525 bufferlist bl;
3526 bl.push_back(create_write_raw(ictx, buf, data_len));
3527 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
3528 tracepoint(librbd, writesame_exit, r);
3529 return r;
3530 }
3531
3532 extern "C" int rbd_aio_create_completion(void *cb_arg,
3533 rbd_callback_t complete_cb,
3534 rbd_completion_t *c)
3535 {
3536 librbd::RBD::AioCompletion *rbd_comp =
3537 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
3538 *c = (rbd_completion_t) rbd_comp;
3539 return 0;
3540 }
3541
3542 extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
3543 const char *buf, rbd_completion_t c)
3544 {
3545 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3546 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3547 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3548
3549 bufferlist bl;
3550 bl.push_back(create_write_raw(ictx, buf, len));
3551 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3552 std::move(bl), 0);
3553 tracepoint(librbd, aio_write_exit, 0);
3554 return 0;
3555 }
3556
3557 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
3558 const char *buf, rbd_completion_t c, int op_flags)
3559 {
3560 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3561 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3562 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3563 ictx->read_only, off, len, buf, comp->pc, op_flags);
3564
3565 bufferlist bl;
3566 bl.push_back(create_write_raw(ictx, buf, len));
3567 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3568 std::move(bl), op_flags);
3569 tracepoint(librbd, aio_write_exit, 0);
3570 return 0;
3571 }
3572
3573 extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
3574 int iovcnt, uint64_t off, rbd_completion_t c)
3575 {
3576 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3577 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3578
3579 // convert the scatter list into a bufferlist
3580 ssize_t len = 0;
3581 bufferlist bl;
3582 for (int i = 0; i < iovcnt; ++i) {
3583 const struct iovec &io = iov[i];
3584 len += io.iov_len;
3585 if (len < 0) {
3586 break;
3587 }
3588
3589 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
3590 io.iov_len));
3591 }
3592
3593 int r = 0;
3594 if (iovcnt <= 0 || len < 0) {
3595 r = -EINVAL;
3596 }
3597
3598 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
3599 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3600 comp->pc);
3601 if (r == 0) {
3602 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3603 std::move(bl), 0);
3604 }
3605 tracepoint(librbd, aio_write_exit, r);
3606 return r;
3607 }
3608
3609 extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
3610 rbd_completion_t c)
3611 {
3612 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3613 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3614 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
3615 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard);
3616 tracepoint(librbd, aio_discard_exit, 0);
3617 return 0;
3618 }
3619
3620 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
3621 char *buf, rbd_completion_t c)
3622 {
3623 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3624 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3625 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3626 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3627 librbd::io::ReadResult{buf, len}, 0);
3628 tracepoint(librbd, aio_read_exit, 0);
3629 return 0;
3630 }
3631
3632 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
3633 char *buf, rbd_completion_t c, int op_flags)
3634 {
3635 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3636 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3637 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3638 ictx->read_only, off, len, buf, comp->pc, op_flags);
3639 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3640 librbd::io::ReadResult{buf, len},op_flags);
3641 tracepoint(librbd, aio_read_exit, 0);
3642 return 0;
3643 }
3644
3645 extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
3646 int iovcnt, uint64_t off, rbd_completion_t c)
3647 {
3648 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3649 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3650
3651 ssize_t len = 0;
3652 for (int i = 0; i < iovcnt; ++i) {
3653 len += iov[i].iov_len;
3654 if (len < 0) {
3655 break;
3656 }
3657 }
3658
3659 int r = 0;
3660 if (iovcnt == 0 || len < 0) {
3661 r = -EINVAL;
3662 }
3663
3664 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
3665 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3666 comp->pc);
3667 if (r == 0) {
3668 librbd::io::ReadResult read_result;
3669 if (iovcnt == 1) {
3670 read_result = librbd::io::ReadResult(
3671 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
3672 } else {
3673 read_result = librbd::io::ReadResult(iov, iovcnt);
3674 }
3675 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3676 std::move(read_result), 0);
3677 }
3678 tracepoint(librbd, aio_read_exit, r);
3679 return r;
3680 }
3681
3682 extern "C" int rbd_flush(rbd_image_t image)
3683 {
3684 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3685 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3686 int r = librbd::flush(ictx);
3687 tracepoint(librbd, flush_exit, r);
3688 return r;
3689 }
3690
3691 extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
3692 {
3693 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3694 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3695 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
3696 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
3697 tracepoint(librbd, aio_flush_exit, 0);
3698 return 0;
3699 }
3700
3701 extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
3702 const char *buf, size_t data_len, rbd_completion_t c,
3703 int op_flags)
3704 {
3705 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3706 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3707 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3708 ictx->read_only, off, len, data_len <= 0 ? NULL : buf, data_len, comp->pc,
3709 op_flags);
3710
3711 if (data_len <= 0 || len % data_len) {
3712 tracepoint(librbd, aio_writesame_exit, -EINVAL);
3713 return -EINVAL;
3714 }
3715
3716 if (mem_is_zero(buf, data_len)) {
3717 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false);
3718 tracepoint(librbd, aio_writesame_exit, 0);
3719 return 0;
3720 }
3721
3722 bufferlist bl;
3723 bl.push_back(create_write_raw(ictx, buf, data_len));
3724 ictx->io_work_queue->aio_writesame(get_aio_completion(comp), off, len,
3725 std::move(bl), op_flags);
3726 tracepoint(librbd, aio_writesame_exit, 0);
3727 return 0;
3728 }
3729
3730 extern "C" int rbd_invalidate_cache(rbd_image_t image)
3731 {
3732 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3733 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3734 int r = librbd::invalidate_cache(ictx);
3735 tracepoint(librbd, invalidate_cache_exit, r);
3736 return r;
3737 }
3738
3739 extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
3740 {
3741 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3742 librbd::io::AioCompletion *cs[numcomp];
3743 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
3744 int r = librbd::poll_io_events(ictx, cs, numcomp);
3745 tracepoint(librbd, poll_io_events_exit, r);
3746 if (r > 0) {
3747 for (int i = 0; i < r; ++i)
3748 comps[i] = cs[i]->rbd_comp;
3749 }
3750 return r;
3751 }
3752
3753 extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
3754 {
3755 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3756 string val_s;
3757 tracepoint(librbd, metadata_get_enter, ictx, key);
3758 int r = librbd::metadata_get(ictx, key, &val_s);
3759 if (r < 0) {
3760 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3761 return r;
3762 }
3763 if (*vallen < val_s.size() + 1) {
3764 r = -ERANGE;
3765 *vallen = val_s.size() + 1;
3766 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3767 } else {
3768 strncpy(value, val_s.c_str(), val_s.size() + 1);
3769 tracepoint(librbd, metadata_get_exit, r, key, value);
3770 }
3771 return r;
3772 }
3773
3774 extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
3775 {
3776 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3777 tracepoint(librbd, metadata_set_enter, ictx, key, value);
3778 int r = ictx->operations->metadata_set(key, value);
3779 tracepoint(librbd, metadata_set_exit, r);
3780 return r;
3781 }
3782
3783 extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
3784 {
3785 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3786 tracepoint(librbd, metadata_remove_enter, ictx, key);
3787 int r = ictx->operations->metadata_remove(key);
3788 tracepoint(librbd, metadata_remove_exit, r);
3789 return r;
3790 }
3791
3792 extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
3793 char *key, size_t *key_len, char *value, size_t *val_len)
3794 {
3795 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3796 tracepoint(librbd, metadata_list_enter, ictx);
3797 map<string, bufferlist> pairs;
3798 int r = librbd::metadata_list(ictx, start, max, &pairs);
3799 size_t key_total_len = 0, val_total_len = 0;
3800 bool too_short = false;
3801 for (map<string, bufferlist>::iterator it = pairs.begin();
3802 it != pairs.end(); ++it) {
3803 key_total_len += it->first.size() + 1;
3804 val_total_len += it->second.length() + 1;
3805 }
3806 if (*key_len < key_total_len || *val_len < val_total_len)
3807 too_short = true;
3808 *key_len = key_total_len;
3809 *val_len = val_total_len;
3810 if (too_short) {
3811 tracepoint(librbd, metadata_list_exit, -ERANGE);
3812 return -ERANGE;
3813 }
3814
3815 char *key_p = key, *value_p = value;
3816
3817 for (map<string, bufferlist>::iterator it = pairs.begin();
3818 it != pairs.end(); ++it) {
3819 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
3820 key_p += it->first.size() + 1;
3821 strncpy(value_p, it->second.c_str(), it->second.length());
3822 value_p += it->second.length();
3823 *value_p = '\0';
3824 value_p++;
3825 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
3826 }
3827 tracepoint(librbd, metadata_list_exit, r);
3828 return r;
3829 }
3830
3831 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
3832 {
3833 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3834 return librbd::api::Mirror<>::image_enable(ictx, false);
3835 }
3836
3837 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
3838 {
3839 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3840 return librbd::api::Mirror<>::image_disable(ictx, force);
3841 }
3842
3843 extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
3844 {
3845 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3846 return librbd::api::Mirror<>::image_promote(ictx, force);
3847 }
3848
3849 extern "C" int rbd_mirror_image_demote(rbd_image_t image)
3850 {
3851 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3852 return librbd::api::Mirror<>::image_demote(ictx);
3853 }
3854
3855 extern "C" int rbd_mirror_image_resync(rbd_image_t image)
3856 {
3857 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3858 return librbd::api::Mirror<>::image_resync(ictx);
3859 }
3860
3861 extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
3862 rbd_mirror_image_info_t *mirror_image_info,
3863 size_t info_size)
3864 {
3865 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3866
3867 librbd::mirror_image_info_t cpp_mirror_image;
3868 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image,
3869 sizeof(cpp_mirror_image));
3870 if (r < 0) {
3871 return r;
3872 }
3873
3874 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
3875 return 0;
3876 }
3877
3878 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
3879 rbd_mirror_image_status_t *status,
3880 size_t status_size)
3881 {
3882 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3883
3884 librbd::mirror_image_status_t cpp_status;
3885 int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status,
3886 sizeof(cpp_status));
3887 if (r < 0) {
3888 return r;
3889 }
3890
3891 mirror_image_status_cpp_to_c(cpp_status, status);
3892 return 0;
3893 }
3894
3895 extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
3896 rbd_completion_t c) {
3897 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3898 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3899 librbd::api::Mirror<>::image_promote(
3900 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3901 get_aio_completion(comp)));
3902 return 0;
3903 }
3904
3905 extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
3906 rbd_completion_t c) {
3907 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3908 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3909 librbd::api::Mirror<>::image_demote(
3910 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3911 get_aio_completion(comp)));
3912 return 0;
3913 }
3914
3915 extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
3916 rbd_mirror_image_info_t *info,
3917 size_t info_size,
3918 rbd_completion_t c) {
3919 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3920 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3921
3922 if (sizeof(rbd_mirror_image_info_t) > info_size) {
3923 return -ERANGE;
3924 }
3925
3926 auto ctx = new C_MirrorImageGetInfo(
3927 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3928 get_aio_completion(comp)));
3929 librbd::api::Mirror<>::image_get_info(
3930 ictx, &ctx->cpp_mirror_image_info, sizeof(ctx->cpp_mirror_image_info), ctx);
3931 return 0;
3932 }
3933
3934 extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
3935 rbd_mirror_image_status_t *status,
3936 size_t status_size,
3937 rbd_completion_t c) {
3938 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3939 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3940
3941 if (sizeof(rbd_mirror_image_status_t) > status_size) {
3942 return -ERANGE;
3943 }
3944
3945 auto ctx = new C_MirrorImageGetStatus(
3946 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3947 get_aio_completion(comp)));
3948 librbd::api::Mirror<>::image_get_status(
3949 ictx, &ctx->cpp_mirror_image_status, sizeof(ctx->cpp_mirror_image_status),
3950 ctx);
3951 return 0;
3952 }
3953
3954 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
3955 rbd_update_callback_t watch_cb, void *arg)
3956 {
3957 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3958 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
3959 tracepoint(librbd, update_watch_enter, ictx, wctx);
3960 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
3961 tracepoint(librbd, update_watch_exit, r, wctx->handle);
3962 *handle = reinterpret_cast<uint64_t>(wctx);
3963 return r;
3964 }
3965
3966 extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
3967 {
3968 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3969 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
3970 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
3971 int r = ictx->state->unregister_update_watcher(wctx->handle);
3972 delete wctx;
3973 tracepoint(librbd, update_unwatch_exit, r);
3974 return r;
3975 }
3976
3977 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
3978 {
3979 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3980 return comp->is_complete();
3981 }
3982
3983 extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
3984 {
3985 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3986 return comp->wait_for_complete();
3987 }
3988
3989 extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
3990 {
3991 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3992 return comp->get_return_value();
3993 }
3994
3995 extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
3996 {
3997 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3998 return comp->get_arg();
3999 }
4000
4001 extern "C" void rbd_aio_release(rbd_completion_t c)
4002 {
4003 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4004 comp->release();
4005 }
4006
4007 extern "C" int rbd_group_create(rados_ioctx_t p, const char *name)
4008 {
4009 librados::IoCtx io_ctx;
4010 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4011 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4012 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
4013 io_ctx.get_id(), name);
4014 int r = librbd::api::Group<>::create(io_ctx, name);
4015 tracepoint(librbd, group_create_exit, r);
4016 return r;
4017 }
4018
4019 extern "C" int rbd_group_remove(rados_ioctx_t p, const char *name)
4020 {
4021 librados::IoCtx io_ctx;
4022 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4023 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4024 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
4025 io_ctx.get_id(), name);
4026 int r = librbd::api::Group<>::remove(io_ctx, name);
4027 tracepoint(librbd, group_remove_exit, r);
4028 return r;
4029 }
4030
4031 extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size)
4032 {
4033 librados::IoCtx io_ctx;
4034 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4035 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4036 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
4037 io_ctx.get_id());
4038
4039 vector<string> cpp_names;
4040 int r = librbd::list(io_ctx, cpp_names);
4041
4042 if (r == -ENOENT) {
4043 *size = 0;
4044 *names = '\0';
4045 tracepoint(librbd, group_list_exit, 0);
4046 return 0;
4047 }
4048
4049 if (r < 0) {
4050 tracepoint(librbd, group_list_exit, r);
4051 return r;
4052 }
4053
4054 size_t expected_size = 0;
4055
4056 for (size_t i = 0; i < cpp_names.size(); i++) {
4057 expected_size += cpp_names[i].size() + 1;
4058 }
4059 if (*size < expected_size) {
4060 *size = expected_size;
4061 tracepoint(librbd, group_list_exit, -ERANGE);
4062 return -ERANGE;
4063 }
4064
4065 if (!names)
4066 return -EINVAL;
4067
4068 names[expected_size] = '\0';
4069 for (int i = 0; i < (int)cpp_names.size(); i++) {
4070 const char* name = cpp_names[i].c_str();
4071 tracepoint(librbd, group_list_entry, name);
4072 strcpy(names, name);
4073 names += strlen(names) + 1;
4074 }
4075 tracepoint(librbd, group_list_exit, (int)expected_size);
4076 return (int)expected_size;
4077 }
4078
4079 extern "C" int rbd_group_image_add(
4080 rados_ioctx_t group_p, const char *group_name,
4081 rados_ioctx_t image_p, const char *image_name)
4082 {
4083 librados::IoCtx group_ioctx;
4084 librados::IoCtx image_ioctx;
4085
4086 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4087 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4088
4089 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4090 tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(),
4091 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
4092 image_ioctx.get_id(), image_name);
4093
4094 int r = librbd::api::Group<>::image_add(group_ioctx, group_name, image_ioctx,
4095 image_name);
4096
4097 tracepoint(librbd, group_image_add_exit, r);
4098 return r;
4099 }
4100
4101 extern "C" int rbd_group_image_remove(
4102 rados_ioctx_t group_p, const char *group_name,
4103 rados_ioctx_t image_p, const char *image_name)
4104 {
4105 librados::IoCtx group_ioctx;
4106 librados::IoCtx image_ioctx;
4107
4108 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4109 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4110
4111 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4112 tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(),
4113 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
4114 image_ioctx.get_id(), image_name);
4115
4116 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
4117 image_ioctx, image_name);
4118
4119 tracepoint(librbd, group_image_remove_exit, r);
4120 return r;
4121 }
4122
4123 extern "C" int rbd_group_image_remove_by_id(rados_ioctx_t group_p,
4124 const char *group_name,
4125 rados_ioctx_t image_p,
4126 const char *image_id)
4127 {
4128 librados::IoCtx group_ioctx;
4129 librados::IoCtx image_ioctx;
4130
4131 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4132 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4133
4134 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4135 tracepoint(librbd, group_image_remove_by_id_enter,
4136 group_ioctx.get_pool_name().c_str(),
4137 group_ioctx.get_id(), group_name,
4138 image_ioctx.get_pool_name().c_str(),
4139 image_ioctx.get_id(), image_id);
4140
4141 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
4142 image_ioctx, image_id);
4143
4144 tracepoint(librbd, group_image_remove_by_id_exit, r);
4145 return r;
4146 }
4147
4148 extern "C" int rbd_group_image_list(rados_ioctx_t group_p,
4149 const char *group_name,
4150 rbd_group_image_status_t *images,
4151 size_t *image_size)
4152 {
4153 librados::IoCtx group_ioctx;
4154 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4155
4156 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4157 tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(),
4158 group_ioctx.get_id(), group_name);
4159
4160 std::vector<librbd::group_image_status_t> cpp_images;
4161 int r = librbd::api::Group<>::image_list(group_ioctx, group_name,
4162 &cpp_images);
4163
4164 if (r == -ENOENT) {
4165 tracepoint(librbd, group_image_list_exit, 0);
4166 return 0;
4167 }
4168
4169 if (r < 0) {
4170 tracepoint(librbd, group_image_list_exit, r);
4171 return r;
4172 }
4173
4174 if (*image_size < cpp_images.size()) {
4175 tracepoint(librbd, group_image_list_exit, -ERANGE);
4176 return -ERANGE;
4177 }
4178
4179 for (size_t i = 0; i < cpp_images.size(); ++i) {
4180 group_image_status_cpp_to_c(cpp_images[i], &images[i]);
4181 }
4182
4183 tracepoint(librbd, group_image_list_exit, r);
4184 return r;
4185 }
4186
4187 extern "C" int rbd_image_get_group(rados_ioctx_t image_p,
4188 const char *image_name,
4189 rbd_group_spec_t *c_group_spec)
4190 {
4191 librados::IoCtx io_ctx;
4192 librados::IoCtx::from_rados_ioctx_t(image_p, io_ctx);
4193
4194 librbd::ImageCtx *ictx = new librbd::ImageCtx(image_name, "", "", io_ctx, false);
4195 int r = ictx->state->open(false);
4196 if (r < 0) {
4197 tracepoint(librbd, open_image_exit, r);
4198 return r;
4199 }
4200
4201 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
4202 librbd::group_spec_t group_spec;
4203 r = librbd::api::Group<>::image_get_group(ictx, &group_spec);
4204 group_spec_cpp_to_c(group_spec, c_group_spec);
4205 tracepoint(librbd, image_get_group_exit, r);
4206 ictx->state->close();
4207 return r;
4208 }
4209
4210 extern "C" void rbd_group_spec_cleanup(rbd_group_spec_t *group_spec) {
4211 free(group_spec->name);
4212 }
4213
4214 extern "C" void rbd_group_image_status_cleanup(
4215 rbd_group_image_status_t *image) {
4216 free(image->spec.name);
4217 }
4218
4219 extern "C" void rbd_group_image_status_list_cleanup(
4220 rbd_group_image_status_t *images,
4221 size_t len) {
4222 for (size_t i = 0; i < len; ++i) {
4223 rbd_group_image_status_cleanup(&images[i]);
4224 }
4225 }