]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/librbd.cc
542dd28ab38d1c9a079299920fcd85bf07676358
[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::get_create_timestamp(struct timespec *timestamp)
1015 {
1016 ImageCtx *ictx = (ImageCtx *)ctx;
1017 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
1018 ictx->read_only);
1019 utime_t time = ictx->get_create_timestamp();
1020 time.to_timespec(timestamp);
1021 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
1022 return 0;
1023 }
1024
1025 int Image::overlap(uint64_t *overlap)
1026 {
1027 ImageCtx *ictx = (ImageCtx *)ctx;
1028 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1029 int r = librbd::get_overlap(ictx, overlap);
1030 tracepoint(librbd, get_overlap_exit, r, *overlap);
1031 return r;
1032 }
1033
1034 int Image::get_id(std::string *id)
1035 {
1036 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1037 if (ictx->old_format) {
1038 return -EINVAL;
1039 }
1040 *id = ictx->id;
1041 return 0;
1042 }
1043
1044 std::string Image::get_block_name_prefix()
1045 {
1046 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1047 return ictx->object_prefix;
1048 }
1049
1050 int64_t Image::get_data_pool_id()
1051 {
1052 ImageCtx *ictx = reinterpret_cast<ImageCtx *>(ctx);
1053 return ictx->data_ctx.get_id();
1054 }
1055
1056 int Image::parent_info(string *parent_pool_name, string *parent_name,
1057 string *parent_snap_name)
1058 {
1059 return parent_info2(parent_pool_name, parent_name, nullptr,
1060 parent_snap_name);
1061 }
1062
1063 int Image::parent_info2(string *parent_pool_name, string *parent_name,
1064 string *parent_id, string *parent_snap_name)
1065 {
1066 ImageCtx *ictx = (ImageCtx *)ctx;
1067 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
1068 ictx->snap_name.c_str(), ictx->read_only);
1069 int r = librbd::get_parent_info(ictx, parent_pool_name, parent_name,
1070 parent_id, parent_snap_name);
1071 tracepoint(librbd, get_parent_info_exit, r,
1072 parent_pool_name ? parent_pool_name->c_str() : NULL,
1073 parent_name ? parent_name->c_str() : NULL,
1074 parent_id ? parent_id->c_str() : NULL,
1075 parent_snap_name ? parent_snap_name->c_str() : NULL);
1076 return r;
1077 }
1078
1079 int Image::get_flags(uint64_t *flags)
1080 {
1081 ImageCtx *ictx = (ImageCtx *)ctx;
1082 tracepoint(librbd, get_flags_enter, ictx);
1083 int r = librbd::get_flags(ictx, flags);
1084 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
1085 return r;
1086 }
1087
1088 int Image::set_image_notification(int fd, int type)
1089 {
1090 ImageCtx *ictx = (ImageCtx *)ctx;
1091 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
1092 int r = librbd::set_image_notification(ictx, fd, type);
1093 tracepoint(librbd, set_image_notification_exit, ictx, r);
1094 return r;
1095 }
1096
1097 int Image::is_exclusive_lock_owner(bool *is_owner)
1098 {
1099 ImageCtx *ictx = (ImageCtx *)ctx;
1100 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
1101 int r = librbd::is_exclusive_lock_owner(ictx, is_owner);
1102 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
1103 return r;
1104 }
1105
1106 int Image::lock_acquire(rbd_lock_mode_t lock_mode)
1107 {
1108 ImageCtx *ictx = (ImageCtx *)ctx;
1109 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
1110 int r = librbd::lock_acquire(ictx, lock_mode);
1111 tracepoint(librbd, lock_acquire_exit, ictx, r);
1112 return r;
1113 }
1114
1115 int Image::lock_release()
1116 {
1117 ImageCtx *ictx = (ImageCtx *)ctx;
1118 tracepoint(librbd, lock_release_enter, ictx);
1119 int r = librbd::lock_release(ictx);
1120 tracepoint(librbd, lock_release_exit, ictx, r);
1121 return r;
1122 }
1123
1124 int Image::lock_get_owners(rbd_lock_mode_t *lock_mode,
1125 std::list<std::string> *lock_owners)
1126 {
1127 ImageCtx *ictx = (ImageCtx *)ctx;
1128 tracepoint(librbd, lock_get_owners_enter, ictx);
1129 int r = librbd::lock_get_owners(ictx, lock_mode, lock_owners);
1130 tracepoint(librbd, lock_get_owners_exit, ictx, r);
1131 return r;
1132 }
1133
1134 int Image::lock_break(rbd_lock_mode_t lock_mode,
1135 const std::string &lock_owner)
1136 {
1137 ImageCtx *ictx = (ImageCtx *)ctx;
1138 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner.c_str());
1139 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
1140 tracepoint(librbd, lock_break_exit, ictx, r);
1141 return r;
1142 }
1143
1144 int Image::rebuild_object_map(ProgressContext &prog_ctx)
1145 {
1146 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1147 return ictx->operations->rebuild_object_map(prog_ctx);
1148 }
1149
1150 int Image::check_object_map(ProgressContext &prog_ctx)
1151 {
1152 ImageCtx *ictx = reinterpret_cast<ImageCtx*>(ctx);
1153 return ictx->operations->check_object_map(prog_ctx);
1154 }
1155
1156 int Image::copy(IoCtx& dest_io_ctx, const char *destname)
1157 {
1158 ImageCtx *ictx = (ImageCtx *)ctx;
1159 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);
1160 ImageOptions opts;
1161 librbd::NoOpProgressContext prog_ctx;
1162 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1163 tracepoint(librbd, copy_exit, r);
1164 return r;
1165 }
1166
1167 int Image::copy2(Image& dest)
1168 {
1169 ImageCtx *srcctx = (ImageCtx *)ctx;
1170 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1171 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);
1172 librbd::NoOpProgressContext prog_ctx;
1173 int r = librbd::copy(srcctx, destctx, prog_ctx, 0);
1174 tracepoint(librbd, copy2_exit, r);
1175 return r;
1176 }
1177
1178 int Image::copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts)
1179 {
1180 ImageCtx *ictx = (ImageCtx *)ctx;
1181 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);
1182 librbd::NoOpProgressContext prog_ctx;
1183 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
1184 tracepoint(librbd, copy3_exit, r);
1185 return r;
1186 }
1187
1188 int Image::copy4(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts, size_t sparse_size)
1189 {
1190 ImageCtx *ictx = (ImageCtx *)ctx;
1191 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);
1192 librbd::NoOpProgressContext prog_ctx;
1193 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, sparse_size);
1194 tracepoint(librbd, copy4_exit, r);
1195 return r;
1196 }
1197
1198 int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
1199 librbd::ProgressContext &pctx)
1200 {
1201 ImageCtx *ictx = (ImageCtx *)ctx;
1202 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);
1203 ImageOptions opts;
1204 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1205 tracepoint(librbd, copy_exit, r);
1206 return r;
1207 }
1208
1209 int Image::copy_with_progress2(Image& dest, librbd::ProgressContext &pctx)
1210 {
1211 ImageCtx *srcctx = (ImageCtx *)ctx;
1212 ImageCtx *destctx = (ImageCtx *)dest.ctx;
1213 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);
1214 int r = librbd::copy(srcctx, destctx, pctx, 0);
1215 tracepoint(librbd, copy2_exit, r);
1216 return r;
1217 }
1218
1219 int Image::copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
1220 ImageOptions& opts,
1221 librbd::ProgressContext &pctx)
1222 {
1223 ImageCtx *ictx = (ImageCtx *)ctx;
1224 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);
1225 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
1226 tracepoint(librbd, copy3_exit, r);
1227 return r;
1228 }
1229
1230 int Image::copy_with_progress4(IoCtx& dest_io_ctx, const char *destname,
1231 ImageOptions& opts,
1232 librbd::ProgressContext &pctx,
1233 size_t sparse_size)
1234 {
1235 ImageCtx *ictx = (ImageCtx *)ctx;
1236 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);
1237 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, sparse_size);
1238 tracepoint(librbd, copy4_exit, r);
1239 return r;
1240 }
1241
1242 int Image::flatten()
1243 {
1244 ImageCtx *ictx = (ImageCtx *)ctx;
1245 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1246 librbd::NoOpProgressContext prog_ctx;
1247 int r = ictx->operations->flatten(prog_ctx);
1248 tracepoint(librbd, flatten_exit, r);
1249 return r;
1250 }
1251
1252 int Image::flatten_with_progress(librbd::ProgressContext& prog_ctx)
1253 {
1254 ImageCtx *ictx = (ImageCtx *)ctx;
1255 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
1256 int r = ictx->operations->flatten(prog_ctx);
1257 tracepoint(librbd, flatten_exit, r);
1258 return r;
1259 }
1260
1261 int Image::list_children(set<pair<string, string> > *children)
1262 {
1263 ImageCtx *ictx = (ImageCtx *)ctx;
1264 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1265 int r = librbd::list_children(ictx, *children);
1266 if (r >= 0) {
1267 for (set<pair<string, string> >::const_iterator it = children->begin();
1268 it != children->end(); ++it) {
1269 tracepoint(librbd, list_children_entry, it->first.c_str(), it->second.c_str());
1270 }
1271 }
1272 tracepoint(librbd, list_children_exit, r);
1273 return r;
1274 }
1275
1276 int Image::list_lockers(std::list<librbd::locker_t> *lockers,
1277 bool *exclusive, string *tag)
1278 {
1279 ImageCtx *ictx = (ImageCtx *)ctx;
1280 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1281 int r = librbd::list_lockers(ictx, lockers, exclusive, tag);
1282 if (r >= 0) {
1283 for (std::list<librbd::locker_t>::const_iterator it = lockers->begin();
1284 it != lockers->end(); ++it) {
1285 tracepoint(librbd, list_lockers_entry, it->client.c_str(), it->cookie.c_str(), it->address.c_str());
1286 }
1287 }
1288 tracepoint(librbd, list_lockers_exit, r);
1289 return r;
1290 }
1291
1292 int Image::lock_exclusive(const string& cookie)
1293 {
1294 ImageCtx *ictx = (ImageCtx *)ctx;
1295 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1296 int r = librbd::lock(ictx, true, cookie, "");
1297 tracepoint(librbd, lock_exclusive_exit, r);
1298 return r;
1299 }
1300
1301 int Image::lock_shared(const string& cookie, const std::string& tag)
1302 {
1303 ImageCtx *ictx = (ImageCtx *)ctx;
1304 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str(), tag.c_str());
1305 int r = librbd::lock(ictx, false, cookie, tag);
1306 tracepoint(librbd, lock_shared_exit, r);
1307 return r;
1308 }
1309
1310 int Image::unlock(const string& cookie)
1311 {
1312 ImageCtx *ictx = (ImageCtx *)ctx;
1313 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie.c_str());
1314 int r = librbd::unlock(ictx, cookie);
1315 tracepoint(librbd, unlock_exit, r);
1316 return r;
1317 }
1318
1319 int Image::break_lock(const string& client, const string& cookie)
1320 {
1321 ImageCtx *ictx = (ImageCtx *)ctx;
1322 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client.c_str(), cookie.c_str());
1323 int r = librbd::break_lock(ictx, client, cookie);
1324 tracepoint(librbd, break_lock_exit, r);
1325 return r;
1326 }
1327
1328 int Image::snap_create(const char *snap_name)
1329 {
1330 ImageCtx *ictx = (ImageCtx *)ctx;
1331 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1332 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
1333 snap_name);
1334 tracepoint(librbd, snap_create_exit, r);
1335 return r;
1336 }
1337
1338 int Image::snap_remove(const char *snap_name)
1339 {
1340 ImageCtx *ictx = (ImageCtx *)ctx;
1341 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1342 librbd::NoOpProgressContext prog_ctx;
1343 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
1344 tracepoint(librbd, snap_remove_exit, r);
1345 return r;
1346 }
1347
1348 int Image::snap_remove2(const char *snap_name, uint32_t flags, ProgressContext& pctx)
1349 {
1350 ImageCtx *ictx = (ImageCtx *)ctx;
1351 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
1352 int r = librbd::snap_remove(ictx, snap_name, flags, pctx);
1353 tracepoint(librbd, snap_remove_exit, r);
1354 return r;
1355 }
1356
1357 int Image::snap_rollback(const char *snap_name)
1358 {
1359 ImageCtx *ictx = (ImageCtx *)ctx;
1360 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1361 librbd::NoOpProgressContext prog_ctx;
1362 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1363 tracepoint(librbd, snap_rollback_exit, r);
1364 return r;
1365 }
1366
1367 int Image::snap_rename(const char *srcname, const char *dstname)
1368 {
1369 ImageCtx *ictx = (ImageCtx *)ctx;
1370 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
1371 int r = ictx->operations->snap_rename(srcname, dstname);
1372 tracepoint(librbd, snap_rename_exit, r);
1373 return r;
1374 }
1375
1376 int Image::snap_rollback_with_progress(const char *snap_name,
1377 ProgressContext& prog_ctx)
1378 {
1379 ImageCtx *ictx = (ImageCtx *)ctx;
1380 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1381 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
1382 tracepoint(librbd, snap_rollback_exit, r);
1383 return r;
1384 }
1385
1386 int Image::snap_protect(const char *snap_name)
1387 {
1388 ImageCtx *ictx = (ImageCtx *)ctx;
1389 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1390 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
1391 tracepoint(librbd, snap_protect_exit, r);
1392 return r;
1393 }
1394
1395 int Image::snap_unprotect(const char *snap_name)
1396 {
1397 ImageCtx *ictx = (ImageCtx *)ctx;
1398 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1399 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
1400 tracepoint(librbd, snap_unprotect_exit, r);
1401 return r;
1402 }
1403
1404 int Image::snap_is_protected(const char *snap_name, bool *is_protected)
1405 {
1406 ImageCtx *ictx = (ImageCtx *)ctx;
1407 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1408 int r = librbd::snap_is_protected(ictx, snap_name, is_protected);
1409 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
1410 return r;
1411 }
1412
1413 int Image::snap_list(vector<librbd::snap_info_t>& snaps)
1414 {
1415 ImageCtx *ictx = (ImageCtx *)ctx;
1416 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, &snaps);
1417 int r = librbd::snap_list(ictx, snaps);
1418 if (r >= 0) {
1419 for (int i = 0, n = snaps.size(); i < n; i++) {
1420 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name.c_str());
1421 }
1422 }
1423 tracepoint(librbd, snap_list_exit, r, snaps.size());
1424 if (r >= 0) {
1425 // A little ugly, but the C++ API doesn't need a Image::snap_list_end,
1426 // and we want the tracepoints to mirror the C API
1427 tracepoint(librbd, snap_list_end_enter, &snaps);
1428 tracepoint(librbd, snap_list_end_exit);
1429 }
1430 return r;
1431 }
1432
1433 bool Image::snap_exists(const char *snap_name)
1434 {
1435 ImageCtx *ictx = (ImageCtx *)ctx;
1436 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
1437 ictx->snap_name.c_str(), ictx->read_only, snap_name);
1438 bool exists;
1439 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, &exists);
1440 tracepoint(librbd, snap_exists_exit, r, exists);
1441 if (r < 0) {
1442 // lie to caller since we don't know the real answer yet.
1443 return false;
1444 }
1445 return exists;
1446 }
1447
1448 // A safer verion of snap_exists.
1449 int Image::snap_exists2(const char *snap_name, bool *exists)
1450 {
1451 ImageCtx *ictx = (ImageCtx *)ctx;
1452 tracepoint(librbd, snap_exists_enter, ictx, ictx->name.c_str(),
1453 ictx->snap_name.c_str(), ictx->read_only, snap_name);
1454 int r = librbd::snap_exists(ictx, cls::rbd::UserSnapshotNamespace(), snap_name, exists);
1455 tracepoint(librbd, snap_exists_exit, r, *exists);
1456 return r;
1457 }
1458
1459 int Image::snap_get_timestamp(uint64_t snap_id, struct timespec *timestamp)
1460 {
1461 ImageCtx *ictx = (ImageCtx *)ctx;
1462 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
1463 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
1464 tracepoint(librbd, snap_get_timestamp_exit, r);
1465 return r;
1466 }
1467
1468 int Image::snap_get_limit(uint64_t *limit)
1469 {
1470 ImageCtx *ictx = (ImageCtx *)ctx;
1471 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
1472 int r = librbd::snap_get_limit(ictx, limit);
1473 tracepoint(librbd, snap_get_limit_exit, r, *limit);
1474 return r;
1475 }
1476
1477 int Image::snap_set_limit(uint64_t limit)
1478 {
1479 ImageCtx *ictx = (ImageCtx *)ctx;
1480
1481 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
1482 int r = ictx->operations->snap_set_limit(limit);
1483 tracepoint(librbd, snap_set_limit_exit, r);
1484 return r;
1485 }
1486
1487 int Image::snap_set(const char *snap_name)
1488 {
1489 ImageCtx *ictx = (ImageCtx *)ctx;
1490 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
1491 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
1492 tracepoint(librbd, snap_set_exit, r);
1493 return r;
1494 }
1495
1496 ssize_t Image::read(uint64_t ofs, size_t len, bufferlist& bl)
1497 {
1498 ImageCtx *ictx = (ImageCtx *)ctx;
1499 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1500 bufferptr ptr(len);
1501 bl.push_back(std::move(ptr));
1502 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, 0);
1503 tracepoint(librbd, read_exit, r);
1504 return r;
1505 }
1506
1507 ssize_t Image::read2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1508 {
1509 ImageCtx *ictx = (ImageCtx *)ctx;
1510 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1511 ictx->read_only, ofs, len, op_flags);
1512 bufferptr ptr(len);
1513 bl.push_back(std::move(ptr));
1514 int r = ictx->io_work_queue->read(ofs, len, io::ReadResult{&bl}, op_flags);
1515 tracepoint(librbd, read_exit, r);
1516 return r;
1517 }
1518
1519 int64_t Image::read_iterate(uint64_t ofs, size_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_iterate_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 tracepoint(librbd, read_iterate_exit, r);
1527 return r;
1528 }
1529
1530 int Image::read_iterate2(uint64_t ofs, uint64_t len,
1531 int (*cb)(uint64_t, size_t, const char *, void *),
1532 void *arg)
1533 {
1534 ImageCtx *ictx = (ImageCtx *)ctx;
1535 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1536 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
1537 if (r > 0)
1538 r = 0;
1539 tracepoint(librbd, read_iterate2_exit, r);
1540 return (int)r;
1541 }
1542
1543 int Image::diff_iterate(const char *fromsnapname,
1544 uint64_t ofs, uint64_t len,
1545 int (*cb)(uint64_t, size_t, int, void *),
1546 void *arg)
1547 {
1548 ImageCtx *ictx = (ImageCtx *)ctx;
1549 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
1550 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
1551 true, false);
1552 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
1553 cls::rbd::UserSnapshotNamespace(),
1554 fromsnapname, ofs,
1555 len, true, false, cb, arg);
1556 tracepoint(librbd, diff_iterate_exit, r);
1557 return r;
1558 }
1559
1560 int Image::diff_iterate2(const char *fromsnapname, uint64_t ofs, uint64_t len,
1561 bool include_parent, bool whole_object,
1562 int (*cb)(uint64_t, size_t, int, void *), void *arg)
1563 {
1564 ImageCtx *ictx = (ImageCtx *)ctx;
1565 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
1566 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
1567 include_parent, whole_object);
1568 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
1569 cls::rbd::UserSnapshotNamespace(),
1570 fromsnapname, ofs,
1571 len, include_parent,
1572 whole_object, cb, arg);
1573 tracepoint(librbd, diff_iterate_exit, r);
1574 return r;
1575 }
1576
1577 ssize_t Image::write(uint64_t ofs, size_t len, bufferlist& bl)
1578 {
1579 ImageCtx *ictx = (ImageCtx *)ctx;
1580 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());
1581 if (bl.length() < len) {
1582 tracepoint(librbd, write_exit, -EINVAL);
1583 return -EINVAL;
1584 }
1585 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, 0);
1586 tracepoint(librbd, write_exit, r);
1587 return r;
1588 }
1589
1590 ssize_t Image::write2(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1591 {
1592 ImageCtx *ictx = (ImageCtx *)ctx;
1593 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only,
1594 ofs, len, bl.length() < len ? NULL : bl.c_str(), op_flags);
1595 if (bl.length() < len) {
1596 tracepoint(librbd, write_exit, -EINVAL);
1597 return -EINVAL;
1598 }
1599 int r = ictx->io_work_queue->write(ofs, len, bufferlist{bl}, op_flags);
1600 tracepoint(librbd, write_exit, r);
1601 return r;
1602 }
1603
1604 int Image::discard(uint64_t ofs, uint64_t len)
1605 {
1606 ImageCtx *ictx = (ImageCtx *)ctx;
1607 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
1608 if (len > std::numeric_limits<int32_t>::max()) {
1609 tracepoint(librbd, discard_exit, -EINVAL);
1610 return -EINVAL;
1611 }
1612 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
1613 tracepoint(librbd, discard_exit, r);
1614 return r;
1615 }
1616
1617 ssize_t Image::writesame(uint64_t ofs, size_t len, bufferlist& bl, int op_flags)
1618 {
1619 ImageCtx *ictx = (ImageCtx *)ctx;
1620 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1621 ictx->read_only, ofs, len, bl.length() <= 0 ? NULL : bl.c_str(), bl.length(),
1622 op_flags);
1623 if (bl.length() <= 0 || len % bl.length()) {
1624 tracepoint(librbd, writesame_exit, -EINVAL);
1625 return -EINVAL;
1626 }
1627
1628 if (mem_is_zero(bl.c_str(), bl.length())) {
1629 int r = ictx->io_work_queue->discard(ofs, len, false);
1630 tracepoint(librbd, writesame_exit, r);
1631 return r;
1632 }
1633
1634 int r = ictx->io_work_queue->writesame(ofs, len, bufferlist{bl}, op_flags);
1635 tracepoint(librbd, writesame_exit, r);
1636 return r;
1637 }
1638
1639 ssize_t Image::compare_and_write(uint64_t ofs, size_t len,
1640 ceph::bufferlist &cmp_bl, ceph::bufferlist& bl,
1641 uint64_t *mismatch_off, int op_flags)
1642 {
1643 ImageCtx *ictx = (ImageCtx *)ctx;
1644 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
1645 ictx->snap_name.c_str(),
1646 ictx->read_only, ofs, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
1647 bl.length() < len ? NULL : bl.c_str(), op_flags);
1648
1649 if (bl.length() < len) {
1650 tracepoint(librbd, write_exit, -EINVAL);
1651 return -EINVAL;
1652 }
1653
1654 int r = ictx->io_work_queue->compare_and_write(ofs, len, bufferlist{cmp_bl},
1655 bufferlist{bl}, mismatch_off,
1656 op_flags);
1657
1658 tracepoint(librbd, compare_and_write_exit, r);
1659
1660 return r;
1661 }
1662 int Image::aio_write(uint64_t off, size_t len, bufferlist& bl,
1663 RBD::AioCompletion *c)
1664 {
1665 ImageCtx *ictx = (ImageCtx *)ctx;
1666 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);
1667 if (bl.length() < len) {
1668 tracepoint(librbd, aio_write_exit, -EINVAL);
1669 return -EINVAL;
1670 }
1671 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1672 bufferlist{bl}, 0);
1673 tracepoint(librbd, aio_write_exit, 0);
1674 return 0;
1675 }
1676
1677 int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
1678 RBD::AioCompletion *c, int op_flags)
1679 {
1680 ImageCtx *ictx = (ImageCtx *)ctx;
1681 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1682 ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1683 if (bl.length() < len) {
1684 tracepoint(librbd, aio_write_exit, -EINVAL);
1685 return -EINVAL;
1686 }
1687 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1688 bufferlist{bl}, op_flags);
1689 tracepoint(librbd, aio_write_exit, 0);
1690 return 0;
1691 }
1692
1693 int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
1694 {
1695 ImageCtx *ictx = (ImageCtx *)ctx;
1696 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
1697 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard);
1698 tracepoint(librbd, aio_discard_exit, 0);
1699 return 0;
1700 }
1701
1702 int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
1703 RBD::AioCompletion *c)
1704 {
1705 ImageCtx *ictx = (ImageCtx *)ctx;
1706 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);
1707 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1708 << (void *)(bl.c_str() + len - 1) << dendl;
1709 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1710 io::ReadResult{&bl}, 0);
1711 tracepoint(librbd, aio_read_exit, 0);
1712 return 0;
1713 }
1714
1715 int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
1716 RBD::AioCompletion *c, int op_flags)
1717 {
1718 ImageCtx *ictx = (ImageCtx *)ctx;
1719 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1720 ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
1721 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1722 << (void *)(bl.c_str() + len - 1) << dendl;
1723 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1724 io::ReadResult{&bl}, op_flags);
1725 tracepoint(librbd, aio_read_exit, 0);
1726 return 0;
1727 }
1728
1729 int Image::flush()
1730 {
1731 ImageCtx *ictx = (ImageCtx *)ctx;
1732 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1733 int r = librbd::flush(ictx);
1734 tracepoint(librbd, flush_exit, r);
1735 return r;
1736 }
1737
1738 int Image::aio_flush(RBD::AioCompletion *c)
1739 {
1740 ImageCtx *ictx = (ImageCtx *)ctx;
1741 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
1742 ictx->io_work_queue->aio_flush(get_aio_completion(c));
1743 tracepoint(librbd, aio_flush_exit, 0);
1744 return 0;
1745 }
1746
1747 int Image::aio_writesame(uint64_t off, size_t len, bufferlist& bl,
1748 RBD::AioCompletion *c, int op_flags)
1749 {
1750 ImageCtx *ictx = (ImageCtx *)ctx;
1751 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1752 ictx->read_only, off, len, bl.length() <= len ? NULL : bl.c_str(), bl.length(),
1753 c->pc, op_flags);
1754 if (bl.length() <= 0 || len % bl.length()) {
1755 tracepoint(librbd, aio_writesame_exit, -EINVAL);
1756 return -EINVAL;
1757 }
1758
1759 if (mem_is_zero(bl.c_str(), bl.length())) {
1760 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false);
1761 tracepoint(librbd, aio_writesame_exit, 0);
1762 return 0;
1763 }
1764
1765 ictx->io_work_queue->aio_writesame(get_aio_completion(c), off, len,
1766 bufferlist{bl}, op_flags);
1767 tracepoint(librbd, aio_writesame_exit, 0);
1768 return 0;
1769 }
1770
1771 int Image::aio_compare_and_write(uint64_t off, size_t len,
1772 ceph::bufferlist& cmp_bl, ceph::bufferlist& bl,
1773 RBD::AioCompletion *c, uint64_t *mismatch_off,
1774 int op_flags)
1775 {
1776 ImageCtx *ictx = (ImageCtx *)ctx;
1777 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(),
1778 ictx->snap_name.c_str(),
1779 ictx->read_only, off, len, cmp_bl.length() < len ? NULL : cmp_bl.c_str(),
1780 bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1781
1782 if (bl.length() < len) {
1783 tracepoint(librbd, compare_and_write_exit, -EINVAL);
1784 return -EINVAL;
1785 }
1786
1787 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(c), off, len,
1788 bufferlist{cmp_bl}, bufferlist{bl},
1789 mismatch_off, op_flags, false);
1790
1791 tracepoint(librbd, aio_compare_and_write_exit, 0);
1792
1793 return 0;
1794 }
1795
1796 int Image::invalidate_cache()
1797 {
1798 ImageCtx *ictx = (ImageCtx *)ctx;
1799 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1800 int r = librbd::invalidate_cache(ictx);
1801 tracepoint(librbd, invalidate_cache_exit, r);
1802 return r;
1803 }
1804
1805 int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp)
1806 {
1807 io::AioCompletion *cs[numcomp];
1808 ImageCtx *ictx = (ImageCtx *)ctx;
1809 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
1810 int r = librbd::poll_io_events(ictx, cs, numcomp);
1811 tracepoint(librbd, poll_io_events_exit, r);
1812 if (r > 0) {
1813 for (int i = 0; i < numcomp; ++i)
1814 comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
1815 }
1816 return r;
1817 }
1818
1819 int Image::metadata_get(const std::string &key, std::string *value)
1820 {
1821 ImageCtx *ictx = (ImageCtx *)ctx;
1822 tracepoint(librbd, metadata_get_enter, ictx, key.c_str());
1823 int r = librbd::metadata_get(ictx, key, value);
1824 if (r < 0) {
1825 tracepoint(librbd, metadata_get_exit, r, key.c_str(), NULL);
1826 } else {
1827 tracepoint(librbd, metadata_get_exit, r, key.c_str(), value->c_str());
1828 }
1829 return r;
1830 }
1831
1832 int Image::metadata_set(const std::string &key, const std::string &value)
1833 {
1834 ImageCtx *ictx = (ImageCtx *)ctx;
1835 tracepoint(librbd, metadata_set_enter, ictx, key.c_str(), value.c_str());
1836 int r = ictx->operations->metadata_set(key, value);
1837 tracepoint(librbd, metadata_set_exit, r);
1838 return r;
1839 }
1840
1841 int Image::metadata_remove(const std::string &key)
1842 {
1843 ImageCtx *ictx = (ImageCtx *)ctx;
1844 tracepoint(librbd, metadata_remove_enter, ictx, key.c_str());
1845 int r = ictx->operations->metadata_remove(key);
1846 tracepoint(librbd, metadata_remove_exit, r);
1847 return r;
1848 }
1849
1850 int Image::metadata_list(const std::string &start, uint64_t max, map<string, bufferlist> *pairs)
1851 {
1852 ImageCtx *ictx = (ImageCtx *)ctx;
1853 tracepoint(librbd, metadata_list_enter, ictx);
1854 int r = librbd::metadata_list(ictx, start, max, pairs);
1855 if (r >= 0) {
1856 for (map<string, bufferlist>::iterator it = pairs->begin();
1857 it != pairs->end(); ++it) {
1858 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
1859 }
1860 }
1861 tracepoint(librbd, metadata_list_exit, r);
1862 return r;
1863 }
1864
1865 int Image::mirror_image_enable() {
1866 ImageCtx *ictx = (ImageCtx *)ctx;
1867 return librbd::api::Mirror<>::image_enable(ictx, false);
1868 }
1869
1870 int Image::mirror_image_disable(bool force) {
1871 ImageCtx *ictx = (ImageCtx *)ctx;
1872 return librbd::api::Mirror<>::image_disable(ictx, force);
1873 }
1874
1875 int Image::mirror_image_promote(bool force) {
1876 ImageCtx *ictx = (ImageCtx *)ctx;
1877 return librbd::api::Mirror<>::image_promote(ictx, force);
1878 }
1879
1880 int Image::mirror_image_demote() {
1881 ImageCtx *ictx = (ImageCtx *)ctx;
1882 return librbd::api::Mirror<>::image_demote(ictx);
1883 }
1884
1885 int Image::mirror_image_resync()
1886 {
1887 ImageCtx *ictx = (ImageCtx *)ctx;
1888 return librbd::api::Mirror<>::image_resync(ictx);
1889 }
1890
1891 int Image::mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1892 size_t info_size) {
1893 ImageCtx *ictx = (ImageCtx *)ctx;
1894 return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info,
1895 info_size);
1896 }
1897
1898 int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
1899 size_t status_size) {
1900 ImageCtx *ictx = (ImageCtx *)ctx;
1901 return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status,
1902 status_size);
1903 }
1904
1905 int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
1906 ImageCtx *ictx = (ImageCtx *)ctx;
1907 librbd::api::Mirror<>::image_promote(
1908 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1909 get_aio_completion(c)));
1910 return 0;
1911 }
1912
1913 int Image::aio_mirror_image_demote(RBD::AioCompletion *c) {
1914 ImageCtx *ictx = (ImageCtx *)ctx;
1915 librbd::api::Mirror<>::image_demote(
1916 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1917 get_aio_completion(c)));
1918 return 0;
1919 }
1920
1921 int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1922 size_t info_size,
1923 RBD::AioCompletion *c) {
1924 ImageCtx *ictx = (ImageCtx *)ctx;
1925 librbd::api::Mirror<>::image_get_info(
1926 ictx, mirror_image_info, info_size,
1927 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1928 get_aio_completion(c)));
1929 return 0;
1930 }
1931
1932 int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
1933 size_t status_size,
1934 RBD::AioCompletion *c) {
1935 ImageCtx *ictx = (ImageCtx *)ctx;
1936 librbd::api::Mirror<>::image_get_status(
1937 ictx, status, status_size,
1938 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1939 get_aio_completion(c)));
1940 return 0;
1941 }
1942
1943 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
1944 ImageCtx *ictx = (ImageCtx *)ctx;
1945 tracepoint(librbd, update_watch_enter, ictx, wctx);
1946 int r = ictx->state->register_update_watcher(wctx, handle);
1947 tracepoint(librbd, update_watch_exit, r, *handle);
1948 return r;
1949 }
1950
1951 int Image::update_unwatch(uint64_t handle) {
1952 ImageCtx *ictx = (ImageCtx *)ctx;
1953 tracepoint(librbd, update_unwatch_enter, ictx, handle);
1954 int r = ictx->state->unregister_update_watcher(handle);
1955 tracepoint(librbd, update_unwatch_exit, r);
1956 return r;
1957 }
1958
1959 } // namespace librbd
1960
1961 extern "C" void rbd_version(int *major, int *minor, int *extra)
1962 {
1963 if (major)
1964 *major = LIBRBD_VER_MAJOR;
1965 if (minor)
1966 *minor = LIBRBD_VER_MINOR;
1967 if (extra)
1968 *extra = LIBRBD_VER_EXTRA;
1969 }
1970
1971 extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
1972 {
1973 librbd::image_options_create(opts);
1974 }
1975
1976 extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
1977 {
1978 librbd::image_options_destroy(opts);
1979 }
1980
1981 extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
1982 const char* optval)
1983 {
1984 return librbd::image_options_set(opts, optname, optval);
1985 }
1986
1987 extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
1988 uint64_t optval)
1989 {
1990 return librbd::image_options_set(opts, optname, optval);
1991 }
1992
1993 extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
1994 char* optval, size_t maxlen)
1995 {
1996 std::string optval_;
1997
1998 int r = librbd::image_options_get(opts, optname, &optval_);
1999
2000 if (r < 0) {
2001 return r;
2002 }
2003
2004 if (optval_.size() >= maxlen) {
2005 return -E2BIG;
2006 }
2007
2008 strncpy(optval, optval_.c_str(), maxlen);
2009
2010 return 0;
2011 }
2012
2013 extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
2014 uint64_t* optval)
2015 {
2016 return librbd::image_options_get(opts, optname, optval);
2017 }
2018
2019 extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
2020 bool* is_set)
2021 {
2022 return librbd::image_options_is_set(opts, optname, is_set);
2023 }
2024
2025 extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
2026 {
2027 return librbd::image_options_unset(opts, optname);
2028 }
2029
2030 extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
2031 {
2032 librbd::image_options_clear(opts);
2033 }
2034
2035 extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
2036 {
2037 return librbd::image_options_is_empty(opts);
2038 }
2039
2040 /* pool mirroring */
2041 extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
2042 rbd_mirror_mode_t *mirror_mode) {
2043 librados::IoCtx io_ctx;
2044 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2045 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
2046 }
2047
2048 extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
2049 rbd_mirror_mode_t mirror_mode) {
2050 librados::IoCtx io_ctx;
2051 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2052 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
2053 }
2054
2055 extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
2056 size_t uuid_max_length,
2057 const char *cluster_name,
2058 const char *client_name) {
2059 static const std::size_t UUID_LENGTH = 36;
2060
2061 librados::IoCtx io_ctx;
2062 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2063
2064 if (uuid_max_length < UUID_LENGTH + 1) {
2065 return -E2BIG;
2066 }
2067
2068 std::string uuid_str;
2069 int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
2070 client_name);
2071 if (r >= 0) {
2072 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
2073 uuid[uuid_max_length - 1] = '\0';
2074 }
2075 return r;
2076 }
2077
2078 extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
2079 librados::IoCtx io_ctx;
2080 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2081 int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
2082 return r;
2083 }
2084
2085 extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
2086 rbd_mirror_peer_t *peers, int *max_peers) {
2087 librados::IoCtx io_ctx;
2088 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2089
2090 std::vector<librbd::mirror_peer_t> peer_vector;
2091 int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
2092 if (r < 0) {
2093 return r;
2094 }
2095
2096 if (*max_peers < static_cast<int>(peer_vector.size())) {
2097 *max_peers = static_cast<int>(peer_vector.size());
2098 return -ERANGE;
2099 }
2100
2101 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
2102 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
2103 peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
2104 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
2105 }
2106 *max_peers = static_cast<int>(peer_vector.size());
2107 return 0;
2108 }
2109
2110 extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
2111 int max_peers) {
2112 for (int i = 0; i < max_peers; ++i) {
2113 free(peers[i].uuid);
2114 free(peers[i].cluster_name);
2115 free(peers[i].client_name);
2116 }
2117 }
2118
2119 extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
2120 const char *client_name) {
2121 librados::IoCtx io_ctx;
2122 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2123 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
2124 }
2125
2126 extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
2127 const char *cluster_name) {
2128 librados::IoCtx io_ctx;
2129 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2130 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
2131 }
2132
2133 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
2134 const char *start_id, size_t max, char **image_ids,
2135 rbd_mirror_image_status_t *images, size_t *len) {
2136 librados::IoCtx io_ctx;
2137 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2138 std::map<std::string, librbd::mirror_image_status_t> cpp_images;
2139
2140 int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
2141 &cpp_images);
2142 if (r < 0) {
2143 return r;
2144 }
2145
2146 size_t i = 0;
2147 for (auto &it : cpp_images) {
2148 assert(i < max);
2149 const std::string &image_id = it.first;
2150 image_ids[i] = strdup(image_id.c_str());
2151 mirror_image_status_cpp_to_c(it.second, &images[i]);
2152 i++;
2153 }
2154 *len = i;
2155 return 0;
2156 }
2157
2158 extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
2159 rbd_mirror_image_status_t *images, size_t len) {
2160 for (size_t i = 0; i < len; i++) {
2161 free(image_ids[i]);
2162 free(images[i].name);
2163 free(images[i].info.global_id);
2164 free(images[i].description);
2165 }
2166 }
2167
2168 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
2169 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
2170
2171 librados::IoCtx io_ctx;
2172 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2173
2174 std::map<librbd::mirror_image_status_state_t, int> states_;
2175 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
2176 if (r < 0) {
2177 return r;
2178 }
2179
2180 size_t i = 0;
2181 for (auto &it : states_) {
2182 if (i == *maxlen) {
2183 return -ERANGE;
2184 }
2185 states[i] = it.first;
2186 counts[i] = it.second;
2187 i++;
2188 }
2189 *maxlen = i;
2190 return 0;
2191 }
2192
2193 /* images */
2194 extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
2195 {
2196 librados::IoCtx io_ctx;
2197 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2198 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2199 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2200 vector<string> cpp_names;
2201 int r = librbd::list(io_ctx, cpp_names);
2202 if (r < 0) {
2203 tracepoint(librbd, list_exit, r, *size);
2204 return r;
2205 }
2206
2207 size_t expected_size = 0;
2208
2209 for (size_t i = 0; i < cpp_names.size(); i++) {
2210 expected_size += cpp_names[i].size() + 1;
2211 }
2212 if (*size < expected_size) {
2213 *size = expected_size;
2214 tracepoint(librbd, list_exit, -ERANGE, *size);
2215 return -ERANGE;
2216 }
2217
2218 if (!names)
2219 return -EINVAL;
2220
2221 for (int i = 0; i < (int)cpp_names.size(); i++) {
2222 const char* name = cpp_names[i].c_str();
2223 tracepoint(librbd, list_entry, name);
2224 strcpy(names, name);
2225 names += strlen(names) + 1;
2226 }
2227 tracepoint(librbd, list_exit, (int)expected_size, *size);
2228 return (int)expected_size;
2229 }
2230
2231 extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
2232 {
2233 librados::IoCtx io_ctx;
2234 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2235 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2236 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
2237 int r = librbd::create(io_ctx, name, size, order);
2238 tracepoint(librbd, create_exit, r, *order);
2239 return r;
2240 }
2241
2242 extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
2243 uint64_t size, uint64_t features,
2244 int *order)
2245 {
2246 librados::IoCtx io_ctx;
2247 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2248 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2249 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
2250 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
2251 tracepoint(librbd, create2_exit, r, *order);
2252 return r;
2253 }
2254
2255 extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
2256 uint64_t size, uint64_t features,
2257 int *order,
2258 uint64_t stripe_unit, uint64_t stripe_count)
2259 {
2260 librados::IoCtx io_ctx;
2261 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2262 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2263 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
2264 int r = librbd::create(io_ctx, name, size, false, features, order,
2265 stripe_unit, stripe_count);
2266 tracepoint(librbd, create3_exit, r, *order);
2267 return r;
2268 }
2269
2270 extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
2271 uint64_t size, rbd_image_options_t opts)
2272 {
2273 librados::IoCtx io_ctx;
2274 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2275 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2276 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
2277 librbd::ImageOptions opts_(opts);
2278 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
2279 tracepoint(librbd, create4_exit, r);
2280 return r;
2281 }
2282
2283 extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
2284 const char *p_snap_name, rados_ioctx_t c_ioctx,
2285 const char *c_name, uint64_t features, int *c_order)
2286 {
2287 librados::IoCtx p_ioc, c_ioc;
2288 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2289 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2290 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2291 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);
2292 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2293 features, c_order, 0, 0);
2294 tracepoint(librbd, clone_exit, r, *c_order);
2295 return r;
2296 }
2297
2298 extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
2299 const char *p_snap_name, rados_ioctx_t c_ioctx,
2300 const char *c_name, uint64_t features, int *c_order,
2301 uint64_t stripe_unit, int stripe_count)
2302 {
2303 librados::IoCtx p_ioc, c_ioc;
2304 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2305 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2306 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2307 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);
2308 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2309 features, c_order, stripe_unit, stripe_count);
2310 tracepoint(librbd, clone2_exit, r, *c_order);
2311 return r;
2312 }
2313
2314 extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
2315 const char *p_snap_name, rados_ioctx_t c_ioctx,
2316 const char *c_name, rbd_image_options_t c_opts)
2317 {
2318 librados::IoCtx p_ioc, c_ioc;
2319 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2320 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2321 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2322 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);
2323 librbd::ImageOptions c_opts_(c_opts);
2324 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_);
2325 tracepoint(librbd, clone3_exit, r);
2326 return r;
2327 }
2328
2329 extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
2330 {
2331 librados::IoCtx io_ctx;
2332 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2333 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2334 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2335 librbd::NoOpProgressContext prog_ctx;
2336 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2337 tracepoint(librbd, remove_exit, r);
2338 return r;
2339 }
2340
2341 extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
2342 librbd_progress_fn_t cb, void *cbdata)
2343 {
2344 librados::IoCtx io_ctx;
2345 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2346 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2347 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2348 librbd::CProgressContext prog_ctx(cb, cbdata);
2349 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2350 tracepoint(librbd, remove_exit, r);
2351 return r;
2352 }
2353
2354 extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
2355 uint64_t delay) {
2356 librados::IoCtx io_ctx;
2357 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2358 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2359 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
2360 io_ctx.get_id(), name);
2361 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, delay);
2362 tracepoint(librbd, trash_move_exit, r);
2363 return r;
2364 }
2365
2366 extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
2367 rbd_trash_image_info_t *info) {
2368 librados::IoCtx io_ctx;
2369 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
2370
2371 librbd::trash_image_info_t cpp_info;
2372 int r = librbd::trash_get(io_ctx, id, &cpp_info);
2373 if (r < 0) {
2374 return r;
2375 }
2376
2377 trash_image_info_cpp_to_c(cpp_info, info);
2378 return 0;
2379 }
2380
2381 extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
2382 free(info->id);
2383 free(info->name);
2384 }
2385
2386 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
2387 size_t *num_entries) {
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_list_enter,
2392 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2393
2394 vector<librbd::trash_image_info_t> cpp_entries;
2395 int r = librbd::trash_list(io_ctx, cpp_entries);
2396 if (r < 0) {
2397 tracepoint(librbd, trash_list_exit, r, *num_entries);
2398 return r;
2399 }
2400
2401 if (*num_entries < cpp_entries.size()) {
2402 *num_entries = cpp_entries.size();
2403 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
2404 return -ERANGE;
2405 }
2406
2407 int i=0;
2408 for (const auto &entry : cpp_entries) {
2409 trash_image_info_cpp_to_c(entry, &entries[i++]);
2410 }
2411 *num_entries = cpp_entries.size();
2412
2413 return *num_entries;
2414 }
2415
2416 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
2417 size_t num_entries) {
2418 for (size_t i=0; i < num_entries; i++) {
2419 rbd_trash_get_cleanup(&entries[i]);
2420 }
2421 }
2422
2423 extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
2424 bool force) {
2425 librados::IoCtx io_ctx;
2426 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2427 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2428 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2429 io_ctx.get_id(), image_id, force);
2430 librbd::NoOpProgressContext prog_ctx;
2431 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2432 tracepoint(librbd, trash_remove_exit, r);
2433 return r;
2434 }
2435
2436 extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
2437 const char *image_id,
2438 bool force,
2439 librbd_progress_fn_t cb,
2440 void *cbdata) {
2441 librados::IoCtx io_ctx;
2442 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2443 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2444 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2445 io_ctx.get_id(), image_id, force);
2446 librbd::CProgressContext prog_ctx(cb, cbdata);
2447 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2448 tracepoint(librbd, trash_remove_exit, r);
2449 return r;
2450 }
2451
2452 extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
2453 const char *name) {
2454 librados::IoCtx io_ctx;
2455 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2456 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2457 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
2458 io_ctx.get_id(), id, name);
2459 int r = librbd::trash_restore(io_ctx, id, name);
2460 tracepoint(librbd, trash_undelete_exit, r);
2461 return r;
2462 }
2463
2464 extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
2465 const char *destname)
2466 {
2467 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2468 librados::IoCtx dest_io_ctx;
2469 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2470 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);
2471 librbd::ImageOptions opts;
2472 librbd::NoOpProgressContext prog_ctx;
2473 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2474 tracepoint(librbd, copy_exit, r);
2475 return r;
2476 }
2477
2478 extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
2479 {
2480 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2481 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2482 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);
2483 librbd::NoOpProgressContext prog_ctx;
2484 int r = librbd::copy(src, dest, prog_ctx, 0);
2485 tracepoint(librbd, copy2_exit, r);
2486 return r;
2487 }
2488
2489 extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
2490 const char *destname, rbd_image_options_t c_opts)
2491 {
2492 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2493 librados::IoCtx dest_io_ctx;
2494 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2495 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);
2496 librbd::ImageOptions c_opts_(c_opts);
2497 librbd::NoOpProgressContext prog_ctx;
2498 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
2499 tracepoint(librbd, copy3_exit, r);
2500 return r;
2501 }
2502
2503 extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
2504 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
2505 {
2506 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2507 librados::IoCtx dest_io_ctx;
2508 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2509 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);
2510 librbd::ImageOptions c_opts_(c_opts);
2511 librbd::NoOpProgressContext prog_ctx;
2512 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
2513 tracepoint(librbd, copy4_exit, r);
2514 return r;
2515 }
2516
2517 extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
2518 const char *destname,
2519 librbd_progress_fn_t fn, void *data)
2520 {
2521 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2522 librados::IoCtx dest_io_ctx;
2523 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2524 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);
2525 librbd::ImageOptions opts;
2526 librbd::CProgressContext prog_ctx(fn, data);
2527 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2528 tracepoint(librbd, copy_exit, ret);
2529 return ret;
2530 }
2531
2532 extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
2533 librbd_progress_fn_t fn, void *data)
2534 {
2535 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2536 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2537 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);
2538 librbd::CProgressContext prog_ctx(fn, data);
2539 int ret = librbd::copy(src, dest, prog_ctx, 0);
2540 tracepoint(librbd, copy2_exit, ret);
2541 return ret;
2542 }
2543
2544 extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
2545 const char *destname,
2546 rbd_image_options_t dest_opts,
2547 librbd_progress_fn_t fn, void *data)
2548 {
2549 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2550 librados::IoCtx dest_io_ctx;
2551 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2552 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);
2553 librbd::ImageOptions dest_opts_(dest_opts);
2554 librbd::CProgressContext prog_ctx(fn, data);
2555 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
2556 tracepoint(librbd, copy3_exit, ret);
2557 return ret;
2558 }
2559
2560 extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
2561 const char *destname,
2562 rbd_image_options_t dest_opts,
2563 librbd_progress_fn_t fn, void *data, size_t sparse_size)
2564 {
2565 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2566 librados::IoCtx dest_io_ctx;
2567 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2568 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);
2569 librbd::ImageOptions dest_opts_(dest_opts);
2570 librbd::CProgressContext prog_ctx(fn, data);
2571 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
2572 tracepoint(librbd, copy4_exit, ret);
2573 return ret;
2574 }
2575
2576
2577 extern "C" int rbd_flatten(rbd_image_t image)
2578 {
2579 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2580 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2581 librbd::NoOpProgressContext prog_ctx;
2582 int r = ictx->operations->flatten(prog_ctx);
2583 tracepoint(librbd, flatten_exit, r);
2584 return r;
2585 }
2586
2587 extern "C" int rbd_flatten_with_progress(rbd_image_t image,
2588 librbd_progress_fn_t cb, void *cbdata)
2589 {
2590 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2591 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2592 librbd::CProgressContext prog_ctx(cb, cbdata);
2593 int r = ictx->operations->flatten(prog_ctx);
2594 tracepoint(librbd, flatten_exit, r);
2595 return r;
2596 }
2597
2598 extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
2599 const char *destname)
2600 {
2601 librados::IoCtx src_io_ctx;
2602 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
2603 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
2604 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
2605 int r = librbd::rename(src_io_ctx, srcname, destname);
2606 tracepoint(librbd, rename_exit, r);
2607 return r;
2608 }
2609
2610 extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
2611 const char *snap_name)
2612 {
2613 librados::IoCtx io_ctx;
2614 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2615 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2616 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2617 false);
2618 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2619
2620 int r = ictx->state->open(false);
2621 if (r >= 0) {
2622 *image = (rbd_image_t)ictx;
2623 }
2624 tracepoint(librbd, open_image_exit, r);
2625 return r;
2626 }
2627
2628 extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
2629 rbd_image_t *image, const char *snap_name)
2630 {
2631 librados::IoCtx io_ctx;
2632 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2633 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2634 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2635 false);
2636 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2637 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2638
2639 int r = ictx->state->open(false);
2640 if (r < 0) {
2641 delete ictx;
2642 } else {
2643 *image = (rbd_image_t)ictx;
2644 }
2645 tracepoint(librbd, open_image_exit, r);
2646 return r;
2647 }
2648
2649 extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
2650 rbd_image_t *image, const char *snap_name,
2651 rbd_completion_t c)
2652 {
2653 librados::IoCtx io_ctx;
2654 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2655 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2656 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2657 false);
2658 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2659 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);
2660 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2661 tracepoint(librbd, aio_open_image_exit, 0);
2662 return 0;
2663 }
2664
2665 extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
2666 rbd_image_t *image, const char *snap_name,
2667 rbd_completion_t c)
2668 {
2669 librados::IoCtx io_ctx;
2670 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2671 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2672 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2673 false);
2674 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2675 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2676 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
2677 comp->pc);
2678 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2679 tracepoint(librbd, aio_open_image_exit, 0);
2680 return 0;
2681 }
2682
2683 extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
2684 rbd_image_t *image, const char *snap_name)
2685 {
2686 librados::IoCtx io_ctx;
2687 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2688 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2689 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2690 true);
2691 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2692
2693 int r = ictx->state->open(false);
2694 if (r >= 0) {
2695 *image = (rbd_image_t)ictx;
2696 }
2697 tracepoint(librbd, open_image_exit, r);
2698 return r;
2699 }
2700
2701 extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
2702 rbd_image_t *image, const char *snap_name)
2703 {
2704 librados::IoCtx io_ctx;
2705 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2706 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2707 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2708 true);
2709 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2710 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2711
2712 int r = ictx->state->open(false);
2713 if (r < 0) {
2714 delete ictx;
2715 } else {
2716 *image = (rbd_image_t)ictx;
2717 }
2718 tracepoint(librbd, open_image_exit, r);
2719 return r;
2720 }
2721
2722 extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
2723 rbd_image_t *image, const char *snap_name,
2724 rbd_completion_t c)
2725 {
2726 librados::IoCtx io_ctx;
2727 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2728 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2729 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2730 true);
2731 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2732 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);
2733 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2734 image));
2735 tracepoint(librbd, aio_open_image_exit, 0);
2736 return 0;
2737 }
2738
2739 extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
2740 rbd_image_t *image,
2741 const char *snap_name,
2742 rbd_completion_t c)
2743 {
2744 librados::IoCtx io_ctx;
2745 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2746 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2747 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2748 true);
2749 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2750 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2751 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2752 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2753 image));
2754 tracepoint(librbd, aio_open_image_exit, 0);
2755 return 0;
2756 }
2757
2758 extern "C" int rbd_close(rbd_image_t image)
2759 {
2760 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2761 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2762
2763 int r = ictx->state->close();
2764
2765 tracepoint(librbd, close_image_exit, r);
2766 return r;
2767 }
2768
2769 extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
2770 {
2771 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2772 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2773 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
2774 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
2775 get_aio_completion(comp)));
2776 tracepoint(librbd, aio_close_image_exit, 0);
2777 return 0;
2778 }
2779
2780 extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
2781 {
2782 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2783 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2784 librbd::NoOpProgressContext prog_ctx;
2785 int r = ictx->operations->resize(size, true, prog_ctx);
2786 tracepoint(librbd, resize_exit, r);
2787 return r;
2788 }
2789
2790 extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
2791 librbd_progress_fn_t cb, void *cbdata)
2792 {
2793 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2794 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2795 librbd::CProgressContext prog_ctx(cb, cbdata);
2796 int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
2797 tracepoint(librbd, resize_exit, r);
2798 return r;
2799 }
2800
2801 extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
2802 librbd_progress_fn_t cb, void *cbdata)
2803 {
2804 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2805 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2806 librbd::CProgressContext prog_ctx(cb, cbdata);
2807 int r = ictx->operations->resize(size, true, prog_ctx);
2808 tracepoint(librbd, resize_exit, r);
2809 return r;
2810 }
2811
2812 extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
2813 size_t infosize)
2814 {
2815 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2816 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2817 int r = librbd::info(ictx, *info, infosize);
2818 tracepoint(librbd, stat_exit, r, info);
2819 return r;
2820 }
2821
2822 extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
2823 {
2824 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2825 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2826 int r = librbd::get_old_format(ictx, old);
2827 tracepoint(librbd, get_old_format_exit, r, *old);
2828 return r;
2829 }
2830
2831 extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
2832 {
2833 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2834 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2835 int r = librbd::get_size(ictx, size);
2836 tracepoint(librbd, get_size_exit, r, *size);
2837 return r;
2838 }
2839
2840 extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
2841 {
2842 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2843 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2844 int r = librbd::get_features(ictx, features);
2845 tracepoint(librbd, get_features_exit, r, *features);
2846 return r;
2847 }
2848
2849 extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
2850 uint8_t enabled)
2851 {
2852 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2853 bool features_enabled = enabled != 0;
2854 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
2855 int r = ictx->operations->update_features(features, features_enabled);
2856 tracepoint(librbd, update_features_exit, r);
2857 return r;
2858 }
2859
2860 extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
2861 {
2862 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2863 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2864 *stripe_unit = ictx->get_stripe_unit();
2865 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
2866 return 0;
2867 }
2868
2869 extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
2870 {
2871 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2872 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2873 *stripe_count = ictx->get_stripe_count();
2874 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
2875 return 0;
2876 }
2877
2878 extern "C" int rbd_get_create_timestamp(rbd_image_t image,
2879 struct timespec *timestamp)
2880 {
2881 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2882 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
2883 ictx->read_only);
2884 utime_t time = ictx->get_create_timestamp();
2885 time.to_timespec(timestamp);
2886 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
2887 return 0;
2888 }
2889
2890 extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
2891 {
2892 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2893 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2894 int r = librbd::get_overlap(ictx, overlap);
2895 tracepoint(librbd, get_overlap_exit, r, *overlap);
2896 return r;
2897 }
2898
2899 extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
2900 {
2901 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2902 if (ictx->old_format) {
2903 return -EINVAL;
2904 }
2905 if (ictx->id.size() >= id_len) {
2906 return -ERANGE;
2907 }
2908
2909 strncpy(id, ictx->id.c_str(), id_len - 1);
2910 id[id_len - 1] = '\0';
2911 return 0;
2912 }
2913
2914 extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
2915 size_t prefix_len)
2916 {
2917 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2918 if (ictx->object_prefix.size() >= prefix_len) {
2919 return -ERANGE;
2920 }
2921
2922 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
2923 prefix[prefix_len - 1] = '\0';
2924 return 0;
2925 }
2926
2927 extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
2928 {
2929 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2930 return ictx->data_ctx.get_id();
2931 }
2932
2933 extern "C" int rbd_get_parent_info(rbd_image_t image,
2934 char *parent_pool_name, size_t ppool_namelen,
2935 char *parent_name, size_t pnamelen,
2936 char *parent_snap_name, size_t psnap_namelen)
2937 {
2938 return rbd_get_parent_info2(image, parent_pool_name, ppool_namelen,
2939 parent_name, pnamelen, nullptr, 0,
2940 parent_snap_name, psnap_namelen);
2941 }
2942
2943 extern "C" int rbd_get_parent_info2(rbd_image_t image,
2944 char *parent_pool_name,
2945 size_t ppool_namelen,
2946 char *parent_name, size_t pnamelen,
2947 char *parent_id, size_t pidlen,
2948 char *parent_snap_name,
2949 size_t psnap_namelen)
2950 {
2951 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2952 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
2953 ictx->snap_name.c_str(), ictx->read_only);
2954 string p_pool_name, p_name, p_id, p_snap_name;
2955
2956 int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_id,
2957 &p_snap_name);
2958 if (r < 0) {
2959 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
2960 return r;
2961 }
2962
2963 if (parent_pool_name) {
2964 if (p_pool_name.length() + 1 > ppool_namelen) {
2965 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2966 return -ERANGE;
2967 }
2968
2969 strcpy(parent_pool_name, p_pool_name.c_str());
2970 }
2971 if (parent_name) {
2972 if (p_name.length() + 1 > pnamelen) {
2973 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2974 return -ERANGE;
2975 }
2976
2977 strcpy(parent_name, p_name.c_str());
2978 }
2979 if (parent_id) {
2980 if (p_id.length() + 1 > pidlen) {
2981 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2982 return -ERANGE;
2983 }
2984
2985 strcpy(parent_id, p_id.c_str());
2986 }
2987 if (parent_snap_name) {
2988 if (p_snap_name.length() + 1 > psnap_namelen) {
2989 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2990 return -ERANGE;
2991 }
2992
2993 strcpy(parent_snap_name, p_snap_name.c_str());
2994 }
2995
2996 tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name,
2997 parent_id, parent_snap_name);
2998 return 0;
2999 }
3000
3001 extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
3002 {
3003 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3004 tracepoint(librbd, get_flags_enter, ictx);
3005 int r = librbd::get_flags(ictx, flags);
3006 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
3007 return r;
3008 }
3009
3010 extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
3011 {
3012 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3013 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
3014 int r = librbd::set_image_notification(ictx, fd, type);
3015 tracepoint(librbd, set_image_notification_exit, ictx, r);
3016 return r;
3017 }
3018
3019 extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
3020 {
3021 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3022 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
3023 bool owner;
3024 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
3025 *is_owner = owner ? 1 : 0;
3026 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
3027 return r;
3028 }
3029
3030 extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
3031 {
3032 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3033 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
3034 int r = librbd::lock_acquire(ictx, lock_mode);
3035 tracepoint(librbd, lock_acquire_exit, ictx, r);
3036 return r;
3037 }
3038
3039 extern "C" int rbd_lock_release(rbd_image_t image)
3040 {
3041 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3042 tracepoint(librbd, lock_release_enter, ictx);
3043 int r = librbd::lock_release(ictx);
3044 tracepoint(librbd, lock_release_exit, ictx, r);
3045 return r;
3046 }
3047
3048 extern "C" int rbd_lock_get_owners(rbd_image_t image,
3049 rbd_lock_mode_t *lock_mode,
3050 char **lock_owners,
3051 size_t *max_lock_owners)
3052 {
3053 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3054 tracepoint(librbd, lock_get_owners_enter, ictx);
3055 std::list<std::string> lock_owner_list;
3056 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
3057 if (r >= 0) {
3058 if (*max_lock_owners >= lock_owner_list.size()) {
3059 *max_lock_owners = 0;
3060 for (auto &lock_owner : lock_owner_list) {
3061 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
3062 }
3063 } else {
3064 *max_lock_owners = lock_owner_list.size();
3065 r = -ERANGE;
3066 }
3067 }
3068 tracepoint(librbd, lock_get_owners_exit, ictx, r);
3069 return r;
3070 }
3071
3072 extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
3073 size_t lock_owner_count)
3074 {
3075 for (size_t i = 0; i < lock_owner_count; ++i) {
3076 free(lock_owners[i]);
3077 }
3078 }
3079
3080 extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
3081 const char *lock_owner)
3082 {
3083 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3084 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
3085 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
3086 tracepoint(librbd, lock_break_exit, ictx, r);
3087 return r;
3088 }
3089
3090 extern "C" int rbd_rebuild_object_map(rbd_image_t image,
3091 librbd_progress_fn_t cb, void *cbdata)
3092 {
3093 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3094 librbd::CProgressContext prog_ctx(cb, cbdata);
3095 return ictx->operations->rebuild_object_map(prog_ctx);
3096 }
3097
3098 /* snapshots */
3099 extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
3100 {
3101 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3102 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3103 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
3104 snap_name);
3105 tracepoint(librbd, snap_create_exit, r);
3106 return r;
3107 }
3108
3109 extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
3110 {
3111 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3112 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
3113 int r = ictx->operations->snap_rename(srcname, dstname);
3114 tracepoint(librbd, snap_rename_exit, r);
3115 return r;
3116 }
3117
3118 extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
3119 {
3120 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3121 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3122 librbd::NoOpProgressContext prog_ctx;
3123 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
3124 tracepoint(librbd, snap_remove_exit, r);
3125 return r;
3126 }
3127
3128 extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
3129 librbd_progress_fn_t cb, void *cbdata)
3130 {
3131 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3132 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
3133 librbd::CProgressContext prog_ctx(cb, cbdata);
3134 int r = librbd::snap_remove(ictx, snap_name, flags, prog_ctx);
3135 tracepoint(librbd, snap_remove_exit, r);
3136 return r;
3137 }
3138
3139 extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
3140 {
3141 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3142 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3143 librbd::NoOpProgressContext prog_ctx;
3144 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3145 tracepoint(librbd, snap_rollback_exit, r);
3146 return r;
3147 }
3148
3149 extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
3150 const char *snap_name,
3151 librbd_progress_fn_t cb,
3152 void *cbdata)
3153 {
3154 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3155 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3156 librbd::CProgressContext prog_ctx(cb, cbdata);
3157 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3158 tracepoint(librbd, snap_rollback_exit, r);
3159 return r;
3160 }
3161
3162 extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
3163 int *max_snaps)
3164 {
3165 vector<librbd::snap_info_t> cpp_snaps;
3166 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3167 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
3168
3169 if (!max_snaps) {
3170 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
3171 return -EINVAL;
3172 }
3173
3174 int r = librbd::snap_list(ictx, cpp_snaps);
3175 if (r == -ENOENT) {
3176 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
3177 return 0;
3178 }
3179 if (r < 0) {
3180 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3181 return r;
3182 }
3183 if (*max_snaps < (int)cpp_snaps.size() + 1) {
3184 *max_snaps = (int)cpp_snaps.size() + 1;
3185 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
3186 return -ERANGE;
3187 }
3188
3189 int i;
3190
3191 for (i = 0; i < (int)cpp_snaps.size(); i++) {
3192 snaps[i].id = cpp_snaps[i].id;
3193 snaps[i].size = cpp_snaps[i].size;
3194 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
3195 if (!snaps[i].name) {
3196 for (int j = 0; j < i; j++)
3197 free((void *)snaps[j].name);
3198 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
3199 return -ENOMEM;
3200 }
3201 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
3202 }
3203 snaps[i].id = 0;
3204 snaps[i].size = 0;
3205 snaps[i].name = NULL;
3206
3207 r = (int)cpp_snaps.size();
3208 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3209 return r;
3210 }
3211
3212 extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
3213 {
3214 tracepoint(librbd, snap_list_end_enter, snaps);
3215 while (snaps->name) {
3216 free((void *)snaps->name);
3217 snaps++;
3218 }
3219 tracepoint(librbd, snap_list_end_exit);
3220 }
3221
3222 extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
3223 {
3224 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3225 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3226 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
3227 tracepoint(librbd, snap_protect_exit, r);
3228 return r;
3229 }
3230
3231 extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
3232 {
3233 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3234 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3235 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
3236 tracepoint(librbd, snap_unprotect_exit, r);
3237 return r;
3238 }
3239
3240 extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
3241 int *is_protected)
3242 {
3243 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3244 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3245 bool protected_snap;
3246 int r = librbd::snap_is_protected(ictx, snap_name, &protected_snap);
3247 if (r < 0) {
3248 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
3249 return r;
3250 }
3251 *is_protected = protected_snap ? 1 : 0;
3252 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
3253 return 0;
3254 }
3255
3256 extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
3257 {
3258 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3259 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
3260 int r = librbd::snap_get_limit(ictx, limit);
3261 tracepoint(librbd, snap_get_limit_exit, r, *limit);
3262 return r;
3263 }
3264
3265 extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
3266 {
3267 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3268 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
3269 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
3270 tracepoint(librbd, snap_get_timestamp_exit, r);
3271 return r;
3272 }
3273
3274 extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
3275 {
3276 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3277 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
3278 int r = librbd::snap_set_limit(ictx, limit);
3279 tracepoint(librbd, snap_set_limit_exit, r);
3280 return r;
3281 }
3282
3283 extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
3284 {
3285 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3286 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3287 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
3288 tracepoint(librbd, snap_set_exit, r);
3289 return r;
3290 }
3291
3292 extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
3293 size_t *pools_len, char *images,
3294 size_t *images_len)
3295 {
3296 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3297 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3298 set<pair<string, string> > image_set;
3299
3300 int r = librbd::list_children(ictx, image_set);
3301 if (r < 0) {
3302 tracepoint(librbd, list_children_exit, r);
3303 return r;
3304 }
3305
3306 size_t pools_total = 0;
3307 size_t images_total = 0;
3308 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3309 it != image_set.end(); ++it) {
3310 pools_total += it->first.length() + 1;
3311 images_total += it->second.length() + 1;
3312 }
3313
3314 bool too_short = false;
3315 if (pools_total > *pools_len)
3316 too_short = true;
3317 if (images_total > *images_len)
3318 too_short = true;
3319 *pools_len = pools_total;
3320 *images_len = images_total;
3321 if (too_short) {
3322 tracepoint(librbd, list_children_exit, -ERANGE);
3323 return -ERANGE;
3324 }
3325
3326 char *pools_p = pools;
3327 char *images_p = images;
3328 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3329 it != image_set.end(); ++it) {
3330 const char* pool = it->first.c_str();
3331 strcpy(pools_p, pool);
3332 pools_p += it->first.length() + 1;
3333 const char* image = it->second.c_str();
3334 strcpy(images_p, image);
3335 images_p += it->second.length() + 1;
3336 tracepoint(librbd, list_children_entry, pool, image);
3337 }
3338
3339 ssize_t ret = image_set.size();
3340 tracepoint(librbd, list_children_exit, ret);
3341 return ret;
3342 }
3343
3344 extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
3345 char *tag, size_t *tag_len,
3346 char *clients, size_t *clients_len,
3347 char *cookies, size_t *cookies_len,
3348 char *addrs, size_t *addrs_len)
3349 {
3350 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3351 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3352 std::list<librbd::locker_t> lockers;
3353 bool exclusive_bool;
3354 string tag_str;
3355
3356 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
3357 if (r < 0) {
3358 tracepoint(librbd, list_lockers_exit, r);
3359 return r;
3360 }
3361
3362 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
3363
3364 *exclusive = (int)exclusive_bool;
3365 size_t clients_total = 0;
3366 size_t cookies_total = 0;
3367 size_t addrs_total = 0;
3368 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3369 it != lockers.end(); ++it) {
3370 clients_total += it->client.length() + 1;
3371 cookies_total += it->cookie.length() + 1;
3372 addrs_total += it->address.length() + 1;
3373 }
3374
3375 bool too_short = ((clients_total > *clients_len) ||
3376 (cookies_total > *cookies_len) ||
3377 (addrs_total > *addrs_len) ||
3378 (tag_str.length() + 1 > *tag_len));
3379 *clients_len = clients_total;
3380 *cookies_len = cookies_total;
3381 *addrs_len = addrs_total;
3382 *tag_len = tag_str.length() + 1;
3383 if (too_short) {
3384 tracepoint(librbd, list_lockers_exit, -ERANGE);
3385 return -ERANGE;
3386 }
3387
3388 strcpy(tag, tag_str.c_str());
3389 char *clients_p = clients;
3390 char *cookies_p = cookies;
3391 char *addrs_p = addrs;
3392 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3393 it != lockers.end(); ++it) {
3394 const char* client = it->client.c_str();
3395 strcpy(clients_p, client);
3396 clients_p += it->client.length() + 1;
3397 const char* cookie = it->cookie.c_str();
3398 strcpy(cookies_p, cookie);
3399 cookies_p += it->cookie.length() + 1;
3400 const char* address = it->address.c_str();
3401 strcpy(addrs_p, address);
3402 addrs_p += it->address.length() + 1;
3403 tracepoint(librbd, list_lockers_entry, client, cookie, address);
3404 }
3405
3406 ssize_t ret = lockers.size();
3407 tracepoint(librbd, list_lockers_exit, ret);
3408 return ret;
3409 }
3410
3411 extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
3412 {
3413 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3414 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3415 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
3416 tracepoint(librbd, lock_exclusive_exit, r);
3417 return r;
3418 }
3419
3420 extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
3421 const char *tag)
3422 {
3423 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3424 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
3425 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
3426 tracepoint(librbd, lock_shared_exit, r);
3427 return r;
3428 }
3429
3430 extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
3431 {
3432 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3433 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3434 int r = librbd::unlock(ictx, cookie ? cookie : "");
3435 tracepoint(librbd, unlock_exit, r);
3436 return r;
3437 }
3438
3439 extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
3440 const char *cookie)
3441 {
3442 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3443 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
3444 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
3445 tracepoint(librbd, break_lock_exit, r);
3446 return r;
3447 }
3448
3449 /* I/O */
3450 extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
3451 char *buf)
3452 {
3453 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3454 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3455 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3456 0);
3457 tracepoint(librbd, read_exit, r);
3458 return r;
3459 }
3460
3461 extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
3462 char *buf, int op_flags)
3463 {
3464 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3465 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
3466 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
3467 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3468 op_flags);
3469 tracepoint(librbd, read_exit, r);
3470 return r;
3471 }
3472
3473
3474 extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_t len,
3475 int (*cb)(uint64_t, size_t, const char *, void *),
3476 void *arg)
3477 {
3478 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3479 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3480 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3481 tracepoint(librbd, read_iterate_exit, r);
3482 return r;
3483 }
3484
3485 extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
3486 int (*cb)(uint64_t, size_t, const char *, void *),
3487 void *arg)
3488 {
3489 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3490 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3491 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3492 if (r > 0)
3493 r = 0;
3494 tracepoint(librbd, read_iterate2_exit, r);
3495 return (int)r;
3496 }
3497
3498 extern "C" int rbd_diff_iterate(rbd_image_t image,
3499 const char *fromsnapname,
3500 uint64_t ofs, uint64_t len,
3501 int (*cb)(uint64_t, size_t, int, void *),
3502 void *arg)
3503 {
3504 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3505 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3506 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3507 true, false);
3508 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3509 cls::rbd::UserSnapshotNamespace(),
3510 fromsnapname, ofs, len,
3511 true, false, cb, arg);
3512 tracepoint(librbd, diff_iterate_exit, r);
3513 return r;
3514 }
3515
3516 extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
3517 uint64_t ofs, uint64_t len,
3518 uint8_t include_parent, uint8_t whole_object,
3519 int (*cb)(uint64_t, size_t, int, void *),
3520 void *arg)
3521 {
3522 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3523 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3524 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3525 include_parent != 0, whole_object != 0);
3526 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3527 cls::rbd::UserSnapshotNamespace(),
3528 fromsnapname, ofs, len,
3529 include_parent, whole_object,
3530 cb, arg);
3531 tracepoint(librbd, diff_iterate_exit, r);
3532 return r;
3533 }
3534
3535 extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
3536 const char *buf)
3537 {
3538 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3539 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
3540
3541 bufferlist bl;
3542 bl.push_back(create_write_raw(ictx, buf, len));
3543 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
3544 tracepoint(librbd, write_exit, r);
3545 return r;
3546 }
3547
3548 extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
3549 const char *buf, int op_flags)
3550 {
3551 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3552 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
3553 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
3554
3555 bufferlist bl;
3556 bl.push_back(create_write_raw(ictx, buf, len));
3557 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
3558 tracepoint(librbd, write_exit, r);
3559 return r;
3560 }
3561
3562
3563 extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
3564 {
3565 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3566 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3567 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
3568 tracepoint(librbd, discard_exit, r);
3569 return r;
3570 }
3571
3572 extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
3573 const char *buf, size_t data_len, int op_flags)
3574 {
3575 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3576 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3577 ictx->read_only, ofs, len, data_len <= 0 ? NULL : buf, data_len, op_flags);
3578
3579 if (data_len <= 0 || len % data_len) {
3580 tracepoint(librbd, writesame_exit, -EINVAL);
3581 return -EINVAL;
3582 }
3583
3584 if (mem_is_zero(buf, data_len)) {
3585 int r = ictx->io_work_queue->discard(ofs, len, false);
3586 tracepoint(librbd, writesame_exit, r);
3587 return r;
3588 }
3589
3590 bufferlist bl;
3591 bl.push_back(create_write_raw(ictx, buf, data_len));
3592 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
3593 tracepoint(librbd, writesame_exit, r);
3594 return r;
3595 }
3596
3597 extern "C" ssize_t rbd_compare_and_write(rbd_image_t image,
3598 uint64_t ofs, size_t len,
3599 const char *cmp_buf,
3600 const char *buf,
3601 uint64_t *mismatch_off,
3602 int op_flags)
3603 {
3604 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3605 tracepoint(librbd, compare_and_write_enter, ictx, ictx->name.c_str(),
3606 ictx->snap_name.c_str(), ictx->read_only, ofs,
3607 len, cmp_buf, buf, op_flags);
3608
3609 bufferlist cmp_bl;
3610 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len));
3611 bufferlist bl;
3612 bl.push_back(create_write_raw(ictx, buf, len));
3613
3614 int r = ictx->io_work_queue->compare_and_write(ofs, len, std::move(cmp_bl),
3615 std::move(bl), mismatch_off,
3616 op_flags);
3617 tracepoint(librbd, compare_and_write_exit, r);
3618 return r;
3619 }
3620
3621 extern "C" int rbd_aio_create_completion(void *cb_arg,
3622 rbd_callback_t complete_cb,
3623 rbd_completion_t *c)
3624 {
3625 librbd::RBD::AioCompletion *rbd_comp =
3626 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
3627 *c = (rbd_completion_t) rbd_comp;
3628 return 0;
3629 }
3630
3631 extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
3632 const char *buf, rbd_completion_t c)
3633 {
3634 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3635 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3636 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3637
3638 bufferlist bl;
3639 bl.push_back(create_write_raw(ictx, buf, len));
3640 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3641 std::move(bl), 0);
3642 tracepoint(librbd, aio_write_exit, 0);
3643 return 0;
3644 }
3645
3646 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
3647 const char *buf, rbd_completion_t c, int op_flags)
3648 {
3649 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3650 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3651 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3652 ictx->read_only, off, len, buf, comp->pc, op_flags);
3653
3654 bufferlist bl;
3655 bl.push_back(create_write_raw(ictx, buf, len));
3656 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3657 std::move(bl), op_flags);
3658 tracepoint(librbd, aio_write_exit, 0);
3659 return 0;
3660 }
3661
3662 extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
3663 int iovcnt, uint64_t off, rbd_completion_t c)
3664 {
3665 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3666 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3667
3668 // convert the scatter list into a bufferlist
3669 ssize_t len = 0;
3670 bufferlist bl;
3671 for (int i = 0; i < iovcnt; ++i) {
3672 const struct iovec &io = iov[i];
3673 len += io.iov_len;
3674 if (len < 0) {
3675 break;
3676 }
3677
3678 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
3679 io.iov_len));
3680 }
3681
3682 int r = 0;
3683 if (iovcnt <= 0 || len < 0) {
3684 r = -EINVAL;
3685 }
3686
3687 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
3688 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3689 comp->pc);
3690 if (r == 0) {
3691 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3692 std::move(bl), 0);
3693 }
3694 tracepoint(librbd, aio_write_exit, r);
3695 return r;
3696 }
3697
3698 extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
3699 rbd_completion_t c)
3700 {
3701 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3702 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3703 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
3704 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard);
3705 tracepoint(librbd, aio_discard_exit, 0);
3706 return 0;
3707 }
3708
3709 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
3710 char *buf, rbd_completion_t c)
3711 {
3712 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3713 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3714 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3715 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3716 librbd::io::ReadResult{buf, len}, 0);
3717 tracepoint(librbd, aio_read_exit, 0);
3718 return 0;
3719 }
3720
3721 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
3722 char *buf, rbd_completion_t c, int op_flags)
3723 {
3724 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3725 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3726 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3727 ictx->read_only, off, len, buf, comp->pc, op_flags);
3728 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3729 librbd::io::ReadResult{buf, len},op_flags);
3730 tracepoint(librbd, aio_read_exit, 0);
3731 return 0;
3732 }
3733
3734 extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
3735 int iovcnt, uint64_t off, rbd_completion_t c)
3736 {
3737 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3738 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3739
3740 ssize_t len = 0;
3741 for (int i = 0; i < iovcnt; ++i) {
3742 len += iov[i].iov_len;
3743 if (len < 0) {
3744 break;
3745 }
3746 }
3747
3748 int r = 0;
3749 if (iovcnt == 0 || len < 0) {
3750 r = -EINVAL;
3751 }
3752
3753 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
3754 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3755 comp->pc);
3756 if (r == 0) {
3757 librbd::io::ReadResult read_result;
3758 if (iovcnt == 1) {
3759 read_result = librbd::io::ReadResult(
3760 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
3761 } else {
3762 read_result = librbd::io::ReadResult(iov, iovcnt);
3763 }
3764 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3765 std::move(read_result), 0);
3766 }
3767 tracepoint(librbd, aio_read_exit, r);
3768 return r;
3769 }
3770
3771 extern "C" int rbd_flush(rbd_image_t image)
3772 {
3773 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3774 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3775 int r = librbd::flush(ictx);
3776 tracepoint(librbd, flush_exit, r);
3777 return r;
3778 }
3779
3780 extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
3781 {
3782 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3783 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3784 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
3785 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
3786 tracepoint(librbd, aio_flush_exit, 0);
3787 return 0;
3788 }
3789
3790 extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
3791 const char *buf, size_t data_len, rbd_completion_t c,
3792 int op_flags)
3793 {
3794 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3795 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3796 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3797 ictx->read_only, off, len, data_len <= 0 ? NULL : buf, data_len, comp->pc,
3798 op_flags);
3799
3800 if (data_len <= 0 || len % data_len) {
3801 tracepoint(librbd, aio_writesame_exit, -EINVAL);
3802 return -EINVAL;
3803 }
3804
3805 if (mem_is_zero(buf, data_len)) {
3806 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false);
3807 tracepoint(librbd, aio_writesame_exit, 0);
3808 return 0;
3809 }
3810
3811 bufferlist bl;
3812 bl.push_back(create_write_raw(ictx, buf, data_len));
3813 ictx->io_work_queue->aio_writesame(get_aio_completion(comp), off, len,
3814 std::move(bl), op_flags);
3815 tracepoint(librbd, aio_writesame_exit, 0);
3816 return 0;
3817 }
3818
3819 extern "C" ssize_t rbd_aio_compare_and_write(rbd_image_t image, uint64_t off,
3820 size_t len, const char *cmp_buf,
3821 const char *buf, rbd_completion_t c,
3822 uint64_t *mismatch_off,
3823 int op_flags)
3824 {
3825 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3826 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3827 tracepoint(librbd, aio_compare_and_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3828 ictx->read_only, off, len, cmp_buf, buf, comp->pc, op_flags);
3829
3830 bufferlist cmp_bl;
3831 cmp_bl.push_back(create_write_raw(ictx, cmp_buf, len));
3832 bufferlist bl;
3833 bl.push_back(create_write_raw(ictx, buf, len));
3834 ictx->io_work_queue->aio_compare_and_write(get_aio_completion(comp), off, len,
3835 std::move(cmp_bl), std::move(bl),
3836 mismatch_off, op_flags, false);
3837
3838 tracepoint(librbd, aio_compare_and_write_exit, 0);
3839 return 0;
3840 }
3841
3842 extern "C" int rbd_invalidate_cache(rbd_image_t image)
3843 {
3844 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3845 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3846 int r = librbd::invalidate_cache(ictx);
3847 tracepoint(librbd, invalidate_cache_exit, r);
3848 return r;
3849 }
3850
3851 extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
3852 {
3853 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3854 librbd::io::AioCompletion *cs[numcomp];
3855 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
3856 int r = librbd::poll_io_events(ictx, cs, numcomp);
3857 tracepoint(librbd, poll_io_events_exit, r);
3858 if (r > 0) {
3859 for (int i = 0; i < r; ++i)
3860 comps[i] = cs[i]->rbd_comp;
3861 }
3862 return r;
3863 }
3864
3865 extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
3866 {
3867 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3868 string val_s;
3869 tracepoint(librbd, metadata_get_enter, ictx, key);
3870 int r = librbd::metadata_get(ictx, key, &val_s);
3871 if (r < 0) {
3872 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3873 return r;
3874 }
3875 if (*vallen < val_s.size() + 1) {
3876 r = -ERANGE;
3877 *vallen = val_s.size() + 1;
3878 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3879 } else {
3880 strncpy(value, val_s.c_str(), val_s.size() + 1);
3881 tracepoint(librbd, metadata_get_exit, r, key, value);
3882 }
3883 return r;
3884 }
3885
3886 extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
3887 {
3888 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3889 tracepoint(librbd, metadata_set_enter, ictx, key, value);
3890 int r = ictx->operations->metadata_set(key, value);
3891 tracepoint(librbd, metadata_set_exit, r);
3892 return r;
3893 }
3894
3895 extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
3896 {
3897 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3898 tracepoint(librbd, metadata_remove_enter, ictx, key);
3899 int r = ictx->operations->metadata_remove(key);
3900 tracepoint(librbd, metadata_remove_exit, r);
3901 return r;
3902 }
3903
3904 extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
3905 char *key, size_t *key_len, char *value, size_t *val_len)
3906 {
3907 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3908 tracepoint(librbd, metadata_list_enter, ictx);
3909 map<string, bufferlist> pairs;
3910 int r = librbd::metadata_list(ictx, start, max, &pairs);
3911 size_t key_total_len = 0, val_total_len = 0;
3912 bool too_short = false;
3913 for (map<string, bufferlist>::iterator it = pairs.begin();
3914 it != pairs.end(); ++it) {
3915 key_total_len += it->first.size() + 1;
3916 val_total_len += it->second.length() + 1;
3917 }
3918 if (*key_len < key_total_len || *val_len < val_total_len)
3919 too_short = true;
3920 *key_len = key_total_len;
3921 *val_len = val_total_len;
3922 if (too_short) {
3923 tracepoint(librbd, metadata_list_exit, -ERANGE);
3924 return -ERANGE;
3925 }
3926
3927 char *key_p = key, *value_p = value;
3928
3929 for (map<string, bufferlist>::iterator it = pairs.begin();
3930 it != pairs.end(); ++it) {
3931 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
3932 key_p += it->first.size() + 1;
3933 strncpy(value_p, it->second.c_str(), it->second.length());
3934 value_p += it->second.length();
3935 *value_p = '\0';
3936 value_p++;
3937 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
3938 }
3939 tracepoint(librbd, metadata_list_exit, r);
3940 return r;
3941 }
3942
3943 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
3944 {
3945 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3946 return librbd::api::Mirror<>::image_enable(ictx, false);
3947 }
3948
3949 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
3950 {
3951 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3952 return librbd::api::Mirror<>::image_disable(ictx, force);
3953 }
3954
3955 extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
3956 {
3957 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3958 return librbd::api::Mirror<>::image_promote(ictx, force);
3959 }
3960
3961 extern "C" int rbd_mirror_image_demote(rbd_image_t image)
3962 {
3963 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3964 return librbd::api::Mirror<>::image_demote(ictx);
3965 }
3966
3967 extern "C" int rbd_mirror_image_resync(rbd_image_t image)
3968 {
3969 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3970 return librbd::api::Mirror<>::image_resync(ictx);
3971 }
3972
3973 extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
3974 rbd_mirror_image_info_t *mirror_image_info,
3975 size_t info_size)
3976 {
3977 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3978
3979 librbd::mirror_image_info_t cpp_mirror_image;
3980 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image,
3981 sizeof(cpp_mirror_image));
3982 if (r < 0) {
3983 return r;
3984 }
3985
3986 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
3987 return 0;
3988 }
3989
3990 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
3991 rbd_mirror_image_status_t *status,
3992 size_t status_size)
3993 {
3994 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3995
3996 librbd::mirror_image_status_t cpp_status;
3997 int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status,
3998 sizeof(cpp_status));
3999 if (r < 0) {
4000 return r;
4001 }
4002
4003 mirror_image_status_cpp_to_c(cpp_status, status);
4004 return 0;
4005 }
4006
4007 extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
4008 rbd_completion_t c) {
4009 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4010 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4011 librbd::api::Mirror<>::image_promote(
4012 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
4013 get_aio_completion(comp)));
4014 return 0;
4015 }
4016
4017 extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
4018 rbd_completion_t c) {
4019 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4020 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4021 librbd::api::Mirror<>::image_demote(
4022 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
4023 get_aio_completion(comp)));
4024 return 0;
4025 }
4026
4027 extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
4028 rbd_mirror_image_info_t *info,
4029 size_t info_size,
4030 rbd_completion_t c) {
4031 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4032 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4033
4034 if (sizeof(rbd_mirror_image_info_t) > info_size) {
4035 return -ERANGE;
4036 }
4037
4038 auto ctx = new C_MirrorImageGetInfo(
4039 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
4040 get_aio_completion(comp)));
4041 librbd::api::Mirror<>::image_get_info(
4042 ictx, &ctx->cpp_mirror_image_info, sizeof(ctx->cpp_mirror_image_info), ctx);
4043 return 0;
4044 }
4045
4046 extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
4047 rbd_mirror_image_status_t *status,
4048 size_t status_size,
4049 rbd_completion_t c) {
4050 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4051 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4052
4053 if (sizeof(rbd_mirror_image_status_t) > status_size) {
4054 return -ERANGE;
4055 }
4056
4057 auto ctx = new C_MirrorImageGetStatus(
4058 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
4059 get_aio_completion(comp)));
4060 librbd::api::Mirror<>::image_get_status(
4061 ictx, &ctx->cpp_mirror_image_status, sizeof(ctx->cpp_mirror_image_status),
4062 ctx);
4063 return 0;
4064 }
4065
4066 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
4067 rbd_update_callback_t watch_cb, void *arg)
4068 {
4069 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4070 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
4071 tracepoint(librbd, update_watch_enter, ictx, wctx);
4072 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
4073 tracepoint(librbd, update_watch_exit, r, wctx->handle);
4074 *handle = reinterpret_cast<uint64_t>(wctx);
4075 return r;
4076 }
4077
4078 extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
4079 {
4080 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
4081 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
4082 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
4083 int r = ictx->state->unregister_update_watcher(wctx->handle);
4084 delete wctx;
4085 tracepoint(librbd, update_unwatch_exit, r);
4086 return r;
4087 }
4088
4089 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
4090 {
4091 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4092 return comp->is_complete();
4093 }
4094
4095 extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
4096 {
4097 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4098 return comp->wait_for_complete();
4099 }
4100
4101 extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
4102 {
4103 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4104 return comp->get_return_value();
4105 }
4106
4107 extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
4108 {
4109 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4110 return comp->get_arg();
4111 }
4112
4113 extern "C" void rbd_aio_release(rbd_completion_t c)
4114 {
4115 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4116 comp->release();
4117 }
4118
4119 extern "C" int rbd_group_create(rados_ioctx_t p, const char *name)
4120 {
4121 librados::IoCtx io_ctx;
4122 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4123 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4124 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
4125 io_ctx.get_id(), name);
4126 int r = librbd::api::Group<>::create(io_ctx, name);
4127 tracepoint(librbd, group_create_exit, r);
4128 return r;
4129 }
4130
4131 extern "C" int rbd_group_remove(rados_ioctx_t p, const char *name)
4132 {
4133 librados::IoCtx io_ctx;
4134 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4135 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4136 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
4137 io_ctx.get_id(), name);
4138 int r = librbd::api::Group<>::remove(io_ctx, name);
4139 tracepoint(librbd, group_remove_exit, r);
4140 return r;
4141 }
4142
4143 extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size)
4144 {
4145 librados::IoCtx io_ctx;
4146 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4147 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4148 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
4149 io_ctx.get_id());
4150
4151 vector<string> cpp_names;
4152 int r = librbd::list(io_ctx, cpp_names);
4153 if (r < 0) {
4154 tracepoint(librbd, group_list_exit, r);
4155 return r;
4156 }
4157
4158 size_t expected_size = 0;
4159
4160 for (size_t i = 0; i < cpp_names.size(); i++) {
4161 expected_size += cpp_names[i].size() + 1;
4162 }
4163 if (*size < expected_size) {
4164 *size = expected_size;
4165 tracepoint(librbd, group_list_exit, -ERANGE);
4166 return -ERANGE;
4167 }
4168
4169 if (!names)
4170 return -EINVAL;
4171
4172 names[expected_size] = '\0';
4173 for (int i = 0; i < (int)cpp_names.size(); i++) {
4174 const char* name = cpp_names[i].c_str();
4175 tracepoint(librbd, group_list_entry, name);
4176 strcpy(names, name);
4177 names += strlen(names) + 1;
4178 }
4179 tracepoint(librbd, group_list_exit, (int)expected_size);
4180 return (int)expected_size;
4181 }
4182
4183 extern "C" int rbd_group_image_add(
4184 rados_ioctx_t group_p, const char *group_name,
4185 rados_ioctx_t image_p, const char *image_name)
4186 {
4187 librados::IoCtx group_ioctx;
4188 librados::IoCtx image_ioctx;
4189
4190 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4191 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4192
4193 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4194 tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(),
4195 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
4196 image_ioctx.get_id(), image_name);
4197
4198 int r = librbd::api::Group<>::image_add(group_ioctx, group_name, image_ioctx,
4199 image_name);
4200
4201 tracepoint(librbd, group_image_add_exit, r);
4202 return r;
4203 }
4204
4205 extern "C" int rbd_group_image_remove(
4206 rados_ioctx_t group_p, const char *group_name,
4207 rados_ioctx_t image_p, const char *image_name)
4208 {
4209 librados::IoCtx group_ioctx;
4210 librados::IoCtx image_ioctx;
4211
4212 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4213 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4214
4215 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4216 tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(),
4217 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
4218 image_ioctx.get_id(), image_name);
4219
4220 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
4221 image_ioctx, image_name);
4222
4223 tracepoint(librbd, group_image_remove_exit, r);
4224 return r;
4225 }
4226
4227 extern "C" int rbd_group_image_remove_by_id(rados_ioctx_t group_p,
4228 const char *group_name,
4229 rados_ioctx_t image_p,
4230 const char *image_id)
4231 {
4232 librados::IoCtx group_ioctx;
4233 librados::IoCtx image_ioctx;
4234
4235 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4236 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4237
4238 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4239 tracepoint(librbd, group_image_remove_by_id_enter,
4240 group_ioctx.get_pool_name().c_str(),
4241 group_ioctx.get_id(), group_name,
4242 image_ioctx.get_pool_name().c_str(),
4243 image_ioctx.get_id(), image_id);
4244
4245 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
4246 image_ioctx, image_id);
4247
4248 tracepoint(librbd, group_image_remove_by_id_exit, r);
4249 return r;
4250 }
4251
4252 extern "C" int rbd_group_image_list(rados_ioctx_t group_p,
4253 const char *group_name,
4254 rbd_group_image_status_t *images,
4255 size_t *image_size)
4256 {
4257 librados::IoCtx group_ioctx;
4258 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4259
4260 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4261 tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(),
4262 group_ioctx.get_id(), group_name);
4263
4264 std::vector<librbd::group_image_status_t> cpp_images;
4265 int r = librbd::api::Group<>::image_list(group_ioctx, group_name,
4266 &cpp_images);
4267
4268 if (r == -ENOENT) {
4269 tracepoint(librbd, group_image_list_exit, 0);
4270 return 0;
4271 }
4272
4273 if (r < 0) {
4274 tracepoint(librbd, group_image_list_exit, r);
4275 return r;
4276 }
4277
4278 if (*image_size < cpp_images.size()) {
4279 tracepoint(librbd, group_image_list_exit, -ERANGE);
4280 return -ERANGE;
4281 }
4282
4283 for (size_t i = 0; i < cpp_images.size(); ++i) {
4284 group_image_status_cpp_to_c(cpp_images[i], &images[i]);
4285 }
4286
4287 tracepoint(librbd, group_image_list_exit, r);
4288 return r;
4289 }
4290
4291 extern "C" int rbd_image_get_group(rados_ioctx_t image_p,
4292 const char *image_name,
4293 rbd_group_spec_t *c_group_spec)
4294 {
4295 librados::IoCtx io_ctx;
4296 librados::IoCtx::from_rados_ioctx_t(image_p, io_ctx);
4297
4298 librbd::ImageCtx *ictx = new librbd::ImageCtx(image_name, "", "", io_ctx, false);
4299 int r = ictx->state->open(false);
4300 if (r < 0) {
4301 tracepoint(librbd, open_image_exit, r);
4302 return r;
4303 }
4304
4305 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
4306 librbd::group_spec_t group_spec;
4307 r = librbd::api::Group<>::image_get_group(ictx, &group_spec);
4308 group_spec_cpp_to_c(group_spec, c_group_spec);
4309 tracepoint(librbd, image_get_group_exit, r);
4310 ictx->state->close();
4311 return r;
4312 }
4313
4314 extern "C" void rbd_group_spec_cleanup(rbd_group_spec_t *group_spec) {
4315 free(group_spec->name);
4316 }
4317
4318 extern "C" void rbd_group_image_status_cleanup(
4319 rbd_group_image_status_t *image) {
4320 free(image->spec.name);
4321 }
4322
4323 extern "C" void rbd_group_image_status_list_cleanup(
4324 rbd_group_image_status_t *images,
4325 size_t len) {
4326 for (size_t i = 0; i < len; ++i) {
4327 rbd_group_image_status_cleanup(&images[i]);
4328 }
4329 }