]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/librbd.cc
update sources to v12.1.0
[ceph.git] / ceph / src / librbd / librbd.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14#include "include/int_types.h"
15
16#include <errno.h>
17
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
54using std::string;
55using std::vector;
56
57using ceph::bufferlist;
58using librados::snap_t;
59using librados::IoCtx;
60
61namespace {
62
63TracepointProvider::Traits tracepoint_traits("librbd_tp.so", "rbd_tracing");
64
65buffer::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
72CephContext* get_cct(IoCtx &io_ctx) {
73 return reinterpret_cast<CephContext*>(io_ctx.cct());
74}
75
76librbd::io::AioCompletion* get_aio_completion(librbd::RBD::AioCompletion *comp) {
77 return reinterpret_cast<librbd::io::AioCompletion *>(comp->pc);
78}
79
80struct 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
104struct 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
125struct 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
144struct 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
157void 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
164void 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
170void 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
177void 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
187void 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
196struct 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
218struct 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
242namespace 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
31f18b77
FG
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
7c673cae
FG
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 int Image::aio_write(uint64_t off, size_t len, bufferlist& bl,
1640 RBD::AioCompletion *c)
1641 {
1642 ImageCtx *ictx = (ImageCtx *)ctx;
1643 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);
1644 if (bl.length() < len) {
1645 tracepoint(librbd, aio_write_exit, -EINVAL);
1646 return -EINVAL;
1647 }
1648 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1649 bufferlist{bl}, 0);
1650 tracepoint(librbd, aio_write_exit, 0);
1651 return 0;
1652 }
1653
1654 int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
1655 RBD::AioCompletion *c, int op_flags)
1656 {
1657 ImageCtx *ictx = (ImageCtx *)ctx;
1658 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1659 ictx->read_only, off, len, bl.length() < len ? NULL : bl.c_str(), c->pc, op_flags);
1660 if (bl.length() < len) {
1661 tracepoint(librbd, aio_write_exit, -EINVAL);
1662 return -EINVAL;
1663 }
1664 ictx->io_work_queue->aio_write(get_aio_completion(c), off, len,
1665 bufferlist{bl}, op_flags);
1666 tracepoint(librbd, aio_write_exit, 0);
1667 return 0;
1668 }
1669
1670 int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
1671 {
1672 ImageCtx *ictx = (ImageCtx *)ctx;
1673 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
1674 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, ictx->skip_partial_discard);
1675 tracepoint(librbd, aio_discard_exit, 0);
1676 return 0;
1677 }
1678
1679 int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
1680 RBD::AioCompletion *c)
1681 {
1682 ImageCtx *ictx = (ImageCtx *)ctx;
1683 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);
1684 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1685 << (void *)(bl.c_str() + len - 1) << dendl;
1686 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1687 io::ReadResult{&bl}, 0);
1688 tracepoint(librbd, aio_read_exit, 0);
1689 return 0;
1690 }
1691
1692 int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
1693 RBD::AioCompletion *c, int op_flags)
1694 {
1695 ImageCtx *ictx = (ImageCtx *)ctx;
1696 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1697 ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
1698 ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
1699 << (void *)(bl.c_str() + len - 1) << dendl;
1700 ictx->io_work_queue->aio_read(get_aio_completion(c), off, len,
1701 io::ReadResult{&bl}, op_flags);
1702 tracepoint(librbd, aio_read_exit, 0);
1703 return 0;
1704 }
1705
1706 int Image::flush()
1707 {
1708 ImageCtx *ictx = (ImageCtx *)ctx;
1709 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1710 int r = librbd::flush(ictx);
1711 tracepoint(librbd, flush_exit, r);
1712 return r;
1713 }
1714
1715 int Image::aio_flush(RBD::AioCompletion *c)
1716 {
1717 ImageCtx *ictx = (ImageCtx *)ctx;
1718 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
1719 ictx->io_work_queue->aio_flush(get_aio_completion(c));
1720 tracepoint(librbd, aio_flush_exit, 0);
1721 return 0;
1722 }
1723
1724 int Image::aio_writesame(uint64_t off, size_t len, bufferlist& bl,
1725 RBD::AioCompletion *c, int op_flags)
1726 {
1727 ImageCtx *ictx = (ImageCtx *)ctx;
1728 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
1729 ictx->read_only, off, len, bl.length() <= len ? NULL : bl.c_str(), bl.length(),
1730 c->pc, op_flags);
1731 if (bl.length() <= 0 || len % bl.length()) {
1732 tracepoint(librbd, aio_writesame_exit, -EINVAL);
1733 return -EINVAL;
1734 }
1735
1736 if (mem_is_zero(bl.c_str(), bl.length())) {
1737 ictx->io_work_queue->aio_discard(get_aio_completion(c), off, len, false);
1738 tracepoint(librbd, aio_writesame_exit, 0);
1739 return 0;
1740 }
1741
1742 ictx->io_work_queue->aio_writesame(get_aio_completion(c), off, len,
1743 bufferlist{bl}, op_flags);
1744 tracepoint(librbd, aio_writesame_exit, 0);
1745 return 0;
1746 }
1747
1748
1749 int Image::invalidate_cache()
1750 {
1751 ImageCtx *ictx = (ImageCtx *)ctx;
1752 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
1753 int r = librbd::invalidate_cache(ictx);
1754 tracepoint(librbd, invalidate_cache_exit, r);
1755 return r;
1756 }
1757
1758 int Image::poll_io_events(RBD::AioCompletion **comps, int numcomp)
1759 {
1760 io::AioCompletion *cs[numcomp];
1761 ImageCtx *ictx = (ImageCtx *)ctx;
1762 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
1763 int r = librbd::poll_io_events(ictx, cs, numcomp);
1764 tracepoint(librbd, poll_io_events_exit, r);
1765 if (r > 0) {
1766 for (int i = 0; i < numcomp; ++i)
1767 comps[i] = (RBD::AioCompletion *)cs[i]->rbd_comp;
1768 }
1769 return r;
1770 }
1771
1772 int Image::metadata_get(const std::string &key, std::string *value)
1773 {
1774 ImageCtx *ictx = (ImageCtx *)ctx;
1775 tracepoint(librbd, metadata_get_enter, ictx, key.c_str());
1776 int r = librbd::metadata_get(ictx, key, value);
1777 if (r < 0) {
1778 tracepoint(librbd, metadata_get_exit, r, key.c_str(), NULL);
1779 } else {
1780 tracepoint(librbd, metadata_get_exit, r, key.c_str(), value->c_str());
1781 }
1782 return r;
1783 }
1784
1785 int Image::metadata_set(const std::string &key, const std::string &value)
1786 {
1787 ImageCtx *ictx = (ImageCtx *)ctx;
1788 tracepoint(librbd, metadata_set_enter, ictx, key.c_str(), value.c_str());
1789 int r = ictx->operations->metadata_set(key, value);
1790 tracepoint(librbd, metadata_set_exit, r);
1791 return r;
1792 }
1793
1794 int Image::metadata_remove(const std::string &key)
1795 {
1796 ImageCtx *ictx = (ImageCtx *)ctx;
1797 tracepoint(librbd, metadata_remove_enter, ictx, key.c_str());
1798 int r = ictx->operations->metadata_remove(key);
1799 tracepoint(librbd, metadata_remove_exit, r);
1800 return r;
1801 }
1802
1803 int Image::metadata_list(const std::string &start, uint64_t max, map<string, bufferlist> *pairs)
1804 {
1805 ImageCtx *ictx = (ImageCtx *)ctx;
1806 tracepoint(librbd, metadata_list_enter, ictx);
1807 int r = librbd::metadata_list(ictx, start, max, pairs);
1808 if (r >= 0) {
1809 for (map<string, bufferlist>::iterator it = pairs->begin();
1810 it != pairs->end(); ++it) {
1811 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
1812 }
1813 }
1814 tracepoint(librbd, metadata_list_exit, r);
1815 return r;
1816 }
1817
1818 int Image::mirror_image_enable() {
1819 ImageCtx *ictx = (ImageCtx *)ctx;
1820 return librbd::api::Mirror<>::image_enable(ictx, false);
1821 }
1822
1823 int Image::mirror_image_disable(bool force) {
1824 ImageCtx *ictx = (ImageCtx *)ctx;
1825 return librbd::api::Mirror<>::image_disable(ictx, force);
1826 }
1827
1828 int Image::mirror_image_promote(bool force) {
1829 ImageCtx *ictx = (ImageCtx *)ctx;
1830 return librbd::api::Mirror<>::image_promote(ictx, force);
1831 }
1832
1833 int Image::mirror_image_demote() {
1834 ImageCtx *ictx = (ImageCtx *)ctx;
1835 return librbd::api::Mirror<>::image_demote(ictx);
1836 }
1837
1838 int Image::mirror_image_resync()
1839 {
1840 ImageCtx *ictx = (ImageCtx *)ctx;
1841 return librbd::api::Mirror<>::image_resync(ictx);
1842 }
1843
1844 int Image::mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1845 size_t info_size) {
1846 ImageCtx *ictx = (ImageCtx *)ctx;
1847 return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info,
1848 info_size);
1849 }
1850
1851 int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
1852 size_t status_size) {
1853 ImageCtx *ictx = (ImageCtx *)ctx;
1854 return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status,
1855 status_size);
1856 }
1857
1858 int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
1859 ImageCtx *ictx = (ImageCtx *)ctx;
1860 librbd::api::Mirror<>::image_promote(
1861 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1862 get_aio_completion(c)));
1863 return 0;
1864 }
1865
1866 int Image::aio_mirror_image_demote(RBD::AioCompletion *c) {
1867 ImageCtx *ictx = (ImageCtx *)ctx;
1868 librbd::api::Mirror<>::image_demote(
1869 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1870 get_aio_completion(c)));
1871 return 0;
1872 }
1873
1874 int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
1875 size_t info_size,
1876 RBD::AioCompletion *c) {
1877 ImageCtx *ictx = (ImageCtx *)ctx;
1878 librbd::api::Mirror<>::image_get_info(
1879 ictx, mirror_image_info, info_size,
1880 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1881 get_aio_completion(c)));
1882 return 0;
1883 }
1884
1885 int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
1886 size_t status_size,
1887 RBD::AioCompletion *c) {
1888 ImageCtx *ictx = (ImageCtx *)ctx;
1889 librbd::api::Mirror<>::image_get_status(
1890 ictx, status, status_size,
1891 new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
1892 get_aio_completion(c)));
1893 return 0;
1894 }
1895
1896 int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
1897 ImageCtx *ictx = (ImageCtx *)ctx;
1898 tracepoint(librbd, update_watch_enter, ictx, wctx);
1899 int r = ictx->state->register_update_watcher(wctx, handle);
1900 tracepoint(librbd, update_watch_exit, r, *handle);
1901 return r;
1902 }
1903
1904 int Image::update_unwatch(uint64_t handle) {
1905 ImageCtx *ictx = (ImageCtx *)ctx;
1906 tracepoint(librbd, update_unwatch_enter, ictx, handle);
1907 int r = ictx->state->unregister_update_watcher(handle);
1908 tracepoint(librbd, update_unwatch_exit, r);
1909 return r;
1910 }
1911
1912} // namespace librbd
1913
1914extern "C" void rbd_version(int *major, int *minor, int *extra)
1915{
1916 if (major)
1917 *major = LIBRBD_VER_MAJOR;
1918 if (minor)
1919 *minor = LIBRBD_VER_MINOR;
1920 if (extra)
1921 *extra = LIBRBD_VER_EXTRA;
1922}
1923
1924extern "C" void rbd_image_options_create(rbd_image_options_t* opts)
1925{
1926 librbd::image_options_create(opts);
1927}
1928
1929extern "C" void rbd_image_options_destroy(rbd_image_options_t opts)
1930{
1931 librbd::image_options_destroy(opts);
1932}
1933
1934extern "C" int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
1935 const char* optval)
1936{
1937 return librbd::image_options_set(opts, optname, optval);
1938}
1939
1940extern "C" int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
1941 uint64_t optval)
1942{
1943 return librbd::image_options_set(opts, optname, optval);
1944}
1945
1946extern "C" int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
1947 char* optval, size_t maxlen)
1948{
1949 std::string optval_;
1950
1951 int r = librbd::image_options_get(opts, optname, &optval_);
1952
1953 if (r < 0) {
1954 return r;
1955 }
1956
1957 if (optval_.size() >= maxlen) {
1958 return -E2BIG;
1959 }
1960
1961 strncpy(optval, optval_.c_str(), maxlen);
1962
1963 return 0;
1964}
1965
1966extern "C" int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
1967 uint64_t* optval)
1968{
1969 return librbd::image_options_get(opts, optname, optval);
1970}
1971
1972extern "C" int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
1973 bool* is_set)
1974{
1975 return librbd::image_options_is_set(opts, optname, is_set);
1976}
1977
1978extern "C" int rbd_image_options_unset(rbd_image_options_t opts, int optname)
1979{
1980 return librbd::image_options_unset(opts, optname);
1981}
1982
1983extern "C" void rbd_image_options_clear(rbd_image_options_t opts)
1984{
1985 librbd::image_options_clear(opts);
1986}
1987
1988extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts)
1989{
1990 return librbd::image_options_is_empty(opts);
1991}
1992
1993/* pool mirroring */
1994extern "C" int rbd_mirror_mode_get(rados_ioctx_t p,
1995 rbd_mirror_mode_t *mirror_mode) {
1996 librados::IoCtx io_ctx;
1997 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
1998 return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode);
1999}
2000
2001extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
2002 rbd_mirror_mode_t mirror_mode) {
2003 librados::IoCtx io_ctx;
2004 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2005 return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
2006}
2007
2008extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
2009 size_t uuid_max_length,
2010 const char *cluster_name,
2011 const char *client_name) {
2012 static const std::size_t UUID_LENGTH = 36;
2013
2014 librados::IoCtx io_ctx;
2015 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2016
2017 if (uuid_max_length < UUID_LENGTH + 1) {
2018 return -E2BIG;
2019 }
2020
2021 std::string uuid_str;
2022 int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
2023 client_name);
2024 if (r >= 0) {
2025 strncpy(uuid, uuid_str.c_str(), uuid_max_length);
2026 uuid[uuid_max_length - 1] = '\0';
2027 }
2028 return r;
2029}
2030
2031extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
2032 librados::IoCtx io_ctx;
2033 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2034 int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
2035 return r;
2036}
2037
2038extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
2039 rbd_mirror_peer_t *peers, int *max_peers) {
2040 librados::IoCtx io_ctx;
2041 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2042
2043 std::vector<librbd::mirror_peer_t> peer_vector;
2044 int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
2045 if (r < 0) {
2046 return r;
2047 }
2048
2049 if (*max_peers < static_cast<int>(peer_vector.size())) {
2050 *max_peers = static_cast<int>(peer_vector.size());
2051 return -ERANGE;
2052 }
2053
2054 for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
2055 peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
2056 peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
2057 peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
2058 }
2059 *max_peers = static_cast<int>(peer_vector.size());
2060 return 0;
2061}
2062
2063extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
2064 int max_peers) {
2065 for (int i = 0; i < max_peers; ++i) {
2066 free(peers[i].uuid);
2067 free(peers[i].cluster_name);
2068 free(peers[i].client_name);
2069 }
2070}
2071
2072extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
2073 const char *client_name) {
2074 librados::IoCtx io_ctx;
2075 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2076 return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
2077}
2078
2079extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
2080 const char *cluster_name) {
2081 librados::IoCtx io_ctx;
2082 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2083 return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
2084}
2085
2086extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
2087 const char *start_id, size_t max, char **image_ids,
2088 rbd_mirror_image_status_t *images, size_t *len) {
2089 librados::IoCtx io_ctx;
2090 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2091 std::map<std::string, librbd::mirror_image_status_t> cpp_images;
2092
2093 int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
2094 &cpp_images);
2095 if (r < 0) {
2096 return r;
2097 }
2098
2099 size_t i = 0;
2100 for (auto &it : cpp_images) {
2101 assert(i < max);
2102 const std::string &image_id = it.first;
2103 image_ids[i] = strdup(image_id.c_str());
2104 mirror_image_status_cpp_to_c(it.second, &images[i]);
2105 i++;
2106 }
2107 *len = i;
2108 return 0;
2109}
2110
2111extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
2112 rbd_mirror_image_status_t *images, size_t len) {
2113 for (size_t i = 0; i < len; i++) {
2114 free(image_ids[i]);
2115 free(images[i].name);
2116 free(images[i].info.global_id);
2117 free(images[i].description);
2118 }
2119}
2120
2121extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
2122 rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
2123
2124 librados::IoCtx io_ctx;
2125 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2126
2127 std::map<librbd::mirror_image_status_state_t, int> states_;
2128 int r = librbd::api::Mirror<>::image_status_summary(io_ctx, &states_);
2129 if (r < 0) {
2130 return r;
2131 }
2132
2133 size_t i = 0;
2134 for (auto &it : states_) {
2135 if (i == *maxlen) {
2136 return -ERANGE;
2137 }
2138 states[i] = it.first;
2139 counts[i] = it.second;
2140 i++;
2141 }
2142 *maxlen = i;
2143 return 0;
2144}
2145
2146/* images */
2147extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
2148{
2149 librados::IoCtx io_ctx;
2150 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2151 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2152 tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2153 vector<string> cpp_names;
2154 int r = librbd::list(io_ctx, cpp_names);
7c673cae
FG
2155 if (r < 0) {
2156 tracepoint(librbd, list_exit, r, *size);
2157 return r;
2158 }
2159
2160 size_t expected_size = 0;
2161
2162 for (size_t i = 0; i < cpp_names.size(); i++) {
2163 expected_size += cpp_names[i].size() + 1;
2164 }
2165 if (*size < expected_size) {
2166 *size = expected_size;
2167 tracepoint(librbd, list_exit, -ERANGE, *size);
2168 return -ERANGE;
2169 }
2170
2171 if (!names)
2172 return -EINVAL;
2173
2174 for (int i = 0; i < (int)cpp_names.size(); i++) {
2175 const char* name = cpp_names[i].c_str();
2176 tracepoint(librbd, list_entry, name);
2177 strcpy(names, name);
2178 names += strlen(names) + 1;
2179 }
2180 tracepoint(librbd, list_exit, (int)expected_size, *size);
2181 return (int)expected_size;
2182}
2183
2184extern "C" int rbd_create(rados_ioctx_t p, const char *name, uint64_t size, int *order)
2185{
2186 librados::IoCtx io_ctx;
2187 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2188 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2189 tracepoint(librbd, create_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, *order);
2190 int r = librbd::create(io_ctx, name, size, order);
2191 tracepoint(librbd, create_exit, r, *order);
2192 return r;
2193}
2194
2195extern "C" int rbd_create2(rados_ioctx_t p, const char *name,
2196 uint64_t size, uint64_t features,
2197 int *order)
2198{
2199 librados::IoCtx io_ctx;
2200 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2201 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2202 tracepoint(librbd, create2_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order);
2203 int r = librbd::create(io_ctx, name, size, false, features, order, 0, 0);
2204 tracepoint(librbd, create2_exit, r, *order);
2205 return r;
2206}
2207
2208extern "C" int rbd_create3(rados_ioctx_t p, const char *name,
2209 uint64_t size, uint64_t features,
2210 int *order,
2211 uint64_t stripe_unit, uint64_t stripe_count)
2212{
2213 librados::IoCtx io_ctx;
2214 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2215 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2216 tracepoint(librbd, create3_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, features, *order, stripe_unit, stripe_count);
2217 int r = librbd::create(io_ctx, name, size, false, features, order,
2218 stripe_unit, stripe_count);
2219 tracepoint(librbd, create3_exit, r, *order);
2220 return r;
2221}
2222
2223extern "C" int rbd_create4(rados_ioctx_t p, const char *name,
2224 uint64_t size, rbd_image_options_t opts)
2225{
2226 librados::IoCtx io_ctx;
2227 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2228 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2229 tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
2230 librbd::ImageOptions opts_(opts);
2231 int r = librbd::create(io_ctx, name, "", size, opts_, "", "", false);
2232 tracepoint(librbd, create4_exit, r);
2233 return r;
2234}
2235
2236extern "C" int rbd_clone(rados_ioctx_t p_ioctx, const char *p_name,
2237 const char *p_snap_name, rados_ioctx_t c_ioctx,
2238 const char *c_name, uint64_t features, int *c_order)
2239{
2240 librados::IoCtx p_ioc, c_ioc;
2241 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2242 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2243 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2244 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);
2245 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2246 features, c_order, 0, 0);
2247 tracepoint(librbd, clone_exit, r, *c_order);
2248 return r;
2249}
2250
2251extern "C" int rbd_clone2(rados_ioctx_t p_ioctx, const char *p_name,
2252 const char *p_snap_name, rados_ioctx_t c_ioctx,
2253 const char *c_name, uint64_t features, int *c_order,
2254 uint64_t stripe_unit, int stripe_count)
2255{
2256 librados::IoCtx p_ioc, c_ioc;
2257 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2258 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2259 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2260 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);
2261 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name,
2262 features, c_order, stripe_unit, stripe_count);
2263 tracepoint(librbd, clone2_exit, r, *c_order);
2264 return r;
2265}
2266
2267extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
2268 const char *p_snap_name, rados_ioctx_t c_ioctx,
2269 const char *c_name, rbd_image_options_t c_opts)
2270{
2271 librados::IoCtx p_ioc, c_ioc;
2272 librados::IoCtx::from_rados_ioctx_t(p_ioctx, p_ioc);
2273 librados::IoCtx::from_rados_ioctx_t(c_ioctx, c_ioc);
2274 TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc));
2275 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);
2276 librbd::ImageOptions c_opts_(c_opts);
2277 int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_);
2278 tracepoint(librbd, clone3_exit, r);
2279 return r;
2280}
2281
2282extern "C" int rbd_remove(rados_ioctx_t p, const char *name)
2283{
2284 librados::IoCtx io_ctx;
2285 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2286 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2287 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2288 librbd::NoOpProgressContext prog_ctx;
2289 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2290 tracepoint(librbd, remove_exit, r);
2291 return r;
2292}
2293
2294extern "C" int rbd_remove_with_progress(rados_ioctx_t p, const char *name,
2295 librbd_progress_fn_t cb, void *cbdata)
2296{
2297 librados::IoCtx io_ctx;
2298 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2299 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2300 tracepoint(librbd, remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name);
2301 librbd::CProgressContext prog_ctx(cb, cbdata);
2302 int r = librbd::remove(io_ctx, name, "", prog_ctx);
2303 tracepoint(librbd, remove_exit, r);
2304 return r;
2305}
2306
2307extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
2308 uint64_t delay) {
2309 librados::IoCtx io_ctx;
2310 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2311 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2312 tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(),
2313 io_ctx.get_id(), name);
2314 int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, delay);
2315 tracepoint(librbd, trash_move_exit, r);
2316 return r;
2317}
2318
2319extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
2320 rbd_trash_image_info_t *info) {
2321 librados::IoCtx io_ctx;
2322 librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
2323
2324 librbd::trash_image_info_t cpp_info;
2325 int r = librbd::trash_get(io_ctx, id, &cpp_info);
2326 if (r < 0) {
2327 return r;
2328 }
2329
2330 trash_image_info_cpp_to_c(cpp_info, info);
2331 return 0;
2332}
2333
2334extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
2335 free(info->id);
2336 free(info->name);
2337}
2338
2339extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
2340 size_t *num_entries) {
2341 librados::IoCtx io_ctx;
2342 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2343 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2344 tracepoint(librbd, trash_list_enter,
2345 io_ctx.get_pool_name().c_str(), io_ctx.get_id());
2346
2347 vector<librbd::trash_image_info_t> cpp_entries;
2348 int r = librbd::trash_list(io_ctx, cpp_entries);
2349 if (r < 0) {
2350 tracepoint(librbd, trash_list_exit, r, *num_entries);
2351 return r;
2352 }
2353
2354 if (*num_entries < cpp_entries.size()) {
2355 *num_entries = cpp_entries.size();
2356 tracepoint(librbd, trash_list_exit, -ERANGE, *num_entries);
2357 return -ERANGE;
2358 }
2359
2360 int i=0;
2361 for (const auto &entry : cpp_entries) {
2362 trash_image_info_cpp_to_c(entry, &entries[i++]);
2363 }
2364 *num_entries = cpp_entries.size();
2365
2366 return *num_entries;
2367}
2368
2369extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
2370 size_t num_entries) {
2371 for (size_t i=0; i < num_entries; i++) {
2372 rbd_trash_get_cleanup(&entries[i]);
2373 }
2374}
2375
2376extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id,
2377 bool force) {
2378 librados::IoCtx io_ctx;
2379 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2380 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2381 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2382 io_ctx.get_id(), image_id, force);
2383 librbd::NoOpProgressContext prog_ctx;
2384 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2385 tracepoint(librbd, trash_remove_exit, r);
2386 return r;
2387}
2388
2389extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p,
2390 const char *image_id,
2391 bool force,
2392 librbd_progress_fn_t cb,
2393 void *cbdata) {
2394 librados::IoCtx io_ctx;
2395 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2396 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2397 tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(),
2398 io_ctx.get_id(), image_id, force);
2399 librbd::CProgressContext prog_ctx(cb, cbdata);
2400 int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx);
2401 tracepoint(librbd, trash_remove_exit, r);
2402 return r;
2403}
2404
2405extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id,
2406 const char *name) {
2407 librados::IoCtx io_ctx;
2408 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2409 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2410 tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
2411 io_ctx.get_id(), id, name);
2412 int r = librbd::trash_restore(io_ctx, id, name);
2413 tracepoint(librbd, trash_undelete_exit, r);
2414 return r;
2415}
2416
2417extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
2418 const char *destname)
2419{
2420 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2421 librados::IoCtx dest_io_ctx;
2422 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2423 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);
2424 librbd::ImageOptions opts;
2425 librbd::NoOpProgressContext prog_ctx;
2426 int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2427 tracepoint(librbd, copy_exit, r);
2428 return r;
2429}
2430
2431extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
2432{
2433 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2434 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2435 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);
2436 librbd::NoOpProgressContext prog_ctx;
2437 int r = librbd::copy(src, dest, prog_ctx, 0);
2438 tracepoint(librbd, copy2_exit, r);
2439 return r;
2440}
2441
2442extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
2443 const char *destname, rbd_image_options_t c_opts)
2444{
2445 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2446 librados::IoCtx dest_io_ctx;
2447 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2448 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);
2449 librbd::ImageOptions c_opts_(c_opts);
2450 librbd::NoOpProgressContext prog_ctx;
2451 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
2452 tracepoint(librbd, copy3_exit, r);
2453 return r;
2454}
2455
2456extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
2457 const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
2458{
2459 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2460 librados::IoCtx dest_io_ctx;
2461 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2462 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);
2463 librbd::ImageOptions c_opts_(c_opts);
2464 librbd::NoOpProgressContext prog_ctx;
2465 int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
2466 tracepoint(librbd, copy4_exit, r);
2467 return r;
2468}
2469
2470extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
2471 const char *destname,
2472 librbd_progress_fn_t fn, void *data)
2473{
2474 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2475 librados::IoCtx dest_io_ctx;
2476 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2477 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);
2478 librbd::ImageOptions opts;
2479 librbd::CProgressContext prog_ctx(fn, data);
2480 int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
2481 tracepoint(librbd, copy_exit, ret);
2482 return ret;
2483}
2484
2485extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
2486 librbd_progress_fn_t fn, void *data)
2487{
2488 librbd::ImageCtx *src = (librbd::ImageCtx *)srcp;
2489 librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
2490 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);
2491 librbd::CProgressContext prog_ctx(fn, data);
2492 int ret = librbd::copy(src, dest, prog_ctx, 0);
2493 tracepoint(librbd, copy2_exit, ret);
2494 return ret;
2495}
2496
2497extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
2498 const char *destname,
2499 rbd_image_options_t dest_opts,
2500 librbd_progress_fn_t fn, void *data)
2501{
2502 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2503 librados::IoCtx dest_io_ctx;
2504 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2505 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);
2506 librbd::ImageOptions dest_opts_(dest_opts);
2507 librbd::CProgressContext prog_ctx(fn, data);
2508 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
2509 tracepoint(librbd, copy3_exit, ret);
2510 return ret;
2511}
2512
2513extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
2514 const char *destname,
2515 rbd_image_options_t dest_opts,
2516 librbd_progress_fn_t fn, void *data, size_t sparse_size)
2517{
2518 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2519 librados::IoCtx dest_io_ctx;
2520 librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
2521 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);
2522 librbd::ImageOptions dest_opts_(dest_opts);
2523 librbd::CProgressContext prog_ctx(fn, data);
2524 int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
2525 tracepoint(librbd, copy4_exit, ret);
2526 return ret;
2527}
2528
2529
2530extern "C" int rbd_flatten(rbd_image_t image)
2531{
2532 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2533 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2534 librbd::NoOpProgressContext prog_ctx;
2535 int r = ictx->operations->flatten(prog_ctx);
2536 tracepoint(librbd, flatten_exit, r);
2537 return r;
2538}
2539
2540extern "C" int rbd_flatten_with_progress(rbd_image_t image,
2541 librbd_progress_fn_t cb, void *cbdata)
2542{
2543 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2544 tracepoint(librbd, flatten_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2545 librbd::CProgressContext prog_ctx(cb, cbdata);
2546 int r = ictx->operations->flatten(prog_ctx);
2547 tracepoint(librbd, flatten_exit, r);
2548 return r;
2549}
2550
2551extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname,
2552 const char *destname)
2553{
2554 librados::IoCtx src_io_ctx;
2555 librados::IoCtx::from_rados_ioctx_t(src_p, src_io_ctx);
2556 TracepointProvider::initialize<tracepoint_traits>(get_cct(src_io_ctx));
2557 tracepoint(librbd, rename_enter, src_io_ctx.get_pool_name().c_str(), src_io_ctx.get_id(), srcname, destname);
2558 int r = librbd::rename(src_io_ctx, srcname, destname);
2559 tracepoint(librbd, rename_exit, r);
2560 return r;
2561}
2562
2563extern "C" int rbd_open(rados_ioctx_t p, const char *name, rbd_image_t *image,
2564 const char *snap_name)
2565{
2566 librados::IoCtx io_ctx;
2567 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2568 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2569 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2570 false);
2571 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2572
2573 int r = ictx->state->open(false);
2574 if (r >= 0) {
2575 *image = (rbd_image_t)ictx;
2576 }
2577 tracepoint(librbd, open_image_exit, r);
2578 return r;
2579}
2580
2581extern "C" int rbd_open_by_id(rados_ioctx_t p, const char *id,
2582 rbd_image_t *image, const char *snap_name)
2583{
2584 librados::IoCtx io_ctx;
2585 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2586 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2587 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2588 false);
2589 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2590 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2591
2592 int r = ictx->state->open(false);
2593 if (r < 0) {
2594 delete ictx;
2595 } else {
2596 *image = (rbd_image_t)ictx;
2597 }
2598 tracepoint(librbd, open_image_exit, r);
2599 return r;
2600}
2601
2602extern "C" int rbd_aio_open(rados_ioctx_t p, const char *name,
2603 rbd_image_t *image, const char *snap_name,
2604 rbd_completion_t c)
2605{
2606 librados::IoCtx io_ctx;
2607 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2608 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2609 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2610 false);
2611 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2612 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);
2613 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2614 tracepoint(librbd, aio_open_image_exit, 0);
2615 return 0;
2616}
2617
2618extern "C" int rbd_aio_open_by_id(rados_ioctx_t p, const char *id,
2619 rbd_image_t *image, const char *snap_name,
2620 rbd_completion_t c)
2621{
2622 librados::IoCtx io_ctx;
2623 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2624 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2625 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2626 false);
2627 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2628 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2629 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only,
2630 comp->pc);
2631 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp), image));
2632 tracepoint(librbd, aio_open_image_exit, 0);
2633 return 0;
2634}
2635
2636extern "C" int rbd_open_read_only(rados_ioctx_t p, const char *name,
2637 rbd_image_t *image, const char *snap_name)
2638{
2639 librados::IoCtx io_ctx;
2640 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2641 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2642 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2643 true);
2644 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2645
2646 int r = ictx->state->open(false);
2647 if (r >= 0) {
2648 *image = (rbd_image_t)ictx;
2649 }
2650 tracepoint(librbd, open_image_exit, r);
2651 return r;
2652}
2653
2654extern "C" int rbd_open_by_id_read_only(rados_ioctx_t p, const char *id,
2655 rbd_image_t *image, const char *snap_name)
2656{
2657 librados::IoCtx io_ctx;
2658 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2659 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2660 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2661 true);
2662 tracepoint(librbd, open_image_enter, ictx, ictx->name.c_str(),
2663 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2664
2665 int r = ictx->state->open(false);
2666 if (r < 0) {
2667 delete ictx;
2668 } else {
2669 *image = (rbd_image_t)ictx;
2670 }
2671 tracepoint(librbd, open_image_exit, r);
2672 return r;
2673}
2674
2675extern "C" int rbd_aio_open_read_only(rados_ioctx_t p, const char *name,
2676 rbd_image_t *image, const char *snap_name,
2677 rbd_completion_t c)
2678{
2679 librados::IoCtx io_ctx;
2680 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2681 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2682 librbd::ImageCtx *ictx = new librbd::ImageCtx(name, "", snap_name, io_ctx,
2683 true);
2684 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2685 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);
2686 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2687 image));
2688 tracepoint(librbd, aio_open_image_exit, 0);
2689 return 0;
2690}
2691
2692extern "C" int rbd_aio_open_by_id_read_only(rados_ioctx_t p, const char *id,
2693 rbd_image_t *image,
2694 const char *snap_name,
2695 rbd_completion_t c)
2696{
2697 librados::IoCtx io_ctx;
2698 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
2699 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
2700 librbd::ImageCtx *ictx = new librbd::ImageCtx("", id, snap_name, io_ctx,
2701 true);
2702 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2703 tracepoint(librbd, aio_open_image_enter, ictx, ictx->name.c_str(),
2704 ictx->id.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
2705 ictx->state->open(false, new C_OpenComplete(ictx, get_aio_completion(comp),
2706 image));
2707 tracepoint(librbd, aio_open_image_exit, 0);
2708 return 0;
2709}
2710
2711extern "C" int rbd_close(rbd_image_t image)
2712{
2713 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2714 tracepoint(librbd, close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str());
2715
2716 int r = ictx->state->close();
2717
2718 tracepoint(librbd, close_image_exit, r);
2719 return r;
2720}
2721
2722extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
2723{
2724 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2725 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
2726 tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc);
2727 ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE,
2728 get_aio_completion(comp)));
2729 tracepoint(librbd, aio_close_image_exit, 0);
2730 return 0;
2731}
2732
2733extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
2734{
2735 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2736 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2737 librbd::NoOpProgressContext prog_ctx;
2738 int r = ictx->operations->resize(size, true, prog_ctx);
2739 tracepoint(librbd, resize_exit, r);
2740 return r;
2741}
2742
2743extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
2744 librbd_progress_fn_t cb, void *cbdata)
2745{
2746 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2747 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2748 librbd::CProgressContext prog_ctx(cb, cbdata);
2749 int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
2750 tracepoint(librbd, resize_exit, r);
2751 return r;
2752}
2753
2754extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
2755 librbd_progress_fn_t cb, void *cbdata)
2756{
2757 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2758 tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
2759 librbd::CProgressContext prog_ctx(cb, cbdata);
2760 int r = ictx->operations->resize(size, true, prog_ctx);
2761 tracepoint(librbd, resize_exit, r);
2762 return r;
2763}
2764
2765extern "C" int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
2766 size_t infosize)
2767{
2768 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2769 tracepoint(librbd, stat_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2770 int r = librbd::info(ictx, *info, infosize);
2771 tracepoint(librbd, stat_exit, r, info);
2772 return r;
2773}
2774
2775extern "C" int rbd_get_old_format(rbd_image_t image, uint8_t *old)
2776{
2777 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2778 tracepoint(librbd, get_old_format_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2779 int r = librbd::get_old_format(ictx, old);
2780 tracepoint(librbd, get_old_format_exit, r, *old);
2781 return r;
2782}
2783
2784extern "C" int rbd_get_size(rbd_image_t image, uint64_t *size)
2785{
2786 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2787 tracepoint(librbd, get_size_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2788 int r = librbd::get_size(ictx, size);
2789 tracepoint(librbd, get_size_exit, r, *size);
2790 return r;
2791}
2792
2793extern "C" int rbd_get_features(rbd_image_t image, uint64_t *features)
2794{
2795 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2796 tracepoint(librbd, get_features_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2797 int r = librbd::get_features(ictx, features);
2798 tracepoint(librbd, get_features_exit, r, *features);
2799 return r;
2800}
2801
2802extern "C" int rbd_update_features(rbd_image_t image, uint64_t features,
2803 uint8_t enabled)
2804{
2805 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2806 bool features_enabled = enabled != 0;
2807 tracepoint(librbd, update_features_enter, ictx, features, features_enabled);
2808 int r = ictx->operations->update_features(features, features_enabled);
2809 tracepoint(librbd, update_features_exit, r);
2810 return r;
2811}
2812
2813extern "C" int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
2814{
2815 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2816 tracepoint(librbd, get_stripe_unit_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2817 *stripe_unit = ictx->get_stripe_unit();
2818 tracepoint(librbd, get_stripe_unit_exit, 0, *stripe_unit);
2819 return 0;
2820}
2821
2822extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
2823{
2824 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2825 tracepoint(librbd, get_stripe_count_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2826 *stripe_count = ictx->get_stripe_count();
2827 tracepoint(librbd, get_stripe_count_exit, 0, *stripe_count);
2828 return 0;
2829}
2830
31f18b77
FG
2831extern "C" int rbd_get_create_timestamp(rbd_image_t image,
2832 struct timespec *timestamp)
2833{
2834 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2835 tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(),
2836 ictx->read_only);
2837 utime_t time = ictx->get_create_timestamp();
2838 time.to_timespec(timestamp);
2839 tracepoint(librbd, get_create_timestamp_exit, 0, timestamp);
2840 return 0;
2841}
2842
7c673cae
FG
2843extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
2844{
2845 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2846 tracepoint(librbd, get_overlap_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
2847 int r = librbd::get_overlap(ictx, overlap);
2848 tracepoint(librbd, get_overlap_exit, r, *overlap);
2849 return r;
2850}
2851
2852extern "C" int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
2853{
2854 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2855 if (ictx->old_format) {
2856 return -EINVAL;
2857 }
2858 if (ictx->id.size() >= id_len) {
2859 return -ERANGE;
2860 }
2861
2862 strncpy(id, ictx->id.c_str(), id_len - 1);
2863 id[id_len - 1] = '\0';
2864 return 0;
2865}
2866
2867extern "C" int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
2868 size_t prefix_len)
2869{
2870 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2871 if (ictx->object_prefix.size() >= prefix_len) {
2872 return -ERANGE;
2873 }
2874
2875 strncpy(prefix, ictx->object_prefix.c_str(), prefix_len - 1);
2876 prefix[prefix_len - 1] = '\0';
2877 return 0;
2878}
2879
2880extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image)
2881{
2882 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx *>(image);
2883 return ictx->data_ctx.get_id();
2884}
2885
2886extern "C" int rbd_get_parent_info(rbd_image_t image,
2887 char *parent_pool_name, size_t ppool_namelen,
2888 char *parent_name, size_t pnamelen,
2889 char *parent_snap_name, size_t psnap_namelen)
2890{
2891 return rbd_get_parent_info2(image, parent_pool_name, ppool_namelen,
2892 parent_name, pnamelen, nullptr, 0,
2893 parent_snap_name, psnap_namelen);
2894}
2895
2896extern "C" int rbd_get_parent_info2(rbd_image_t image,
2897 char *parent_pool_name,
2898 size_t ppool_namelen,
2899 char *parent_name, size_t pnamelen,
2900 char *parent_id, size_t pidlen,
2901 char *parent_snap_name,
2902 size_t psnap_namelen)
2903{
2904 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2905 tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(),
2906 ictx->snap_name.c_str(), ictx->read_only);
2907 string p_pool_name, p_name, p_id, p_snap_name;
2908
2909 int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_id,
2910 &p_snap_name);
2911 if (r < 0) {
2912 tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL);
2913 return r;
2914 }
2915
2916 if (parent_pool_name) {
2917 if (p_pool_name.length() + 1 > ppool_namelen) {
2918 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2919 return -ERANGE;
2920 }
2921
2922 strcpy(parent_pool_name, p_pool_name.c_str());
2923 }
2924 if (parent_name) {
2925 if (p_name.length() + 1 > pnamelen) {
2926 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2927 return -ERANGE;
2928 }
2929
2930 strcpy(parent_name, p_name.c_str());
2931 }
2932 if (parent_id) {
2933 if (p_id.length() + 1 > pidlen) {
2934 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2935 return -ERANGE;
2936 }
2937
2938 strcpy(parent_id, p_id.c_str());
2939 }
2940 if (parent_snap_name) {
2941 if (p_snap_name.length() + 1 > psnap_namelen) {
2942 tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL);
2943 return -ERANGE;
2944 }
2945
2946 strcpy(parent_snap_name, p_snap_name.c_str());
2947 }
2948
2949 tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name,
2950 parent_id, parent_snap_name);
2951 return 0;
2952}
2953
2954extern "C" int rbd_get_flags(rbd_image_t image, uint64_t *flags)
2955{
2956 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2957 tracepoint(librbd, get_flags_enter, ictx);
2958 int r = librbd::get_flags(ictx, flags);
2959 tracepoint(librbd, get_flags_exit, ictx, r, *flags);
2960 return r;
2961}
2962
2963extern "C" int rbd_set_image_notification(rbd_image_t image, int fd, int type)
2964{
2965 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2966 tracepoint(librbd, set_image_notification_enter, ictx, fd, type);
2967 int r = librbd::set_image_notification(ictx, fd, type);
2968 tracepoint(librbd, set_image_notification_exit, ictx, r);
2969 return r;
2970}
2971
2972extern "C" int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
2973{
2974 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2975 tracepoint(librbd, is_exclusive_lock_owner_enter, ictx);
2976 bool owner;
2977 int r = librbd::is_exclusive_lock_owner(ictx, &owner);
2978 *is_owner = owner ? 1 : 0;
2979 tracepoint(librbd, is_exclusive_lock_owner_exit, ictx, r, *is_owner);
2980 return r;
2981}
2982
2983extern "C" int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
2984{
2985 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2986 tracepoint(librbd, lock_acquire_enter, ictx, lock_mode);
2987 int r = librbd::lock_acquire(ictx, lock_mode);
2988 tracepoint(librbd, lock_acquire_exit, ictx, r);
2989 return r;
2990}
2991
2992extern "C" int rbd_lock_release(rbd_image_t image)
2993{
2994 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
2995 tracepoint(librbd, lock_release_enter, ictx);
2996 int r = librbd::lock_release(ictx);
2997 tracepoint(librbd, lock_release_exit, ictx, r);
2998 return r;
2999}
3000
3001extern "C" int rbd_lock_get_owners(rbd_image_t image,
3002 rbd_lock_mode_t *lock_mode,
3003 char **lock_owners,
3004 size_t *max_lock_owners)
3005{
3006 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3007 tracepoint(librbd, lock_get_owners_enter, ictx);
3008 std::list<std::string> lock_owner_list;
3009 int r = librbd::lock_get_owners(ictx, lock_mode, &lock_owner_list);
3010 if (r >= 0) {
3011 if (*max_lock_owners >= lock_owner_list.size()) {
3012 *max_lock_owners = 0;
3013 for (auto &lock_owner : lock_owner_list) {
3014 lock_owners[(*max_lock_owners)++] = strdup(lock_owner.c_str());
3015 }
3016 } else {
3017 *max_lock_owners = lock_owner_list.size();
3018 r = -ERANGE;
3019 }
3020 }
3021 tracepoint(librbd, lock_get_owners_exit, ictx, r);
3022 return r;
3023}
3024
3025extern "C" void rbd_lock_get_owners_cleanup(char **lock_owners,
3026 size_t lock_owner_count)
3027{
3028 for (size_t i = 0; i < lock_owner_count; ++i) {
3029 free(lock_owners[i]);
3030 }
3031}
3032
3033extern "C" int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
3034 const char *lock_owner)
3035{
3036 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3037 tracepoint(librbd, lock_break_enter, ictx, lock_mode, lock_owner);
3038 int r = librbd::lock_break(ictx, lock_mode, lock_owner);
3039 tracepoint(librbd, lock_break_exit, ictx, r);
3040 return r;
3041}
3042
3043extern "C" int rbd_rebuild_object_map(rbd_image_t image,
3044 librbd_progress_fn_t cb, void *cbdata)
3045{
3046 librbd::ImageCtx *ictx = reinterpret_cast<librbd::ImageCtx*>(image);
3047 librbd::CProgressContext prog_ctx(cb, cbdata);
3048 return ictx->operations->rebuild_object_map(prog_ctx);
3049}
3050
3051/* snapshots */
3052extern "C" int rbd_snap_create(rbd_image_t image, const char *snap_name)
3053{
3054 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3055 tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3056 int r = ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
3057 snap_name);
3058 tracepoint(librbd, snap_create_exit, r);
3059 return r;
3060}
3061
3062extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
3063{
3064 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3065 tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
3066 int r = ictx->operations->snap_rename(srcname, dstname);
3067 tracepoint(librbd, snap_rename_exit, r);
3068 return r;
3069}
3070
3071extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
3072{
3073 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3074 tracepoint(librbd, snap_remove_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3075 librbd::NoOpProgressContext prog_ctx;
3076 int r = librbd::snap_remove(ictx, snap_name, 0, prog_ctx);
3077 tracepoint(librbd, snap_remove_exit, r);
3078 return r;
3079}
3080
3081extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags,
3082 librbd_progress_fn_t cb, void *cbdata)
3083{
3084 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3085 tracepoint(librbd, snap_remove2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name, flags);
3086 librbd::CProgressContext prog_ctx(cb, cbdata);
3087 int r = librbd::snap_remove(ictx, snap_name, flags, prog_ctx);
3088 tracepoint(librbd, snap_remove_exit, r);
3089 return r;
3090}
3091
3092extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name)
3093{
3094 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3095 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3096 librbd::NoOpProgressContext prog_ctx;
3097 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3098 tracepoint(librbd, snap_rollback_exit, r);
3099 return r;
3100}
3101
3102extern "C" int rbd_snap_rollback_with_progress(rbd_image_t image,
3103 const char *snap_name,
3104 librbd_progress_fn_t cb,
3105 void *cbdata)
3106{
3107 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3108 tracepoint(librbd, snap_rollback_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3109 librbd::CProgressContext prog_ctx(cb, cbdata);
3110 int r = ictx->operations->snap_rollback(cls::rbd::UserSnapshotNamespace(), snap_name, prog_ctx);
3111 tracepoint(librbd, snap_rollback_exit, r);
3112 return r;
3113}
3114
3115extern "C" int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
3116 int *max_snaps)
3117{
3118 vector<librbd::snap_info_t> cpp_snaps;
3119 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3120 tracepoint(librbd, snap_list_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snaps);
3121
3122 if (!max_snaps) {
3123 tracepoint(librbd, snap_list_exit, -EINVAL, 0);
3124 return -EINVAL;
3125 }
3126
3127 int r = librbd::snap_list(ictx, cpp_snaps);
3128 if (r == -ENOENT) {
3129 tracepoint(librbd, snap_list_exit, 0, *max_snaps);
3130 return 0;
3131 }
3132 if (r < 0) {
3133 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3134 return r;
3135 }
3136 if (*max_snaps < (int)cpp_snaps.size() + 1) {
3137 *max_snaps = (int)cpp_snaps.size() + 1;
3138 tracepoint(librbd, snap_list_exit, -ERANGE, *max_snaps);
3139 return -ERANGE;
3140 }
3141
3142 int i;
3143
3144 for (i = 0; i < (int)cpp_snaps.size(); i++) {
3145 snaps[i].id = cpp_snaps[i].id;
3146 snaps[i].size = cpp_snaps[i].size;
3147 snaps[i].name = strdup(cpp_snaps[i].name.c_str());
3148 if (!snaps[i].name) {
3149 for (int j = 0; j < i; j++)
3150 free((void *)snaps[j].name);
3151 tracepoint(librbd, snap_list_exit, -ENOMEM, *max_snaps);
3152 return -ENOMEM;
3153 }
3154 tracepoint(librbd, snap_list_entry, snaps[i].id, snaps[i].size, snaps[i].name);
3155 }
3156 snaps[i].id = 0;
3157 snaps[i].size = 0;
3158 snaps[i].name = NULL;
3159
3160 r = (int)cpp_snaps.size();
3161 tracepoint(librbd, snap_list_exit, r, *max_snaps);
3162 return r;
3163}
3164
3165extern "C" void rbd_snap_list_end(rbd_snap_info_t *snaps)
3166{
3167 tracepoint(librbd, snap_list_end_enter, snaps);
3168 while (snaps->name) {
3169 free((void *)snaps->name);
3170 snaps++;
3171 }
3172 tracepoint(librbd, snap_list_end_exit);
3173}
3174
3175extern "C" int rbd_snap_protect(rbd_image_t image, const char *snap_name)
3176{
3177 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3178 tracepoint(librbd, snap_protect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3179 int r = ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), snap_name);
3180 tracepoint(librbd, snap_protect_exit, r);
3181 return r;
3182}
3183
3184extern "C" int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
3185{
3186 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3187 tracepoint(librbd, snap_unprotect_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3188 int r = ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), snap_name);
3189 tracepoint(librbd, snap_unprotect_exit, r);
3190 return r;
3191}
3192
3193extern "C" int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
3194 int *is_protected)
3195{
3196 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3197 tracepoint(librbd, snap_is_protected_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3198 bool protected_snap;
3199 int r = librbd::snap_is_protected(ictx, snap_name, &protected_snap);
3200 if (r < 0) {
3201 tracepoint(librbd, snap_is_protected_exit, r, *is_protected ? 1 : 0);
3202 return r;
3203 }
3204 *is_protected = protected_snap ? 1 : 0;
3205 tracepoint(librbd, snap_is_protected_exit, 0, *is_protected ? 1 : 0);
3206 return 0;
3207}
3208
3209extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
3210{
3211 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3212 tracepoint(librbd, snap_get_limit_enter, ictx, ictx->name.c_str());
3213 int r = librbd::snap_get_limit(ictx, limit);
3214 tracepoint(librbd, snap_get_limit_exit, r, *limit);
3215 return r;
3216}
3217
3218extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
3219{
3220 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3221 tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str());
3222 int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp);
3223 tracepoint(librbd, snap_get_timestamp_exit, r);
3224 return r;
3225}
3226
3227extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
3228{
3229 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3230 tracepoint(librbd, snap_set_limit_enter, ictx, ictx->name.c_str(), limit);
3231 int r = librbd::snap_set_limit(ictx, limit);
3232 tracepoint(librbd, snap_set_limit_exit, r);
3233 return r;
3234}
3235
3236extern "C" int rbd_snap_set(rbd_image_t image, const char *snap_name)
3237{
3238 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3239 tracepoint(librbd, snap_set_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
3240 int r = librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), snap_name);
3241 tracepoint(librbd, snap_set_exit, r);
3242 return r;
3243}
3244
3245extern "C" ssize_t rbd_list_children(rbd_image_t image, char *pools,
3246 size_t *pools_len, char *images,
3247 size_t *images_len)
3248{
3249 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3250 tracepoint(librbd, list_children_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3251 set<pair<string, string> > image_set;
3252
3253 int r = librbd::list_children(ictx, image_set);
3254 if (r < 0) {
3255 tracepoint(librbd, list_children_exit, r);
3256 return r;
3257 }
3258
3259 size_t pools_total = 0;
3260 size_t images_total = 0;
3261 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3262 it != image_set.end(); ++it) {
3263 pools_total += it->first.length() + 1;
3264 images_total += it->second.length() + 1;
3265 }
3266
3267 bool too_short = false;
3268 if (pools_total > *pools_len)
3269 too_short = true;
3270 if (images_total > *images_len)
3271 too_short = true;
3272 *pools_len = pools_total;
3273 *images_len = images_total;
3274 if (too_short) {
3275 tracepoint(librbd, list_children_exit, -ERANGE);
3276 return -ERANGE;
3277 }
3278
3279 char *pools_p = pools;
3280 char *images_p = images;
3281 for (set<pair<string, string> >::const_iterator it = image_set.begin();
3282 it != image_set.end(); ++it) {
3283 const char* pool = it->first.c_str();
3284 strcpy(pools_p, pool);
3285 pools_p += it->first.length() + 1;
3286 const char* image = it->second.c_str();
3287 strcpy(images_p, image);
3288 images_p += it->second.length() + 1;
3289 tracepoint(librbd, list_children_entry, pool, image);
3290 }
3291
3292 ssize_t ret = image_set.size();
3293 tracepoint(librbd, list_children_exit, ret);
3294 return ret;
3295}
3296
3297extern "C" ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
3298 char *tag, size_t *tag_len,
3299 char *clients, size_t *clients_len,
3300 char *cookies, size_t *cookies_len,
3301 char *addrs, size_t *addrs_len)
3302{
3303 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3304 tracepoint(librbd, list_lockers_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3305 std::list<librbd::locker_t> lockers;
3306 bool exclusive_bool;
3307 string tag_str;
3308
3309 int r = list_lockers(ictx, &lockers, &exclusive_bool, &tag_str);
3310 if (r < 0) {
3311 tracepoint(librbd, list_lockers_exit, r);
3312 return r;
3313 }
3314
3315 ldout(ictx->cct, 20) << "list_lockers r = " << r << " lockers.size() = " << lockers.size() << dendl;
3316
3317 *exclusive = (int)exclusive_bool;
3318 size_t clients_total = 0;
3319 size_t cookies_total = 0;
3320 size_t addrs_total = 0;
3321 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3322 it != lockers.end(); ++it) {
3323 clients_total += it->client.length() + 1;
3324 cookies_total += it->cookie.length() + 1;
3325 addrs_total += it->address.length() + 1;
3326 }
3327
3328 bool too_short = ((clients_total > *clients_len) ||
3329 (cookies_total > *cookies_len) ||
3330 (addrs_total > *addrs_len) ||
3331 (tag_str.length() + 1 > *tag_len));
3332 *clients_len = clients_total;
3333 *cookies_len = cookies_total;
3334 *addrs_len = addrs_total;
3335 *tag_len = tag_str.length() + 1;
3336 if (too_short) {
3337 tracepoint(librbd, list_lockers_exit, -ERANGE);
3338 return -ERANGE;
3339 }
3340
3341 strcpy(tag, tag_str.c_str());
3342 char *clients_p = clients;
3343 char *cookies_p = cookies;
3344 char *addrs_p = addrs;
3345 for (list<librbd::locker_t>::const_iterator it = lockers.begin();
3346 it != lockers.end(); ++it) {
3347 const char* client = it->client.c_str();
3348 strcpy(clients_p, client);
3349 clients_p += it->client.length() + 1;
3350 const char* cookie = it->cookie.c_str();
3351 strcpy(cookies_p, cookie);
3352 cookies_p += it->cookie.length() + 1;
3353 const char* address = it->address.c_str();
3354 strcpy(addrs_p, address);
3355 addrs_p += it->address.length() + 1;
3356 tracepoint(librbd, list_lockers_entry, client, cookie, address);
3357 }
3358
3359 ssize_t ret = lockers.size();
3360 tracepoint(librbd, list_lockers_exit, ret);
3361 return ret;
3362}
3363
3364extern "C" int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
3365{
3366 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3367 tracepoint(librbd, lock_exclusive_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3368 int r = librbd::lock(ictx, true, cookie ? cookie : "", "");
3369 tracepoint(librbd, lock_exclusive_exit, r);
3370 return r;
3371}
3372
3373extern "C" int rbd_lock_shared(rbd_image_t image, const char *cookie,
3374 const char *tag)
3375{
3376 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3377 tracepoint(librbd, lock_shared_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie, tag);
3378 int r = librbd::lock(ictx, false, cookie ? cookie : "", tag ? tag : "");
3379 tracepoint(librbd, lock_shared_exit, r);
3380 return r;
3381}
3382
3383extern "C" int rbd_unlock(rbd_image_t image, const char *cookie)
3384{
3385 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3386 tracepoint(librbd, unlock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, cookie);
3387 int r = librbd::unlock(ictx, cookie ? cookie : "");
3388 tracepoint(librbd, unlock_exit, r);
3389 return r;
3390}
3391
3392extern "C" int rbd_break_lock(rbd_image_t image, const char *client,
3393 const char *cookie)
3394{
3395 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3396 tracepoint(librbd, break_lock_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, client, cookie);
3397 int r = librbd::break_lock(ictx, client, cookie ? cookie : "");
3398 tracepoint(librbd, break_lock_exit, r);
3399 return r;
3400}
3401
3402/* I/O */
3403extern "C" ssize_t rbd_read(rbd_image_t image, uint64_t ofs, size_t len,
3404 char *buf)
3405{
3406 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3407 tracepoint(librbd, read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3408 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3409 0);
3410 tracepoint(librbd, read_exit, r);
3411 return r;
3412}
3413
3414extern "C" ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
3415 char *buf, int op_flags)
3416{
3417 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3418 tracepoint(librbd, read2_enter, ictx, ictx->name.c_str(),
3419 ictx->snap_name.c_str(), ictx->read_only, ofs, len, op_flags);
3420 int r = ictx->io_work_queue->read(ofs, len, librbd::io::ReadResult{buf, len},
3421 op_flags);
3422 tracepoint(librbd, read_exit, r);
3423 return r;
3424}
3425
3426
3427extern "C" int64_t rbd_read_iterate(rbd_image_t image, uint64_t ofs, size_t len,
3428 int (*cb)(uint64_t, size_t, const char *, void *),
3429 void *arg)
3430{
3431 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3432 tracepoint(librbd, read_iterate_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3433 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3434 tracepoint(librbd, read_iterate_exit, r);
3435 return r;
3436}
3437
3438extern "C" int rbd_read_iterate2(rbd_image_t image, uint64_t ofs, uint64_t len,
3439 int (*cb)(uint64_t, size_t, const char *, void *),
3440 void *arg)
3441{
3442 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3443 tracepoint(librbd, read_iterate2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3444 int64_t r = librbd::read_iterate(ictx, ofs, len, cb, arg);
3445 if (r > 0)
3446 r = 0;
3447 tracepoint(librbd, read_iterate2_exit, r);
3448 return (int)r;
3449}
3450
3451extern "C" int rbd_diff_iterate(rbd_image_t image,
3452 const char *fromsnapname,
3453 uint64_t ofs, uint64_t len,
3454 int (*cb)(uint64_t, size_t, int, void *),
3455 void *arg)
3456{
3457 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3458 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3459 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3460 true, false);
3461 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3462 cls::rbd::UserSnapshotNamespace(),
3463 fromsnapname, ofs, len,
3464 true, false, cb, arg);
3465 tracepoint(librbd, diff_iterate_exit, r);
3466 return r;
3467}
3468
3469extern "C" int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
3470 uint64_t ofs, uint64_t len,
3471 uint8_t include_parent, uint8_t whole_object,
3472 int (*cb)(uint64_t, size_t, int, void *),
3473 void *arg)
3474{
3475 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3476 tracepoint(librbd, diff_iterate_enter, ictx, ictx->name.c_str(),
3477 ictx->snap_name.c_str(), ictx->read_only, fromsnapname, ofs, len,
3478 include_parent != 0, whole_object != 0);
3479 int r = librbd::api::DiffIterate<>::diff_iterate(ictx,
3480 cls::rbd::UserSnapshotNamespace(),
3481 fromsnapname, ofs, len,
3482 include_parent, whole_object,
3483 cb, arg);
3484 tracepoint(librbd, diff_iterate_exit, r);
3485 return r;
3486}
3487
3488extern "C" ssize_t rbd_write(rbd_image_t image, uint64_t ofs, size_t len,
3489 const char *buf)
3490{
3491 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3492 tracepoint(librbd, write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf);
3493
3494 bufferlist bl;
3495 bl.push_back(create_write_raw(ictx, buf, len));
3496 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), 0);
3497 tracepoint(librbd, write_exit, r);
3498 return r;
3499}
3500
3501extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
3502 const char *buf, int op_flags)
3503{
3504 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3505 tracepoint(librbd, write2_enter, ictx, ictx->name.c_str(),
3506 ictx->snap_name.c_str(), ictx->read_only, ofs, len, buf, op_flags);
3507
3508 bufferlist bl;
3509 bl.push_back(create_write_raw(ictx, buf, len));
3510 int r = ictx->io_work_queue->write(ofs, len, std::move(bl), op_flags);
3511 tracepoint(librbd, write_exit, r);
3512 return r;
3513}
3514
3515
3516extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
3517{
3518 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3519 tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len);
3520 int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard);
3521 tracepoint(librbd, discard_exit, r);
3522 return r;
3523}
3524
3525extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len,
3526 const char *buf, size_t data_len, int op_flags)
3527{
3528 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3529 tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3530 ictx->read_only, ofs, len, data_len <= 0 ? NULL : buf, data_len, op_flags);
3531
3532 if (data_len <= 0 || len % data_len) {
3533 tracepoint(librbd, writesame_exit, -EINVAL);
3534 return -EINVAL;
3535 }
3536
3537 if (mem_is_zero(buf, data_len)) {
3538 int r = ictx->io_work_queue->discard(ofs, len, false);
3539 tracepoint(librbd, writesame_exit, r);
3540 return r;
3541 }
3542
3543 bufferlist bl;
3544 bl.push_back(create_write_raw(ictx, buf, data_len));
3545 int r = ictx->io_work_queue->writesame(ofs, len, std::move(bl), op_flags);
3546 tracepoint(librbd, writesame_exit, r);
3547 return r;
3548}
3549
3550extern "C" int rbd_aio_create_completion(void *cb_arg,
3551 rbd_callback_t complete_cb,
3552 rbd_completion_t *c)
3553{
3554 librbd::RBD::AioCompletion *rbd_comp =
3555 new librbd::RBD::AioCompletion(cb_arg, complete_cb);
3556 *c = (rbd_completion_t) rbd_comp;
3557 return 0;
3558}
3559
3560extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
3561 const char *buf, rbd_completion_t c)
3562{
3563 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3564 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3565 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3566
3567 bufferlist bl;
3568 bl.push_back(create_write_raw(ictx, buf, len));
3569 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3570 std::move(bl), 0);
3571 tracepoint(librbd, aio_write_exit, 0);
3572 return 0;
3573}
3574
3575extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
3576 const char *buf, rbd_completion_t c, int op_flags)
3577{
3578 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3579 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3580 tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3581 ictx->read_only, off, len, buf, comp->pc, op_flags);
3582
3583 bufferlist bl;
3584 bl.push_back(create_write_raw(ictx, buf, len));
3585 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3586 std::move(bl), op_flags);
3587 tracepoint(librbd, aio_write_exit, 0);
3588 return 0;
3589}
3590
3591extern "C" int rbd_aio_writev(rbd_image_t image, const struct iovec *iov,
3592 int iovcnt, uint64_t off, rbd_completion_t c)
3593{
3594 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3595 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3596
3597 // convert the scatter list into a bufferlist
3598 ssize_t len = 0;
3599 bufferlist bl;
3600 for (int i = 0; i < iovcnt; ++i) {
3601 const struct iovec &io = iov[i];
3602 len += io.iov_len;
3603 if (len < 0) {
3604 break;
3605 }
3606
3607 bl.push_back(create_write_raw(ictx, static_cast<char*>(io.iov_base),
3608 io.iov_len));
3609 }
3610
3611 int r = 0;
3612 if (iovcnt <= 0 || len < 0) {
3613 r = -EINVAL;
3614 }
3615
3616 tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(),
3617 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3618 comp->pc);
3619 if (r == 0) {
3620 ictx->io_work_queue->aio_write(get_aio_completion(comp), off, len,
3621 std::move(bl), 0);
3622 }
3623 tracepoint(librbd, aio_write_exit, r);
3624 return r;
3625}
3626
3627extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
3628 rbd_completion_t c)
3629{
3630 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3631 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3632 tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
3633 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, ictx->skip_partial_discard);
3634 tracepoint(librbd, aio_discard_exit, 0);
3635 return 0;
3636}
3637
3638extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
3639 char *buf, rbd_completion_t c)
3640{
3641 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3642 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3643 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
3644 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3645 librbd::io::ReadResult{buf, len}, 0);
3646 tracepoint(librbd, aio_read_exit, 0);
3647 return 0;
3648}
3649
3650extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
3651 char *buf, rbd_completion_t c, int op_flags)
3652{
3653 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3654 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3655 tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3656 ictx->read_only, off, len, buf, comp->pc, op_flags);
3657 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3658 librbd::io::ReadResult{buf, len},op_flags);
3659 tracepoint(librbd, aio_read_exit, 0);
3660 return 0;
3661}
3662
3663extern "C" int rbd_aio_readv(rbd_image_t image, const struct iovec *iov,
3664 int iovcnt, uint64_t off, rbd_completion_t c)
3665{
3666 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3667 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3668
3669 ssize_t len = 0;
3670 for (int i = 0; i < iovcnt; ++i) {
3671 len += iov[i].iov_len;
3672 if (len < 0) {
3673 break;
3674 }
3675 }
3676
3677 int r = 0;
3678 if (iovcnt == 0 || len < 0) {
3679 r = -EINVAL;
3680 }
3681
3682 tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(),
3683 ictx->snap_name.c_str(), ictx->read_only, off, len, NULL,
3684 comp->pc);
3685 if (r == 0) {
3686 librbd::io::ReadResult read_result;
3687 if (iovcnt == 1) {
3688 read_result = librbd::io::ReadResult(
3689 static_cast<char *>(iov[0].iov_base), iov[0].iov_len);
3690 } else {
3691 read_result = librbd::io::ReadResult(iov, iovcnt);
3692 }
3693 ictx->io_work_queue->aio_read(get_aio_completion(comp), off, len,
3694 std::move(read_result), 0);
3695 }
3696 tracepoint(librbd, aio_read_exit, r);
3697 return r;
3698}
3699
3700extern "C" int rbd_flush(rbd_image_t image)
3701{
3702 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3703 tracepoint(librbd, flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3704 int r = librbd::flush(ictx);
3705 tracepoint(librbd, flush_exit, r);
3706 return r;
3707}
3708
3709extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
3710{
3711 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3712 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3713 tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
3714 ictx->io_work_queue->aio_flush(get_aio_completion(comp));
3715 tracepoint(librbd, aio_flush_exit, 0);
3716 return 0;
3717}
3718
3719extern "C" int rbd_aio_writesame(rbd_image_t image, uint64_t off, size_t len,
3720 const char *buf, size_t data_len, rbd_completion_t c,
3721 int op_flags)
3722{
3723 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3724 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3725 tracepoint(librbd, aio_writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
3726 ictx->read_only, off, len, data_len <= 0 ? NULL : buf, data_len, comp->pc,
3727 op_flags);
3728
3729 if (data_len <= 0 || len % data_len) {
3730 tracepoint(librbd, aio_writesame_exit, -EINVAL);
3731 return -EINVAL;
3732 }
3733
3734 if (mem_is_zero(buf, data_len)) {
3735 ictx->io_work_queue->aio_discard(get_aio_completion(comp), off, len, false);
3736 tracepoint(librbd, aio_writesame_exit, 0);
3737 return 0;
3738 }
3739
3740 bufferlist bl;
3741 bl.push_back(create_write_raw(ictx, buf, data_len));
3742 ictx->io_work_queue->aio_writesame(get_aio_completion(comp), off, len,
3743 std::move(bl), op_flags);
3744 tracepoint(librbd, aio_writesame_exit, 0);
3745 return 0;
3746}
3747
3748extern "C" int rbd_invalidate_cache(rbd_image_t image)
3749{
3750 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3751 tracepoint(librbd, invalidate_cache_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only);
3752 int r = librbd::invalidate_cache(ictx);
3753 tracepoint(librbd, invalidate_cache_exit, r);
3754 return r;
3755}
3756
3757extern "C" int rbd_poll_io_events(rbd_image_t image, rbd_completion_t *comps, int numcomp)
3758{
3759 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3760 librbd::io::AioCompletion *cs[numcomp];
3761 tracepoint(librbd, poll_io_events_enter, ictx, numcomp);
3762 int r = librbd::poll_io_events(ictx, cs, numcomp);
3763 tracepoint(librbd, poll_io_events_exit, r);
3764 if (r > 0) {
3765 for (int i = 0; i < r; ++i)
3766 comps[i] = cs[i]->rbd_comp;
3767 }
3768 return r;
3769}
3770
3771extern "C" int rbd_metadata_get(rbd_image_t image, const char *key, char *value, size_t *vallen)
3772{
3773 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3774 string val_s;
3775 tracepoint(librbd, metadata_get_enter, ictx, key);
3776 int r = librbd::metadata_get(ictx, key, &val_s);
3777 if (r < 0) {
3778 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3779 return r;
3780 }
3781 if (*vallen < val_s.size() + 1) {
3782 r = -ERANGE;
3783 *vallen = val_s.size() + 1;
3784 tracepoint(librbd, metadata_get_exit, r, key, NULL);
3785 } else {
3786 strncpy(value, val_s.c_str(), val_s.size() + 1);
3787 tracepoint(librbd, metadata_get_exit, r, key, value);
3788 }
3789 return r;
3790}
3791
3792extern "C" int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
3793{
3794 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3795 tracepoint(librbd, metadata_set_enter, ictx, key, value);
3796 int r = ictx->operations->metadata_set(key, value);
3797 tracepoint(librbd, metadata_set_exit, r);
3798 return r;
3799}
3800
3801extern "C" int rbd_metadata_remove(rbd_image_t image, const char *key)
3802{
3803 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3804 tracepoint(librbd, metadata_remove_enter, ictx, key);
3805 int r = ictx->operations->metadata_remove(key);
3806 tracepoint(librbd, metadata_remove_exit, r);
3807 return r;
3808}
3809
3810extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
3811 char *key, size_t *key_len, char *value, size_t *val_len)
3812{
3813 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3814 tracepoint(librbd, metadata_list_enter, ictx);
3815 map<string, bufferlist> pairs;
3816 int r = librbd::metadata_list(ictx, start, max, &pairs);
3817 size_t key_total_len = 0, val_total_len = 0;
3818 bool too_short = false;
3819 for (map<string, bufferlist>::iterator it = pairs.begin();
3820 it != pairs.end(); ++it) {
3821 key_total_len += it->first.size() + 1;
3822 val_total_len += it->second.length() + 1;
3823 }
3824 if (*key_len < key_total_len || *val_len < val_total_len)
3825 too_short = true;
3826 *key_len = key_total_len;
3827 *val_len = val_total_len;
3828 if (too_short) {
3829 tracepoint(librbd, metadata_list_exit, -ERANGE);
3830 return -ERANGE;
3831 }
3832
3833 char *key_p = key, *value_p = value;
3834
3835 for (map<string, bufferlist>::iterator it = pairs.begin();
3836 it != pairs.end(); ++it) {
3837 strncpy(key_p, it->first.c_str(), it->first.size() + 1);
3838 key_p += it->first.size() + 1;
3839 strncpy(value_p, it->second.c_str(), it->second.length());
3840 value_p += it->second.length();
3841 *value_p = '\0';
3842 value_p++;
3843 tracepoint(librbd, metadata_list_entry, it->first.c_str(), it->second.c_str());
3844 }
3845 tracepoint(librbd, metadata_list_exit, r);
3846 return r;
3847}
3848
3849extern "C" int rbd_mirror_image_enable(rbd_image_t image)
3850{
3851 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3852 return librbd::api::Mirror<>::image_enable(ictx, false);
3853}
3854
3855extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
3856{
3857 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3858 return librbd::api::Mirror<>::image_disable(ictx, force);
3859}
3860
3861extern "C" int rbd_mirror_image_promote(rbd_image_t image, bool force)
3862{
3863 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3864 return librbd::api::Mirror<>::image_promote(ictx, force);
3865}
3866
3867extern "C" int rbd_mirror_image_demote(rbd_image_t image)
3868{
3869 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3870 return librbd::api::Mirror<>::image_demote(ictx);
3871}
3872
3873extern "C" int rbd_mirror_image_resync(rbd_image_t image)
3874{
3875 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3876 return librbd::api::Mirror<>::image_resync(ictx);
3877}
3878
3879extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
3880 rbd_mirror_image_info_t *mirror_image_info,
3881 size_t info_size)
3882{
3883 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3884
3885 librbd::mirror_image_info_t cpp_mirror_image;
3886 int r = librbd::api::Mirror<>::image_get_info(ictx, &cpp_mirror_image,
3887 sizeof(cpp_mirror_image));
3888 if (r < 0) {
3889 return r;
3890 }
3891
3892 mirror_image_info_cpp_to_c(cpp_mirror_image, mirror_image_info);
3893 return 0;
3894}
3895
3896extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
3897 rbd_mirror_image_status_t *status,
3898 size_t status_size)
3899{
3900 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3901
3902 librbd::mirror_image_status_t cpp_status;
3903 int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status,
3904 sizeof(cpp_status));
3905 if (r < 0) {
3906 return r;
3907 }
3908
3909 mirror_image_status_cpp_to_c(cpp_status, status);
3910 return 0;
3911}
3912
3913extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
3914 rbd_completion_t c) {
3915 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3916 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3917 librbd::api::Mirror<>::image_promote(
3918 ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3919 get_aio_completion(comp)));
3920 return 0;
3921}
3922
3923extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image,
3924 rbd_completion_t c) {
3925 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3926 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3927 librbd::api::Mirror<>::image_demote(
3928 ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3929 get_aio_completion(comp)));
3930 return 0;
3931}
3932
3933extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
3934 rbd_mirror_image_info_t *info,
3935 size_t info_size,
3936 rbd_completion_t c) {
3937 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3938 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3939
3940 if (sizeof(rbd_mirror_image_info_t) > info_size) {
3941 return -ERANGE;
3942 }
3943
3944 auto ctx = new C_MirrorImageGetInfo(
3945 info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3946 get_aio_completion(comp)));
3947 librbd::api::Mirror<>::image_get_info(
3948 ictx, &ctx->cpp_mirror_image_info, sizeof(ctx->cpp_mirror_image_info), ctx);
3949 return 0;
3950}
3951
3952extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
3953 rbd_mirror_image_status_t *status,
3954 size_t status_size,
3955 rbd_completion_t c) {
3956 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3957 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3958
3959 if (sizeof(rbd_mirror_image_status_t) > status_size) {
3960 return -ERANGE;
3961 }
3962
3963 auto ctx = new C_MirrorImageGetStatus(
3964 status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
3965 get_aio_completion(comp)));
3966 librbd::api::Mirror<>::image_get_status(
3967 ictx, &ctx->cpp_mirror_image_status, sizeof(ctx->cpp_mirror_image_status),
3968 ctx);
3969 return 0;
3970}
3971
3972extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
3973 rbd_update_callback_t watch_cb, void *arg)
3974{
3975 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3976 C_UpdateWatchCB *wctx = new C_UpdateWatchCB(watch_cb, arg);
3977 tracepoint(librbd, update_watch_enter, ictx, wctx);
3978 int r = ictx->state->register_update_watcher(wctx, &wctx->handle);
3979 tracepoint(librbd, update_watch_exit, r, wctx->handle);
3980 *handle = reinterpret_cast<uint64_t>(wctx);
3981 return r;
3982}
3983
3984extern "C" int rbd_update_unwatch(rbd_image_t image, uint64_t handle)
3985{
3986 librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
3987 C_UpdateWatchCB *wctx = reinterpret_cast<C_UpdateWatchCB *>(handle);
3988 tracepoint(librbd, update_unwatch_enter, ictx, wctx->handle);
3989 int r = ictx->state->unregister_update_watcher(wctx->handle);
3990 delete wctx;
3991 tracepoint(librbd, update_unwatch_exit, r);
3992 return r;
3993}
3994
3995extern "C" int rbd_aio_is_complete(rbd_completion_t c)
3996{
3997 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
3998 return comp->is_complete();
3999}
4000
4001extern "C" int rbd_aio_wait_for_complete(rbd_completion_t c)
4002{
4003 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4004 return comp->wait_for_complete();
4005}
4006
4007extern "C" ssize_t rbd_aio_get_return_value(rbd_completion_t c)
4008{
4009 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4010 return comp->get_return_value();
4011}
4012
4013extern "C" void *rbd_aio_get_arg(rbd_completion_t c)
4014{
4015 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4016 return comp->get_arg();
4017}
4018
4019extern "C" void rbd_aio_release(rbd_completion_t c)
4020{
4021 librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
4022 comp->release();
4023}
4024
4025extern "C" int rbd_group_create(rados_ioctx_t p, const char *name)
4026{
4027 librados::IoCtx io_ctx;
4028 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4029 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4030 tracepoint(librbd, group_create_enter, io_ctx.get_pool_name().c_str(),
4031 io_ctx.get_id(), name);
4032 int r = librbd::api::Group<>::create(io_ctx, name);
4033 tracepoint(librbd, group_create_exit, r);
4034 return r;
4035}
4036
4037extern "C" int rbd_group_remove(rados_ioctx_t p, const char *name)
4038{
4039 librados::IoCtx io_ctx;
4040 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4041 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4042 tracepoint(librbd, group_remove_enter, io_ctx.get_pool_name().c_str(),
4043 io_ctx.get_id(), name);
4044 int r = librbd::api::Group<>::remove(io_ctx, name);
4045 tracepoint(librbd, group_remove_exit, r);
4046 return r;
4047}
4048
4049extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size)
4050{
4051 librados::IoCtx io_ctx;
4052 librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
4053 TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
4054 tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
4055 io_ctx.get_id());
4056
4057 vector<string> cpp_names;
4058 int r = librbd::list(io_ctx, cpp_names);
7c673cae
FG
4059 if (r < 0) {
4060 tracepoint(librbd, group_list_exit, r);
4061 return r;
4062 }
4063
4064 size_t expected_size = 0;
4065
4066 for (size_t i = 0; i < cpp_names.size(); i++) {
4067 expected_size += cpp_names[i].size() + 1;
4068 }
4069 if (*size < expected_size) {
4070 *size = expected_size;
4071 tracepoint(librbd, group_list_exit, -ERANGE);
4072 return -ERANGE;
4073 }
4074
4075 if (!names)
4076 return -EINVAL;
4077
4078 names[expected_size] = '\0';
4079 for (int i = 0; i < (int)cpp_names.size(); i++) {
4080 const char* name = cpp_names[i].c_str();
4081 tracepoint(librbd, group_list_entry, name);
4082 strcpy(names, name);
4083 names += strlen(names) + 1;
4084 }
4085 tracepoint(librbd, group_list_exit, (int)expected_size);
4086 return (int)expected_size;
4087}
4088
4089extern "C" int rbd_group_image_add(
4090 rados_ioctx_t group_p, const char *group_name,
4091 rados_ioctx_t image_p, const char *image_name)
4092{
4093 librados::IoCtx group_ioctx;
4094 librados::IoCtx image_ioctx;
4095
4096 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4097 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4098
4099 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4100 tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(),
4101 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
4102 image_ioctx.get_id(), image_name);
4103
4104 int r = librbd::api::Group<>::image_add(group_ioctx, group_name, image_ioctx,
4105 image_name);
4106
4107 tracepoint(librbd, group_image_add_exit, r);
4108 return r;
4109}
4110
4111extern "C" int rbd_group_image_remove(
4112 rados_ioctx_t group_p, const char *group_name,
4113 rados_ioctx_t image_p, const char *image_name)
4114{
4115 librados::IoCtx group_ioctx;
4116 librados::IoCtx image_ioctx;
4117
4118 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4119 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4120
4121 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4122 tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(),
4123 group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(),
4124 image_ioctx.get_id(), image_name);
4125
4126 int r = librbd::api::Group<>::image_remove(group_ioctx, group_name,
4127 image_ioctx, image_name);
4128
4129 tracepoint(librbd, group_image_remove_exit, r);
4130 return r;
4131}
4132
4133extern "C" int rbd_group_image_remove_by_id(rados_ioctx_t group_p,
4134 const char *group_name,
4135 rados_ioctx_t image_p,
4136 const char *image_id)
4137{
4138 librados::IoCtx group_ioctx;
4139 librados::IoCtx image_ioctx;
4140
4141 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4142 librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx);
4143
4144 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4145 tracepoint(librbd, group_image_remove_by_id_enter,
4146 group_ioctx.get_pool_name().c_str(),
4147 group_ioctx.get_id(), group_name,
4148 image_ioctx.get_pool_name().c_str(),
4149 image_ioctx.get_id(), image_id);
4150
4151 int r = librbd::api::Group<>::image_remove_by_id(group_ioctx, group_name,
4152 image_ioctx, image_id);
4153
4154 tracepoint(librbd, group_image_remove_by_id_exit, r);
4155 return r;
4156}
4157
4158extern "C" int rbd_group_image_list(rados_ioctx_t group_p,
4159 const char *group_name,
4160 rbd_group_image_status_t *images,
4161 size_t *image_size)
4162{
4163 librados::IoCtx group_ioctx;
4164 librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx);
4165
4166 TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
4167 tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(),
4168 group_ioctx.get_id(), group_name);
4169
4170 std::vector<librbd::group_image_status_t> cpp_images;
4171 int r = librbd::api::Group<>::image_list(group_ioctx, group_name,
4172 &cpp_images);
4173
4174 if (r == -ENOENT) {
4175 tracepoint(librbd, group_image_list_exit, 0);
4176 return 0;
4177 }
4178
4179 if (r < 0) {
4180 tracepoint(librbd, group_image_list_exit, r);
4181 return r;
4182 }
4183
4184 if (*image_size < cpp_images.size()) {
4185 tracepoint(librbd, group_image_list_exit, -ERANGE);
4186 return -ERANGE;
4187 }
4188
4189 for (size_t i = 0; i < cpp_images.size(); ++i) {
4190 group_image_status_cpp_to_c(cpp_images[i], &images[i]);
4191 }
4192
4193 tracepoint(librbd, group_image_list_exit, r);
4194 return r;
4195}
4196
4197extern "C" int rbd_image_get_group(rados_ioctx_t image_p,
4198 const char *image_name,
4199 rbd_group_spec_t *c_group_spec)
4200{
4201 librados::IoCtx io_ctx;
4202 librados::IoCtx::from_rados_ioctx_t(image_p, io_ctx);
4203
4204 librbd::ImageCtx *ictx = new librbd::ImageCtx(image_name, "", "", io_ctx, false);
4205 int r = ictx->state->open(false);
4206 if (r < 0) {
4207 tracepoint(librbd, open_image_exit, r);
4208 return r;
4209 }
4210
4211 tracepoint(librbd, image_get_group_enter, ictx->name.c_str());
4212 librbd::group_spec_t group_spec;
4213 r = librbd::api::Group<>::image_get_group(ictx, &group_spec);
4214 group_spec_cpp_to_c(group_spec, c_group_spec);
4215 tracepoint(librbd, image_get_group_exit, r);
4216 ictx->state->close();
4217 return r;
4218}
4219
4220extern "C" void rbd_group_spec_cleanup(rbd_group_spec_t *group_spec) {
4221 free(group_spec->name);
4222}
4223
4224extern "C" void rbd_group_image_status_cleanup(
4225 rbd_group_image_status_t *image) {
4226 free(image->spec.name);
4227}
4228
4229extern "C" void rbd_group_image_status_list_cleanup(
4230 rbd_group_image_status_t *images,
4231 size_t len) {
4232 for (size_t i = 0; i < len; ++i) {
4233 rbd_group_image_status_cleanup(&images[i]);
4234 }
4235}